Repository navigation
Conversation
Port policyengine-us's scanner for engine-time randomness and hash draws as a code-health test. EXEMPT lists the package's SHA-256 digests, which fingerprint, key caches or check content; RATCHET lists today's draws: the splitmix64 helper, the formulas and uprating that call it, and the seeded numpy draws in participation and two scenarios. Cases that need newer syntax are filtered at collection, so no Python reports a skip. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LwQq6H1FBndAKeuXdSGuft
The guard's docstring now says it looks for draws and not for the clock (#2875). The comments on the splitmix64 and Universal Credit entries say which constants the scan recognises, which entries reach the hash and how Simulation.__init__ applies the modifier. Two test rows follow PolicyEngine/policyengine-us#10447 at 221f2fe44, and a changelog fragment records the guard. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e reads it Define uc_new_claimant_health_element_draw, pip_phase_in_draw and would_claim_student_loan as yearly inputs with no formula, and register them with the supplied-input helpers. supplied_input_periods, and with it supplied_by, latest_supplied_input_period and supplied_input, now count a recorded key only when its branch is the one core reads for the period and the tier core reads there still holds the input. latest_supplied_input_period ranks with core's _latest_input_key. set_model_value refuses the three new columns. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LwQq6HUE9hj2BPEjEXLL68
input_source(population, name, period) names the supplied input policyengine-core reads for a registered draw, returns None where none reaches the period, and raises for anything else. In a simulation built from data, Simulation.calculate applies it before core, drops the request's fast-cache entry, and checks core's answer against the source after. calculate_add, calculate_divide and calculate_output refuse a draw, and each counts as a running calculation. set_input refuses a new draw while a calculation runs or a derived value of the draw is stored, and checks would_claim_student_loan's raw values before core casts them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LwQq6HUE9hj2BPEjEXLL68
…cenario Each consumer asks input_source whether a stored input reaches the year. The UC rebalancing modifier compares uc_new_claimant_health_element_draw, promoted to float64, with the new-claimant share; the PIP scenario does the same with pip_phase_in_draw and the phase-in share; student loan uprating uses the stored would_claim_student_loan decision after checking its raw values. Without the column, each runs its existing seeded draw, inline. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LwQq6HUE9hj2BPEjEXLL68
…e core versions The core Dataset route refuses a dataset carrying a stored column whose person, benefit unit or household identifiers do not survive the int32 cast, and one whose stored columns or exempting outcomes are supplied for a later period but not the first, or whose draws change between periods, before it exports anything. A code-health test fails when uv.lock or the installed policyengine-core holds a version outside the qualified set, and another fails on any package read of a stored draw that skips calculate. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LwQq6HUE9hj2BPEjEXLL68
…eachable branch Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LwQq6HUE9hj2BPEjEXLL68
…umers Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LwQq6HUE9hj2BPEjEXLL68
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
juaristi22
left a comment
There was a problem hiding this comment.
GitHub disposition: COMMENT, not approval. This is the completed code review of the implemented storage/input-provenance stage at 10b176a1b419481ed63b1022650bf3b296cfe5d8. The PR remains Draft, exact-head CI is pending, and its declared landing dependencies #2873 and #2877 are unmerged.
Program review
Base repository: PolicyEngine/policyengine-uk
PR number: 2898
Reviewed head SHA: 10b176a
Merge base SHA: 47a2817
Mode: full
Scope: changed behavior and affected dependencies: implemented protected-storage/input-provenance stage, with byte-validated parent reuse
Source manifest: /privatepr-2898-sweep20261108-1725-review-sources.json
Review status: COMPLETE
Source Documents
No source documents registered; see scope and validation.
Critical
None.
Should Address
None.
Suggestions
None.
Evidence Gaps
No material gaps reported.
Notes
- This validates the implemented storage/input-provenance stage, not the draft’s explicitly deferred population classes, sealing, subset and performance work.
- Only the locked Core 3.34.1 runtime was executed here; no new qualification is asserted for another supported Core version.
- No private dataset, population run, installation, source acquisition or GitHub/state/config mutation.
- Hosted CI/readiness and parent-delivery holds are separate coordinator publication guards. The PR remains Draft and both parent branches are open.
- Policy/source review is not applicable: engine-storage/provenance infrastructure, no statutory rule or policy-value change. The version1 source manifest is intentionally empty.
- Parent2873/2877 exact ancestors and nine unchanged dependency/test files were verified;35+51 prior technical members were rehashed. Historical389/202 passes are not added to626current passes.
- GitHub disposition is COMMENT while Draft, pending CI and declared parent landing requirements remain. The assembler's zero-finding code verdict is not a GitHub approval.
- Full-head scope covers24paths; this does not certify the explicitly deferred population sealing, subsets, broad qualification, performance or universal population invariance.
- Timing includes initial monitoring/capture. Reviewer timing starts at its first recorded START; exact dispatch and standalone scope subintervals were not separately timestamped and are not estimated.
Validation Summary
626 passed,0 failed/skip,626distinct test calls across9paths in one serial540-second-bounded campaign. Wrapperexit0/137.17s;pytest132.78s. Core3.34.1 and five other installed pins match lock; exact snapshot import verified. Consumer regressions reach PIP monetary outcomes and UC draw routing; no new native/population campaign.149cached technical artifacts hash-validated. Latest hosted CI at17:37:17UTC on10b176a1b419481ed63b1022650bf3b296cfe5d8:19contexts,11success/8inprogress,no failed contexts,statuses empty. Draft and open parents2873/2877 defer approval. See pr-2898-sweep20261108-1725-review-validation.json and pr-2898-sweep20261108-1725-review-test-output.log.
Timing
elapsed seconds: 955.04s; setup seconds: 2.78s; parallel review seconds: 563.13s; code role seconds: 563.13s; policy role seconds: 0.00s; adjudication seconds: 0.00s; consolidation cleanup seconds: 117.25s
Review Severity
APPROVE. Open findings: 0 critical, 0 should address, 0 suggestions.
Aggregate impact on certified data: passBase Checks: 0 broken by this change, 1 failing on both sides, 0 fixed. Moves flagged for review: 0 (thresholds in Notes
Moves flagged for reviewNone. Spending by benefit and service
Caseloads
Household net income by decileNo household's net income changes in any year. No change in any year: receipts by tax head; government balance, each component counted once; model totals; household income totals; population; poverty rates; people in poverty; inequality; mean household net income in each side's own deciles; standard reform costings (change in gov_balance); standard reforms: change in each reform's target. Checks failing on both base and head (1)
Counted-once checkThe check raised each of 92 components by £1 per unit in 2026-27 and read every head of its totals household by household: its own head must rise by exactly £1, no other tax head may move, no other benefit may rise, and the model's own total must move by what its heads moved. A response that is not finite breaks every rule. The check measures a head that breaks a rule twice more: once holding every other head at its baseline value, and once holding every other head at its value after the first £1 while the component rises again. The head fails where either measurement still shows the response. The check cannot hold a head at a value that is not finite. In each unit where another head is not finite after the first £1, it holds that head at its baseline value, and the second measurement judges no household the unit belongs to. There a head fails wherever it first broke a rule, or wherever the check could not confirm whether its response contains the component. 0 failed and the check skipped 0.
Provenance
Dataset: Receipts by tax head: head levels
Spending by benefit and service: head levels
Caseloads: head levels
Government balance, each component counted once: head levels
Model totals: head levels
Household income totals: head levels
Population: head levels
Poverty rates: head levels
People in poverty: head levels
Inequality: head levels
Mean household net income in each side's own deciles: head levels
Standard reform costings (change in gov_balance): head levels
Standard reforms: change in each reform's target: head levels
|
Addresses #2874
axiom: n/a: microsimulation-only: engine storage guards, no rule changes
Work in progress, for stage 2 of Phase 1a in #2874. After this stage, no calculation in a simulation built from data can store, delete, demote or change a stored draw, or rewire what a read reaches. Everywhere else the code runs as it does today, and no number moves.
The branch starts from #2877's head
5a784a7e9, so it contains #2873's and #2877's commits and lands after both.So far
In a simulation built from data, the two registered draws,
uc_new_claimant_health_element_drawandpip_phase_in_draw, now sit inProtectedMemoryStorage.793468eb3adds that storage. It keeps each value over immutable bytes, accepts only numeric arrays and refuses a derived value over a stored input. During a calculation it also refuses to store, delete or demote an input. A read returns a new read-only view, and pickling keeps each array's byte order.c1e4da397installs the storage on both draws' holders each time the simulation builds its populations, before a data loader supplies values, and gives a situation simulation ordinary storage back. Before each read of a draw,input_sourcechecks that the holder keeps protected storage, and that the simulation's input record and the holder's location record name every input the storage marks.10b176a1bchanges one adoption test to modify the array it supplied, sincetest_cached_arrays_not_written_in_place.pyfails on a write into an array a read returned.Still to come
Scenarioand modifiers, and both guard tests.🤖 Generated with Claude Code