Repository navigation
Record the capital gains realisation response each UK run applies - #621
Conversation
policyengine-uk resolves the capital gains realisation response from a default that can change between model releases (policyengine-uk#2396), so a UK result now records the response it was calculated under: the policyengine-uk release, the caller's explicit gov.simulation.capital_gains_responses settings in the order they apply, and, where the installed release reports it, the resolved assumption. The record travels with the output dataset, the release bundle, the run record and the saved output file; household results carry it under provenance and managed microsimulations in their bundle. A digest of the explicit settings joins the UK storage identity, and a saved output is reused only under the same settings and model release. Part of #602. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The microsimulation guide describes the record a UK run keeps, where it goes, how it joins cache and saved-output identity, and what a managed microsimulation records; the households guide and the run-record table point to it. Part of #602. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The population and household route tests run with stand-ins for policyengine-uk's simulations, which have no tax-benefit system for a response to be resolved from. They now replace the resolver; in the population route's ordering matrix it records an event, so every case checks the record is read after the last modifier and late value. Part of #602. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Good to merge once CI is green, ideally with point 1 fixed first. Points 2-4 are docs or coordination. The design holds up. Explicit settings go into
On the questions in the brief:
What I checked
🤖 Generated with Claude Code |
…ietly From Vahid's review of #621: - The response record now holds where policyengine-uk was installed from when that isn't a package index (direct_url.json: a VCS commit, an archive hash, or a local directory and whether it is editable; never a URL). A saved UK output is reused only from the same release and source, and never under a local directory install, whose code can change while its version stays the same. A branch installed from git can report a published version with another default. - load() raises StaleOutputError, a ValueError, for every saved output it refuses (UK and US), and Simulation.ensure() logs the reason at INFO and reruns instead of logging a warning with a traceback. - The docs say that outputs differing only in a modifier aren't told apart for reuse, that the digest deliberately covers each setting's source and dates, and that the first run after upgrading is a cold one. Merged main (policyengine-uk 2.130.1) first. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks @vahid-ahmadi. Changes are in 98de95c, after merging main (policyengine-uk 2.130.1).
On the data release: agreed, it's outside #602. Outputs already sit beside their input file. Locally, the record, response, dated-reform, snapshot, data-year, run-record and cache tests give 117 passed on 2.130.1. 🤖 Generated with Claude Code |
|
Good to merge. CI is green on 98de95c, and all five points are dealt with. One optional nit below. Round 1 points
New
What I checked
🤖 Generated with Claude Code |
Part of #602.
PR set: CGT retention-rate default (PolicyEngine/policyengine-uk#2396, #602)
Depends on: nothing. It works on the current pin.
Blocks: step 5.
Tracking checklist: checklist on #602
Why
policyengine-uk resolves the capital gains realisation response from a default that changes between releases: #2396 makes it a retention-rate elasticity of 1.0, where it was 0. A UK result should say which assumption it was calculated under, and a saved result shouldn't be reused under another (#602, item 5).
What
The record.
policyengine.tax_benefit_models.uk.capital_gains_responsesbuilds it after every reform and modifier has run. It holds:source: a version control commit, an archive's SHA-256, or a local directory and whether it is editable; never a URL);resolved: the assumption as the release reports it throughcapital_gains_response_assumption, added in Make a retention-rate elasticity of 1 the default CGT realisation response policyengine-uk#2419. That covers the convention, the elasticities for main-rate and relief gains, the MTR elasticity, the separate relief switch, and whether each is the default, an override or set to zero for an MTR elasticity. It isnullon the current pin, which has no such report.request: the caller's explicitgov.simulation.capital_gains_responsessettings in the order they apply (policy, then dynamic), and their SHA-256 digest.Changes a simulation modifier makes aren't listed, as run records don't describe modifiers. So two simulations with the same
idthat differ only in a modifier share a saved output; the docs say to give them different ids.Where it goes:
output_dataset.metadata,release_bundle, run-record results, and the saved output file (one key in the UK HDF5 output)result["provenance"]["capital_gains_responses"], as the US route records SPM provenancepolicyengine_bundle["capital_gains_responses"], one per dataset year; settings that conflict are recorded as an error there and raise when the response is calculatedIdentity:
-cgr-<digest>to itsstorage_id, as US simulations add their SPM settings. The in-process cache and saved-output file names then tell settings apart. The digest covers each setting as given, including its source (policy or dynamic) and dates, so the same value set another way is saved separately. That is deliberate: the record says how the response was asked for.load()reuses a saved UK output only when its record shows the same policyengine-uk release from the same install source, and the same settings. A branch installed from git can report the version of a published release with another default. Under a local directory install, editable or not, no saved UK output is reused, as its code can change while its version stays the same.save()and run records refuse an output whose settings changed after it was calculated.load()raisesStaleOutputError(aValueError, new inpolicyengine.core) for every saved output it refuses, UK and US.ensure()logs the reason at INFO and runs the simulation again, instead of logging a warning with a traceback.Order with #608. #608 (draft) restructures UK saving and loading, adds the same
metadatafield, and also refuses saved outputs without its stamp. This PR is expected first: #608 sits behind #596, #594, #593 and #601, and step 5 depends on this one. Whichever lands second moves its lines into the other's structure. If both land in the same policyengine.py release, saved UK outputs rerun once, not twice. The same note is on #608.Checks
tests/test_uk_cgt_response_records.py(no engine) covers:direct_url.jsonfor each kind of install;tests/test_uk_cgt_responses.pyruns a four-person in-memory 2027 dataset with explicit settings, so it holds whatever the installed default is. It covers:ensure()rerunning an out-of-date output with one INFO record and no warning;provenancebefore comparing, as the US one does.test_uk_dated_reforms.py) now checks every case reads the response after the last modifier and late value. Tests that stand in for policyengine-uk's simulations replace the resolver.resolvedcarries the assumption.🤖 Generated with Claude Code