Skip to content

Lock policyengine-uk 2.177.7 and policyengine-core 3.34.10 and follow what their releases change - #1572

Open
juaristi22 wants to merge 10 commits into
mainfrom
uk-pe-uk-bump-2177
Open

juaristi22 wants to merge 10 commits into
mainfrom
uk-pe-uk-bump-2177

Conversation

@juaristi22

@juaristi22 juaristi22 commented Nov 10, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

The UK lock moves from policyengine-uk 2.174.1 to 2.177.7, the newest release when the pin moved (microcosm#1095). From 2.177.4 policyengine-uk requires policyengine-core 3.34.9 or later, so the UK side's core moves from 3.33.3 to 3.34.10, the newest. The US side stays on 3.32.5, and uv.lock moves those two packages alone. What each release since the lock needs is in #1095's "The next policyengine-uk lock" (the read of 10 November), and the releases after it, 2.177.5 to 2.177.7, are below.

This PR was opened stacked on #1550. #1550 merged on 10 November (bd09f1783), and main at that commit is merged into this branch. After that merge the pin moved from 2.177.4 to 2.177.7, as María chose. 2.177.5 to 2.177.7 add no input.

The three new inputs, signed at their defaults

Each is in UK_ENGINE_DEFAULT_INPUTS with the error it can make, for María's signature:

  • legacy_prescribed_accommodation_capital_exception (2.174.8), at False: the FRS samples private households, so it holds almost no claimant living permanently in prescribed accommodation. Such a claimant's Income Support, income-based JSA or income-related ESA is understated by the tariff income on capital between £6,000 and £10,000.
  • esa_income_appointee_saving (2.175.3), at False: the FRS does not identify appointees, so every reported income-related ESA award ends at the abolition of 1 July 2026. DWP exempted around 500 such claimants. 2025, the calibration year, does not move.
  • cares_for_severely_disabled_person (2.177.3), at True: the FRS records caring hours but not whom the carer cares for. At True, caring hours pay as before, so no figure moves.

An input that gained a formula

From 2.176.1, is_before_universal_credit_qualifying_young_person_terminal_date follows the date of birth, so it leaves the engine's input surface (376 to 378 inputs). frs_education still writes it, and the loader takes a stored value over the formula, as it does for any engine variable. Universal Credit reads it only for a 19-year-old, together with the education condition, which is the same test frs_education sets it from. So the stored value and the formula give the same result.

What the build's engine reads return now

  • 2.174.2 to 2.175.3: as UK: every open data item: uk-data parity, engine locks, the local surface, consumption and high-value homes #1095 lists them. The qualifying young person rule for 16-year-olds; the State Pension age addition; the benefit cap reduction; the Universal Credit deduction flag; reg 60A's Working Tax Credit test; Maternity Allowance in the cap; and the income-related ESA abolition, which moves nothing before July 2026.

  • 2.175.5, 2.175.8 and 2.177.2 (Council Tax Reduction):

    • the pensioner schemes in England, Scotland and Wales add child amounts and family premiums;
    • all of a Scottish pensioner's capital over £10,000 counts in tariff income;
    • Scotland's and Wales's working-age schemes get their own rules;
    • Scotland's counts Carer Support Payment after the overlapping-benefit reduction.

    The council tax rows read council tax net of the reduction.

  • 2.176.0 (Model rent from boarders, lodgers and sub-tenants for the householder policyengine-uk#2002): rent from boarders, lodgers and sub-tenants for the householder.

    • Income tax gives rent-a-room relief on the boarders' and lodgers' rent, which the engine sums for the household head from the rent_paid_as_boarder and rent_paid_as_lodger the build writes.
    • The legacy means tests apply the £20 and board-and-lodging disregards.
    • A boarder or lodger draws no non-dependant deduction.
    • The build keeps the FRS sub-letting rent in property_income.
  • 2.176.1: the qualifying young person's terminal date, above. It now applies to Pension Credit too.

  • 2.176.2:

    • Housing Benefit's and national Council Tax Reduction's non-dependant deductions follow each scheme's rules.
    • Universal Credit changes its LHA bedrooms and its renter exemption.
    • Universal Credit's benefit cap counts welfare benefits without Housing Benefit. A dataset that supplied benefit_cap_welfare_benefits would now also need Housing Benefit before the cap; the build supplies neither.
  • 2.177.0: VAT's survey coverage moves from 0.67 to 0.69. obr.vat stays held.

  • 2.177.2: Marriage Allowance becomes the recipient's tax reduction, and Scottish taxpayers' tax bands apply the Scottish limits to income other than savings and dividends.

  • 2.177.3: Plan 5 borrowers repay nothing before 6 April 2026, the date the student-loans stage already uses. slc.borrowers.plan_5_above_threshold then matches SLC's nil, and slc.repayments.england_plan_5, held, reads nil.

  • 2.177.5 (Bar income-related ESA at pensionable age and on Pension Credit policyengine-uk#2807): no income-related ESA for a claimant who has reached pensionable age, or for a couple that would get Pension Credit without it.

  • 2.177.6 (Count enhanced PIP daily living and AFIP for the enhanced premium policyengine-uk#2808):

    • The legacy enhanced disability premium is paid for enhanced PIP daily living and armed forces independence payment, beside the highest DLA care rate.
    • Four councils' working-age CTR schemes get their own lists.
    • The is_enhanced_disabled_for_benefits the build stores now reaches only Kingston upon Thames's working-age Council Tax Reduction and two deprecated counts, neither of which the build reads.
    • No stage writes armed forces independence payment, so its recipients get the premium only through another qualifying benefit.
  • 2.177.7 (Set reliefs and allowances against income for the least tax policyengine-uk#2830): income tax sets the allowances and reliefs against income in the way that gives the least tax (ITA 2007 s. 25(2)), instead of against non-savings income first.

  • policyengine-core 3.34.10: fixes to cached periods and to inputs on reform branches. The UK side neutralises no variable and uses none of the APIs 3.34.0 removed.

  • The other releases change nothing the build reads at 2024 or 2025, or nothing at all.

What does not move

  • The vendored uprating pins and the bonus-sacrifice anchor change only their version stamps. The CGT projection path keeps its values, within the pinned drift (test_uk_cgt_projection.py).
  • UK_HBAI_GROSS_INCOME_DEDUCTIONS keeps its parity. 2.176.0 adds sublet_income to HBAI income, not to its subtractions, and the build keeps that income in property_income.

Texts and derived files

Every text that described the locked engine was checked against the diff from 2.174.1 to 2.177.7 and now cites 2.177.7. That covers the stage notes, code comments, test docstrings, the ISA and LISA docs, and #1550's PIP points, limited capability and trading allowance texts. Among the variables they cite, 2.177.5 to 2.177.7 change only tax_band's comment.

The take-up stage's note had said the build flags nobody in full-time education. Since #1535 it does, and the note now says so, as the code comment does. The coverage manifest tool's PIP notes and the eFRS known gaps follow.

The concept coverage report, the release input coverage manifest, the H2 fixture, the cited versions and APPROVED_UV_LOCK_SHA256 are regenerated.

Measurement

Two arms run on this machine, one at a time, each a spine and a calibration, at review date 2026-11-10 on #1550's feed (8045b138):

  • a control on main at bd09f1783, this PR's base;
  • this branch's head at 9e58d5844, which is also certified as a national release: rule 1 against the enhanced FRS, the signed release-cut certification, and the stage-1 comparison with the promoted national. Published to the inspect lane by tag, without promotion, it can be loaded by that tag for data drills on a certified dataset.

Rule 1 on the head build refused at first. Five HMRC SPI rows have read person.trading_allowance_full_relief since #1439, and the measure had no entry on the reviewed incumbent-unresolvable register. Main has the same gap. aa08d812b adds María's signed entry and changes nothing the build reads, so the certification reruns on the same build at that commit.

The control is fresh because main's merges since #1550 branched change the national build: #1549's register, #1417's ITL differential check and the fiscal targets. Their results follow in a comment: both arms' gates, the fit, the first stage where the spines differ, and the rows each release moves, with rows of the SPI channel as classes.

Tests

  • Engine tier on policyengine-uk 2.177.7: CI's engine-uk job at 9e58d5844 (72 files on Python 3.13 and 3.14), which includes the H parity test, passed on both, as did every other job of that run.
  • Engine tier on 2.177.4: CI's engine-uk list (72 files), run in full locally because CI stops at the first failure. 315 tests: 313 passed and 2 failed, and 5d6a3e7 fixes both.
    • test_uk_tax_band_measure.py had pinned a known gap "so a fix shows", and 2.177.2 is that fix.
    • The frozen eFRS candidate receipt measures the terminal-date column against its engine default, which 2.176.1 flips; the receipt keeps its original engine provenance.
    • The checklist tests passed: the CGT projection, bus parity, UK_HBAI_GROSS_INCOME_DEDUCTIONS, the uprating pins, the bonus anchor and all 13 concept-mapping tests.
  • Engine-free files on the touched surfaces: 81 files, run in three processes and counted by --junitxml. 3,904 tests: 3,877 passed, 25 skipped and 2 failed, neither from this PR.
  • Checks on 2.177.7:
    • tools/ci_test_plan.py verify;
    • tools/spec_engine_coverage.py --check (42,394 of 42,394 fields, 41 of 41 inventory checks);
    • tools/refresh_concept_coverage.py --engine policyengine-uk --check;
    • the coverage manifest with --check;
    • the H2 fixture, regenerated on 2.177.7 in 9e58d5844. Only the engine versions and four stage contract digests move, and no fixture value.
  • The register entry (aa08d812b): the six engine-free files that read the register pass (228 tests).

Signatures

Awaiting María's signature: the three signed defaults, with the error each can make.

Signed by María on 10 November: the incumbent-unresolvable entry for person.trading_allowance_full_relief (aa08d812b), expiring 10 February 2027.

Not in this PR

Disclosure

No figure in this PR, its commits or its changelog rests on survey records. The numbers are policyengine-uk's parameters and versions, and published figures cited as their publishers'.

🤖 Generated with Claude Code

juaristi22 and others added 4 commits November 10, 2026 13:50
The UK lock moves from policyengine-uk 2.174.1 to 2.177.4, the newest
release (microcosm#1095). From 2.177.4 policyengine-uk requires
policyengine-core 3.34.9 or later, so the UK side's core moves from
3.33.3 to 3.34.10, the newest; the US side stays on 3.32.5. uv.lock
moves those two packages alone.

Three new inputs stay at their defaults and are signed in
UK_ENGINE_DEFAULT_INPUTS, each with the error it can make, for María's
signature: legacy_prescribed_accommodation_capital_exception (2.174.8)
and esa_income_appointee_saving (2.175.3) at False, and
cares_for_severely_disabled_person (2.177.3) at True, which moves no
figure. From 2.176.1
is_before_universal_credit_qualifying_young_person_terminal_date has a
formula from the date of birth, so it leaves the engine's input surface
(376 to 378 inputs); frs_education still writes it, the loader takes it
as an override, and Universal Credit reads it only for a 19-year-old
alongside the education condition, so the result is the engine's own.

No economic pin moves: the vendored uprating pins and the
bonus-sacrifice anchor change only their version stamps. The three
pyproject floors, the approved lock digest, the engine-core pin test,
the concept mapping's version and the concept coverage follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The stage notes, code comments, docstrings and docs that describe the
locked engine now cite 2.177.4, each checked against it: the education
flag's one reader (uc_receiving_education), is_uc_eligible's age and
role conditions, Universal Credit's capital readers, the limited
capability proxy, the PIP categories from points, the trading allowance
claim status, the ISA and Lifetime ISA readers and the capital source
lists are unchanged from 2.174.1 (is_uc_eligible changes only its
reg 60A Working Tax Credit test, from 2.175.1). The two
policy_parameters dependencies of the CGT stages follow the new floor.

The take-up stage's note still said the build flags nobody in full-time
education and named three engine cases; since #1535 frs_education sets
the flag and the lockstep test names a fourth, which the note now
gives, as the code comment does.

The coverage manifest tool's reviewed PIP notes and the eFRS known gaps
follow, and the manifest is regenerated: only those notes and the
source manifest digest move.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d a test

From 2.176.1 is_before_universal_credit_qualifying_young_person_terminal_date
defaults to true, so the eFRS candidate's frozen non-default shares for
that column, which the reader measures against the engine's default,
become the shares of the false values, as
tools/build_uk_release_input_coverage_manifest.py measures the cached
certified candidate. Every other measurement matches the frozen receipt,
which keeps its original engine provenance (2.89.0). The stored values
do not change, and the column stays a populated loader input.

From 2.177.2 (PolicyEngine/policyengine-uk#2828) tax_band applies the
Scottish limits to income other than savings and dividends only, as HMRC
classifies taxpayers. That closes the known gap the tax-band measure test
pinned so a fix would show: the test's Scottish taxpayer with 40,000 of
earnings and 5,000 of dividends is now INTERMEDIATE, not HIGHER, and
Scotland's two national ITL rows move with the fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The charter-H2 fixture is regenerated on policyengine-uk 2.177.4 and
policyengine-core 3.34.10, and a --check run reproduces it byte for
byte. Every node's numerical dependencies name the new engine and core,
four stage contract digests follow the re-stamped notes and dependency
strings, and the fixture's synthetic CGT asset-type facts, which are
sized from the fixture frame after the stages that read the engine, move
by under 0.001%.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@juaristi22
juaristi22 changed the base branch from uk-event-data-pr2 to main November 10, 2026 15:22
juaristi22 and others added 2 commits November 10, 2026 16:52
main moved microcosm-emitter-interface to 0.14.0 (and its floor in
microcosm-build); this branch moved policyengine-uk and the UK side's
policyengine-core. uv.lock merges both, uv lock confirms it unchanged,
and APPROVED_UV_LOCK_SHA256 is that lock's digest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The UK lock moves on from 2.174.1 to 2.177.7, the newest release, after
#1550 merged (microcosm#1095); policyengine-core stays at 3.34.10, and
uv.lock moves policyengine-uk alone. 2.177.5 to 2.177.7 add no input, so
the concept coverage keeps its 378 inputs and only its version moves.
They change what the build's engine reads return:
- 2.177.5 (PolicyEngine/policyengine-uk#2807): no income-related ESA
  for a claimant who has reached pensionable age, or for a couple that
  would get Pension Credit without it.
- 2.177.6 (PolicyEngine/policyengine-uk#2808): the legacy enhanced
  disability premium for enhanced PIP daily living and armed forces
  independence payment beside the highest DLA care rate, and four
  councils' own working-age CTR lists. The is_enhanced_disabled_for_benefits
  the build stores now reaches only Kingston upon Thames's working-age
  Council Tax Reduction and two deprecated counts.
- 2.177.7 (PolicyEngine/policyengine-uk#2830): the allowances and reliefs
  set against income in the way that gives the least tax.

Every text that cites the locked engine was checked against 2.177.7 and
moves with it; only tax_band's comment changed among the variables they
cite. The approved lock digest, the three pyproject floors, the
engine-core pin test, the version stamps of the uprating pins and the
bonus-sacrifice anchor, the coverage manifest and the changelog follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@juaristi22
juaristi22 marked this pull request as ready for review November 10, 2026 16:55
@juaristi22 juaristi22 closed this Nov 10, 2026
@juaristi22 juaristi22 reopened this Nov 10, 2026
tools/graph_uk_spine_fixture.py on the 2.177.7 lock. The fixture's
numerical dependencies record the engine version, so those of 56 nodes
move from 2.177.4 to 2.177.7. Four stage contracts change their digests
with the re-stamped versions: frs_annual_income_spells, salary_sacrifice
and the two CGT stages. sources/fixture.json carries the re-stamped stage
texts. No fixture value moves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@juaristi22 juaristi22 changed the title Lock policyengine-uk 2.177.4 and policyengine-core 3.34.10 and follow what their releases change Lock policyengine-uk 2.177.7 and policyengine-core 3.34.10 and follow what their releases change Nov 10, 2026
juaristi22 and others added 2 commits November 10, 2026 23:48
… pinned enhanced FRS

Rule 1 of the certified head build (microcosm#578, microcosm#823) refused. The pinned enhanced FRS leaves the trading allowance claim status at the engine's UNKNOWN and carries no full-relief group, so it cannot materialize person.trading_allowance_full_relief, which five HMRC SPI rows read since microcosm#1439. Main has the same gap.

María signed the entry on 10 November in the form of the register's other entries, expiring 10 February 2027. The rows stay bound in the national solve, and nothing the build reads moves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…reter refuses it

CI's engine-free (3.14) job at aa08d81 ran on an ubuntu-26.04 runner, whose system Python is 3.14.4, and uv used it instead of downloading 3.14.10. The head-to-head scorer refuses --worker-max-slices before 3.14.7, where replacing a recycled worker can deadlock. test_spawned_workers_score_identically_to_sequential_cli asked for recycling regardless, so it failed there, as it does on this machine's 3.14.6.

On such an interpreter the test now runs only the configurations without recycling. The refusal itself stays tested.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CI's engine-free (3.14) job at 8fc423f ran on an ubuntu-26.04 runner, where uv 0.13.7 wrapped the error for --package microcosm-frame --extra policyengine --extra uk inside "incompatible with the declared conflicts". The test's substring check missed the wrapped phrase. uv wraps at the terminal width, which differs between runners. The check now reads the error with its whitespace collapsed, and passes at COLUMNS=60, where uv wraps the same message.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant