policyengine 6.1.0__tar.gz → 6.1.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (317) hide show
  1. {policyengine-6.1.0 → policyengine-6.1.2}/.gitignore +1 -0
  2. {policyengine-6.1.0 → policyengine-6.1.2}/CHANGELOG.md +18 -0
  3. {policyengine-6.1.0/src/policyengine.egg-info → policyengine-6.1.2}/PKG-INFO +2 -1
  4. {policyengine-6.1.0 → policyengine-6.1.2}/docs/microsim.md +47 -0
  5. {policyengine-6.1.0 → policyengine-6.1.2}/docs/run-records.md +1 -1
  6. {policyengine-6.1.0 → policyengine-6.1.2}/pyproject.toml +2 -1
  7. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/core/run_record.py +9 -0
  8. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/core/simulation.py +9 -1
  9. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/data/bundle/manifest.json +10 -10
  10. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/data/bundle/uk.trace.tro.jsonld +5 -5
  11. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/data/bundle/us.trace.tro.jsonld +5 -5
  12. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/tax_benefit_models/common/model_version.py +31 -1
  13. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/tax_benefit_models/us/datasets.py +86 -6
  14. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/tax_benefit_models/us/household.py +8 -1
  15. policyengine-6.1.2/src/policyengine/tax_benefit_models/us/legacy_inputs.py +398 -0
  16. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/tax_benefit_models/us/model.py +46 -6
  17. {policyengine-6.1.0 → policyengine-6.1.2/src/policyengine.egg-info}/PKG-INFO +2 -1
  18. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine.egg-info/SOURCES.txt +3 -0
  19. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine.egg-info/requires.txt +1 -0
  20. {policyengine-6.1.0 → policyengine-6.1.2}/tests/fixtures/household_calculator_snapshots/us_married_two_kids_high_income.json +4 -4
  21. {policyengine-6.1.0 → policyengine-6.1.2}/tests/fixtures/household_calculator_snapshots/us_single_adult_employment_income.json +1 -1
  22. {policyengine-6.1.0 → policyengine-6.1.2}/tests/fixtures/household_calculator_snapshots/us_single_adult_no_income.json +1 -1
  23. {policyengine-6.1.0 → policyengine-6.1.2}/tests/fixtures/household_calculator_snapshots/us_single_parent_one_child.json +2 -2
  24. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_household_impact.py +13 -1
  25. policyengine-6.1.2/tests/test_us_legacy_inputs.py +656 -0
  26. policyengine-6.1.2/tests/test_us_legacy_inputs_integration.py +704 -0
  27. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_us_native_alignment.py +2 -1
  28. {policyengine-6.1.0 → policyengine-6.1.2}/uv.lock +91 -1
  29. {policyengine-6.1.0 → policyengine-6.1.2}/.claude/policyengine-guide.md +0 -0
  30. {policyengine-6.1.0 → policyengine-6.1.2}/.claude/quick-reference.md +0 -0
  31. {policyengine-6.1.0 → policyengine-6.1.2}/.github/CONTRIBUTING.md +0 -0
  32. {policyengine-6.1.0 → policyengine-6.1.2}/.github/bump_version.py +0 -0
  33. {policyengine-6.1.0 → policyengine-6.1.2}/.github/capture-version.sh +0 -0
  34. {policyengine-6.1.0 → policyengine-6.1.2}/.github/changelog_template.md +0 -0
  35. {policyengine-6.1.0 → policyengine-6.1.2}/.github/check-changelog.sh +0 -0
  36. {policyengine-6.1.0 → policyengine-6.1.2}/.github/copilot-instructions.md +0 -0
  37. {policyengine-6.1.0 → policyengine-6.1.2}/.github/dispatch-policyengine-release.sh +0 -0
  38. {policyengine-6.1.0 → policyengine-6.1.2}/.github/fetch_version.py +0 -0
  39. {policyengine-6.1.0 → policyengine-6.1.2}/.github/get-changelog-diff.sh +0 -0
  40. {policyengine-6.1.0 → policyengine-6.1.2}/.github/has-functional-changes.sh +0 -0
  41. {policyengine-6.1.0 → policyengine-6.1.2}/.github/is-version-number-acceptable.sh +0 -0
  42. {policyengine-6.1.0 → policyengine-6.1.2}/.github/publish-git-tag.sh +0 -0
  43. {policyengine-6.1.0 → policyengine-6.1.2}/.github/wait-for-pypi.sh +0 -0
  44. {policyengine-6.1.0 → policyengine-6.1.2}/.github/workflows/draft-pdf.yml +0 -0
  45. {policyengine-6.1.0 → policyengine-6.1.2}/.github/workflows/pr_code_changes.yaml +0 -0
  46. {policyengine-6.1.0 → policyengine-6.1.2}/.github/workflows/pr_docs_changes.yaml +0 -0
  47. {policyengine-6.1.0 → policyengine-6.1.2}/.github/workflows/push.yaml +0 -0
  48. {policyengine-6.1.0 → policyengine-6.1.2}/.python-version +0 -0
  49. {policyengine-6.1.0 → policyengine-6.1.2}/AGENTS.md +0 -0
  50. {policyengine-6.1.0 → policyengine-6.1.2}/CITATION.cff +0 -0
  51. {policyengine-6.1.0 → policyengine-6.1.2}/CLAUDE.md +0 -0
  52. {policyengine-6.1.0 → policyengine-6.1.2}/CODE_OF_CONDUCT.md +0 -0
  53. {policyengine-6.1.0 → policyengine-6.1.2}/CONTRIBUTING.md +0 -0
  54. {policyengine-6.1.0 → policyengine-6.1.2}/LICENSE +0 -0
  55. {policyengine-6.1.0 → policyengine-6.1.2}/Makefile +0 -0
  56. {policyengine-6.1.0 → policyengine-6.1.2}/README.md +0 -0
  57. {policyengine-6.1.0 → policyengine-6.1.2}/architecture.png +0 -0
  58. {policyengine-6.1.0 → policyengine-6.1.2}/architecture.svg +0 -0
  59. {policyengine-6.1.0 → policyengine-6.1.2}/changelog.d/.gitkeep +0 -0
  60. {policyengine-6.1.0 → policyengine-6.1.2}/docs/.gitignore +0 -0
  61. {policyengine-6.1.0 → policyengine-6.1.2}/docs/_generator/README.md +0 -0
  62. {policyengine-6.1.0 → policyengine-6.1.2}/docs/_generator/build_reference.py +0 -0
  63. {policyengine-6.1.0 → policyengine-6.1.2}/docs/_quarto.yml +0 -0
  64. {policyengine-6.1.0 → policyengine-6.1.2}/docs/bundles.md +0 -0
  65. {policyengine-6.1.0 → policyengine-6.1.2}/docs/countries.md +0 -0
  66. {policyengine-6.1.0 → policyengine-6.1.2}/docs/data-publishing-design.md +0 -0
  67. {policyengine-6.1.0 → policyengine-6.1.2}/docs/decile-impact-spec.md +0 -0
  68. {policyengine-6.1.0 → policyengine-6.1.2}/docs/dev.md +0 -0
  69. {policyengine-6.1.0 → policyengine-6.1.2}/docs/engineering/runbooks/build-m-us-populace-certification.md +0 -0
  70. {policyengine-6.1.0 → policyengine-6.1.2}/docs/engineering/runbooks/canonical-spm-development.md +0 -0
  71. {policyengine-6.1.0 → policyengine-6.1.2}/docs/engineering/skills/README.md +0 -0
  72. {policyengine-6.1.0 → policyengine-6.1.2}/docs/engineering/skills/data-certification.md +0 -0
  73. {policyengine-6.1.0 → policyengine-6.1.2}/docs/engineering/skills/github-prs.md +0 -0
  74. {policyengine-6.1.0 → policyengine-6.1.2}/docs/engineering/skills/repository-guidance.md +0 -0
  75. {policyengine-6.1.0 → policyengine-6.1.2}/docs/examples.md +0 -0
  76. {policyengine-6.1.0 → policyengine-6.1.2}/docs/getting-started.md +0 -0
  77. {policyengine-6.1.0 → policyengine-6.1.2}/docs/households.md +0 -0
  78. {policyengine-6.1.0 → policyengine-6.1.2}/docs/impact-analysis.md +0 -0
  79. {policyengine-6.1.0 → policyengine-6.1.2}/docs/index.md +0 -0
  80. {policyengine-6.1.0 → policyengine-6.1.2}/docs/methodology/index.md +0 -0
  81. {policyengine-6.1.0 → policyengine-6.1.2}/docs/methodology/model-architecture.md +0 -0
  82. {policyengine-6.1.0 → policyengine-6.1.2}/docs/methodology/us-health-costs.md +0 -0
  83. {policyengine-6.1.0 → policyengine-6.1.2}/docs/outputs.md +0 -0
  84. {policyengine-6.1.0 → policyengine-6.1.2}/docs/programs/index.md +0 -0
  85. {policyengine-6.1.0 → policyengine-6.1.2}/docs/programs/us-chip.md +0 -0
  86. {policyengine-6.1.0 → policyengine-6.1.2}/docs/reference/index.md +0 -0
  87. {policyengine-6.1.0 → policyengine-6.1.2}/docs/reforms.md +0 -0
  88. {policyengine-6.1.0 → policyengine-6.1.2}/docs/regions.md +0 -0
  89. {policyengine-6.1.0 → policyengine-6.1.2}/docs/release-bundles.md +0 -0
  90. {policyengine-6.1.0 → policyengine-6.1.2}/docs/trace-case-study.md +0 -0
  91. {policyengine-6.1.0 → policyengine-6.1.2}/docs/visualisation.md +0 -0
  92. {policyengine-6.1.0 → policyengine-6.1.2}/examples/belgium_axiom_pilot.py +0 -0
  93. {policyengine-6.1.0 → policyengine-6.1.2}/examples/employment_income_variation_uk.py +0 -0
  94. {policyengine-6.1.0 → policyengine-6.1.2}/examples/employment_income_variation_us.py +0 -0
  95. {policyengine-6.1.0 → policyengine-6.1.2}/examples/household_impact_example.py +0 -0
  96. {policyengine-6.1.0 → policyengine-6.1.2}/examples/income_bands_uk.py +0 -0
  97. {policyengine-6.1.0 → policyengine-6.1.2}/examples/income_distribution_us.py +0 -0
  98. {policyengine-6.1.0 → policyengine-6.1.2}/examples/paper_repro_uk.py +0 -0
  99. {policyengine-6.1.0 → policyengine-6.1.2}/examples/policy_change_uk.py +0 -0
  100. {policyengine-6.1.0 → policyengine-6.1.2}/examples/speedtest_us_simulation.py +0 -0
  101. {policyengine-6.1.0 → policyengine-6.1.2}/examples/us_budgetary_impact.py +0 -0
  102. {policyengine-6.1.0 → policyengine-6.1.2}/paper-preview.html +0 -0
  103. {policyengine-6.1.0 → policyengine-6.1.2}/paper.bib +0 -0
  104. {policyengine-6.1.0 → policyengine-6.1.2}/paper.md +0 -0
  105. {policyengine-6.1.0 → policyengine-6.1.2}/scripts/bundle.py +0 -0
  106. {policyengine-6.1.0 → policyengine-6.1.2}/scripts/certify_data_release.py +0 -0
  107. {policyengine-6.1.0 → policyengine-6.1.2}/scripts/check_data_staleness.py +0 -0
  108. {policyengine-6.1.0 → policyengine-6.1.2}/scripts/check_native_spm_loading.py +0 -0
  109. {policyengine-6.1.0 → policyengine-6.1.2}/scripts/check_release_credentials.py +0 -0
  110. {policyengine-6.1.0 → policyengine-6.1.2}/scripts/export_bundle_release_assets.py +0 -0
  111. {policyengine-6.1.0 → policyengine-6.1.2}/scripts/generate_bundle_artifacts.py +0 -0
  112. {policyengine-6.1.0 → policyengine-6.1.2}/scripts/generate_trace_tros.py +0 -0
  113. {policyengine-6.1.0 → policyengine-6.1.2}/scripts/prepare_package_bundle_update.py +0 -0
  114. {policyengine-6.1.0 → policyengine-6.1.2}/scripts/release_lock.py +0 -0
  115. {policyengine-6.1.0 → policyengine-6.1.2}/scripts/spm_bundle.py +0 -0
  116. {policyengine-6.1.0 → policyengine-6.1.2}/setup.cfg +0 -0
  117. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/__init__.py +0 -0
  118. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/bundle.py +0 -0
  119. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/cli.py +0 -0
  120. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/core/__init__.py +0 -0
  121. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/core/cache.py +0 -0
  122. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/core/dataset.py +0 -0
  123. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/core/dynamic.py +0 -0
  124. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/core/output.py +0 -0
  125. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/core/parameter.py +0 -0
  126. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/core/parameter_node.py +0 -0
  127. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/core/parameter_value.py +0 -0
  128. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/core/policy.py +0 -0
  129. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/core/region.py +0 -0
  130. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/core/scoping_strategy.py +0 -0
  131. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/core/spm.py +0 -0
  132. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/core/tax_benefit_model.py +0 -0
  133. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/core/tax_benefit_model_version.py +0 -0
  134. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/core/variable.py +0 -0
  135. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/countries/__init__.py +0 -0
  136. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/countries/uk/__init__.py +0 -0
  137. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/countries/uk/regions.py +0 -0
  138. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/countries/us/__init__.py +0 -0
  139. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/countries/us/data/__init__.py +0 -0
  140. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/countries/us/data/districts.py +0 -0
  141. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/countries/us/data/places.py +0 -0
  142. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/countries/us/data/states.py +0 -0
  143. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/countries/us/regions.py +0 -0
  144. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/data/__init__.py +0 -0
  145. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/data/schemas/trace_tro.schema.json +0 -0
  146. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/data/uk_geography_assets.py +0 -0
  147. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/derivations/__init__.py +0 -0
  148. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/derivations/narrate.py +0 -0
  149. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/derivations/trace.py +0 -0
  150. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/graph/__init__.py +0 -0
  151. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/graph/extractor.py +0 -0
  152. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/graph/graph.py +0 -0
  153. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/outputs/__init__.py +0 -0
  154. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/outputs/aggregate.py +0 -0
  155. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/outputs/change_aggregate.py +0 -0
  156. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/outputs/cliff_impact.py +0 -0
  157. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/outputs/congressional_district_impact.py +0 -0
  158. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/outputs/constituency_impact.py +0 -0
  159. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/outputs/decile_analysis.py +0 -0
  160. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/outputs/decile_grouping.py +0 -0
  161. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/outputs/decile_impact.py +0 -0
  162. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/outputs/extra_variables.py +0 -0
  163. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/outputs/inequality.py +0 -0
  164. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/outputs/intra_decile_impact.py +0 -0
  165. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/outputs/labor_supply_response.py +0 -0
  166. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/outputs/local_authority_impact.py +0 -0
  167. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/outputs/poverty.py +0 -0
  168. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/outputs/program_statistics.py +0 -0
  169. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/outputs/uk_geography_assets.py +0 -0
  170. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/outputs/uk_geography_impact.py +0 -0
  171. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/provenance/__init__.py +0 -0
  172. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/provenance/bundle_validation.py +0 -0
  173. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/provenance/certification.py +0 -0
  174. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/provenance/dataset_materialization.py +0 -0
  175. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/provenance/manifest.py +0 -0
  176. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/provenance/pyproject_pins.py +0 -0
  177. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/provenance/spm_configuration.py +0 -0
  178. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/provenance/trace.py +0 -0
  179. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/provenance/verify.py +0 -0
  180. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/provenance/zenodo.py +0 -0
  181. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/results/__init__.py +0 -0
  182. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/results/schema.py +0 -0
  183. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/results/trace_tro.py +0 -0
  184. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/results/tracking.py +0 -0
  185. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/tax_benefit_models/be/__init__.py +0 -0
  186. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/tax_benefit_models/be/datasets.py +0 -0
  187. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/tax_benefit_models/be/model.py +0 -0
  188. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/tax_benefit_models/common/__init__.py +0 -0
  189. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/tax_benefit_models/common/axes.py +0 -0
  190. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/tax_benefit_models/common/extra_variables.py +0 -0
  191. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/tax_benefit_models/common/household.py +0 -0
  192. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/tax_benefit_models/common/reform.py +0 -0
  193. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/tax_benefit_models/common/result.py +0 -0
  194. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/tax_benefit_models/uk/__init__.py +0 -0
  195. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/tax_benefit_models/uk/analysis.py +0 -0
  196. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/tax_benefit_models/uk/datasets.py +0 -0
  197. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/tax_benefit_models/uk/household.py +0 -0
  198. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/tax_benefit_models/uk/model.py +0 -0
  199. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/tax_benefit_models/us/__init__.py +0 -0
  200. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/tax_benefit_models/us/analysis.py +0 -0
  201. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/tax_benefit_models/us/spm.py +0 -0
  202. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/utils/__init__.py +0 -0
  203. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/utils/dates.py +0 -0
  204. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/utils/design.py +0 -0
  205. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/utils/entity_utils.py +0 -0
  206. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/utils/errors.py +0 -0
  207. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/utils/hashing.py +0 -0
  208. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/utils/household_validation.py +0 -0
  209. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/utils/parameter_labels.py +0 -0
  210. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/utils/parametric_reforms.py +0 -0
  211. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine/utils/plotting.py +0 -0
  212. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine.egg-info/dependency_links.txt +0 -0
  213. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine.egg-info/entry_points.txt +0 -0
  214. {policyengine-6.1.0 → policyengine-6.1.2}/src/policyengine.egg-info/top_level.txt +0 -0
  215. {policyengine-6.1.0 → policyengine-6.1.2}/tests/__init__.py +0 -0
  216. {policyengine-6.1.0 → policyengine-6.1.2}/tests/conftest.py +0 -0
  217. {policyengine-6.1.0 → policyengine-6.1.2}/tests/fixtures/__init__.py +0 -0
  218. {policyengine-6.1.0 → policyengine-6.1.2}/tests/fixtures/filtering_fixtures.py +0 -0
  219. {policyengine-6.1.0 → policyengine-6.1.2}/tests/fixtures/household_calculator_snapshots/uk_couple_two_kids.json +0 -0
  220. {policyengine-6.1.0 → policyengine-6.1.2}/tests/fixtures/household_calculator_snapshots/uk_model_surface.json +0 -0
  221. {policyengine-6.1.0 → policyengine-6.1.2}/tests/fixtures/household_calculator_snapshots/uk_single_adult_employment_income.json +0 -0
  222. {policyengine-6.1.0 → policyengine-6.1.2}/tests/fixtures/household_calculator_snapshots/uk_single_adult_no_income.json +0 -0
  223. {policyengine-6.1.0 → policyengine-6.1.2}/tests/fixtures/household_calculator_snapshots/uk_single_parent_one_child.json +0 -0
  224. {policyengine-6.1.0 → policyengine-6.1.2}/tests/fixtures/household_calculator_snapshots/us_model_surface.json +0 -0
  225. {policyengine-6.1.0 → policyengine-6.1.2}/tests/fixtures/parameter_labels_fixtures.py +0 -0
  226. {policyengine-6.1.0 → policyengine-6.1.2}/tests/fixtures/parametric_reforms_fixtures.py +0 -0
  227. {policyengine-6.1.0 → policyengine-6.1.2}/tests/fixtures/poverty_by_demographics_fixtures.py +0 -0
  228. {policyengine-6.1.0 → policyengine-6.1.2}/tests/fixtures/region_fixtures.py +0 -0
  229. {policyengine-6.1.0 → policyengine-6.1.2}/tests/fixtures/release_tros/README.md +0 -0
  230. {policyengine-6.1.0 → policyengine-6.1.2}/tests/fixtures/release_tros/country-models.lock.toml +0 -0
  231. {policyengine-6.1.0 → policyengine-6.1.2}/tests/fixtures/release_tros/manifest.json +0 -0
  232. {policyengine-6.1.0 → policyengine-6.1.2}/tests/fixtures/release_tros/us-release_manifest.json +0 -0
  233. {policyengine-6.1.0 → policyengine-6.1.2}/tests/fixtures/release_tros/us.trace.tro.jsonld +0 -0
  234. {policyengine-6.1.0 → policyengine-6.1.2}/tests/fixtures/spm_development.py +0 -0
  235. {policyengine-6.1.0 → policyengine-6.1.2}/tests/fixtures/us_reform_fixtures.py +0 -0
  236. {policyengine-6.1.0 → policyengine-6.1.2}/tests/fixtures/variable_label_fixtures.py +0 -0
  237. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_aggregate.py +0 -0
  238. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_be_axiom_pilot.py +0 -0
  239. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_budgetary_impact.py +0 -0
  240. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_bump_version.py +0 -0
  241. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_bundle.py +0 -0
  242. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_bundle_metadata.py +0 -0
  243. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_cache.py +0 -0
  244. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_certify_data_release.py +0 -0
  245. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_change_aggregate.py +0 -0
  246. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_cliff_impact.py +0 -0
  247. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_cliff_impact_analysis.py +0 -0
  248. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_congressional_district_impact.py +0 -0
  249. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_constituency_impact.py +0 -0
  250. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_dataset_materialization.py +0 -0
  251. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_dataset_persistence.py +0 -0
  252. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_dataset_runtime.py +0 -0
  253. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_dataset_source.py +0 -0
  254. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_decile_grouping.py +0 -0
  255. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_derivations.py +0 -0
  256. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_dict_reforms_on_simulation.py +0 -0
  257. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_entity_mapping.py +0 -0
  258. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_entity_utils.py +0 -0
  259. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_entity_utils_characterization.py +0 -0
  260. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_errors.py +0 -0
  261. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_extra_variables.py +0 -0
  262. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_filtering.py +0 -0
  263. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_generate_trace_tros.py +0 -0
  264. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_graph/__init__.py +0 -0
  265. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_graph/conftest.py +0 -0
  266. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_graph/test_extractor.py +0 -0
  267. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_household_calculator_snapshot.py +0 -0
  268. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_inequality.py +0 -0
  269. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_intra_decile_impact.py +0 -0
  270. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_labor_supply_response.py +0 -0
  271. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_local_authority_impact.py +0 -0
  272. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_manifest_version_mismatch.py +0 -0
  273. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_models.py +0 -0
  274. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_pandas3_compatibility.py +0 -0
  275. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_parameter_labels.py +0 -0
  276. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_parameter_nodes.py +0 -0
  277. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_parameter_values.py +0 -0
  278. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_parametric_reforms.py +0 -0
  279. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_poverty.py +0 -0
  280. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_poverty_by_demographics.py +0 -0
  281. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_poverty_run.py +0 -0
  282. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_preservation_mirror.py +0 -0
  283. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_program_statistics.py +0 -0
  284. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_pyproject_pins.py +0 -0
  285. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_region.py +0 -0
  286. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_region_group_strategy.py +0 -0
  287. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_release_credentials.py +0 -0
  288. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_release_lock.py +0 -0
  289. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_release_manifests.py +0 -0
  290. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_release_tro_generation.py +0 -0
  291. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_results.py +0 -0
  292. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_run_record.py +0 -0
  293. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_scoping_strategy.py +0 -0
  294. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_small_follow_ups.py +0 -0
  295. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_spm_bundle_bootstrap.py +0 -0
  296. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_spm_bundle_tooling.py +0 -0
  297. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_spm_decile.py +0 -0
  298. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_spm_development_authentication.py +0 -0
  299. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_spm_household.py +0 -0
  300. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_spm_model.py +0 -0
  301. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_spm_selection.py +0 -0
  302. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_spm_selection_schema.py +0 -0
  303. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_trace_tro.py +0 -0
  304. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_trace_tro_verify.py +0 -0
  305. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_uk_analysis.py +0 -0
  306. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_uk_geography_assets.py +0 -0
  307. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_uk_program_statistics.py +0 -0
  308. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_uk_regions.py +0 -0
  309. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_us_long_term_datasets.py +0 -0
  310. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_us_microsim_structural_reforms.py +0 -0
  311. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_us_native_hdf_weights.py +0 -0
  312. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_us_program_statistics.py +0 -0
  313. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_us_reform_application.py +0 -0
  314. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_us_regions.py +0 -0
  315. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_variable_labels.py +0 -0
  316. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_variable_metadata.py +0 -0
  317. {policyengine-6.1.0 → policyengine-6.1.2}/tests/test_zenodo_mirror.py +0 -0
@@ -7,3 +7,4 @@ _build/
7
7
  .env
8
8
  **/.DS_Store
9
9
  build/
10
+ .hypothesis/
@@ -1,3 +1,21 @@
1
+ ## [6.1.2] - 2026-09-27
2
+
3
+ ### Changed
4
+
5
+ - US files written before the WIC take-up mapping are no longer reused, because they may have lost the draw or were calculated without it. `Simulation.load()` raises for a saved US output that has no record of renamed stored inputs (`Simulation.ensure()` calculates it again), `load_datasets` raises for such a year file, and `ensure_datasets` creates such year files again.
6
+
7
+ ### Fixed
8
+
9
+ - Map the stored US WIC take-up draw `would_claim_wic` onto `takes_up_wic_if_eligible` when loading US data, so policyengine-us 2.x no longer gives WIC to every WIC-eligible person in data that stores the draw under its old name, such as the certified default. `Simulation.run()`, `managed_microsimulation` and `create_datasets` apply the mapping and record the renames applied (output dataset metadata, `release_bundle`, saved output and year files, run records and `policyengine_bundle`). A stored table that is not in the simulation's person order, or that stores the draw for only part of a year, is refused. The mapping turns itself off once the data stores `takes_up_wic_if_eligible` or the engine defines `would_claim_wic` again.
10
+
11
+
12
+ ## [6.1.1] - 2026-09-22
13
+
14
+ ### Fixed
15
+
16
+ - Decode enum values to their names in US household calculation results.
17
+
18
+
1
19
  ## [6.1.0] - 2026-09-21
2
20
 
3
21
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: policyengine
3
- Version: 6.1.0
3
+ Version: 6.1.2
4
4
  Summary: A package to conduct policy analysis using PolicyEngine tax-benefit models.
5
5
  Author-email: PolicyEngine <hello@policyengine.org>
6
6
  License: GNU AFFERO GENERAL PUBLIC LICENSE
@@ -710,6 +710,7 @@ Requires-Dist: ruff>=0.9.0; extra == "dev"
710
710
  Requires-Dist: towncrier>=24.8.0; extra == "dev"
711
711
  Requires-Dist: mypy>=1.11.0; extra == "dev"
712
712
  Requires-Dist: pytest-cov>=5.0.0; extra == "dev"
713
+ Requires-Dist: hypothesis>=6.100.0; extra == "dev"
713
714
  Requires-Dist: policyengine-core==3.32.5; extra == "dev"
714
715
  Requires-Dist: policyengine-us==2.2.1; extra == "dev"
715
716
  Requires-Dist: policyengine-uk==2.90.2; extra == "dev"
@@ -324,6 +324,53 @@ mode. GCS dataset URIs are not supported.
324
324
  For managed simulations, `sim.policyengine_bundle` records the actual source
325
325
  package, repository type, revision, verified SHA-256, and local path.
326
326
 
327
+ ## Renamed inputs in stored data
328
+
329
+ A country engine sets a stored column as an input only when it defines a
330
+ variable of that name. When policyengine-us renames an input, data written
331
+ before the rename keeps the old name, and the engine would skip it.
332
+ `policyengine.tax_benefit_models.us.legacy_inputs.LEGACY_INPUT_RENAMES` lists
333
+ each such rename; today it holds one entry, `would_claim_wic` →
334
+ `takes_up_wic_if_eligible` (the WIC take-up draw, PolicyEngine/microcosm#1026).
335
+
336
+ Every US load path applies it: `Simulation.run()`, `managed_microsimulation`
337
+ and `create_datasets` (and so `ensure_datasets` when it creates year files).
338
+ A rename applies when the data stores the old name, the engine does not define
339
+ the old name but does define the new one, and the data does not already store
340
+ the new name. The new input is then set from the stored values for every month
341
+ of every dataset year. The stored table must list the simulation's entity IDs
342
+ in the simulation's order, or loading fails rather than attach values to the
343
+ wrong people. Only values stored for a whole year are mapped, so a file that
344
+ stores the old name for part of a year, and not the new name, is refused. The
345
+ mapping turns itself off once the data stores the new name, or if the engine
346
+ defines the old name again.
347
+
348
+ The renames applied are recorded as `{old: new}` (`{}` when none applied):
349
+
350
+ - `Simulation.run()`: `simulation.output_dataset.metadata["legacy_input_renames"]`,
351
+ also shown as `simulation.release_bundle["legacy_input_renames"]`. It
352
+ includes renames applied when the input year file was cut, so a run over a
353
+ `create_datasets` year file records the rename even though the file already
354
+ stores the new name. A US `save()` writes the record into the output file,
355
+ `load()` restores it, and a run record's `results.json` binds it;
356
+ - `managed_microsimulation`: `sim.policyengine_bundle["legacy_input_renames"]`;
357
+ - `create_datasets`: each year file, and each returned dataset's
358
+ `metadata["legacy_input_renames"]`.
359
+
360
+ `{}` means that no stored column was mapped. It does not show that the data
361
+ carried the draw: data that stores neither name runs with the new input's
362
+ default, which for WIC is full take-up.
363
+
364
+ Files written before this mapping existed have no record, and are not reused:
365
+
366
+ - A saved US output may have been calculated without the mapped inputs.
367
+ `load()` refuses it, and `ensure()` runs the simulation again and saves the new
368
+ output.
369
+ - A year file that `ensure_datasets` or `create_datasets` wrote stores
370
+ neither name, so the draw is lost from it. `ensure_datasets` creates such
371
+ year files again, and `load_datasets` refuses them. A year file opened
372
+ directly, as `PolicyEngineUSDataset(filepath=...)`, is not checked.
373
+
327
374
  ## Pinned model versions
328
375
 
329
376
  Every `policyengine` release pins specific country-model and country-data versions so results are reproducible. `pe.us.model` and `pe.uk.model` expose the pinned `TaxBenefitModelVersion`.
@@ -46,7 +46,7 @@ The directory contains:
46
46
  | `bundle.trace.tro.jsonld` | The certified bundle TRO (model + data pins) |
47
47
  | `reform.json` | The reform as parameter values with effective dates |
48
48
  | `input.json` | Input dataset hash, dynamics, scoping, extra variables |
49
- | `results.json` | Output dataset hash and per-entity table summaries |
49
+ | `results.json` | Output dataset hash and per-entity table summaries; for US runs, the SPM receipt and the renamed stored inputs mapped onto live ones (see [Renamed inputs in stored data](microsim.md#renamed-inputs-in-stored-data)) |
50
50
 
51
51
  All payload files are written with the same canonical JSON used for
52
52
  hashing, so the record verifies offline exactly as written.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "policyengine"
7
- version = "6.1.0"
7
+ version = "6.1.2"
8
8
  description = "A package to conduct policy analysis using PolicyEngine tax-benefit models."
9
9
  readme = "README.md"
10
10
  authors = [
@@ -68,6 +68,7 @@ dev = [
68
68
  "towncrier>=24.8.0",
69
69
  "mypy>=1.11.0",
70
70
  "pytest-cov>=5.0.0",
71
+ "hypothesis>=6.100.0",
71
72
  "policyengine-core==3.32.5",
72
73
  "policyengine-us==2.2.1",
73
74
  "policyengine-uk==2.90.2",
@@ -184,6 +184,15 @@ def build_simulation_run_record_payloads(
184
184
  input_payload["spm"] = simulation.spm_config
185
185
  results_payload["spm"] = simulation.spm_provenance()
186
186
 
187
+ # Stored inputs the country loader mapped onto renamed live inputs (for
188
+ # example the US WIC take-up draw) change the results, so the record
189
+ # binds them. See ``policyengine.tax_benefit_models.us.legacy_inputs``.
190
+ renames = (getattr(simulation.output_dataset, "metadata", None) or {}).get(
191
+ "legacy_input_renames"
192
+ )
193
+ if renames is not None:
194
+ results_payload["legacy_input_renames"] = dict(renames)
195
+
187
196
  return {"reform": reform, "input": input_payload, "results": results_payload}
188
197
 
189
198
 
@@ -240,7 +240,7 @@ class Simulation(BaseModel):
240
240
  if self.tax_benefit_model_version is not None
241
241
  else {}
242
242
  )
243
- result = {
243
+ result: dict[str, Any] = {
244
244
  **bundle,
245
245
  "dataset_filepath": self.dataset.filepath
246
246
  if self.dataset is not None
@@ -250,4 +250,12 @@ class Simulation(BaseModel):
250
250
  recorded = getattr(self.output_dataset, "metadata", {}).get("spm_config")
251
251
  result["spm_config"] = dict(recorded or self.spm_config)
252
252
  result["spm"] = self.spm_provenance()
253
+ # Stored inputs the country loader mapped onto renamed live inputs
254
+ # (for example the US WIC take-up draw), as the run recorded them.
255
+ # See ``policyengine.tax_benefit_models.us.legacy_inputs``.
256
+ renames = (getattr(self.output_dataset, "metadata", None) or {}).get(
257
+ "legacy_input_renames"
258
+ )
259
+ if renames is not None:
260
+ result["legacy_input_renames"] = dict(renames)
253
261
  return result
@@ -1,10 +1,10 @@
1
1
  {
2
- "bundle_version": "6.1.0",
2
+ "bundle_version": "6.1.2",
3
3
  "citation": {
4
4
  "publisher": "PolicyEngine",
5
- "title": "PolicyEngine bundle 6.1.0",
5
+ "title": "PolicyEngine bundle 6.1.2",
6
6
  "type": "software-bundle",
7
- "version": "6.1.0"
7
+ "version": "6.1.2"
8
8
  },
9
9
  "countries": {
10
10
  "uk": {
@@ -17,7 +17,7 @@
17
17
  "data_releases": {
18
18
  "uk": {
19
19
  "build_id": "policyengine-uk-data-1.56.16",
20
- "bundle_id": "uk-6.1.0",
20
+ "bundle_id": "uk-6.1.2",
21
21
  "certification": {
22
22
  "built_with_model_git_sha": "12a1e028afeef08d8b2d74ee03fd9de3a78b2dd3",
23
23
  "built_with_model_version": "2.89.2",
@@ -99,7 +99,7 @@
99
99
  "version": "2.90.2",
100
100
  "wheel_url": "https://files.pythonhosted.org/packages/ec/da/658bff2df6094bd7bf2b0f561ff60fd41508adbd0a3af29b4553c83bc678/policyengine_uk-2.90.2-py3-none-any.whl"
101
101
  },
102
- "policyengine_version": "6.1.0",
102
+ "policyengine_version": "6.1.2",
103
103
  "region_datasets": {
104
104
  "national": {
105
105
  "path_template": "enhanced_frs_2024_25.h5"
@@ -112,7 +112,7 @@
112
112
  },
113
113
  "us": {
114
114
  "build_id": "populace-us-2024-spm-20260915",
115
- "bundle_id": "us-6.1.0",
115
+ "bundle_id": "us-6.1.2",
116
116
  "certification": {
117
117
  "built_with_model_version": "2.2.1",
118
118
  "certified_by": "policyengine.py bundle certification",
@@ -210,7 +210,7 @@
210
210
  "version": "2.2.1",
211
211
  "wheel_url": "https://files.pythonhosted.org/packages/5e/09/86ac3968d2a18e28fce3ba1186fc21728e9f299b96a806d6f204f1e0aaed/policyengine_us-2.2.1-py3-none-any.whl"
212
212
  },
213
- "policyengine_version": "6.1.0",
213
+ "policyengine_version": "6.1.2",
214
214
  "region_datasets": {
215
215
  "national": {
216
216
  "path_template": "populace_us_2024.h5"
@@ -290,10 +290,10 @@
290
290
  "packages": {
291
291
  "policyengine": {
292
292
  "import_name": "policyengine",
293
- "install_requirement": "policyengine==6.1.0",
293
+ "install_requirement": "policyengine==6.1.2",
294
294
  "name": "policyengine",
295
295
  "role": "bundle_carrier",
296
- "version": "6.1.0"
296
+ "version": "6.1.2"
297
297
  },
298
298
  "policyengine-core": {
299
299
  "import_name": "policyengine_core",
@@ -329,6 +329,6 @@
329
329
  "wheel_url": "https://files.pythonhosted.org/packages/19/a0/c484f69a0ebf88a9b9fd0ac28176f8df66550f46714f1b0c5ec0b360824e/spm_calculator-1.0.0-py3-none-any.whl"
330
330
  }
331
331
  },
332
- "policyengine_version": "6.1.0",
332
+ "policyengine_version": "6.1.2",
333
333
  "schema_version": 2
334
334
  }
@@ -18,18 +18,18 @@
18
18
  "schema:url": "https://policyengine.org"
19
19
  },
20
20
  "schema:dateCreated": "2026-08-18T14:20:32.100961Z",
21
- "schema:description": "TRACE TRO for certified runtime bundle uk-6.1.0 covering the bundle manifest, the certified dataset artifact, the country model wheel, and the country data release manifest when it is available.",
21
+ "schema:description": "TRACE TRO for certified runtime bundle uk-6.1.2 covering the bundle manifest, the certified dataset artifact, the country model wheel, and the country data release manifest when it is available.",
22
22
  "schema:name": "policyengine uk certified bundle TRO",
23
23
  "trov:createdWith": {
24
24
  "@type": "schema:SoftwareApplication",
25
25
  "schema:name": "policyengine",
26
- "schema:softwareVersion": "6.1.0"
26
+ "schema:softwareVersion": "6.1.2"
27
27
  },
28
28
  "trov:hasArrangement": [
29
29
  {
30
30
  "@id": "arrangement/1",
31
31
  "@type": "trov:ArtifactArrangement",
32
- "rdfs:comment": "Certified arrangement for bundle uk-6.1.0.",
32
+ "rdfs:comment": "Certified arrangement for bundle uk-6.1.2.",
33
33
  "trov:hasArtifactLocation": [
34
34
  {
35
35
  "@id": "arrangement/1/location/bundle_manifest",
@@ -75,7 +75,7 @@
75
75
  "@type": "trov:ResearchArtifact",
76
76
  "schema:name": "policyengine.py bundle manifest for uk",
77
77
  "trov:mimeType": "application/json",
78
- "trov:sha256": "241b8728f2babe04be9c1b321846160038b7d47edca5661c58444e4148884c1f"
78
+ "trov:sha256": "d7e6308efd9e711f238a4d4a3aa8bc07e0962f3f4c9596e9ad6490ff5c63e45a"
79
79
  },
80
80
  {
81
81
  "@id": "composition/1/artifact/data_release_manifest",
@@ -102,7 +102,7 @@
102
102
  "trov:hasFingerprint": {
103
103
  "@id": "composition/1/fingerprint",
104
104
  "@type": "trov:CompositionFingerprint",
105
- "trov:sha256": "ed5fba0990295673642c2e186d68015eca106b5ffc953a62cdfe15a8ffb48192"
105
+ "trov:sha256": "d79d22d81bd1d48bfaf836ab3c03ba79721e77594b9695929cb163b872f00373"
106
106
  }
107
107
  },
108
108
  "trov:hasPerformance": {
@@ -17,18 +17,18 @@
17
17
  "schema:name": "PolicyEngine",
18
18
  "schema:url": "https://policyengine.org"
19
19
  },
20
- "schema:description": "TRACE TRO for certified runtime bundle us-6.1.0 covering the bundle manifest, the certified dataset artifact, the country model wheel, and the country data release manifest when it is available.",
20
+ "schema:description": "TRACE TRO for certified runtime bundle us-6.1.2 covering the bundle manifest, the certified dataset artifact, the country model wheel, and the country data release manifest when it is available.",
21
21
  "schema:name": "policyengine us certified bundle TRO",
22
22
  "trov:createdWith": {
23
23
  "@type": "schema:SoftwareApplication",
24
24
  "schema:name": "policyengine",
25
- "schema:softwareVersion": "6.1.0"
25
+ "schema:softwareVersion": "6.1.2"
26
26
  },
27
27
  "trov:hasArrangement": [
28
28
  {
29
29
  "@id": "arrangement/1",
30
30
  "@type": "trov:ArtifactArrangement",
31
- "rdfs:comment": "Certified arrangement for bundle us-6.1.0.",
31
+ "rdfs:comment": "Certified arrangement for bundle us-6.1.2.",
32
32
  "trov:hasArtifactLocation": [
33
33
  {
34
34
  "@id": "arrangement/1/location/bundle_manifest",
@@ -74,7 +74,7 @@
74
74
  "@type": "trov:ResearchArtifact",
75
75
  "schema:name": "policyengine.py bundle manifest for us",
76
76
  "trov:mimeType": "application/json",
77
- "trov:sha256": "241b8728f2babe04be9c1b321846160038b7d47edca5661c58444e4148884c1f"
77
+ "trov:sha256": "d7e6308efd9e711f238a4d4a3aa8bc07e0962f3f4c9596e9ad6490ff5c63e45a"
78
78
  },
79
79
  {
80
80
  "@id": "composition/1/artifact/data_release_manifest",
@@ -101,7 +101,7 @@
101
101
  "trov:hasFingerprint": {
102
102
  "@id": "composition/1/fingerprint",
103
103
  "@type": "trov:CompositionFingerprint",
104
- "trov:sha256": "2194fc8929886115f14970c8dbce80e1d7e362a6423ef38c2649025c26f6307d"
104
+ "trov:sha256": "75052afc5a871ead813d47d3a5dd61b7085e963a164e7047870e705919420192"
105
105
  }
106
106
  },
107
107
  "trov:hasPerformance": {
@@ -358,6 +358,9 @@ class MicrosimulationModelVersion(TaxBenefitModelVersion):
358
358
  serialized_spm = None
359
359
  if self.country_code == "us":
360
360
  from policyengine.core.spm import SPMProvenance
361
+ from policyengine.tax_benefit_models.us.legacy_inputs import (
362
+ RENAMES_RECORD_KEY,
363
+ )
361
364
 
362
365
  receipt = SPMProvenance.model_validate(simulation.spm_provenance())
363
366
  if (
@@ -374,6 +377,17 @@ class MicrosimulationModelVersion(TaxBenefitModelVersion):
374
377
  },
375
378
  sort_keys=True,
376
379
  )
380
+ # ``PolicyEngineUSDataset.save()`` writes this record into the
381
+ # file, and ``load()`` refuses an output without it.
382
+ renames = (getattr(simulation.output_dataset, "metadata", None) or {}).get(
383
+ RENAMES_RECORD_KEY
384
+ )
385
+ if renames is None:
386
+ raise ValueError(
387
+ "This US output does not record which renamed stored "
388
+ "inputs were mapped when it was calculated; run again "
389
+ "before saving"
390
+ )
377
391
  simulation.output_dataset.save()
378
392
  if serialized_spm is not None:
379
393
  # Store UTF-8 JSON in a dataset rather than an attribute: the
@@ -399,6 +413,10 @@ class MicrosimulationModelVersion(TaxBenefitModelVersion):
399
413
  receipt = None
400
414
  if self.country_code == "us":
401
415
  from policyengine.core.spm import SPMProvenance
416
+ from policyengine.tax_benefit_models.us.legacy_inputs import (
417
+ RENAMES_RECORD_KEY,
418
+ read_renames_record,
419
+ )
402
420
 
403
421
  with h5py.File(filepath, "r") as stream:
404
422
  raw = (
@@ -406,6 +424,7 @@ class MicrosimulationModelVersion(TaxBenefitModelVersion):
406
424
  if "policyengine_spm" in stream
407
425
  else None
408
426
  )
427
+ recorded_renames = read_renames_record(filepath)
409
428
  if raw is None:
410
429
  raise ValueError(
411
430
  "Saved US simulation has no SPM configuration or receipt"
@@ -414,6 +433,15 @@ class MicrosimulationModelVersion(TaxBenefitModelVersion):
414
433
  if recorded["config"] != simulation.spm_config:
415
434
  raise ValueError("Saved US simulation uses different SPM settings")
416
435
  receipt = SPMProvenance.model_validate(recorded["provenance"])
436
+ # Outputs saved before stored inputs were mapped onto renamed
437
+ # live inputs were calculated without them (for example with
438
+ # every WIC-eligible person taking WIC up), so they are not
439
+ # reused. ``Simulation.ensure()`` runs such a simulation again.
440
+ if recorded_renames is None:
441
+ raise ValueError(
442
+ "Saved US simulation predates the mapping of renamed "
443
+ "stored inputs (it has no record of them); run it again"
444
+ )
417
445
 
418
446
  simulation.output_dataset = self._dataset_class(
419
447
  id=simulation.id,
@@ -428,7 +456,9 @@ class MicrosimulationModelVersion(TaxBenefitModelVersion):
428
456
 
429
457
  simulation.spm_receipt = receipt
430
458
  simulation.spm = SPMSelection.model_validate(recorded["config"])
431
- simulation.output_dataset.metadata["spm_config"] = recorded["config"]
459
+ simulation.output_dataset.metadata.update(
460
+ {"spm_config": recorded["config"], RENAMES_RECORD_KEY: recorded_renames}
461
+ )
432
462
 
433
463
  if os.path.exists(filepath):
434
464
  simulation.created_at = datetime.datetime.fromtimestamp(
@@ -24,6 +24,14 @@ from policyengine.provenance.manifest import (
24
24
  from policyengine.tax_benefit_models.common.model_version import (
25
25
  build_runtime_dataset_provenance,
26
26
  )
27
+ from policyengine.tax_benefit_models.us.legacy_inputs import (
28
+ RENAMES_RECORD_KEY,
29
+ apply_legacy_input_renames_to_microsimulation,
30
+ check_yearly_periods,
31
+ pending_legacy_input_renames,
32
+ read_renames_record,
33
+ write_renames_record,
34
+ )
27
35
  from policyengine.utils.hashing import sha256_file
28
36
 
29
37
 
@@ -97,12 +105,22 @@ class PolicyEngineUSDataset(Dataset):
97
105
  store["spm_unit"] = pd.DataFrame(self.data.spm_unit)
98
106
  store["tax_unit"] = pd.DataFrame(self.data.tax_unit)
99
107
  store["household"] = pd.DataFrame(self.data.household)
108
+ # The renamed stored inputs mapped when this data was cut or
109
+ # calculated. Its presence marks a year file or output as written
110
+ # with the mapping (see ``legacy_inputs.RENAMES_H5_DATASET``).
111
+ renames = self.metadata.get(RENAMES_RECORD_KEY)
112
+ if renames is not None:
113
+ write_renames_record(filepath, renames)
100
114
 
101
115
  def load(self) -> None:
102
116
  """Load dataset from HDF5 file into this instance."""
103
117
  filepath = self.filepath
104
- if _is_policyengine_core_h5(Path(filepath)):
105
- self.data = _load_policyengine_core_h5(Path(filepath), self.year)
118
+ path = Path(filepath)
119
+ renames = read_renames_record(path)
120
+ if renames is not None:
121
+ self.metadata[RENAMES_RECORD_KEY] = renames
122
+ if _is_policyengine_core_h5(path):
123
+ self.data = _load_policyengine_core_h5(path, self.year)
106
124
  return
107
125
 
108
126
  with pd.HDFStore(filepath, mode="r") as store:
@@ -194,10 +212,20 @@ def _core_h5_entity_lengths(h5_file: h5py.File, year: int) -> dict[str, int]:
194
212
  return lengths
195
213
 
196
214
 
197
- def _core_h5_variable_entities() -> dict[str, str]:
215
+ def _core_h5_variable_entities() -> tuple[dict[str, str], dict[str, str]]:
216
+ """Return each variable's entity, and the pending renames ``{legacy: live}``."""
198
217
  from policyengine_us.system import system
199
218
 
200
- return {name: variable.entity.key for name, variable in system.variables.items()}
219
+ entities = {
220
+ name: variable.entity.key for name, variable in system.variables.items()
221
+ }
222
+ # A stored input the engine has since renamed belongs to its live input's
223
+ # entity. Without this its entity is guessed from its length, and a column
224
+ # as long as two entities is dropped before the rename can map it.
225
+ pending = pending_legacy_input_renames(system.variables)
226
+ for legacy, live in pending.items():
227
+ entities[legacy] = entities[live]
228
+ return entities, pending
201
229
 
202
230
 
203
231
  def _validate_entity_ids(data: dict[str, pd.DataFrame]) -> None:
@@ -288,11 +316,24 @@ def _load_policyengine_core_h5(path: Path, year: int) -> USYearData:
288
316
  """Load a PolicyEngine core variable/period H5 into .py entity DataFrames."""
289
317
 
290
318
  data = {entity: pd.DataFrame() for entity in US_ENTITY_KEYS}
291
- variable_entities = _core_h5_variable_entities()
319
+ variable_entities, pending_renames = _core_h5_variable_entities()
292
320
 
293
321
  with h5py.File(path, "r") as h5_file:
294
322
  entity_lengths = _core_h5_entity_lengths(h5_file, year)
295
323
  for variable_name in h5_file.keys():
324
+ live_name = pending_renames.get(variable_name)
325
+ if live_name is not None and live_name not in h5_file:
326
+ # A stored legacy column is mapped onto every month of the
327
+ # year, so a part-year value is refused, as it is when
328
+ # ``managed_microsimulation`` reads this file. A file that
329
+ # also stores the live name loads that natively, and its
330
+ # legacy column is left alone on both paths.
331
+ node = h5_file[variable_name]
332
+ check_yearly_periods(
333
+ variable_name,
334
+ node.keys() if isinstance(node, h5py.Group) else [],
335
+ path,
336
+ )
296
337
  values = _read_core_h5_period_values(h5_file, variable_name, year)
297
338
  entity = variable_entities.get(variable_name)
298
339
  if entity is None:
@@ -353,6 +394,9 @@ def create_datasets(
353
394
  )
354
395
  dataset_stem = source.name
355
396
  sim = Microsimulation(dataset=source.path, spm=resolve_spm_selection())
397
+ # Map stored inputs the engine has since renamed before extracting,
398
+ # so each year's file stores the live input rather than dropping it.
399
+ legacy_input_renames = apply_legacy_input_renames_to_microsimulation(sim)
356
400
 
357
401
  for year in years:
358
402
  # Get all input variables from the simulation
@@ -496,6 +540,9 @@ def create_datasets(
496
540
  description=f"US Dataset for year {year} based on {dataset_stem}",
497
541
  filepath=f"{data_folder}/{dataset_stem}_year_{year}.h5",
498
542
  year=int(year),
543
+ metadata={
544
+ RENAMES_RECORD_KEY: dict(sorted(legacy_input_renames.items()))
545
+ },
499
546
  data=USYearData(
500
547
  person=MicroDataFrame(person_df, weights="person_weight"),
501
548
  household=MicroDataFrame(household_df, weights="household_weight"),
@@ -515,6 +562,16 @@ def create_datasets(
515
562
  return result
516
563
 
517
564
 
565
+ def _year_file_records_renames(path: Path) -> bool:
566
+ """Return whether a year file records the renamed stored inputs mapped.
567
+
568
+ ``create_datasets`` writes the record into every year file (``{}`` when
569
+ nothing needed mapping). Files written before it did may have lost a
570
+ renamed input such as the WIC take-up draw.
571
+ """
572
+ return read_renames_record(path) is not None
573
+
574
+
518
575
  def load_datasets(
519
576
  datasets: Optional[list[str]] = None,
520
577
  years: list[int] = [2024, 2025, 2026, 2027, 2028],
@@ -522,6 +579,11 @@ def load_datasets(
522
579
  ) -> dict[str, PolicyEngineUSDataset]:
523
580
  """Load PolicyEngineUSDataset instances from saved HDF5 files.
524
581
 
582
+ A year file without the record of renamed stored inputs that
583
+ ``create_datasets`` writes was cut before those inputs were mapped, and
584
+ may have lost one (see ``legacy_inputs.RENAMES_H5_DATASET``), so it is
585
+ refused.
586
+
525
587
  Args:
526
588
  datasets: List of HuggingFace dataset paths (used to derive file names)
527
589
  years: List of years to load data for
@@ -537,6 +599,17 @@ def load_datasets(
537
599
  dataset_stem = dataset_logical_name(resolved_dataset)
538
600
  for year in years:
539
601
  filepath = f"{data_folder}/{dataset_stem}_year_{year}.h5"
602
+ if Path(filepath).exists() and not _year_file_records_renames(
603
+ Path(filepath)
604
+ ):
605
+ raise ValueError(
606
+ f"US year file {filepath} has no record of the renamed "
607
+ "stored inputs mapped when it was cut, so it was written "
608
+ "before policyengine.py mapped them and may have lost "
609
+ "the WIC take-up draw (every WIC-eligible person would "
610
+ "then take WIC up). Regenerate it with ensure_datasets() "
611
+ "or create_datasets()."
612
+ )
540
613
  us_dataset = PolicyEngineUSDataset(
541
614
  name=f"{dataset_stem}-year-{year}",
542
615
  description=f"US Dataset for year {year} based on {dataset_stem}",
@@ -1182,6 +1255,11 @@ def ensure_datasets(
1182
1255
  ) -> dict[str, PolicyEngineUSDataset]:
1183
1256
  """Ensure datasets exist, loading if available or creating if not.
1184
1257
 
1258
+ Year files without the record of renamed stored inputs that
1259
+ ``create_datasets`` writes were cut before those inputs were mapped, and
1260
+ may have lost one such as the WIC take-up draw, so they are created
1261
+ again rather than loaded.
1262
+
1185
1263
  Args:
1186
1264
  datasets: List of HuggingFace dataset paths
1187
1265
  years: List of years to load/create data for
@@ -1199,7 +1277,9 @@ def ensure_datasets(
1199
1277
  dataset_stem = dataset_logical_name(resolved_dataset)
1200
1278
  for year in years:
1201
1279
  filepath = Path(f"{data_folder}/{dataset_stem}_year_{year}.h5")
1202
- if not filepath.exists():
1280
+ # A year file written before renamed stored inputs were mapped
1281
+ # may have lost them, so it is regenerated rather than reused.
1282
+ if not filepath.exists() or not _year_file_records_renames(filepath):
1203
1283
  all_exist = False
1204
1284
  break
1205
1285
  if not all_exist:
@@ -292,7 +292,14 @@ def calculate_household(
292
292
  result = HouseholdResult()
293
293
  for entity, columns in output_columns.items():
294
294
  raw = {
295
- variable: list(simulation.calculate(variable, period=year, map_to=entity))
295
+ variable: list(
296
+ simulation.calculate(
297
+ variable,
298
+ period=year,
299
+ map_to=entity,
300
+ decode_enums=True,
301
+ )
302
+ )
296
303
  for variable in columns
297
304
  }
298
305
  if entity == "person":