Repository navigation
Add composable Social Security benefit levers - #10400
Merged
Merged
Conversation
MaxGhenis
marked this pull request as ready for review
October 23, 2026 10:05
7 tasks done
Run the unchanged input checks in a dedicated Rest group and preserve three isolated processes, distinct reports, and failure propagation. Avoid the differential parent's redundant country import and allow slower probes within a bounded hang guard.
Main's #10401 (ee6c1c5) added the ss-calculator-engine and ss-calculator-differential Rest groups beside this branch's social-security-inputs group. The Makefile keeps all three groups, their file lists and recipes, and lists all three files in REST_LISTED_TESTS so the core and remaining groups don't run them twice. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 27, 2026
Contributor
Author
|
US + core hub merge audit, us#10400 at
|
MaxGhenis
added a commit
that referenced
this pull request
Oct 27, 2026
Main added tools/social_security_preflight.py (#10400), which checks a stored dataset's SHA-256 before a Social Security reform is scored, as system.py checks the default dataset's. Its hashlib import and _file_sha256 are exempt like system.py's, so the calls that reach _file_sha256 are no draw helper calls. The package scan of this head is clean. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
added a commit
that referenced
this pull request
Oct 27, 2026
Main raised pe-us's core floor to 3.33.1 (#10400). From 3.33.1 core's subsample rebuilds from recorded inputs and never calls spm.py's _get_exportable_input_periods override (policyengine-core#573), so the override only changed to_input_dataframe and to_input_dict with include_computed_variables=True, which nothing calls. It goes, with PRESENCE_TESTED_INPUTS. section_911's call passes include_computed_variables=False and is unaffected. The lint job's start-month step ran the tests on the locked core because that core's subsample reached the override. The lock is now 3.33.2, so it no longer does; the PR test job's microsimulation group runs the same file on the latest core. The step goes. The subsample tests stay: a calculated default must still not come back as a supplied column. They pass, with the other start-month tests, on cores 3.33.1, 3.33.2 and 3.33.12. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 27, 2026
This was referenced Oct 27, 2026
MaxGhenis
added a commit
that referenced
this pull request
Oct 28, 2026
#10400 was squash-merged as 9969420, so Git's merge base is the pre-#10400 commit d453360 and every file #10400 added and this branch then changed shows as an add/add conflict. Each was resolved against #10400's head a6dcc92: - The four social_security_*_pia_ratio_factor.py variables, Makefile and tests/code_health/test_rest_python_groups.py: main's copy equals #10400's head, so this branch's filled version (built on that head) is kept. - tests/core/_social_security_state_backend.py: this branch's copy equals #10400's head and main changed it afterwards (#10504, Core 3.33.13 names), so main's version is kept. - changelog.d/ss-benefit-levers.added.md: main's release compiled and removed it; removed here too. A merge-tree run with a6dcc92 as the base gives the same tree apart from the version files (CHANGELOG.md, pyproject.toml, uv.lock), which this merge takes from main. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
added a commit
that referenced
this pull request
Oct 28, 2026
Merges main 8ea4342 (which carries #10400) into 1aeb9e4. Resolved hunks: - Makefile, test-yaml-structural-other: the one conflict. Took main's recipe unchanged. SSA stays excluded from the per-subdir run and has its own per-file run with POLICYENGINE_BATCH_WORKERS=1, so this PR's three SSA YAML files run one file per process (review P2 #2). - policyengine_us/system.py: merged without a conflict. #10400 adds an import, a module-level install of its input hooks, a class attribute and a migrate call in each simulation constructor. This PR adds the current-law cap snapshot inside CountryTaxBenefitSystem.__init__. The hunks do not overlap. make format changed nothing after the merge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Public Social Security components compose benefit levers over reported sources. Later writes to a benefit source refresh formula-derived results at or after Core's earliest dependency number, so subsequent calculations use the surviving current source. The read-time source model preserves independent public and explicit reported inputs across loading, copying and extraction.
Design
The formulas compose joint COLA, a neutral PIA-ratio extension point, across-the-board changes and supplied payable-share factors. Historical effective/payment months, rounding and bend points remain covered. Rates and payable shares are validated; OASI-only cuts protect DI and require a fund designation for positive dependent benefits. Reserved calculated-source modes fail explicitly. Exact compound totals are retained, with separately supplied annual amounts required when annual factors differ.
Round 4 chose read-time source resolution after the eager state machine found that dataset public input → raw reported write → extraction/reload could erase the original registered source. This removes automatic twin arrays, automatic-origin/stamp maps and replay retagging. Initial public inputs remain registered Core inputs on reserved public-source branches, hidden from public formula reads so scored-year levers can apply. Later public writes remain final overrides in their own periods. Annual reported reads use an explicit twin at or before the request; otherwise they read and uprate the surviving public source. Exact compound requests retain exact-input precedence.
Source snapshots serialize actual public values and initial/final placement. Legacy origin metadata remains readable. Initial routing and later source writes follow
RULING-10400-refresh-scope-2026-10-26.md, rules 1–5 and the Round 7 addendum:sinceis the minimumStoreHistory.earliest_dependency(name, period)over the public component and its_reportedtwin. Formula-derived physical arrays and fast-only calculated returns dated at or aftersinceare eligible. A fast-only calculated return whose date was lost is intentionally treated as eligible when a cutoff exists; an unknown date cannot establish that the return predates the cutoff.since=Nonemeans no drop. Supplied inputs, raw nonderived values, physical values excluded from the fast-only rule, and derived returns numbered beforesinceretain their protections. An unrelated formula stored at or aftersincecan be dropped: this is Core's intended conservative approximation, not an exact dependency graph.The bounded refresh uses
Simulation._get_store_history,StoreHistory.earliest_dependency, storageget_known_branch_periods,is_derivedand_sequence_numbers, and_delete_exact/Holder._evict_fast_cache. It bumps_input_epochand taints_calculation_framesor calls_taint_waiting_framesasSimulation._drop_computeddoes. The whole fast cache is cleared only after an eligible physical derived array or identity-matching fast-only calculated return is dropped; an undated fast-only return counts as a drop whensinceis non-null. Without a drop, the adapter leaves the cache, epoch and frames unchanged. For skipped-storage returns,_cache_result/Holder._record_storecaptures a pending number, and a dict subclass commits that date only on actual fast-cache insertion. A helper store without insertion cannot redate a live memo. StoreHistory’s first-store record supplies the cutoff, not the current return’s date. Core's bulkSimulation.delete_arrays(name)replaces the memo dictionary while keeping other names' arrays, so an enabled adapter hook carries forward each surviving date only when the key still holds the identical array object. This retains pre-cutoff dates rather than inventing new ones. History is retained: pruning all records as Core's broader drop does would forget raw seeds that this adapter preserves. These paths were read in Core 3.33.1, installed 3.33.2 and tag3.33.12(037960caba89d089bb42a1ffc911afb7f0c4abb3).A dataset rebuild detaches Core's old holders while retaining their calculation fast-cache entries. Loading therefore snapshots the old derived returns’ numbers and weak references. The same cutoff removes eligible returns still held by the fast cache; this metadata retains no old holder, population or array and no old holder changes the new input registry. Rebuild snapshots end with loading. For skipped-storage returns, the fast-cache dict subclass keeps only numeric dates as additional committed metadata, keyed by actual requested cache keys. Pending formula stores use weak simulation keys and weak array references with cleanup; the cache owner is weak. Native clone/drop paths reset the dictionary, so independent branches share no mutable metadata. Pickle preserves memo values and numeric dates, omits pending/weak ownership state, and advances Core’s sequence counter past restored dates. Capture is restricted to enabled skipped-storage policies; ordinary physical stores keep using storage metadata. Snapshot selection uses
Holder._branch_storing, storagehas/is_derivedand sequence keys, without decoding disk arrays. The synthetic backend can memoize an exact reported-source read without creating a derived array. Native Core 3.33.2 and 3.33.12 return the tested exact source before memo insertion; real-Core tests now assert that no memo existed. The narrow reported-source eviction throughHolder._evict_fast_cacheremains defensive for backends that memoize that view. It does not clear unrelated fast-cache entries or bump the drop epoch when no derived value is removed.The adapter no longer calls
Simulation._drop_values_that_may_depend_onfrom low-level_setor from representation-only migration. Core's ownHolder.set_inputcall remains on branch setters and retains Core's raw-seed removal behavior on that route. The preservation guarantee concerns the adapter's additional refresh; it does not change Core's own cleanup.The Core floor remains
>=3.33.1, and the committed lock retains 3.33.2. The legacy differential reference remains pinned to main8986e05cab65d56435a23df1910e2d35f2c5f5bf; pinned-reference fetches, the three-process guard, separate JUnit output and failure propagation remain in place.Input-route audit
The source audit covers Core 3.33.2 and 3.33.12. Their recorded-input helpers distinguish supplied inputs from derived caches and unregistered raw stores. Core 3.33.12 additionally performs overlapping-period cleanup after an ordinary
Holder.set_input; that can remove a raw annual cache after a compound input is stored. The reference model follows actual source survival rather than requiring a virtual twin to remain physically stored.Simulation/Microsimulation, raw Core datasets, fresh/existing builders and YAML inputsfinally, including stores completed before an exception. The machine covers datasets, builders and YAML; country tests cover both wrappers and public-column H5 ingress.Simulation.set_input, directHolder.set_input, delegating setters_setin everyis_inputmode, inside/outside input contexts and with branch argumentsput_in_cache, raw handler stores and stores followed by an exceptionhelpers.get_stored_inputsees a registered initial source on its reserved branch without making that source visible to public calculations. Real-Core tests, generated machine rules and 24 new equality routes cover initial-source allocations; month/rolling compounds and partial handlers also have country-free coverage._set/put_in_cacheand formula cachesThe compatibility adapter is restricted to the four benefit components and their reported twins. Arbitrary external storage mutation, foreign snapshot formats and all possible Core callers are outside the finite generated coverage.
Invariants and backend scope
After every generated step, on each live simulation and retained copy, reported readers must select the surviving explicit source at or before the request, or the surviving public source when fallback is allowed. Exact compound totals keep their own precedence. Public final overrides stay final, derived caches cannot become sources, and later writes cannot alter earlier copies. Registered sources and raw nonderived values are modeled separately; the model accounts for Core's own branch-setter raw cleanup. No automatic-origin map exists.
All four components are read through reported → base → public formulas with a nonneutral synthetic factor. New rules compare helper allocations with Core without hooks, retain caller/raw values and formula arrays stored before a write's cutoff, and label the post-cutoff unrelated-formula drop as intended. They compose initial inputs with divide/dispatch/default FLOW month helpers, month/rolling compounds, real
calculate_add, custom and store-then-raise handlers, and physical source deletion/fallback. Existing branch-builder, restoration, extraction/reload, explicit priority, raw/derived writes, failure identity and copy rules remain.The backend now uses Core periods,
InMemoryStorage,StoreHistory,next_sequence_number,Holder._record_store,_record_inputs,_input_unchanged,_has_unnumbered_values,_evict_fast_cache, and Core's_get_store_history,_drop_values_that_may_depend_on,_drop_computed, frame context/taint functions and period helpers. It does not replace the dependency drop withpass.Remaining substitutions (listed in the backend docstring): Holder construction, default arrays and disk-storage construction create one-person float arrays and JSON disk bytes; array conversion, validation and storage lookup now use Core. Population/entity/system/parameter descriptors, builder
explicit_singular_entities,register_variable,add_person_entity,add_group_entity,add_default_group_entity,declare_person_entity,declare_entityandjoin_with_persons, dataset dictionary loading and entity dump serialization are fixture plumbing. Simulation construction and population lookup attach these tiny entities; the single-thread calculation entry point, acyclic cycle/period checks, formula chain and result cast replace full-country calculation setup. Macro-cache reads are disabled and one-person subsampling is unsupported. Public write/copy/replay/extraction/dump bodies, memory/input tiers and source restoration remain production Core/US paths. The fixture does not claim full-country or threaded execution coverage; standalone real-Core tests use actual TaxBenefitSystem, Simulation, periods, branches and storage without these substitutions.Each example now generates a blacklist with opt-out caching or variables-to-drop policy over a nonempty subset of the four components’ public/base/reported names and one unrelated formula (13 names). Configuration remains deterministic:
max_examples=60,stateful_step_count=25,deadline=None,derandomize=True,report_multiple_bugs=False. Amounts span zero to $48,000 for general rules; helper totals span $24,000–$48,000. All four components, annual 2023–2025, exact multiyear periods, month/rolling helper compounds and 2023–2026 reader requests remain covered. Runtime and actual generated/invalid example counts are recorded below.Intended differences from main
The difference is scoped to a benefit source written after values were calculated. Both audited Core versions return immediately from
_drop_values_that_may_depend_onfor an ordinary simulation without a parent branch. Main therefore retains previously calculated benefit components or downstream totals after these writes. This PR refreshes formula-derived arrays numbered at or after the public/twin dependency cutoff for the four components' source writes, as required by the latest-source invariant and the refresh-scope ruling. Ordinary set-then-calculate use and reform/lever paths remain subject to the current-law differential and existing lever assertions.The refresh cutoff intentionally over-approximates dependencies across holders: an unrelated formula numbered at or after
sinceis also dropped and recalculated, as Core does on branches (test_bounded_refresh_intentionally_drops_derived_value_after_since). A formula numbered beforesincesurvives. The reviewer's cached77had no source dependency (since=None) and now survives untouched. A changed value from an unrelated refreshed formula would require its own earlier source change without invalidation, the same latent main-cache issue addressed by the ruling.The shared differential probe normalizes only formula-derived arrays after the source changes. Identical cleanup runs in both checkouts; it drops no supplied input or raw nonderived seed, and no value comparison is removed. Separate intended-difference tests assert the head's fresh results before normalization, using arithmetic expectations and comments recording main's stale values. The state machine and input regressions likewise check runtime invalidation before any normalization.
Here
U_yis the country model's per-capita Social Security uprating index in yeary. The independent 2026/2024 ratio is(1,665,942,000,000 / 352,304,000) / (1,454,424,000,000 / 346,588,000) = 1.1268465847171525, represented as1.1268465518951416in float32. The 2026/2023 ratio for the compound-setter route is(1,665,942,000,000 / 352,304,000) / (1,379,268,000,000 / 342,835,000), represented as1.1753813028335571in float32. Values below are the Core 3.33.12 float32 results recorded for these routes. Each component is multiplied and the components are added in float32, matching Core; the two-person rows use component-by-component sums rather than multiplying a combined total.extraction_rewrite_simulationsocial_security@2024 = 36,000 + 0 + 0 + 0 = 36,00024,000extraction_rewrite_microsimulationsocial_security@2024 = 36,000 + 0 + 0 + 0 = 36,00024,000complete_export_rewritesocial_security@2026 = 36,000 + 1,800 × U_2026/U_2024 + 600 × U_2026/U_2024 ≈ 38,704.43359375; the second person's componentwise float32 sum6,000 × U_2026/U_2024 + 1,200 × U_2026/U_2024 + 300 × U_2026/U_2024 ≈ 8,451.3486328125is unchanged[26,704.431640625, 8,451.3486328125]dataset_builder_extraction_rewritesocial_security_retirement@2026 = 36,000 × U_2026/U_2024 ≈ 40,566.476562527,044.31640625setter_failed_after_loadingsocial_security_retirement@2026 = 24,000 × U_2026/U_2023 ≈ 28,209.150390625after the setter stores and raises14,104.5751953125, from the earlier12,000 × U_2026/U_2023sourcedump_restore_legacy_public_overridesocial_security_retirement@2026 = 24,000 × U_2026/U_2024 ≈ 27,044.3164062513,522.158203125dump_restore_both_names_overridesocial_security_retirement@2026 = 24,000 × U_2026/U_2024 ≈ 27,044.3164062513,522.158203125clonesocial_security@2026 = 24,000 + 1,800 × U_2026/U_2024 + 600 × U_2026/U_2024 ≈ 26,704.431640625; the second person's same componentwise float32 sum remains8,451.3486328125[16,226.58984375, 8,451.3486328125]Retained round-4 coverage
Round 4's builder replacement and store-then-raise fixes remain: an initial builder replacement reports $24,000, and a successful store followed by an exception retains $24,000 and the original exception object. Legacy, both-name and raw dumps restore $12,000 and follow a later $24,000 public override; an explicit $6,000 twin keeps priority. Read-time resolution rejects formula caches and removed tiers. Prior head
582625618d5d88f1fec8aef7d392cc584c1d5698passed 32/32 CI jobs in run 40292085299, including the original 50 routes/953 arrays and eight intended differences. The current changes leave.github/, pinned reference fetches, the three-process guard, the committed Core 3.33.2 lock and>=3.33.1floor unchanged. Main has not been merged because GitHub reports the PR mergeable.Round 5
2a289b5347: P2-1 routes the existing hidden initial source through Core'shelpers.get_stored_input. Divide, dispatch and ordinary FLOW month allocation retain Core's existing-input precedence, without exposing the source as a final public value.2a289b5347: P2-2 removes the additional low-level Core dependency drop. The review sequence (warm branch future value, raw independent seed99, direct public_set(is_input=True)) retains99.2a289b5347: P2-3 replaces the whole-simulation purge with the ruling's sequence-bounded, derived-only drop. Tests cover pre-cutoff and post-cutoff formulas, raw/input values, minimum twin history, and no dependency. The reviewer's cached77is the no-source-dependency case: nothing is dropped.2a289b5347: P3 stores physical originals on the installedHolder.get_arraywrapper and recovers them on reinstall afterimportlib.reload. Reload → reinstall → write → read retains the correct value.a439daee95: extend the same bounded rule to dataset rebuild returns using transient weak metadata; preserve new supplied-input registration/export and defensively evict an exact reported source memo for backends that create one, without a global cache purge. Three dataset regressions and two exact-source read cases use real Core (Round 6 adds explicit no-memo assertions).82d52dbfea: replace the machine's stubbed Core bookkeeping and add helper, rolling/month, real compound calculation, custom/partly failing handler, deletion and preservation compositions.2e7cccd799: add 24 helper equality routes to the unchanged original 50 routes and eight intended-difference tests.57dc1952ae: move the unchanged 126 synthetic input cases frommicrosimulation/tocore/, isolated in thesocial-security-inputsRest group. Their prior CI process took 6:20 (312.62s pytest). The local 4 GiB-capped run reached its loaded-host timeout at 1801.01s with 2.385 GiB peak process-group RSS; CI at reviewed head57dc1952aepassed all 126 on Rest shard 5 in 5:24.92 process wall (287.657s pytest), with 2.741 GiB peak RSS. Keep the three-process partition/report/failure guard across Rest inputs and Microsimulation base/current law. Restrict differential conftest discovery so its parent does not load a third country system (prior CI startup to pytest session: 26.85s), and raise the per-probe hang guard to 900s against about 290s per probe in prior CI. At reviewed head57dc1952aeMicrosimulation passed in 52:42, leaving 7:18 below its 60-minute limit; SPM took 21:28 and the microsimulation step 30:39 (base process about 21:32, differential about 9:07). The differential is the only added process left in that job and stays below the 10-minute allowance. Startup to its pytest session was 0.41s, versus 26.85s at82d52dbfea. No route, assertion, normalization, workflow or job limit changes.Round-5 validation
Final source head:
57dc1952aeb1b92fd2db8db831cbc5a19f7914d1.82d52dbfea, no country import82d52dbfea, Core 3.33.282d52dbfea, Core 3.33.1282d52dbfeacore/test_social_security_inputs.py: one local run under the required 4 GiB/1800s cap; timed out on the loaded host, peak process-group RSS 2.385 GiB. Start load1 was 79.44. The file is byte-for-byte unchanged. At reviewed head57dc1952aeCI passed all 126 on Rest shard 5 in 287.657s pytest / 5:24.92 process wall, peak RSS 2.741 GiB.57dc1952aeb1b92fd2db8db831cbc5a19f7914d1, run 40354752593 passed all 82 tests: 74 normalized equality routes against pinned main8986e05cab65d56435a23df1910e2d35f2c5f5bfand 8 intended differences, in 546.02s pytest and about 9:07 process wall including startup and shutdown.test_rest_python_groups.py: 59 passed in 588.02s;test_make_test_matches_ci.py: 5 passed in 20.26s. The no-history dry-run plan assigns the moved file once to isolatedsocial-security-inputson shard 6, estimated at 30s/file + 60s/process. A new one-file group uses the global median when timing history is available.make formatpassed before every commit; finaluv lock --check --offlinepassed with the same lock hash. No.github/,pyproject.tomlor lock changes.57dc1952ae57dc1952ae57dc1952aeb1b92fd2db8db831cbc5a19f7914d1: 33 of 33 jobs passed. Full Suite - Microsimulation took 52:42 (SPM 21:28, microsimulation step 30:39), against 38-42 minutes on main; the input checks ran in Rest shard 5 (126 passed). The Documentation workflow's build passed; its Pages deploy job was skipped.Country-free runs use
--confcutdir=policyengine_us/tests/corewith pytest's default import mode, preventing the parent country conftest import. Core 3.33.12 verification uses the existing separate environment; no relock was needed. Python tests exercise API/storage/cache compositions that YAML cannot express, using one-person systems. The real-Core file and machine run in the existing Rest core group. The 126 synthetic input tests run in their own Rest Python group, with no national dataset. The normalized differential and intended-difference tests run in their own pytest process on the existing Microsimulation runner and reuse one loaded system per probe. No CI jobs or workflow steps are added.The prior 50-route/953-array differential took 446.71s in Core 3.33.12 CI. Historical local timings use Core 3.33.2 on a shared host and are not a controlled comparison with CI. Their peak RSS was not separately recorded. This build records capped process-group RSS and wall time below. Historical CI measurements above are labelled with their original head. At reviewed head
57dc1952aethe existingtest_microsim.pycases totalled 1058.715s, versus the supplied main range of 797–993s and prior PR range of 1015–1019s. These are separate runners rather than a controlled performance comparison; the round-5 build changes no simulation logic. The sandbox denied thesysctlCLI, so load gates useos.getloadavg, reading the same Darwin load averages.Round-5 mutation checks
These mutation measurements are from prior head
82d52dbfea; the round-5 build changes no production source or targeted mutation regression.All four independent round-5 mutants reached their targeted regression assertions (exit 1); none survived or needed a cap kill. Each ran in a scratch copy with the final production source/test snapshot, separately under the required 2 GB/900-second cap. The pushed branch was never mutated. These are deterministic targeted-test failure sequences; no Hypothesis shrinking was needed.
p2_1_hidden_helper_sourcep2_2_raw_branch_seedp2_3_unbounded_refreshp3_reload_originalsAll local test files run separately in the foreground with the six required thread settings and the memory/time caps. Country-importing files are started only below the host's load threshold; no population microsimulation is run. No PR/issue comments and no CI jobs are added.
Round 6
Final source head:
5c0e93ecd68afb2e6fe95fe9d894087437c3bb8d.13216f9be9closes the remaining P2 for formula returns whose holders keep no array underopt_out_cachepluscache_blacklist, ormemory_config.variables_to_drop. Rebuilds and writes on existing simulations collect these returns as additional bounded-drop witnesses. Inputs, raw seeds, pre-cutoff returns andsince=Noneretain the ruling's protections. Exact reported-read tests now assert the absence of a native memo; their narrow eviction remains defensive.fb4d238831generates either cache policy over a nonempty subset of 13 names: all four components' public, base and reported names, plus an unrelated formula. Every existing invariant still runs after every step on all retained simulations/copies, and the unrelated reader is also checked. Settings remain deterministic at 60 examples × 25 steps. The model follows Core's ignored opted-out rawput_in_cachewrites while retaining low-level raw_setcoverage.06092f17bfextends real-Core coverage to both public and reported source writes, including ordinary setters and direct branch_set(is_input=True)without rebuild.871ee0eeabcommits a return's actual_record_storenumber only when Core inserts that return into the fast cache. A lazily installed dict subclass observes bracket assignment; numeric dates are keyed by the actual requested memo key. Pending stores have weak simulation keys and weak array references, and the cache has a weak owner. A helper's numbered return without memo insertion cannot replace a live memo's date, even when it reuses the same ndarray. Clone/drop paths still start with an empty Core dictionary; pickle retains values and numeric dates without serializing weak ownership or pending stores.d55a67302fadvances Core's process-wide sequence counter past restored memo dates. The two pickle regressions simulate a fresh counter below a later recalculated memo, whose number is newer than StoreHistory's retained first record.5c0e93ecd6preserves a memo’s existing date when a backend repeats the identical-array insertion without another store. A matching new pending store still supplies the new date. The real-Core preservation cases exercise duplicate assignments too; the machine’s backend naturally performs them.StoreHistory supplies only the public/twin dependency cutoff; it never supplies the current return's date. The collector excludes physical nonderived inputs/raw values and read-time source views. An eligible physical deletion or identity-matching fast-only formula return is required before clearing the whole fast cache, advancing
_input_epochand tainting frames. Without a witness, those states remain unchanged. The adapter adds no Core dependency-drop call on low-level_set; Core's own branch-setter cleanup remains intact.57dc1952aesince=3).since=28locally;22in the review's process).Manual memo clearing makes both baseline reproducers return $24,000, confirming the stale-return mechanism. The 20-case source-write matrix covers both configurations, both initial values, dataset public loading, public/reported setters and public/reported low-level branch writes. Baseline ordinary public writes already return $24,000 because the physical override masks stale intermediates; they fail the required memo-drop/epoch assertions. Rebuild and reported-write cases also expose stale numerical values.
The real-Core file adds 46 cases to the retained 54: the 20 source-write combinations, pre-cutoff survival (2), intended post-cutoff unrelated deletion (2), a later recalculation of the same key (2), physical raw/input preservation on main and branch (8), nonmemoized fresh/reused arrays before/after the cutoff (8), unread-source loading (2), and pickle/counter restoration (2). The final 100-case file against the unchanged
57dc1952aemodule in a scratch tree produced 38 failures and 62 passes in 137.61s, including the strengthened pickle/counter and duplicate-assignment checks. The failures are the 20 source-write cases, 2 intended unrelated drops, 2 later recalculations, 8 caller-preservation cases' missing-drop/epoch assertions, 4 post-cutoff nonmemoized-store cases and 2 pickle cases. The 8 new negative/preservation cases pass there.The generated machine itself catches
57dc1952aein 458.26s under the 2 GB/900-second cap. Its returned shrunk example selects the blacklist policy for all 12 component names (leaving the unrelated formula outside that subset), warms the invariant readers, then runs:The assertion is the reported 2024 reader returning 0 instead of 2. Hypothesis stopped further shrinking after five minutes of slow progress; this was an assertion failure, not a cap kill or proof of a globally minimal example. The final-head machine passed all 60 examples (7 invalid) in 140.77s locally; the measured CI time is below.
Native Core 3.33.2 and tag 3.33.12 return the tested straight-line exact reported source from
get_arraybefore memo insertion. Both real-Core exact-read cases now assert no reported memo existed before the write. They establish correct values and unrelated-cache/epoch preservation, rather than a native need for eviction. The synthetic calculation entry memoizes exact reads, so the narrow source-view eviction is retained and labelled defensive. This does not claim coverage of arbitrary concurrent mutation or every custom backend.core/test_social_security_inputs.pyfb4d238831, before insertion-observer refinements, timed out at 1800.2s after 94 passing progress dots, with no displayed failure or completed JUnit result. Start load1 64.400. Final-head CI supplies the full 126 passed result (Rest shard 6).test_rest_python_groups.py, final sourcemake formatanduv lock --check --offlinepassed; no relock. No.github/, differential, normalization, intended-difference test or job-timeout changes. No local folders, suites, differential or national microsimulation runs.57dc1952ae, run 40354752593: 7.402s, recovered from artifact12666967148,rest-python-test-timings-shard-3/rest-python-core-1.xml. This is historical, not the expanded machine's final-head time.5c0e93ecd68afb2e6fe95fe9d894087437c3bb8d100 passed; moved input126 passed (Rest shard 6, artifact 12704963668 / rest-python-social-security-inputs.xml). Machine 1 passed in 5.766s, from Rest shard2artifact12705501880 / rest-python-core-1.xml; below the required 300s. Grouping guard 59 passed (Rest shard 3, artifact 12705022672 / rest-python-remaining.xml). Full Suite - Microsimulation total44m49s (02:10:38Z–02:55:27Z, including setup and cleanup); 74 equality routes and 8 intended differencesall passed (82 cases, artifact 12705244572 / simulation-social-security-current-law.xml).All local checks ran one file per foreground process with the required four-thread limits and
OMP_WAIT_POLICY=PASSIVE. Country-importing files were started only below load1 100. Local checks use installed Core 3.33.2; final-head CI supplies 3.33.12 validation. The real-Core file and machine remain in their existing Rest group, and the moved input file retains its existing isolated Rest group. No PR or issue comments were posted.Round 7
Final source head:
a6dcc92217ae60127edd588295684f332713ff1a.6498687a0dcloses the remaining P2: Core's bulkSimulation.delete_arrays(name)keeps unrelated fast-cache arrays while replacing the dictionary and losing its date metadata. The adapter snapshots only dates and weak array references, calls native deletion, and transfers a date only if its key still contains the identical array. Reusing the existing cache subclass preserves the established insertion, removal and pickle semantics; the hook handles the sole supported native replacement that keeps values. It does not redate returns from StoreHistory's first-store number.The same commit adds the intended fail-safe from the ruling's addendum: with non-null
since, an undated fast-only calculated return is treated as post-cutoff, dropped and counted. Normal cache clearing,_input_epochadvance and frame tainting follow. Source-view exclusions run first, physical holder values use their separate path, and supplied inputs/raw seeds remain untouched. Withsince=None, the adapter still does nothing.df0ec80c7eexposes installed Core's actualSimulation.delete_arraysbody in the existing country-free backend and adds two generated rules.bulk_delete_formula_cacheselects a component's public/base/reported name or the unrelated formula on a retained state, avoiding deletion of caller source values.bulk_delete_then_reported_writecomposes a fresh initial source, a public read, bulk deletion of a generated name and a reported write before unrelated invariant reads can mask a lost fast-only date. Both existing invariants still run after every generated step on every retained state. Settings remain deterministic atmax_examples=60,stateful_step_count=25,derandomize=True,deadline=Noneandreport_multiple_bugs=False.a6dcc92217fixes a reference-fixture interaction exposed by the first merged-head CI run. The calculator-off fixture had removedgov.contrib.ssa.benefit_leversandgov.ssa.cola_history, although both already belonged to the retained reported-benefit formulas before the main merge. It now removes only the four calculator-only parameter namespaces, retaining all calculator-variable removal and all eight existing comparison cases. The earlier run atdf0ec80c7ehad six missing-parameter failures and two passes in this unit file. No local differential was run; final-head CI supplies validation. The protected 74-route microsimulation differential is unchanged.The hub's main merge
a7cf9ad820kept both sides of the Makefile Rest-group conflict.ss-calculator-engine,ss-calculator-differentialandsocial-security-inputsretain their separate files; this round changes no Makefile groups,.github/files, job limits, microsimulation tests, differential routes, normalization or intended differences.The six reproductions first load retirement $12,000, omit public/base holder storage, read public retirement and bulk-delete an unrelated formula. After the later $24,000 source refresh:
5c0e93ecd6: public / reportedopt_out_cache+ blacklistopt_out_cache+ blacklistopt_out_cache+ blacklist_set(is_input=True)variables_to_dropvariables_to_dropvariables_to_drop_set(is_input=True)Before writing the fail-safe, source inspection confirmed the premise at Core 3.33.1, installed 3.33.2 and 3.33.12. There are only two fast-cache entry assignments: the converged fixed-point path (
calculate, line 1502 in 3.33.12) and the calculated-result tail (_calculate, line 1971). Exact physical holder reads return before the latter insertion. A newly supplied input substituted by_cache_resultrequires a visible physical input slot through_input_set_meanwhile; it cannot be mistaken for a fast-only return. Raw cache writes either store physically or return without inserting a memo. “Calculated return” includes defaults, uprating/carry-over and the SpiralError fallback. Existing reported-source-view exclusions remain in force.Simulation.delete_arrays(name)Simulation.delete_arrays(name, period)purge_cache_of_invalid_valuesandSimulation.set_inputpop.Holder._evict_fast_cacheand input-helper evictiondel/popremoves each affected value and its date; invisible-branch writes preserve both._drop_computedcloneperiod_branch.drop_inherited_values_purge_derived_arrays_cache_resultre-wrapThe real-Core file adds 20 cases to the retained 100: the six refresh reproductions, pre-cutoff date preservation across unrelated bulk deletion (2), identical-array-only witness transfer (2), bulk deletion of the component itself with a surviving base (2), period deletion (4), the intended plain-dict-copy fail-safe with supplied-input/raw-seed preservation on not-kept names (2), and an unread-source rebuild after bulk deletion with
since=None(2). The independentprobe_details.pypasses again: retained caches do not retain simulations/populations/holders, popped arrays collect, pending metadata contains only integer dates and weak references, old rebuild objects collect, and dating/serialization/helper/restore checks retain their behavior.Using only
5c0e93ecd6's production module in a scratch tree, the new-case harness reaches 12 intended assertion failures, 6 passes and 2 hook-only skips, with no unexpected statuses. All six refresh combinations fail at the $24,000 public/reported assertion with public $12,000; both pre-cutoff cases fail at the missing original-date assertion; both component-delete cases fail at the public $24,000 assertion; and both plain-dict-copy fail-safe cases fail because the stale public memo remains. The four period cases and two no-cutoff cases already pass. The two identity-transfer tests require the new adapter hook and are skipped against the old module rather than reported as baseline regressions.Machine catch against
5c0e93ecd6under the required 2 GB / 900-second cap: assertion failure in 317.18s, without a cap kill; shrinking stopped after slow progress. Shrunk failing example and assertion: blacklist{social_security_retirement}; dataset public retirement $24,000 at 2023; then twobulk_delete_then_reported_write(amount=12001, component="social_security_retirement", name=...)steps deletingsocial_security_retirementandsocial_security_retirement_base, respectively. Both invariants run after initialization and each operation. The last public 2024 invariant returns 24,000 instead of 24,002 (the reported source is 12,001 with the fixture's factor 2). This is the returned shrunk example, not a claim of global minimality. The primitive deletion rule alone did not expose the bug in its deterministic run: warmed unrelated physical formulas could be dropped by the subsequent write and clear the stale memo. The composite rule keeps the critical operations together before those reads while retaining every invariant after every generated step.probe_details.py5c0e93ecd6modulecore/test_social_security_inputs.pycode_health/test_rest_python_groups.pymake formatpassed; lock check passed with the lockfile unchanged;.github/, Makefile,pyproject.toml, lock and microsimulation diffs are empty;env -u UV_FROZEN uv lock --checkwithout relocking.a6dcc92217ae60127edd588295684f332713ff1aCurrent-head artifact sources: Rest shard 3,
rest-python-core-1.xml, records the real-Core cases and machine testcase; its decoded Hypothesis statistics show 60 passing / 0 failing / 6 invalid examples and 11.10s generation. The same artifact'srest-python-ss-calculator-differential.xmlrecords all eight calculator comparisons. Rest shard 5,rest-python-social-security-inputs.xml, records the 126 input cases; Rest shard 1,rest-python-remaining.xml, records the 61 grouping cases. Simulation artifact,simulation-social-security-current-law.xml, records the 82 protected differential cases.The four required local files ran at
df0ec80c7e; the subsequent commit changes only the calculator reference fixture. All local files run separately in the foreground with the required four-thread limits andOMP_WAIT_POLICY=PASSIVE. Country-importing files start only at load1 ≤ 100. No local folders, suites, differential or microsimulation runs; no CI jobs, workflow steps or timeout changes. No PR or issue comments are posted.impact: Current-law equality on the 74 normalized routes against pinned main
8986e05cab65d56435a23df1910e2d35f2c5f5bf, with 8 intended differences limited to benefit sources written after values were calculated. Hub microsimulation at this head (default dataset, 2026 and 2027, main at the merge baseee6c1c5166againsta6dcc92217, one side at a time under the shared heavy-job lock):social_security, its four components,taxable_social_security,ssi,state_income_tax,income_tax,household_net_incomeandhousehold_benefitsare unchanged in both years, with 0 records changed. The 2026 Social Security total is $1.68tn on both sides.axiom: n/a: composable reform options and input compatibility; no current-law legal provision is added or changed.