Skip to content

Catch in-place list edits and scale metadata changes in the Budget contract's shared-parameter check - #583

Draft
MaxGhenis wants to merge 3 commits into
mainfrom
w1-contract-snapshot-hardening
Draft

MaxGhenis wants to merge 3 commits into
mainfrom
w1-contract-snapshot-hardening

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #582

Review: GPT-6.1 Sol and an independent Opus 5.5 review both approved 7226ded, each with P3 notes. Their notes are fixed in the latest commit (below). CI is next.

Follow-up to #577, the UK Budget reform contract. GPT-6.1 Sol's round-4 review approved #577 and left two P3 notes on module_parameters_unchanged. That's the run-level check that policyengine-uk's shared parameter state is unchanged after a contract run: the module system, and the processed, statutory and projected caches. The reviewer executed both notes on fresh core trees.

What this changes

  • Values are frozen. shared_state records each timeline value as JSON text. Before, it kept the live value, so a list-valued parameter changed in place (append) compared equal to its own snapshot.
  • Node and scale metadata are watched. The check now compares the root's, each node's and each scale's metadata as well. A scale's metadata.type picks its tax-scale class (single_amount or marginal_amount).
  • Band order is watched. Each scale records its bands' names in order, so an added, removed or reordered band shows. A positional reform such as scale[0].rate targets whichever band comes first.
  • No value can stop the run. _frozen falls back to repr when a value can't be JSON (non-string keys, a cycle).

Tests

tests/test_uk_budget_reform_contract.py adds four tests on a fake shared tree:

  • a list changed in place;
  • a scale's type changed, then restored (which passes), and then a band appended;
  • bands reversed, then restored, and the root's metadata changed;
  • a value with non-string keys, compared without raising.

Results:

  • On pinned policyengine-uk: 33 passed, 4 skipped.
  • With policyengine-uk main (which includes #2305):
    • The run-level tests pass.
    • The real shared state still compares unchanged: 2,405 names in the system and processed trees, 2,348 in the statutory tree, and 1,536 projected timelines.
    • Snapshot and comparison take 0.2 s and 0.3 s on this machine.

🤖 Generated with Claude Code

MaxGhenis and others added 3 commits October 12, 2026 05:00
GPT-6.1 Sol's round-4 P3 notes on #577:
- shared_state records values as JSON text, so a list-valued parameter
  changed in place no longer compares equal to its own snapshot.
- Node and scale metadata, and each scale's band count, are compared
  too (a scale's type picks its tax-scale class).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reviews of #583 (GPT-6.1 Sol and Opus 5.5, both APPROVE with P3 notes):
- each scale records its bands' names in order, so a reordered band
  (which changes what a positional reform targets) shows, as well as an
  added or removed one;
- the root's metadata is compared too;
- _frozen falls back to repr when a value cannot be JSON (non-string
  keys, a cycle), so the snapshot cannot crash the run;
- the row's check text names what it compares.

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.

Budget reform contract: catch in-place list edits and scale metadata changes in shared parameters

1 participant