Repository navigation
Store the metadata v3 reads in the v2 catalog from PolicyEngine.py's public records (catalog format 2) - #4023
Draft
anth-volk wants to merge 8 commits into
Conversation
Catalog format 2 stores the metadata the app's v3 workspace reads, which PolicyEngine.py now publishes in its public records: - model versions: the catalog format, entities and basic inputs; - variables: the input and hidden-input flags, the module, the parameter named by adds or subtracts, and enum value labels; - parameters: the economy and household flags. Revision f5c1d9b4685b was autogenerated against the v2 configuration and adds every column as nullable with no default, so catalog versions published before format 2 keep them empty. It writes no data. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…g format 2
The extractor now reads, only from PolicyEngine.py's public records:
- each model version's entities (key, plural, person flag) and basic
inputs;
- each variable's input and hidden-input flags, module, the parameter path
its adds or subtracts names, and its enum values' declared labels;
- each parameter's economy and household flags.
Bracket schedules already arrive as public parameter nodes, with their
stored label or none. Extraction fails with a specific message when the
public model publishes no entities or basic inputs, has other than one
person entity, names a basic input or a parameter path that is not
published, gives enum labels that do not match the possible values or are
not JSON scalars, or gives a flag that is not a boolean.
normalize_model_metadata normalizes this metadata apart from the certified
data release, and an opt-in parity test compares every new field for the
US and the UK with what /{country}/metadata builds. The v2 integration
check runs it with the installed-catalog test.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Publication now stages and inserts each model version's catalog format, entities and basic inputs, each variable's input and hidden-input flags, module, parameter paths and enum values (as ordered value and label objects), and each parameter's economy and household flags. Publication never rewrites a stored version. When the same PolicyEngine.py version is published again, a version stored before catalog format 2 (a null catalog_format) is compared without format 2's fields, so it keeps them empty, and a version stored with format 2 must match on them too. The Stage 9 metadata document describes the format, and the changelog fragment covers the whole change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…elease provides A UK release with the constituency and local-authority weight matrices keeps the weight_replacement filter on the national dataset. A release without them that routes the region type to its own dataset through region_datasets, as newer PolicyEngine.py releases do, now gives each region a row filter on that dataset's constituency_code_oa or la_code_oa household column with the region's ONS code; the existing verification checks that the column exists before a new version is published. A release with neither stops publication with a message naming the matrix, the region type and the region. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Extraction now checks first that the installed PolicyEngine.py publishes catalog format 2's fields on the model version, every variable and every parameter, and fails naming each missing one. On 6.7.5 it used to stop at the first enum variable with "enum values do not match its possible values", which hid the cause. An enum label that is not JSON-compatible, such as NaN, now fails naming its variable and value. Entities or basic inputs that are present but not a sequence fail with "must be a sequence", and the Stage 9 document says that an empty basic-input list is stored as empty. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The parity test compared enum labels with ==, which treats 1, 1.0 and True as equal, so a label stored with the wrong type passed. It now compares each label's type name as well. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The publication tests stored only null enum values and parameter paths, so the JSON inserts and the comparison on republication never ran on stored values. A fixture now adds an enum variable with a string and an integer label, and a variable whose adds and subtracts are named by parameters. The tests check that they are stored exactly, the integer label as an integer, that republishing the same catalog changes nothing, and that a changed enum label or parameter path fails without changing the stored rows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
TaxBenefitModelVersion.entities and Variable.enum_values were typed as lists of untyped dictionaries. They are now lists of the TypedDicts CatalogEntity (key, plural, is_person) and CatalogEnumValue (value and declared label), which match EntityRecord and EnumValueRecord, and publication builds the stored JSON through them, so readers of these columns get the keys and value types without checking the shape again. The column types are unchanged, so there is no schema change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk
added this pull request to stack #4011
October 22, 2026 18:27
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #4022
Important
This PR must not merge before its PolicyEngine.py bump commit. On the locked PolicyEngine.py 6.7.5, every catalog extraction now stops with "the installed PolicyEngine.py does not publish catalog format 2's fields", including the seed job's catalog publication during a deploy. The bump commit cannot be written yet. It waits for:
microcosm_uk_2024_25, which newer PolicyEngine.py releases use, and then updated installed-catalog counts.The PRs stacked above this one wait with it.
Summary
Catalog format 2 stores the metadata the app's v3 workspace reads, taken only from PolicyEngine.py's public records (PolicyEngine/policyengine.py#701), never from a country package's tax-benefit system or a private PolicyEngine.py method.
Schema. Revision
f5c1d9b4685b(onfa7fa1035444) was autogenerated against the v2 configuration with no corrections. It adds nullable columns with no defaults, so catalog versions published earlier keep them empty, and it writes no data:tax_benefit_model_versions:catalog_format,entities,basic_inputs;variables:is_input_variable,hidden_input,module_name,adds_parameter_path,subtracts_parameter_path,enum_values;parameters:economy,household.entitiesandenum_valuesare typed withCatalogEntityandCatalogEnumValue.Extraction.
normalize_model_metadatareads entities (key, plural, person flag), basic inputs, variable flags and modules, the parameter path thataddsorsubtractsnames (beside the list PolicyEngine.py resolves, which stays), enum values with their declared labels (an integer label stays an integer), and parameter flags.Storage and comparison. Publication stages and inserts the new fields. When the same PolicyEngine.py version is published again, a version stored before format 2 (null
catalog_format) is compared without the format 2 fields and keeps them empty; a format 2 version must match on them too. Publication never rewrites a stored version.UK regions in newer releases. Newer certified UK releases have no constituency or local-authority weight matrices and route those regions to their own dataset through
region_datasets.weight_replacement.row_filteronconstituency_code_oaorla_code_oawith the ONS code, on the routed dataset. The existing verification checks that the column exists before a new version is published.Parity check.
tests/integration/test_v2_catalog_metadata_parity.py(opt-in throughRUN_V2_CATALOG_COMPATIBILITY=1) compares every new field with/{country}/metadatafor the US and the UK. Enum labels are compared with their types. The v2 integration check runs it in its existing installed-catalog step.Parity with
/{country}/metadataMeasured against PolicyEngine.py #701's branch installed locally (6.10.0 with the new fields). 0 mismatches in every field:
addssubtractsgovparameters (economy and household flags)Every
govbracket schedule is a catalog node, and its stored label matches the label/{country}/metadatashows when one is stored. A local publication of the full installed catalog with format 2 fields took 19.1 s, and republishing with the comparison 11.8 s.What the PolicyEngine.py bump commit must change
policyengine[models]==6.7.5inpyproject.tomlanddocker/Dockerfile→ the release containing Publish the model metadata the Public API can only read through a private method policyengine.py#701, thenuv lock.REVIEWED_DEFAULT_DATASETS["uk"]in catalog extraction. Newer releases default tomicrocosm_uk_2024_25; this needs the decision above. With 6.10.0 installed, extraction stops at "uk default dataset does not match the reviewed selection". With that default accepted in memory only, scoping places all 1,015 UK regions:microcosm_uk_2024_25;microcosm_uk_2024_25_dense.tests/integration/test_v2_catalog_installed.py: the exact counts, which 6.10.0 changes to 7,337 variables, 30,214 parameter nodes, 104,172 parameters and 1,194,360 values, plus the UK dataset expectations.tests/unit/services/test_metadata_service.py::test_default_dataset_uses_user_facing_label[uk-Enhanced FRS], which fails with the newer UK default dataset.region,constituency_code_oaandla_code_oacolumns could not be run locally (no read access to the UK data), so it first runs in the seed job.Open decision left to a person
Local authority
N09000011is in PolicyEngine.py's newer local-authority list but not in the Public API's list, which keeps 360 local authorities and 1,015 UK regions. Whether to add it is not decided here.Migration notes
/{country}/metadataand the other v1 routes are unchanged.Environment variables
None read or added. The v2 integration workflow only adds a test file to an existing step, whose
RUN_V2_CATALOG_COMPATIBILITYstays a literal"1".Testing
GitHub Actions runs on this branch are cancelled at the user's request, so the evidence is local. Commits are listed from the bottom of the branch.
c1608c089columns and revisionKeyError: 'catalog_format'; revision chain and new-revision tests (no child offa7fa1035444); lifecycle testKeyErrorwith the revision removedalembic checkclean; 1,105 v2 unit tests98ce64876extraction and parity testCATALOG_FORMAT,normalize_model_metadata); workflow test did not find the parity test41cead6a5storage and comparison739bbc1c8UK scoping for newer releasesweight_replacement; three cases got the old message7e0352949naming missing fields0340aaf58label types in the parity testd20f7435fround-trip and change detection18d014a92typed JSON columnsImportError: CatalogEntityOn the final branch:
scripts/run_quality_guards.py,python -m scripts.rules validateandguard: clean;scripts/export_migration_contracts.py: no changes;make testset under the locked 6.7.5: 3,508 passed.Under 6.7.5, the opt-in installed-catalog tests fail with the missing-fields message:
test_v2_catalog_installed.py(1 test) and every parity test. That is expected until the bump commit.There are no inline
# noqasuppressions and no changes underrules/.🤖 Generated with Claude Code