Skip to content

Registration 18 (A-COLA) build: stage 1 on master, stage 2 and close-out (blind replay) - #585

Draft
MaxGhenis wants to merge 13 commits into
masterfrom
acola-reg18-build-blind-20261024
Draft

MaxGhenis wants to merge 13 commits into
masterfrom
acola-reg18-build-blind-20261024

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

Do not merge. The coordinator lands this after independent review and the tier-count slot.

What this PR is

This is a blind replay of the stage-2 builder's tree for Registration 18 (A-COLA), milestone F0 of the mortality, groups and financing design. The builder's sandbox could not write .git, so it left an uncommitted tree. That tree is preserved as preserve/acola-f0-builder-tree-20261024 (05567445). This branch commits it from a lane that has opened nothing on the restricted list and none of the exposed session's text. The lane also ran the dd222b9 worktree equivalence itself and wrote the provenance record, the commit messages and this body itself.

It would supersede #571, which an exposed session committed. The coordinator chooses which one lands.

PSID use follows the project's data-access record. Every test uses invented data. Nothing here runs the registered population; scripts/run_acola_registered.py ran only through its own tests on invented fixtures.

axiom: n/a: microsim-only registered test build

What was built

The base is master 2195258c.

Commit What it does
4bbed4fd Replays stage 1 (9de858d0) with git cherry-pick. It keeps master's tests/tier_counts.json, tests/README-tiers.md and exclusion tuple, and its other 24 files are byte-identical to 9de858d0. Stage 1 holds the separate config and row registry (C0, C1, M0–M4 runnable; C0-D registered and deferred), the runner, the statistics, the nulls with the TR 2026 Table V.C1 capture, the entry script and its guards, and the verbatim specification file (SHA-256 02287d54…).
10c02653 Fix: two missing spaces in the nulls record's December note. The record was regenerated by its script, and every null value, rational, rate and input hash is unchanged.
4ff1fec0 scripts/compare_acola.py, the comparison lane's standard-library script, with its tests on invented comparator records.
a3806e56 The mechanism-L equivalence script, the golden output for dd222b9, and its test.
5ffb0eee The cross-check between stage 1's Table V.C1 capture and master's data.tr2026 accessor for the COLAs effective December 2027–2029.
b0e01614 The delayed-credit disclosure test and the design note docs/design/acola_trust_fund_implementation.md.
f02181e9 An added test showing that a registered run carries the 48-month cap. It refuses parameters that differ from the committed statutory capture, and statutory_value_checks compares max_delayed_months.
dae71963 The design note: replay citations, the worktree equivalence, and a more precise item 17 (the claimant's own worker record and the aged widow(er) path).
7cd45ee7 Housekeeping: the five new src/ files go into POST_REVIEW_SOURCE_EXCLUSIONS, its exact-tuple test and the reachability test, and the tier manifest is recounted.
6abb6726 The equivalence provenance record, and the design note's build-commit sentence.
0a3299df The fixes for review r1b's four findings (see "Fixes after review r1b" below): scripts/compare_acola.py, tests/acola_track/test_compare.py, tests/acola_track/test_statistics.py, the design note and the tier files.
7cef506f Writes the footer property's thin space (U+2009) and narrow no-break space (U+202F) as Python escape sequences rather than literal characters; the test data's values do not change. Its message shows the two characters themselves where it means their escape sequences.
1ea4d1fc The fixes for review r2's four findings (see "Fixes after review r2" below): scripts/compare_acola.py, tests/acola_track/test_compare.py, tests/acola_track/test_statistics.py, the design note and the tier files.

Compared with the builder's tree, four files differ: the two nulls files, the disclosure test and the design note, each from a commit above. The provenance record and the tier files changed as the brief requires. 0a3299df then changes scripts/compare_acola.py, tests/acola_track/test_compare.py and tests/acola_track/test_statistics.py as well. No shared benefit module changes. This branch edits none of cola_track_a/, scenario_benefits.py, estimates/cola_age_profile.py, track_a_v2/, fra68_track/, ss/, claiming.py, engine/, gates.yaml, track_b/ or runs/*.json.

Invariants and the tests that check them

Property tests use Hypothesis; every input is invented. Test files are under tests/acola_track/.

Invariant Tests
Accounting. Component totals sum to T_s; T_base = T_base,OASI + T_base,DI; P = s_OASI·P_OASI + s_DI·P_DI where both denominators are positive. test_statistics.py::test_accounting_identity_and_cut_bound_on_invented_components (property; it asserts all three identities), ::test_component_accounting_and_spouse_three_classes
Identity. The ratio of means equals P when S_base = S_reform. Under mechanism L the sets are equal by construction, so equal counts are not evidence; the artifact says so. test_statistics.py::test_accounting_identity_and_cut_bound_on_invented_components (property; every reform benefit positive, so the sets are equal)
Zero reform. With annual_reduction = 0, every change statistic, falling share and null is exactly 0, while median benefit levels stay equal and positive. test_nulls.py::test_zero_reform_is_exactly_zero (property), ::test_build_zero_reform_nulls_are_all_exactly_zero, test_statistics.py::test_zero_reform_has_exact_zero_changes_share_and_floors, test_timing_properties.py::test_cut_bounds_monotonicity_and_zero_reform_on_rounded_paths (property)
Bounds. Under a cut, worker-path individual changes lie in [N_full, 0], with a tested allowance for propagated dime flooring. Dual entitlement is an intended, labelled exception: a cut to the claimant's own PIA can raise the spouse excess by more than it lowers the own benefit. test_timing_properties.py::test_cut_bounds_monotonicity_and_zero_reform_on_rounded_paths (property), test_statistics.py::test_accounting_identity_and_cut_bound_on_invented_components (property), ::test_mint_order_falling_share_and_individual_cut_bounds (property; band medians of individual changes in [−100, 0]), ::test_valid_dual_entitlement_can_raise_benefits_under_registered_cut, ::test_dual_entitlement_bound_violation_is_structural_under_dime_floors (property)
Monotonicity (intended). A larger cut, or an earlier first reduced year, weakly lowers P and every individual benefit, outside the dual-entitlement exception: an auxiliary excess paid beside the person's own worker benefit can rise, while the own worker component still weakly falls. test_statistics.py::test_registered_emitter_is_monotone_in_the_cut_outside_dual_entitlement (property on the registered emitter reference_benefit_rows, varying TrackAConfig.annual_reduction and RegisteredRow.first_reduced_determination_year on invented cohorts built from public classes, with two explicit examples), ::test_emitter_cohort_reaches_every_path_and_dual_entitlement, ::test_larger_or_earlier_cut_weakly_lowers_p_and_every_benefit (property on scenario_benefits' worker, spouse and widow(er) path functions), test_timing_properties.py::test_cut_bounds_monotonicity_and_zero_reform_on_rounded_paths (property)
Determinism. The same seed gives the same draw, and person order changes no statistic or floor. test_runner.py::test_same_draw_seed_is_deterministic, test_timing_properties.py::test_registered_draw_root_and_module_stream_are_deterministic (property), test_statistics.py::test_cost_and_mint_order_independent_including_every_floor
Weighted median. Permutation and weight-scale invariance; the ordinary median under equal weights; bounded by min and max; the exact-W/2 midpoint in exact arithmetic; zero weights excluded and counted. test_statistics.py::test_median_bounds_permutation_and_weight_scale (property), ::test_equal_positive_weights_match_ordinary_median (property), ::test_registered_exact_weighted_median, ::test_near_half_weight_uses_exact_binary_fraction, ::test_zero_weights_are_excluded_and_counted_for_each_median
Nulls. N = 100·(Π f_k − 1) with each f_k < 1; more reduced increases lower the null; a larger cut lowers it and a larger COLA raises it; the committed record reproduces from its pinned inputs, with 3, 3, 19 and 20 factors. test_nulls.py::test_null_is_exact_product_with_factors_less_than_one, ::test_more_reduced_increases_strictly_lowers_the_null, ::test_larger_reduction_lowers_null_and_larger_cola_raises_it (all properties), ::test_committed_nulls_reproduce_exactly_from_pinned_inputs
compare.py. Each four-corner interval contains the point; C is monotone in d and, for fixed d, in p while p − d > 0; the precision gate and the PWBM and MINT branches follow the registration; interval subtraction is [a, b] − [c, d] = [a − d, b − c]; null fields are reported, never guessed. test_compare.py::test_oact_corners_contain_point_and_monotonicity (property), ::test_pwbm_corner_interval_contains_point (property), ::test_oact_precision_gate_boundary, ::test_mint_interval_branches_and_formats, ::test_interval_subtraction_and_null_propagation, ::test_null_fields_are_reported_never_guessed_and_empty_band_serializes
Reading S. Reading S counts the decimals of the shortest decimal string that denotes the stored double, shifted two places under a percent format, so an integral double counts none. The XLSX branch applies exactly when that count exceeds the HTML display's and the stored value rounds to the display, and reading L with the same counts gives the same branch and interval. Its result does not depend on the caller's decimal context. test_compare.py::test_reading_s_counts_the_shortest_string_of_the_stored_double (property), ::test_reading_s_counts_no_decimal_for_an_integral_stored_double, ::test_mint_shortest_reading_S_and_literal_sensitivity_L, ::test_reading_s_does_not_depend_on_the_ambient_decimal_context (property), ::test_reading_s_counts_decimals_under_a_small_ambient_precision
OACT footer. The footer check accepts the registered words joined by any whitespace runs, no-break and thin spaces included, with any whitespace before them and any run of periods and whitespace after them, and refuses any changed, added, dropped or joined word. Against the check at 6abb6726: it refuses nothing that check accepted; it also accepts any word gap other than one ASCII space, whitespace after a final period, and periods separated by whitespace. test_compare.py::test_oact_footer_check_ignores_only_whitespace_and_final_periods (property), ::test_footer_check_keeps_everything_the_pre_r1_check_accepted (95,400 enumerated footers against the copied 6abb6726 check), ::test_footer_check_accepts_whatever_the_pre_r1_check_accepted (property), ::test_footer_check_and_pre_r1_check_share_one_whitespace_set, ::test_footer_whitespace_before_final_periods_passes_again, ::test_oact_footer_accepts_transcribed_whitespace, ::test_wrong_oact_footer_refuses_without_substitution
Decimal counts. Each decimal count the comparison computes with (OACT's decimals for the two cost rates, PWBM's stored_decimals for the two 2030 cost rates, MINT's html_decimals for each band's cell) equals the decimals its value writes, trailing zeros included. A value written with n decimals passes with a count of n and refuses with any other, before any arithmetic, and the refusal names cells and fields, never values. test_compare.py::test_value_written_with_n_decimals_matches_only_a_count_of_n (property), ::test_decimal_count_matches_the_value_as_written, ::test_wrong_decimal_count_refuses_naming_the_cell_only, ::test_unreadable_count_or_value_never_matches, ::test_decimal_count_check_names_every_counted_cell_and_needs_no_other, ::test_decimal_count_check_accepts_every_record_that_passed_before, ::test_conversion_fixtures_whose_counts_differ_from_their_values_refuse, ::test_decimal_count_check_follows_seal_and_sidecar_and_precedes_arithmetic, ::test_load_keeps_each_written_decimal_for_the_check
Differential. P against v2's all-alive weighted-total cell; the ratio of means against A7; the floors against v2's and A7's conventions. test_statistics.py::test_ratio_means_and_union_differential_against_existing_functions, ::test_cost_floor_matches_v2_and_ratio_means_floor_matches_a7
Guards. The entry script refuses a wrong pointer, a HEAD other than --registered-commit, a dirty tree, an existing artifact or sidecar, and a changed specification file. test_registered_run_script.py::test_preflight_refusal_matrix, ::test_changed_specification_is_refused, ::test_existing_artifact_or_sidecar_is_one_shot_refusal
Unchanged registries. cola_track_a's REGISTERED_ROWS, the exercise-1 and exercise-3 constants and their consumers are byte-unchanged. test_unchanged.py (2 test functions, 8 items)
Start year. Determination years 2010, 2011 and 2027 reach the legacy emitter. On C0, eligibility in 2027, 2028, 2029 and 2030 carries 3, 2, 1 and 0 reduced increases; C1 carries one more. test_timing_properties.py::test_future_start_year_reaches_the_actual_legacy_emitter
No NaN. Undefined floors, empty bands and refused draws serialize as null with a reason under allow_nan=False. test_statistics.py::test_empty_band_and_undefined_floor_serialize_with_reasons, test_registered_run_script.py::test_undefined_values_and_reasons_serialize, ::test_nonfinite_value_is_rejected_before_either_file_is_written
Mechanism L unchanged since dd222b9. Byte-identical canonical output at dd222b9 and at HEAD. test_mechanism_l_equivalence.py (4 tests)
Delayed-credit disclosure. L applies the 48-month cap to invented people born 1917–1942 who claim after FRA, and a registered run cannot carry another cap. test_delayed_credit_disclosure.py (27 items)
TR 2026 COLA cross-check. The Table V.C1 capture and master's data.tr2026 accessor agree for the COLAs effective December 2027, 2028 and 2029. test_tr2026_crosscheck.py

Tests run

Every run used .venv/bin/python -m pytest -p no:cacheprovider with POPULACE_DYNAMICS_PSID_DIR set to an empty directory, serially (pytest-xdist is not installed).

Selection Tree Result
tests/acola_track dae71963 plus the housekeeping diff later committed as 7cd45ee7 289 passed (1,398 s)
tests/acola_track/test_mechanism_l_equivalence.py, rerun after the provenance commit 6abb6726 4 passed
Cleared brief §7 legacy list plus dry-run tests: tests/cola_track_a, tests/fra68_track/test_registered_run_script.py, tests/track_a_v2/test_matrix_estimands.py, tests/estimates/test_cola_age_profile.py, tests/test_scenario_benefits.py, tests/fra68_track/test_dry_run_membership_text.py, tests/track_a_v2/test_dry_run_protocol.py, tests/baselines/test_track_a_inputs.py same as the first row 500 passed, 2 skipped
tests/estimates/test_birth_evidence_artifact.py -k post_review 6abb6726 2 passed
-k tiers_match_policy_manifest, full collection 7cd45ee7 1 passed, 24,907 deselected, 2 skipped
  • The 2 legacy skips. tests/cola_track_a/test_statutory_capture_oracle.py skips because the local policyengine-us checkout is not at the captured revision.
  • The 2 collection skips. Two Track B modules skip at collection because populace.fit is not installed in the repo venv.
  • Formatting. Black (79 columns), ruff and git diff --check are clean on all 25 Python files the branch adds or changes.

Tier counts

Tier Base 2195258c This branch
unit 18,088 18,463
artifact 4,253 4,278
integration_psid 1,450 1,450
reproduction_legacy 520 520
oracle_policyengine 308 308
Total 24,619 25,019

The recount is correct at this branch's base only. Master has moved, so the coordinator's tier-count slot recounts at merge.

Fixes after review r1b (0a3299df, 7cef506f)

Review r1b (Subfleet job 20261025-004712-mgf-f0b-review-r1b, report SHA-256 01478a4bb3874e386ecd2ddc5c81df96975be3015d32b1836489a9257db5bbd9) returned REVISE: one medium finding and three low ones. A blind fix job fixed all four in 0a3299df. Every new test value is invented.

  1. Reading S (medium). compare_acola.py counted the digits of repr(float(raw)), which writes an integral double with a trailing .0, so it counted one stored decimal where the shortest decimal string has none. It now counts Decimal(repr(double)).normalize(), as the cleared brief's definition of reading S requires. Percent formats and non-integral doubles keep their counts. Design note item 21 discloses the discrepancy between the brief's definition and its worked formula, and its resolution.
  2. OACT footer (low). The check now collapses whitespace runs, no-break spaces included, and drops final periods before comparing, so a transcribed .\n, . or no-break space no longer refuses a matching footer.
  3. Context count (low). Design note item 20 states the model's count (the mean over C0's draws of its S_base weight) and the Trustees count (Table IV.B4, intermediate 2030, OASDI beneficiaries, times 1000), and that no scaling applies.
  4. Statistics tests (low). The monotonicity property now asserts on the scenario code's own per-person output, under a larger cut and under an earlier first reduced year. The accounting property asserts that the OASI and DI shares sum to one and that the component totals reproduce T_s.

7cef506f then writes two whitespace characters in the footer property's test data, U+2009 and U+202F, as escape sequences; their values do not change.

test_statistics.py now carries its own copy of invented_params, identical in body, so it no longer imports tests/cola_track_a/test_assembly.py.

Before the code changes, the new properties failed with minimal counterexamples: the stored string "0" under a non-percent format (one decimal counted, none in the shortest form), and the footer followed by ". ". After them, at the content of 7cef506f, under an audit hook that counted every file open and process launch:

  • tests/acola_track/test_compare.py: 57 passed, 2 deselected (test_real_spec_only_null_records_keep_exact_precision and test_consumes_actual_stage1_invented_dry_artifact_layout read files under data/external/, which this fix job does not open; CI runs them);
  • tests/acola_track/test_statistics.py: 52 passed, in four runs by test node (earlier whole-module and grouped attempts stopped at their wall-clock bound on a loaded host);
  • Black (79 columns), ruff and git diff --check: clean on the three changed Python files.

Fixes after review r2 (1ea4d1fc)

Review r2 (Subfleet job 20261101-155159-mgf-f0b-review-r2, report SHA-256 6d9c9f8eb66104ef53dc0be3aa244e90b6447ef0f88b50b97dc8fd9f20991d61) returned REVISE: one medium finding and three low ones. A blind fix job fixed all four in 1ea4d1fc, with the coordinator's leave for this one further change to scripts/compare_acola.py before the registered commit. No registered statistic changes, and every new test uses invented values.

  1. OACT footer (medium). 0a3299df's check refused whitespace before the final periods, such as the footer followed by " .", which the check at 6abb6726 accepted; its message and this body's footer row said any whitespace and final periods pass. oact_footer_matches now compares " ".join(footer.split()).rstrip(". ") with the registered footer. It refuses nothing the 6abb6726 check accepted, by enumeration over 95,400 invented footers against a copy of that check and by a property. Before the fix, the shortest regressions were a whitespace character followed by a period.
  2. Emitter monotonicity (low). The monotonicity property now also drives reference_benefit_rows itself, on invented cohorts built from public classes, under both exposure clocks and both benefit periods; dual entitlement is the labelled exception. Patching the emitter at run time to swap the worker paths, or to raise a sole widow(er)'s benefit under the cut, fails the property; raising a dually entitled spouse's excess, the intended exception, does not.
  3. Decimal context (low). Reading S's normalization runs at 50 digits whatever the caller's decimal context. Before the fix, an ambient precision below the stored double's significant digits miscounted its decimals. Side by side with the previous code at the default context, 300,048 vectors (every invented record and cell in test_compare.py, and 300,000 seeded random doubles, formats and HTML precisions) gave 0 differences.
  4. Decimal counts (low). decimal_count_mismatches checks each count the arithmetic uses against the decimals its value writes, trailing zeros included, and build_comparison refuses on a mismatch after the seal and sidecar checks and before any arithmetic, naming cells and fields only. Every whole invented record that passed still passes. Seven conversion-test fixtures pair a value with a count it does not write; as whole records they now refuse, and a test names each. A float value never matches; _load yields none.

At 1ea4d1fc's content, under an audit hook that counted every file open and process launch (it counted no process launch and refused no open):

  • tests/acola_track/test_compare.py: 160 passed, 2 deselected (the same two tests, which read files under data/external/; CI runs them);
  • tests/acola_track/test_statistics.py: 54 passed;
  • Black (79 columns), ruff and git diff --check: clean on the three changed Python files.

Both modules stay unit tier: unit gains 105 items (103 in test_compare.py, 2 in test_statistics.py) by a tier count before and after the edits, and the tier files change by that difference only.

Mechanism-L equivalence and provenance

  • Registered side. git worktree add --detach .equiv-dd222b9 dd222b9af926c773a0f92732e2d08be507793378 inside the clone. PYTHONPATH=$PWD/.equiv-dd222b9/src .venv/bin/python scripts/acola_mechanism_l_equivalence.py $PWD/.equiv-dd222b9 --output <scratch>.
    • An in-process rerun listed the 117 imported populace_dynamics files. All 117 resolve under the worktree's src and equal dd222b9's blobs.
  • Build side. The same script at 7cd45ee7 with PYTHONPATH=$PWD/src. It imports the same 117 files, byte-identical.
  • Result. Both outputs, and both in-process reruns, are byte-identical to tests/acola_track/mechanism_l_dd222b9.json:
    • output SHA-256 07c59d69544503f87b43e8be5df57f01d773f597aa52b8f4027f40f7f9cc87de;
    • 7 rows × 69 invented persons, 483 records;
    • script SHA-256 5d7eef14e1cd4556e7a6d4d28f3b43f3cb4c442a68ffa6569724b5a831ea7a27.
    • No REG18_MECHANISM_DRIFT. The golden file was not regenerated.
  • Worktree. Removed after the runs.
  • Provenance file. tests/acola_track/mechanism_l_dd222b9.provenance.json (SHA-256 504e60b5…) records the method, both commands, the registered and build commits, the output and script hashes, and the 117 imported files. It also keeps this replay's first-attempt runs (build side at a3806e56, the same output) and the stage-2 builder's earlier git archive export record verbatim (builder file SHA-256 b48fc549…).
  • Mechanism paths since dd222b9. git diff --name-status dd222b9 <master> over cola_track_a/, scenario_benefits.py, estimates/cola_age_profile.py, track_a_v2/, fra68_track/, ss/, claiming.py, engine/ and scripts/run_track_a_registered.py. At 2195258c, f8ffc7d9 and current master fe5ab5ab, it shows only two added files: engine/forward_earnings_s1_v1.py and ss/statutory_delayed_credit.py. No existing file changed.

Coordination (ruling 14)

Against #571, by hash only

Of the 37 paths this branch changes from 2195258c, 30 were byte-identical at #571's head f78efbc6 when this section was written, at 6abb6726. Seven differ. 0a3299df changes three of the 30 (scripts/compare_acola.py, tests/acola_track/test_compare.py and tests/acola_track/test_statistics.py), and the design note and tier files again; 1ea4d1fc changes those three, the design note and the tier files once more. For six, #571 holds the builder's version (checked against the builder's hash list) and this branch holds a commit above:

  • docs/design/acola_spec_only_nulls.json and src/populace_dynamics/acola_track/nulls.py (10c02653);
  • tests/acola_track/test_delayed_credit_disclosure.py (f02181e9);
  • docs/design/acola_trust_fund_implementation.md (dae71963, 6abb6726);
  • tests/tier_counts.json and tests/README-tiers.md (7cd45ee7).

The seventh is tests/acola_track/mechanism_l_dd222b9.provenance.json, which each branch wrote for itself.

🤖 Generated with Claude Code

MaxGhenis and others added 10 commits October 24, 2026 11:44
This commit replays 9de858d0eaf14df7affd5d4e810568a6d41584e9, the
stage-1 build of Registration 18 (A-COLA, decision d658), with
`git cherry-pick 9de858d0` onto origin/master 2195258. Stage 1's
parent, 75cd352, is 510 commits behind master.

Conflicts and how each was resolved:
- tests/tier_counts.json: kept master's version. Stage 1's counts
  were taken on its old base; the close-out recounts the tiers.
- tests/README-tiers.md: kept master's version, for the same reason.
- The exclusion tuple (POST_REVIEW_SOURCE_EXCLUSIONS) did not
  conflict: stage 1 did not edit it. The close-out appends the new
  src/ files to it.

The other 24 files of 9de858d0 are byte-identical to it (checked
blob by blob against 9de858d0's tree).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Stage 1's December note read "include December2030" and "determination
year2029". The note is prose in the committed nulls record, which the
second registration comment will cite, so it should read correctly.

- src/populace_dynamics/acola_track/nulls.py: the note now reads
  "December 2030" and "determination year 2029".
- docs/design/acola_spec_only_nulls.json: regenerated with
  scripts/build_acola_spec_only_nulls.py. Only the december_note line
  changes; every null value, exact rational, rate and input hash is
  unchanged.

tests/acola_track/test_nulls.py passes (17), including the check that
the committed file reproduces exactly from its pinned inputs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
scripts/compare_acola.py is the standard-library script the
validation-only lane runs after the run artifact merges and the seal
opens. It fetches nothing. This commit adds the stage-2 builder's file
unchanged (SHA-256 checked against the builder's hash list).

What it does, as read in the code:
- verify_seal hashes every file the seal lists (SHA-256 and byte
  count), refuses on any mismatch, missing file, path escape or an
  unlisted comparator record, and returns the seal's own SHA-256;
  compare_files then checks the artifact's SHA-256 against its
  .env.json sidecar before it parses the artifact.
- OACT: CL = p - d and C = 100 d / (p - d), with p and d each +/- half
  their last printed unit (from the record's decimal counts) and the
  interval over the four corners; p - d > 0 is asserted at every
  corner. The 0.10 precision gate is applied mechanically and its
  branch recorded.
- PWBM: C = 100 (R - B) / B; a point when both stored values carry six
  or more decimals, otherwise four corners.
- MINT5: reading S (shortest decimal of the stored double, shifted two
  places for a percent format) with half-up and half-even checks
  against the HTML's decimals; reading L as a sensitivity. The headline
  statistic follows the record's median_type; "unsettled" compares both.
- Gaps P - C, N - C, P - N and P - N_model per row (N_MINT, or M1's
  null, on the MINT5 rows) by [a,b] - [c,d] = [a-d, b-c], with the
  model's mean, draw SD and floor beside each. Decimal arithmetic at 50
  digits; decimals are written as JSON strings. No pass band, no
  verdict.

tests/acola_track/test_compare.py tests it on invented comparator
records in the acola-comparator-v1 schema and on the stage-1 invented
dry-run artifact layout. No comparator value is used anywhere.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The stage-2 addendum (section 3, item 3) requires showing that
mechanism L, the cola_track_a benefit path rows C0, C1 and M0-M4 use,
gives identical outputs on invented data at the build and at the
registration commit dd222b9. These
four files are the stage-2 builder's, unchanged (SHA-256 checked
against the builder's hash list):

- scripts/acola_mechanism_l_equivalence.py (SHA-256 5d7eef14...7a27)
  builds one fixed invented population (seed 20261024) and projection
  state, then runs the legacy reference_benefit_rows for every runnable
  A-COLA row and writes canonical JSON of each person's base, reform
  and component amounts. It imports only legacy interfaces that exist
  at both commits, and no acola_track code, so it runs against a
  dd222b9 checkout. The population includes every birth cohort
  1917-1942 claiming at 70, dually entitled spouses, DI and converted
  DI workers, a projected widow and each opening-stock component.
- tests/acola_track/mechanism_l_dd222b9.json is the golden output
  (SHA-256 07c59d69...87de): 69 persons on each of 7 rows.
- tests/acola_track/test_mechanism_l_equivalence.py reruns the script
  at HEAD and asserts byte equality, raising REG18_MECHANISM_DRIFT
  with the differing row/person ids otherwise; it also pins the
  script and golden hashes in the provenance record and checks that
  the script's rows equal the A-COLA registry's track_row() values.
- tests/acola_track/mechanism_l_dd222b9.provenance.json is the
  builder's record (SHA-256 b48fc549...9ed8). The builder's sandbox
  could not create the dd222b9 worktree, so it records a git-archive
  export instead. The next commit replaces it with the worktree run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The stage-2 addendum (section 3, item 4) asks for a test that stage 1's
Table V.C1 capture and master's data/tr2026 accessor give the same
intermediate COLA increases effective December 2027, 2028 and 2029.

tests/acola_track/test_tr2026_crosscheck.py is the stage-2 builder's
file, unchanged. It reads the three captured cells through
acola_track.nulls.tr2026_inputs(), which verifies the snapshot's pinned
hashes, and the same three years through
populace_dynamics.data.tr2026.cola_path(2027, 2029). It asserts the
determination years, December timing, the V.C1 source class and equal
percents as Decimals. It prints no other accessor value.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both files are the stage-2 builder's, unchanged; later commits in this
branch amend them.

tests/acola_track/test_delayed_credit_disclosure.py covers the
addendum's section 3, item 5. Mechanism L computes a retirement
claimant's factor with claiming.benefit_factor
(cola_track_a/benefits.py:345 at master 2195258 and at dd222b9). The
test takes the invented late claimants of the equivalence population,
one per birth year 1917-1942, claiming at 70, where 70 lies more than
48 months past FRA. For each it shows that worker_record's factor is
the 48-month factor, that the same people get a larger factor and
larger base and reform benefits when only the invented bundle's
max_delayed_months is raised to 60, and that 48 is SSAParameters'
default.

docs/design/acola_trust_fund_implementation.md maps every
Registration 18 element to its code and tests, states the invariants,
and holds the section "Disclosures for the second registration
comment": the interpretations (cleared brief section 1 item 2 and
rulings 4-16), the delayed-credit cap with the erratum and the d1408
diagnostic note, C0-D's deferral, and the TR 2026 capture's URL, file,
SHA-256, table, rows and column.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The builder's disclosure test shows the 48-month cap on an invented
parameter bundle and as SSAParameters' default. The disclosure is
about the registered run, whose parameters come from a policyengine-us
checkout, so the test did not yet show that the registered run carries
the same cap.

A registered run compares its runtime parameters with the committed
statutory capture and refuses any mismatch: run_acola raises when
cola_track_a.runner._parameter_consistency, which calls
statutory.statutory_value_checks, is inconsistent, and that check
covers max_delayed_months. The new test,
test_registered_parameter_binding_carries_the_48_month_cap, shows:
- the committed capture data/external/track_a_statutory_parameters.json
  and captured_ssa_parameters() both carry 48 months;
- the delayed-credit check passes for that bundle and fails for one
  with 60 months, so a registered run cannot carry another cap;
- under the committed FRA schedule, a claim at 70 by anyone born
  1917-1942 is more than 48 months past FRA, and benefit_factor at 70
  equals the factor at FRA + 48 months.

Test only; no source change. The disclosure file now passes 27 tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Edits to the stage-2 builder's design note:

- Header: cite the stage-2 brief's erratum and this blind replay's
  brief beside the cleared brief and the stage-2 addendum.
- Mechanism preservation: the builder could not create the dd222b9
  worktree and ran the registered side on a git-archive export, so its
  note listed the worktree run as outstanding. That run is now done:
  the dd222b9 worktree inside the clone, PYTHONPATH on its src, all 117
  imported modules resolving there, and output byte-identical to the
  golden file; the build side at a3806e5 also matches. The paragraph
  now says so, and keeps the builder's export as history. It also
  records that the dd222b9..origin/master path check gives the same
  result at f8ffc7d.
- Disclosure 17: "including late-entitled linked worker records" was
  imprecise. The text now names the two routes read in the code: the
  claimant's own worker record (benefits.py:345, the same line at
  dd222b9) and, on the aged widow(er) path, the deceased worker's
  factor, which widow_benefit_path receives as
  deceased_claim_age_factor and which passes delayed credits through
  (ss/benefits.py widow_benefit). It adds that a registered run carries
  the cap because it refuses parameters that differ from the committed
  capture (48 months; pinned by the previous commit's test), and gives
  the statutory window, 840 - FRA months: 60 at FRA 65, falling to 50
  for 1942 births, as the erratum states.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…iers

Housekeeping for the five new src files of Registration 18's build, as
the cleared builder brief's ruling 3 and the stage-2 addendum's item 6
require.

- scripts/first_estimates_birth_evidence.py: append the five
  acola_track files (__init__, config, nulls, runner, statistics) to
  POST_REVIEW_SOURCE_EXCLUSIONS, so the historical reducer's source
  identity does not change.
- tests/estimates/test_birth_evidence_artifact.py: the exact-tuple test
  lists the same five paths, and the reachability test asserts that the
  acola_track modules are collected but unreachable from the
  birth-evidence reducer.
  These two files are the stage-2 builder's versions, byte for byte.
- tests/tier_counts.json and tests/README-tiers.md: recounted with
  EV/merge-watchers/recount-tiers.py on this tree (empty PSID root).
  Base 2195258: unit 18,088, artifact 4,253, integration_psid 1,450,
  reproduction_legacy 520, oracle_policyengine 308, total 24,619.
  Now: unit 18,352, artifact 4,278, others unchanged, total 24,908.
  That is one unit item more than the builder's recount (24,907),
  from the delayed-credit parameter-path test added on this branch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The stage-2 builder's sandbox could not create a git worktree, so its
provenance record described a git-archive export of dd222b9's imported
sources and left the worktree run and the build-commit pin open. This
commit records those runs, made in this replay.

- Registered side: `git worktree add --detach .equiv-dd222b9 dd222b9`
  inside the clone; scripts/acola_mechanism_l_equivalence.py run with
  the clone's venv and PYTHONPATH on the worktree's src. An in-process
  rerun listed the 117 imported populace_dynamics files, all under the
  worktree's src, equal to dd222b9's blobs and to the builder's list.
- Build side: the same script at 7cd45ee with PYTHONPATH on the
  clone's src; the same 117 files, byte-identical.
- Both outputs, and both in-process reruns, are byte-identical to
  tests/acola_track/mechanism_l_dd222b9.json (SHA-256 07c59d69...,
  7 rows x 69 invented persons). Script SHA-256 5d7eef14... No
  REG18_MECHANISM_DRIFT; the golden file was not regenerated.
- The record keeps the builder's export record verbatim (file SHA-256
  b48fc549...) and notes the replay's first attempt, which made the
  same runs with the build side at a3806e5 before it stopped.
- The worktree is removed.

The design note's mechanism-preservation paragraph now names the build
commit 7cd45ee beside a3806e5.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
social-security-model Ready Ready Preview Nov 2, 2026 10:14am UTC

Request Review

Review r1b (Subfleet job 20261025-004712-mgf-f0b-review-r1b, report
SHA-256 01478a4bb3874e386ecd2ddc5c81df96975be3015d32b1836489a9257db5bbd9)
returned REVISE with one medium and three low findings. This commit
fixes all four. Every new test value is invented.

1. Reading S (medium). scripts/compare_acola.py now counts the stored
   decimals of Decimal(repr(double)).normalize(): the shortest decimal
   string that denotes the stored double, as the cleared builder brief
   defines reading S. The brief's worked formula, repr(float(raw)),
   writes an integral double with a trailing ".0" and counted it as one
   stored decimal, so an integral cell under a non-percent format could
   take the XLSX branch with an interval one tenth as wide as the HTML
   display's. Percent formats and non-integral doubles keep their
   counts. Tests: the reviewer's -17 example (format "0", HTML at 0 and
   at 1 decimal) and a property over invented shortest-form strings
   (count, value, branch, and S agreeing with L on the same counts).
   Before the fix, Hypothesis minimized its counterexample to the
   string "0" under a non-percent format: one decimal counted, none in
   the shortest form.
   The message of 4ff1fec described reading S as the shortest decimal
   of the stored double; the code it added counted repr's digits,
   ".0" included. The code now matches that description.
2. OACT footer (low). The footer check collapses whitespace runs,
   no-break spaces included, and drops final periods before comparing,
   so a transcribed ".\n", ". " or no-break space no longer refuses a
   matching footer. Tests: the reviewer's three cases and a property
   (any whitespace and up to two final periods pass; a changed word
   refuses). Before the fix the property's minimal counterexample was
   the footer followed by ". ".
3. Context count (low). Design note item 20 states both definitions:
   the mean over C0's draws of its S_base weight, and the TR 2026
   Table IV.B4 intermediate 2030 OASDI beneficiary cell times 1000. No
   scaling applies. Item 21 discloses the reading-S discrepancy and its
   resolution, citing review r1b; item 16 now names the normalization.
4. Tests of the statistics (low). The monotonicity property now asserts
   on the scenario code's own per-person 2030 output (old-age and DI
   workers, spouses and widow(er)s with no own record, so none dually
   entitled) under a larger cut and under an earlier first reduced
   year, and on P from those records. Its new name is
   test_larger_or_earlier_cut_weakly_lowers_p_and_every_benefit. The
   accounting property asserts that the OASI and DI shares sum to one
   and that the component totals reproduce T_s in each scenario.

tests/acola_track/test_statistics.py now carries its own copy of
invented_params, identical in body, so it no longer imports
tests/cola_track_a/test_assembly.py, which blind roles may not run.

Tier counts: both modules are unit tier; unit rises by 6 (18,352 to
18,358) and the total to 24,914, in tests/tier_counts.json and
tests/README-tiers.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
In 0a3299d, FOOTER_SPACES in tests/acola_track/test_compare.py holds a
thin space (U+2009) and a narrow no-break space (U+202F) as literal
characters, which read as two more plain spaces. This commit writes them
as " " and " ". The tuple's values do not change, and the
module passes as before (57 passed; the two tests that read files under
data/external/ deselected, as in 0a3299d).

Review r1b: Subfleet job 20261025-004712-mgf-f0b-review-r1b, report
SHA-256 01478a4bb3874e386ecd2ddc5c81df96975be3015d32b1836489a9257db5bbd9
(finding 2's property test).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review r2 (Subfleet job 20261101-155159-mgf-f0b-review-r2, report
SHA-256 6d9c9f8eb66104ef53dc0be3aa244e90b6447ef0f88b50b97dc8fd9f20991d61)
returned REVISE with one medium and three low findings. This commit
fixes all four. The coordinator gave leave for this one further change
to scripts/compare_acola.py before the registered commit. Every new
test value is invented, and no registered statistic changes.

1. OACT footer (medium). oact_footer_matches now compares
   " ".join(footer.split()).rstrip(". ") with the registered footer.
   Fix r1's check refused whitespace before the final periods, such as
   the footer followed by " .", which the check before it accepted.
   str.split() already splits on no-break spaces, so the .replace is
   gone. The new check refuses nothing that the check at 6abb672
   accepted. It also accepts any whitespace run between words other
   than one ASCII space, whitespace after a final period, and periods
   separated by whitespace. A changed, added, dropped or joined word
   still refuses. Tests: the case footer + " .", a gap before the
   periods in the property, the 6abb672 check copied as a reference
   and enumerated over 95,400 invented footers, a sweep of every
   character str.isspace accepts, and a Hypothesis property of the same
   claim. Before the fix, the shortest regressions were two-character
   suffixes: one whitespace character, then a period.
   The message of 0a3299d says its check drops final periods and that
   any whitespace passes; that check refused whitespace before the
   final periods.
2. Emitter monotonicity (low). A property now drives
   reference_benefit_rows on invented cohorts built from public classes,
   varying TrackAConfig.annual_reduction and
   RegisteredRow.first_reduced_determination_year under both exposure
   clocks and both benefit periods. Dual entitlement is the labelled
   exception: a spouse's or widow(er)'s excess paid beside an own
   worker benefit can rise under a cut. Two explicit examples run every
   time: a coverage cohort with every component, both bases and dually
   entitled people, and the same cohort without them, so P is checked.
   A separate test shows the coverage cohort reaches each of these.
3. Decimal context (low). Reading S's normalize() and scaleb() now run
   in localcontext at PRECISION. A test sets an ambient precision of 6,
   too small for the value, and a property varies the ambient precision
   from 1 to 28 digits and the rounding mode. Side by side with the
   previous code at the default context, 300,048 vectors (48 test
   records and cells, 300,000 seeded random doubles, formats and HTML
   precisions) gave 0 differences.
4. Decimal counts (low). decimal_count_mismatches(comparator) returns
   the (cell, field) locators where OACT's decimals, PWBM's
   stored_decimals or MINT's html_decimals differ from the decimals
   their value writes, trailing zeros included. build_comparison calls
   it after the seal and sidecar checks and before any arithmetic, and
   refuses on a mismatch, naming locators only. Every whole invented
   record that passed still passes. Seven conversion-test fixtures pair
   a value with a count it does not write; as whole records they would
   now refuse, and a test names each. A float value never matches, and
   _load yields none.

The design note's comparison paragraph and implementation map describe
the three checks; no disclosure item changes. Tier counts: both modules
stay unit tier; unit rises by 105 (18,358 to 18,463) and the total to
25,019, in tests/tier_counts.json and tests/README-tiers.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch was successfully deployed

1 active deployment
Preview — 1ea4d1fc Deployed Nov 2, 2026 by vercel[bot]
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.

1 participant