From 0e7a770618ddd33e93c470d5c496f1caf9b02071 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Fri, 23 Oct 2026 11:05:35 -0400 Subject: [PATCH 01/17] Let refusal exception notes be deleted again; register guard enums before first use #530's round-14 review found that the shared attribute writer treated deleting __notes__ as an assignment and read args[0], so removing a refusal's exception notes raised IndexError in G, R2, ARF and recomputation. Assignment keeps its list-of-strings check; deletion goes through the original __delattr__. A four-layer test adds and deletes notes and checks provenance and the denominator. Stateful constructors now register their declared enums before the first explicit call. Co-Authored-By: Claude Opus 5.5 --- src/populace_dynamics/track_b/_provenance.py | 9 +++- tests/test_track_b_refusal_notes.py | 56 ++++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 tests/test_track_b_refusal_notes.py diff --git a/src/populace_dynamics/track_b/_provenance.py b/src/populace_dynamics/track_b/_provenance.py index d5c3cae16..8a3caf6fb 100644 --- a/src/populace_dynamics/track_b/_provenance.py +++ b/src/populace_dynamics/track_b/_provenance.py @@ -520,6 +520,13 @@ def _checked_public_methods(cls): if cls not in _RESULT_TYPES and cls not in _DECLARATION_TYPES: _STATEFUL_TYPES.add(cls) + # Stateful constructors need their declared enum kinds before + # __new__ validates the first call's raw arguments. Lazy schema + # binding in __init__ would make explicit choices order dependent. + for annotation in get_type_hints( + cls.__init__, localns={cls.__name__: cls} + ).values(): + _register_annotation_enums(annotation) def guard(method, name): # Inherited wrappers belong to their declaring class. Rewrap the @@ -709,7 +716,7 @@ def checked(*arguments, **keywords): name.startswith("__") and name.endswith("__") ) if not private: - if name == "__notes__": + if name == "__notes__" and args: # BaseException.add_note installs a list, then appends # to that same list. Validate its complete schema while # preserving this caller-owned metadata's identity. diff --git a/tests/test_track_b_refusal_notes.py b/tests/test_track_b_refusal_notes.py new file mode 100644 index 000000000..9be2110b1 --- /dev/null +++ b/tests/test_track_b_refusal_notes.py @@ -0,0 +1,56 @@ +"""Statutory conformance: exception metadata on invented refusals only. + +Notes do not affect money, provenance or denominator accounting. No +population, behavioral or forecast claim is admitted. +""" + +import pytest +from hypothesis import given, settings +from hypothesis import strategies as st + +from populace_dynamics.track_b import gross_benefits as g +from tests.test_track_b_gross_benefits_fix_round_12_contract import ( + EVALUATE, + LAYERS, + _outcome, +) + + +@pytest.mark.parametrize("layer", LAYERS) +@settings(max_examples=10, deadline=None, derandomize=True) +@given(notes=st.lists(st.text(), min_size=1, max_size=4)) +def test_refusal_note_deletion_preserves_provenance_and_denominator( + layer, notes +): + refusal = _outcome(layer, refused=True).unsupported + for note in notes: + refusal.add_note(note) + assert refusal.__notes__ == notes + type(refusal).__delattr__(refusal, "__notes__") + assert not hasattr(refusal, "__notes__") + + def refuse(): + raise refusal + + row = EVALUATE[layer]("notes-deleted", 1, refuse) + assert row.unsupported is refusal + counts = g.count_family_outcomes((row,)) + assert counts.rows == counts.unsupported_rows == 1 + assert counts.unsupported_by_reason == {refusal.reason: (1, 1)} + refusal.add_note("new note") + assert refusal.__notes__ == ["new note"] + + +@pytest.mark.parametrize("layer", LAYERS) +@pytest.mark.parametrize("notes", ("not a list", [1], ("not a list",))) +def test_refusal_note_assignment_still_enforces_schema(layer, notes): + refusal = _outcome(layer, refused=True).unsupported + with pytest.raises(g.InvalidFamilyInput): + type(refusal).__setattr__(refusal, "__notes__", notes) + + +@pytest.mark.parametrize("layer", LAYERS) +def test_missing_refusal_notes_deletion_keeps_attribute_error(layer): + refusal = _outcome(layer, refused=True).unsupported + with pytest.raises(AttributeError): + type(refusal).__delattr__(refusal, "__notes__") From 57756aa18980d8b70f06fffd2c02877fa8e4287d Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Fri, 23 Oct 2026 11:05:35 -0400 Subject: [PATCH 02/17] G part 2 and R2 part (b): deduction before reduction; SSA's operational saving clause Max ruled d1802: the rules lane builds G part 2 (the operational saving clause, per d1338) and R2 part (b), which removes R2's deduction_before_reduction_part_b refusal. Deduction before reduction (Act 203(a)(4); GN 02603.020, .040, .050): - family_benefits_after_deductions and its household form take declared monthly deductions and apply the reduction for the maximum after them. Non-deductees share PTAP / (TOTOB - deductees' OBs), capped at OB and dime-floored. Temporary deductions leave separate households unchanged until permanent (GN 02603.050D, .090). - Supported reasons are an auxiliary's or survivor's own earnings-test deduction (full or partial, permanent or estimated), no child in care, and Parisi, which is unchanged through the new path. Workers' compensation, prisoner and drug-addiction suspensions, foreign work, penalty, maritime and election-certificate events are refused by name. - Reproduced: GN 02603.060 A.1, A.2, B.1, C.1, C.2 (and A.5, A.8, A.9, B.2 through the new path), RS 02501.130B and RS 02501.160 examples 1 and 2. 403(a)(5): SavingsClauseReading on the guard, with SSA_OPERATIONAL the default (RS 00630.400, RS 00615.801B.2) and LITERAL_REFUSAL the named alternative. Existing tests that pin the literal guard now select it. A fall not caused by a PIA increase starts no protection, and a COLA alone starts one only with an age-reduced beneficiary. Membership changes while a protection is active, and unsettled concurrent changes, are refused. R2 part (b): monthly RETFamilyMonth context lets an auxiliary's own deduction release maximum room to the others through the new G entry point. Final deductions flow to R3, and a delayed household increase creates no own-work credit. Missing family facts refuse as deduction_readjustment_requires_family_context. Two source readings are taken under the 2026-10-20 delegation and logged: partial temporary deductions follow RS 02501.160's worked example (us:oasdi-ret-temporary-partial-deduction), and protected equal rates round up to the least sufficient dime, as Act 203(a)(5) requires (us:oasdi-saving-clause-operational-rate-rounding). The brief asked for an absolute invariant that adding a deduction never lowers another beneficiary's rate. GN 02603.050A.1's "no other deduction" condition and .050C's age reserve make that false: a minimized PIA $48 case is pinned, and the invariant is stated as the rules allow. A cross-head harness shows 240 R2 and 240 downstream R3 results unchanged from master, and six rows that R2 refused now compute. Co-Authored-By: Claude Opus 5.5 --- docs/design/track_b_g_gross_benefits.md | 406 +++++++- docs/design/track_b_r2_ret_ledger.md | 285 +++-- scripts/track_b_r2_cross_head.py | 297 ++++++ .../track_b/gross_benefits.py | 980 ++++++++++++++++-- src/populace_dynamics/track_b/ret_ledger.py | 332 +++++- .../data/track_b/gross_benefit_examples.yaml | 799 +++++++++++++- .../track_b/gross_benefit_sources/README.md | 17 + .../gross_benefit_sources/manifest.json | 78 ++ tests/test_track_b_gross_benefits.py | 71 +- ...ack_b_gross_benefits_conformance_report.py | 20 +- .../test_track_b_gross_benefits_deductions.py | 564 ++++++++++ ...track_b_gross_benefits_fix_round_10_api.py | 51 +- ...k_b_gross_benefits_fix_round_10_helpers.py | 18 +- ...k_b_gross_benefits_fix_round_10_objects.py | 4 + ..._gross_benefits_fix_round_10_parameters.py | 12 +- ...ack_b_gross_benefits_fix_round_11_seals.py | 24 +- ..._b_gross_benefits_fix_round_12_contract.py | 12 +- ...ack_b_gross_benefits_fix_round_13_audit.py | 15 + ...ack_b_gross_benefits_fix_round_13_guard.py | 38 +- ...b_gross_benefits_fix_round_15_receivers.py | 8 +- ...rack_b_gross_benefits_fix_round_3_rates.py | 6 +- ...ck_b_gross_benefits_fix_round_5_cohorts.py | 6 +- ...ck_b_gross_benefits_fix_round_6_cohorts.py | 6 +- ...ck_b_gross_benefits_fix_round_7_cohorts.py | 6 +- ...ck_b_gross_benefits_fix_round_7_history.py | 6 +- ...ck_b_gross_benefits_fix_round_8_entries.py | 18 +- ...ck_b_gross_benefits_fix_round_8_history.py | 6 +- ...k_b_gross_benefits_fix_round_9_outcomes.py | 6 +- ...b_gross_benefits_fix_round_9_validation.py | 34 +- .../test_track_b_gross_benefits_properties.py | 20 +- tests/test_track_b_gross_benefits_registry.py | 82 +- tests/test_track_b_gross_benefits_review.py | 28 +- tests/test_track_b_gross_benefits_savings.py | 552 ++++++++++ ...track_b_gross_benefits_sources_20261011.py | 31 +- tests/test_track_b_input_schema.py | 15 +- tests/test_track_b_r3_fix_round_13.py | 27 + tests/test_track_b_ret_ledger.py | 62 +- tests/test_track_b_ret_ledger_deductions.py | 602 +++++++++++ tests/test_track_b_ret_ledger_sources.py | 19 +- tests/track_b_gross_benefit_support.py | 6 +- 40 files changed, 5248 insertions(+), 321 deletions(-) create mode 100644 scripts/track_b_r2_cross_head.py create mode 100644 tests/test_track_b_gross_benefits_deductions.py create mode 100644 tests/test_track_b_gross_benefits_savings.py create mode 100644 tests/test_track_b_ret_ledger_deductions.py diff --git a/docs/design/track_b_g_gross_benefits.md b/docs/design/track_b_g_gross_benefits.md index f4dbd7df3..4b5270722 100644 --- a/docs/design/track_b_g_gross_benefits.md +++ b/docs/design/track_b_g_gross_benefits.md @@ -543,8 +543,11 @@ adds that a saving clause, once established, "will continue in effect until the table or formula maximum becomes larger", and may become payable again. -G computes one month and does not compute the raise. It refuses instead. -`SavingsClauseGuard` carries the protection across one record's months: +The following describes the explicit `LITERAL_REFUSAL` alternative retained +from G v2. The default is now `SSA_OPERATIONAL`, implementing d1338 and the +RS 00630.400 procedures detailed in "Operational saving clause, October 23, +2026" below. `SavingsClauseGuard` carries the chosen reading across one +record's months: - **It protects the total of a qualifying month.** A qualifying month has two or more persons entitled, a binding maximum, and a higher PIA the next @@ -671,7 +674,9 @@ G never falls back to a single-worker computation. | `parisi_before_october_1999` | A binding maximum with dual entitlement before 10/99 | | `independently_entitled_divorced_spouse` | IEDS before January 1985 or a WEP-affected worker record before January 2024 (RS 00202.100) | | `non_aime_formula_pia` | Old-start, special-minimum and frozen-minimum PIAs (RS 00615.740B.1) | -| `savings_clause_403a5` | A governed month whose total fell below a 403(a)(5) protected total, and every later governed month | +| `savings_clause_403a5` | Under explicit `LITERAL_REFUSAL`, a governed month whose total fell below a 403(a)(5) protected total, and every later governed month | +| `savings_clause_membership_change` | Membership or record kind changes during a carried operational protection; the capture supplies no successor protection rule | +| `savings_clause_rate_procedure` | An operational raise needs an uncaptured survivor/dual/deduction/reduced-auxiliary allocation, a simultaneous age-factor change or declining FMAX prevents causal attribution, or the protected rate exceeds OB; the captured procedure does not settle these payments | | `savings_clause_history_unknown` | A month for which a protected total G cannot see may exist (a path not started at entitlement, or a month G did not compute) | | `widow_drc_savings_clause` | A May 1978 beneficiary protected from widow(er) deceased-worker DRC reductions (RS 00615.712) | | `widow_drc_savings_clause_history_unknown` | A widow(er) subject to the maximum has an OB that may include deceased-worker delayed credits, another beneficiary is subject to the maximum, and neither an explicit exclusion nor complete first-ever DIB history rules out May 1978 protection (RS 00615.712; .736B.2b) | @@ -2600,3 +2605,398 @@ to be a set cannot drop a condition between validation and construction. The existing `test_declaration_subclasses_cannot_override_constructor_validation` cases for `Beneficiary`, `WorkerRecord` and `RecordState` retain their original subclass assertions and additionally pin this changing-iterator attack. + +## Deduction before reduction + +Verification class remains statutory conformance on invented and published +cases. `family_benefits_after_deductions(state, beneficiaries, *, +payment_month, params, deductions, households, standalone, +worker_deductions=None)` and `household_benefits_after_deductions(records, +*, payment_month, params, deductions, households, worker_deductions=None)` +implement Act 203(a)(4), first sentence, and GN 02603.020/.040/.050. +Both return the existing sealed family or household result. `deductions` +is a dictionary keyed by beneficiary ID, with `BenefitDeduction(reason, +payable=0, permanent=True)` values. `payable` is an exact nonnegative +`Fraction` after the deduction. `households` maps beneficiary IDs to +nonempty household IDs for the month; every beneficiary must be supplied +when an event is temporary. Ordered beneficiary lists retain their order; +dictionaries retain associations. Types, enum identities and every raw +container entry follow the existing public schema. `worker_deductions` +optionally reserves the number holder's charges against auxiliaries; those +charges do not release room (GN 02603.040B; RS 02501.155B.3.c). + +| Configuration | Result | +|---|---| +| No deductions | Exactly the existing family or household result | +| Auxiliary or survivor own earnings deduction, full or partial | Supported | +| Permanent deduction | GN 02603.050C redistribution | +| Estimated own earnings deduction | Same-household increase; other households retain their previous rate | +| No child in care, full deduction | Supported for spouse or mother/father | +| Dual entitlement | Existing Parisi computation, including zero technical rates | +| Workers' compensation offset | `workers_compensation_offset` | +| Prisoner suspension | `prisoner_suspension` | +| Drug-addiction suspension | `drug_addiction_suspension` | +| Foreign work | `foreign_work_deduction` | +| Penalty | `penalty_deduction` | +| Maritime tax | `maritime_deduction` | +| Missing election certificate | `election_certificate_suspension` | +| Concurrent number-holder reservations and age reductions | `deduction_age_work_interaction` | +| Combined maxima; multiple auxiliary records | Existing named refusals remain | + +The computation first obtains the ordinary G maximum-adjusted rates and +Parisi deductees. For each non-deductee it removes permanent deductees and +same-household temporary deductees from the original-benefit denominator. +The numerator is the available maximum less the applicable deductees' +partial payables and age reductions. The resulting proportional share is +capped at the original benefit and dime-floored before age reduction. A +zero dual rate remains disregarded regardless of another deduction +(GN 02603.050A.2). Explicit dual markers must match the existing own-benefit +declaration and computed payable; they do not apply a second offset. + +`BeneficiaryBenefit.deduction` records the amount withheld from that row's +age-adjusted gross amount after its own-benefit offset, and +`deduction_reason` records the explicit event. For a number-holder partial +month, `reserved_work_deduction` preserves a non-deductee's prior NH charge +beside its resulting rate. R2 retains the NH amount in its ledger. Exact +partial payables and counted reserves can be fractions of a dime because +R2's pro-rata allocation precedes final whole-dollar check rounding. The +original and redistributed rates remain exact dime multiples. No-deduction +results have zero deduction and reserve fields. + +Fixed dual and outside-maximum beneficiaries still bear their NH charges. +Their gross rates stay fixed; their exact `deduction` equals their +`reserved_work_deduction`, with no qualifying `deduction_reason`. The +sealed result permits this equality explicitly. Subject dual payables +reserve the amount remaining after NH charging, because the same NH amount +is already in the global reserve. Outside-maximum NH deductions never enter +that reserve. An outside-maximum own-work event likewise releases no +subject maximum room (403(a)(3)(C); GN 02603.040B; RS 02501.155B.3.c). + +The R2 NH-reservation Hypothesis test covers two minimized counterexamples. +PIA $600/max $900, a spouse with own RIB $10 and two children gives ordinary +auxiliary rates $90/$105/$105. NH excess $600 leaves each auxiliary $60; +a child's own $30 deduction raises the other child to $90 and leaves the +spouse $60. A divorced spouse outside the maximum with three children has +ordinary rates $300/$100/$100/$100. NH excess $600 leaves each auxiliary +$100; one child's own $30 deduction leaves it $70 and raises the other +children to $115 each. The divorced spouse remains $100. Earlier draft +code refunded the fixed beneficiaries' NH charges and incorrectly included +the divorced spouse's NH charge in the subject pool. These were arithmetic +integration errors, not alternative statutory readings. + +Executed invariants in `test_track_b_gross_benefits_deductions.py` are: + +- `test_no_deductions_is_exact_family_and_household_differential`: exact + equality to ordinary G for both public forms, including Parisi families. +- `test_formula_bounds_monotonicity_households_order_and_determinism`: + non-deductee rates do not fall when the first own-earnings deduction is + added in the generated unreduced survivor families; rates do not exceed original benefits, + subject totals do not exceed the maximum, separate-household temporary + rates equal their prior rates, permanent rates equal GN 02603.050C, + determinism and order independence. Hypothesis varies PIA, family size, + partial amount and permanence. +- `test_unsupported_deductions_keep_named_denominator`: every named event + refusal remains in the denominator and invalid IDs are input errors. +- `test_fields_remain_sealed_and_exact`: fractional partial payables remain + exact and results cannot be constructed through their public class. +- `test_nh_partial_reservation_cannot_redistribute_original_rounding_slack`: + a partial NH month does not release the preexisting unused dime-rounding + balance. RS 02501.155B.3.c permits only the auxiliary's actual deduction + to increase the other auxiliaries' partial benefits. + +GN 02603.060 A.1 produces $182.80 for each child after E's full deduction; +A.2 caps E and C1 at $225.30; B.1 leaves E $37.20 and each child $170.40. +C.1 leaves separate-household C1 $137.10 while C2 and C3 receive $182.80. +C.2 keeps the zero dual C2 rate, pays C3 $225.30 and initially pays C1 +$182.80; permanence raises C1 to $225.30. Existing A.5, A.8, A.9 and B.2 +Parisi cases enter unchanged through the new path. A.6 and A.7 require +combined family maxima and remain refused by the declared lane scope. +Workers' compensation examples A.3, A.4 and B.3 remain refused. + +RS 02501.130's no-care months pay the children $83.50 each. +RS 02501.160's full month pays same-household C2 $132 while E and C1 remain +at $99; June's partial C3 payment of $39 gives C2 $119. At permanence E +and C1 receive the same $132 or $119 rates. The captures' original +benefits round upward: PIA $213.10 has quoted OB $159.90 and PIA $242.30 has +quoted spouse OB $121.20. G's post-1982 dime flooring instead yields +$159.80 and $121.10. Equal OB weights make every stated adjusted payment +identical; tests pin both quoted OBs and modern OBs rather than overriding +the arithmetic or claiming historical rounding coverage. The captures do +not date these examples or establish why they used upward rounding. + +### Readings needing judgment + +GN 02603.050D.2 says "there are no partial deductions for temporary work +deductions". RS 02501.160 Example 2 nevertheless instructs immediate +same-household redistribution in June with C3 $39 and C2 $119, while E and +C1 remain $99 until permanence. This implementation follows the explicit +payment example and the dispatch's authorization of estimated partial +amounts. The literal GN sentence would refuse that temporary partial case; +it would withhold C2's $20 June increase. The source assertions pin both +sentences. No switch invents a different benefit amount. + +The interaction of NH reservations and age reductions is not established +by a captured worked example. The implementation refuses that new mixed +configuration by name; ordinary G/R2 age-reduced supported inputs remain +unchanged. No population processing, combined maximum determination, +multiple auxiliary-record selection or annual earnings determination is +in scope here. + + +## Operational saving clause, October 23, 2026 + +Verification class: statutory conformance on invented cases and captured +SSA rules. This extension admits no population, behavioral or forecast +claim. Max's d1338 selects SSA's operational interpretation of 203(a)(5) +(42 U.S.C. 403(a)(5)); d1802 authorizes its implementation here. This section +supersedes earlier descriptions of the default as a refusal. + +### Declared interface and payment meaning + +`SavingsClauseGuard(first_month, *, earlier_months_unknown, +reading=SavingsClauseReading.SSA_OPERATIONAL)` takes an exact `YearMonth`, +a built-in Boolean, and a canonical enum. Its read-only `reading` accessor +returns that enum. `LITERAL_REFUSAL` retains the G v2 behavior, and all +existing tests of that reading select it explicitly. `admit` returns a +sealed `FamilyBenefits`, including a protected result when needed; +`evaluate` returns that result in a sealed outcome. Validation happens once +at each public boundary; provenance and integrity checks do not claim +freshness or caller attribution. + +`BeneficiaryBenefit.age_reduction_factor` retains the exact 402(q) +multiplier before money rounding (Fraction, zero through one). +`FamilyBenefits.worker_reduced_for_age` is a built-in Boolean derived from +the worker's declared reduction months; `worker_age_reduction_factor` stores +the exact Fraction multiplier and must agree with that flag. Rounded money cannot reconstruct +that factor or reliably identify an age reduction at very small amounts. +The established formula maximum, available room, proportional shares and +counted amounts do not change when the saving clause raises payment. +`age_adjusted_rate`, `auxiliary_payable`, and their exact and whole-dollar +totals contain the protected payment; the beneficiary note identifies it. +This implements RS 00630.400's statement: "The established FMAX will not +change—only total benefits payable are affected." + +### Conditions and supported procedures + +Under `SSA_OPERATIONAL`, the prior month must have two or more entitled +persons, a binding maximum, and at least one age-reduced beneficiary. The +next month's PIA must rise and its family total must fall. These are the +four requirements in RS 00630.400's "1972 Family Payment Saving Clause". +Membership and exact worker/auxiliary age factors must be unchanged for the supported +payment computation. A membership-driven decline starts no protection. +A simultaneous change of age factors or a declining formula maximum with +a qualifying overall fall refuses by name because the snapshots do not +isolate the PIA effect. For example, PIA/FMAX $100/$150 with an unreduced +worker, a spouse reduced 36 months and two children pays $145.60. PIA/FMAX +$101/$140 pays $136.70, but the PIA increase alone with FMAX $150 pays +$145.80. The simultaneous maximum decline is therefore not admitted as a +PIA-caused loss. +A later departure without a PIA increase starts no +protection. The guard carries an established protected total under RS +00615.801B.2, also retaining it while the ordinary formula payment overtakes +it because the source says it may become payable again. A change of +entitled identities, roles, worker entitlement or record kind during that +carried protection refuses, including later months after the change. + +| Configuration | Result | +|---|---| +| Life case, only the worker reduced for age, stable auxiliaries | Subtract the new worker rate from the protected family payment, divide by the number of auxiliaries and round to equal dime rates (RS 00630.400) | +| Life case, one reduced spouse and at least one other auxiliary | Divide the family-payment loss by the auxiliary count; apply the spouse's exact RF to that increase and add it to the spouse's ordinary reduced rate; divide the remaining protected amount after the new worker and spouse rates among the other auxiliaries (RS 00630.400) | +| No qualifying age reduction, no PIA increase, or no immediate fall | No operational protection starts | +| Later raw payment is below an established protection | Reapply the captured procedure without changing formula FMAX (RS 00615.801B.2) | +| Entitlement membership changes during carried protection | `savings_clause_membership_change`; the captured 1972 procedure does not say how protection survives the change | +| Survivor, own-benefit offset, deduction, multiple reduced auxiliaries, lone reduced spouse, simultaneous age-factor change or declining FMAX with a qualifying fall, or a protected rate above OB | `savings_clause_rate_procedure`; the captured life-case allocation does not settle these rates | +| Prior history is unknown or a skipped month may hide protection | `savings_clause_history_unknown`, retained in every denominator | +| Explicit literal alternative reaches any later lower governed total | Existing `savings_clause_403a5` refusal; the original broad interpretation remains testable | + +### Invented worked calculations and source integrity + +The capture contains a procedure, not worked dollar figures. These invented +calculations therefore make no claim that their figures are quoted SSA +examples. `test_operational_source_rules_are_quoted_from_captures` checks +every cited rule verbatim against the existing SHA-pinned RS 00630.400 and +RS 00615.801 captures; the original manifest test recomputes their SHA-256. + +1. Only worker reduced: PIA $1,000, FMAX $1,500, worker reduced 60 months + to $700, two children $250 each: $1,200 total. PIA rises to $1,010, + FMAX unchanged, worker $707 and children $245: $1,197. Protection pays + each child ($1,200 − $707)/2 = $246.50, restoring $1,200 exact and + $1,199 after separate whole-dollar floors. Formula FMAX stays $1,500. +2. Worker and spouse reduced: the same initial worker and FMAX, spouse + and two children receive $108.20, $166.60, $166.60: $1,141.40 total. + PIA $1,010 yields worker $707, spouse $106.10, children $163.30 each: + $1,139.70. Loss $1.70 divided by three rounds up to $0.60; the + spouse's 65 percent factor gives $0.39, floored to $0.30. Spouse + $106.40 leaves ($1,141.40 − $707 − $106.40)/2 = $164 per child. + Exact and whole-dollar totals are $1,141.40 and $1,141. +3. Rounding boundary: first case with PIA rising to $1,001 gives worker + $700.70. Equal protected children need $249.65 each; $249.70 each + pays $1,200.10. Rounding each down to $249.60 instead pays $1,199.90. + This ten-cent shortfall is the explicit reading question below. +4. The actual round-11 COLA witness is retained: survivor PIA $4.40, + formula maximum $6.60, two unreduced widows $2.40 each and a + mother/father $1.80, total $6.60. A 2.3 percent COLA yields PIA + $4.50, maximum $6.70, and shares $2.40, $2.40, $1.70: $6.50. + The operational age condition fails, so no protection starts; the + explicit literal reading refuses. There is no assertion that a COLA + alone cannot lower payment. + +### Executed invariants + +- Each reading starts on exactly its own declared conditions: + `test_both_readings_start_exactly_on_their_conditions` (Hypothesis). +- Protected supported payment is at least the protected total; equal-dime + rounding excess is strictly less than the number of remaining auxiliaries + times one dime. Formula FMAX and counted subject total remain unchanged: + the same property and the worker/spouse/rounding example tests. The + deterministic property also checks every protected rate against OB; the + carry property refuses a later lower PIA when its protected rate would + exceed OB (203(a)(4); the capture does not settle above-OB payment). +- Allocation and protection are deterministic and independent of beneficiary + order: `test_operational_is_deterministic_order_independent_and_sealed` + (Hypothesis). +- Carried protection can become payable again: + `test_operational_carries_and_can_become_payable_again` and Hypothesis + `test_operational_carry_membership_refusal_and_denominator_properties`. +- Every named operational refusal preserves the full row and weight: + `test_operational_named_refusals_stay_in_denominator` and the preceding + Hypothesis carry/membership/denominator property. +- Membership-driven declines without PIA increases start no protection: + `test_operational_child_departure_never_starts_without_pia_increase` and + Hypothesis `test_membership_declines_without_pia_increases_never_start_protection`. +- Concurrent changes of exact worker or auxiliary age factors cannot be + silently attributed to a PIA increase or silently treated as unprotected: + Hypothesis `test_simultaneous_basis_change_refuses_ambiguous_fall` + keeps each qualifying mixed-change fall as a named refusal. An improving + worker factor is included: PIA $100/RF60 gives $120; PIA $102/RF59 + gives $119.80, even though changing RF alone raises payment to $120.40. +- Invalid enum values and forged protected outputs are input errors: + `test_default_is_operational_and_literal_is_explicit` and + `test_operational_worker_reduction_protects_payment_not_maximum`. +- The literal alternative retains the original paths and denominator rules + in the pre-existing guard property suite, now explicitly selected. + +### Reading taken: the direction of the operational rounding + +This is the session's reading under Max's 2026-10-20 delegation, logged in +the source-conflict rulings as +`us:oasdi-saving-clause-operational-rate-rounding` (P1: the Act's "assure +... will not be less" fixes the direction the procedure leaves open). +The captured rate procedure says "Difference ÷ By the Number of Auxiliaries +(rounded) = Auxiliary Rate;" and "Difference ÷ the Number of Auxiliaries +Rounded = Increase." It does not state the direction. Act 203(a)(5) says +"smallest amount that would have been required in order to assure that +the total of monthly benefits payable on the basis of such wages and +self-employment income for any such subsequent month will not be less"; +ordinary modern rates under RS 00615.201 round down. The implementation +uses the smallest equal dime rates that meet the protected total (round +up), while still flooring the spouse's age-reduced increase. The boundary +above changes total payment by $0.20 versus flooring equal child rates, +and prevents a $0.10 shortfall. `LITERAL_REFUSAL` is the conservative +alternative when a protected raise would be required. No rounding choice +is hidden; the example and mutation check pin it. A carried protection that +would require an auxiliary rate above OB refuses with +`savings_clause_rate_procedure`: 203(a)(4) describes decreases, while the +captured .400 procedure does not state its OB cap. The minimized executed +case has PIA/maximum $0.40/$0.60, then $0.50/$0.60, then $0.10/$0.10, +a worker reduced 60 months and two children. Before this check the final +children would each receive $0.20 despite dime-rounded OB $0; that is now +an explicit refusal, not an admitted above-OB interpretation. + +RS 00615.801B.2 says "until the table or formula maximum becomes larger" +and immediately adds that "it is possible that the savings clause maximum +may again become payable". The guard retains its protected history through +an intervening larger ordinary payment and refuses membership changes +while that history is carried. This deliberately conservative membership +boundary may refuse a change during an otherwise dormant protection. +The invented case in +`test_operational_carry_membership_refusal_and_denominator_properties` +starts at PIA $1,000, maximum $1,500, a worker reduced for 60 months and +two children: January pays $1,200. February PIA $1,001 establishes the +$1,200 protected floor and pays $1,200.10 after rounding. March's maximum +$1,600 allows the ordinary $1,299.70, while the $1,200 floor and its +January origin remain recorded. Removing one child in April would allow +an ordinary $1,201.20, above that floor, but the dormant-history membership +boundary refuses it. Extinguishing the history in March would instead +admit that $1,201.20. The existing Hypothesis property executes this +boundary and preserves the refused row and weight in the denominator; +the source-quote test pins the complete "may again become payable" rule. + +### Deduction history and protected payment totals + +The saving-clause guard must inspect deduction metadata in both the current +and prior month. Deduction results retain a deductee's pre-offset +`age_adjusted_rate` while changing `auxiliary_payable` and other members' +maximum shares. Those rates therefore cannot establish an operational +family payment without an additional captured rule. Numeric `deduction` +and `reserved_work_deduction` count even when `deduction_reason` is absent +for an NH-only reservation. These fields remain part of each sealed result. + +Executed counterexample: January PIA $1,000, FMAX $1,500, a worker reduced +60 months to $700, and two children. One child's full permanent own-work +deduction leaves the other child $500; actual record payment is $1,200. +The deductee retains a diagnostic $250 age rate, making the pre-offset +saving-clause total $1,450. With PIA $1,010 and no deduction in February, +ordinary payment is $1,197. A guard looking only at February's deduction +flags formerly raised that payment to the spurious $1,450 floor. Candidate +protections now refuse as `savings_clause_rate_procedure` if either month +has a subject deduction. An already carried protection also refuses that +interaction even when the diagnostic pre-offset total is above its floor. +The uncertain history is retained for later months. A month with no active +or candidate protection still returns its genuine result unchanged. + +The existing Hypothesis +`test_operational_carry_membership_refusal_and_denominator_properties` +executes both historical and current-deduction controls, including this +$1,000 example. The gap belongs to RS 00630.400's uncaptured interaction +with GN 02603.050, not to input validity. No protected amount is inferred +from a diagnostic pre-offset total, and every refusal retains its row and +weight. Completing this combined payment procedure remains outside scope. + +### Not in scope + +No combined family maximum, multiple auxiliary records, survivor allocation +extension, unknown-history reconstruction, population application or +empirical claim is added by this saving-clause implementation. + +GN 02603.050A.1 expressly excepts a single full permanent deduction with +no other deduction: "disregard that beneficiary when distributing the +family maximum". Accordingly the implementation reserves no age reduction +for that one row. The invented regression +`test_single_full_permanent_exception_disregards_age_reduction` uses a +$400 PIA, $650 maximum and age-reduced spouse with two children. The children +receive $125 each. Blind application of C's age-reserve formula would retain +$20.90 and pay $114.50 each. This is an intended exception to the general +permanent-formula identity, rather than an alternate default interpretation. +The requested absolute non-deductee monotonicity invariant cannot hold +together with A.1 and C. A.1 says "and no other deduction is involved for +any beneficiary"; C includes "Age reduction amount for all workers or +deductees". Thus adding a second deductee ends the exception and restores +the first deductee's age reserve. The same test pins and property-tests +this intended discontinuity over integer scales 1 through 20. The +minimized invented case has PIA $48, maximum $78, a spouse reduced for 60 +months and three children. Baseline child rates are $7.50 and the spouse's +age reserve is $2.70. A full permanent spouse deduction pays the children +$10 each. Adding a child's $0.10 own deduction leaves that child $7.40 +and gives each other child floor(($30 − $2.70 − $7.40) / 2) = $9.90. +Extending the disregard despite the second deductee would instead pay +$11.30 each, but contradicts A.1's explicit no-other-deduction condition. +The $48 case was minimized on the original maximum/PIA ratio of 13/8, +with dime-aligned amounts and a $0.10 additional deduction, after reducing +the child count from five to three. This is a qualified invariant, not a +silently changed payment rule. +`test_all_dual_beneficiaries_do_not_gain_from_another_deduction` preserves +GN 02603.045's exclusion of dually entitled recipients from increases. + +`test_impossible_payable_precedes_statutory_refusal` property-tests the +input-before-coverage invariant in both new public forms: a payable plus +number-holder reservation above the original benefit is invalid even when +the record carries an otherwise refused workers' compensation offset. Such +an input creates no denominator row. Exact post-reduction bounds are checked +when the ordinary G computation admits that configuration. + +GN 02603.060 A.2's narrative says "That is $548.40 divided by 2 +individuals = 225.30." Its displayed formula correctly gives $274.20 +before the original-benefit cap of $225.30. The existing A.2 test pins the +literal narrative, raw quotient and capped payment side by side. This is +an omitted cap in the narrative, not an alternate arithmetic rule. diff --git a/docs/design/track_b_r2_ret_ledger.md b/docs/design/track_b_r2_ret_ledger.md index ca1436e55..fdfeaa7f8 100644 --- a/docs/design/track_b_r2_ret_ledger.md +++ b/docs/design/track_b_r2_ret_ledger.md @@ -1,14 +1,14 @@ -# Track B R2 (part a): the retirement earnings test ledger +# Track B R2: the retirement earnings test ledger **Verification class: statutory conformance. Admitted scope: retirement earnings test rule mechanics on invented record-years and published statutory worked examples. No population, behavioral or forecast claim.** -**Status: build-only, R2 rules revised 2026-10-14 after PR #528 review -rounds 1–6; shared input boundary revised 2026-10-18 for PR #530 round 15. -No real-data computation.** This is the -single-record ledger core. Deduction before reduction, which can change -the other beneficiaries' gross rates, remains part (b). +**Status: build-only, R2 part (b) revised 2026-10-23 following ruling +d1802; prior R2 review and the G v2 shared boundary remain in force. +No real-data computation.** The single-record ledger now calls G for +deduction-before-reduction readjustment when monthly statutory and +household inputs are supplied (Act 203(a)(4); RS 02501.155A.3–4). The approved Track B design, revision 3, defines R2 in §3.1 as the `apply_ret_year` ledger: entitlement, provisional suspension, final @@ -31,7 +31,8 @@ makes no Axiom or population conformance claim. `tests/test_track_b_ret_ledger_readings.py` checks the ledger money consequences and properties of simultaneous RIB/DIB readings; `tests/test_track_b_ret_ledger_sources.py` pins source bytes, quotations - and monetary worked examples. + and monetary worked examples; `tests/test_track_b_ret_ledger_deductions.py` + covers binding maximum readjustment, household timing and R3 credits. - Source helper: `tests/track_b_ret_ledger_support.py`. - Captures: `tests/data/track_b/ret_ledger_sources/`. The manifest records the URL, UTC retrieval time, byte count and SHA-256 of each capture, @@ -412,17 +413,19 @@ executes the property at computation, sealing and lookup; `test_ret_identity_slots_reject_string_enum_subclasses` covers each identity slot. This changes no apportionment for declared valid inputs. -The binding-survivor fixture now states its original no-care assumption -explicitly. Both `child_in_care=False` and the positive attestation -`child_in_care="cdb"` produce a $796.40 widow rate and $0 CDB auxiliary -rate, retain the entitled CDB's $750 original share, and refuse auxiliary -work as `deduction_before_reduction_part_b`. This is the paired -`test_binding_survivor_maximum_with_zero_rate_cdb_is_deferred_to_part_b`. -G v2 requires the child's identity for positive care; literal boolean -`True` is an input error, pinned by -`test_survivor_care_requires_child_identity_not_boolean_true`. -RS 00615.340's mother/father comparison does not increase this particular -widow rate. No statutory reading changed. +The binding-survivor fixture states its care facts explicitly. Both +`child_in_care=False` and `child_in_care="cdb"` produce a $796.40 widow +rate and $0 CDB auxiliary rate, retaining the entitled CDB's $750 original +share. Part (b) now computes widow excess $100: January final payable +$696.40/check $696 and provisional payable $0. The CDB remains at $0, +because GN 02603.050A.2 excludes a zero dual-entitlement rate regardless +of other deductions. No work deduction or ARF credit is attributed to the +CDB. `test_binding_survivor_maximum_with_zero_rate_cdb_computes_part_b` +executes both care assertions. The former claim that the CDB necessarily +regains room was too broad; technical entitlement still matters to the +separate NH partial-allocation rule. G still requires the child's identity +for positive care, and RS 00615.340's mother/father comparison does not +increase this widow's rate. ## Authority and inputs @@ -798,7 +801,7 @@ not a reconstruction of monetary RET under pre-1978 law. | Calendar record-year from 2000 with an available R1 year | Supported | Act 203(f); RS 02501.021B.6 | | Living RIB worker and spouse/divorced-spouse/child beneficiaries | Supported with the supplied G rates | RS 02501.095 | | Disability NH, or DIB/DWB/CDB elected payment months | Supported own-work exemption; RIB elections remain tested | RS 02501.021B.5.a | -| Deceased record and widow(er), mother/father or child own work | Supported without binding-maximum readjustment | RS 02501.095B.3 | +| Deceased record and widow(er), mother/father or child own work | Supported; binding readjustment requires monthly G facts | RS 02501.095B.3, .155A.3–4 | | Variable monthly rates and entitlement | Supported; twelve months retained | RS 02501.100B.1 | | Pre-1978 entitlement history | Supported for carried legal types and breaks; pre-1978 NSMs never consume initial grace | Act 203(f)(1)(E)'s first qualifying month after December 1977 | | DIB-only months between section 202 entitlements | Supported; preserve the previous section 202 type and its break, so only a genuinely different later section 202 type creates after-break eligibility | Act 203(f)(1)(E); 20 CFR 404.435(b)(2)-(3); RS 02501.030B.2 | @@ -815,7 +818,10 @@ not a reconstruction of monetary RET under pre-1978 law. | Requested prorated suspensions | `PRORATED_SUSPENSION` / `prorated_work_suspension` | RS 02501.100B.5, .120-.125 | | Requested deferred suspensions | `DEFERRED_SUSPENSION` / `deferred_work_suspension` | RS 02501.100B.4 | | Protested partial current-year suspension | `PROTEST_PARTIAL_SUSPENSION` / `protested_partial_work_suspension` | RS 02501.100B.3 requires a different provisional path | -| Auxiliary/survivor own deduction with a binding maximum and another entitled positive original share, including a zero payable rate | `DEDUCTION_BEFORE_REDUCTION` / `deduction_before_reduction_part_b` | Others may gain gross rate; RS 02501.155A.3-4, GN 02603 | +| Auxiliary/survivor own deduction with a binding maximum and complete monthly G facts | Supported full/partial permanent deductions and full estimated suspensions | Act 203(a)(4); RS 02501.155A.2–4; GN 02603.050C/D | +| Separate-household nondeductees | Final increases are paid; estimated increases wait unless in the worker's household | RS 02501.160; GN 02603.090 | +| Binding readjustment without monthly G facts | `FAMILY_CONTEXT_REQUIRED` / `deduction_readjustment_requires_family_context` | Reduced rates do not identify original age and dual-entitlement facts | +| NH reservation combined with auxiliary age reduction | G `deduction_age_work_interaction` | GN 02603.050C/D reserves both amounts; current captures do not settle the interacting reduced-rate derivation | | Two-record entitlement with actual or estimated excess | `TWO_RECORD_EARNINGS` / `excess_earnings_on_two_records` | RS 02501.145-.150 require coordinated records | | Noncovered foreign work | `FOREIGN_WORK` / `noncovered_foreign_work` | Act 203(c); 20 CFR 404.417-.418 | | Refusal of vocational rehabilitation | `VOCATIONAL_REHABILITATION` / `vocational_rehabilitation_refusal` | RS 02501.130 | @@ -823,13 +829,12 @@ not a reconstruction of monetary RET under pre-1978 law. | Unmarried purported deemed entitlement | `DEEMED_ENTITLEMENT_BASIS` / `deemed_entitlement_marriage_basis` | RS 02501.140's wording is broader than Act 203(b)(1)/20 CFR 404.420 | | Ordinary deemed adult CHILD with asserted marriage and age facts | `DEEMED_ENTITLEMENT_BASIS` / `deemed_entitlement_marriage_basis` | Act 203(b)(1)'s adult-child wording is broader than CFR .420's disabled-child basis | -The binding-maximum guard is conservative. This annual interface accepts -a record-month binding flag but does not reconstruct each beneficiary's -maximum membership from post-reduction rates. It therefore refuses an -own deduction with any other entitled positive original share, including -mixed divorced-spouse configurations where a later G-aware interface -could establish that no room is released. Part (b) must retain G's -`subject_to_family_maximum` metadata to narrow that coverage boundary. +The monthly G context establishes maximum membership, original age +reduction and dual entitlement. Its declared baseline must match the R2 +rates, original shares and binding flag. Missing contexts are named +coverage refusals; mismatched contexts are input errors. An earlier G +coverage refusal is held until every supplied month's consistency checks +finish, so later invalid inputs cannot enter a refusal denominator. Each coverage refusal is a `RETConfigurationUnsupported`, a subclass of G's `FamilyConfigurationUnsupported`, and has the common @@ -864,7 +869,7 @@ In the table, unqualified property test names are in | Invariant | Executing tests | | --- | --- | -| Per beneficiary-month, `gross = net_due + deduction`; both actual and provisional deductions lie between zero and gross; the check floors net | `test_every_month_conserves_exact_money_and_checks_are_floored`; `test_auxiliary_own_excess_uses_earliest_entitled_unprotected_months` | +| Per beneficiary-month, `gross = net_due + deduction`; both actual and provisional deductions lie between zero and their respective gross rates; the check floors net | `test_every_month_conserves_exact_money_and_checks_are_floored`; `test_auxiliary_own_excess_uses_earliest_entitled_unprotected_months` | | A worker's charged excess is capped by chargeable benefits; charged plus uncharged equals excess; final deductions attributable to that worker equal charged plus the undistributed residual; no charge exceeds excess | `test_exact_final_charges_are_excess_capped_by_chargeable_benefits`; `test_number_holders_excess_is_charged_before_auxiliarys_own`; `test_auxiliary_own_deductions_are_monotone_with_protected_months_fixed` | | Earlier chargeable months are exhausted before later months | `test_earlier_chargeable_months_are_exhausted_before_later_months`; `test_auxiliary_own_excess_uses_earliest_entitled_unprotected_months` | | Excess cannot carry between years | `test_excess_is_year_local_and_cannot_change_a_clean_later_year`; unit `test_uncharged_excess_does_not_carry_into_the_next_year` | @@ -979,14 +984,17 @@ the residual field never creates a standalone crediting event. `test_entitled_zero_rate_auxiliary_keeps_its_original_partial_share` executes that zero-cap result. This example keeps the zero cap in the allocation; the former complete-redistribution result is unavailable. -In a second G-generated survivor -record, PIA $1,000/max $1,500 gives a widow $796.40 and an entitled CDB -recipient $0 after a $650 own disability benefit, with originals $1,000 -and $750. Widow excess $100 must refuse for part (b): the CDB recipient -can gain family-maximum room despite the current zero payable rate. -`test_entitled_zero_rate_auxiliary_keeps_its_original_partial_share` -and `test_binding_survivor_maximum_with_zero_rate_cdb_is_deferred_to_part_b` -both failed against the restored early implementation before the fixes. +The second G-generated survivor counterexample is now computed by part +(b). PIA $1,000/max $1,500 gives a widow $796.40 and a technically +entitled CDB recipient $0 after a $650 own disability benefit, with +originals $1,000/$750. Widow age reduction is +`ceil_dime(1000 * 60 * .285 / 84) = 203.60`; widow excess $100 leaves +$696.40. GN 02603.050A.2 says to disregard the zero dual recipient +"regardless of other deductions that may apply for any other beneficiary +on record". The CDB stays $0. The remaining maximum room is unused; +there is no unsupported revival of its auxiliary benefit. Both care +variants execute in +`test_binding_survivor_maximum_with_zero_rate_cdb_computes_part_b`. ## Monetary worked examples @@ -1484,73 +1492,166 @@ as excluding any simultaneous RET deductee would instead refuse the example, not produce a different computed amount. This scope reading needs confirmation if the intended part-(a) boundary was broader. -## What part (b) needs from G +## Deduction before reduction and the G contract + +Act 203(a)(4) requires deductions before reduction for the maximum. +RS 02501.155A.1–2 first charges each working auxiliary or survivor's own +adjusted rate. Full deductees then leave the redistribution denominator; +partial deductees reserve their payable amount. G applies GN 02603.050C/D +and retained Parisi treatment. R2 charges NH excess first, then each +auxiliary's own excess, and submits the complete monthly event mapping +once all workers have been charged. Nonworkers alone receive readjustment. +This preserves statutory ordering and beneficiary order independence. -The current G entry point is: +The public monthly entry point is: ```python -family_benefits( +family_benefits_after_deductions( state: RecordState, beneficiaries: Sequence[Beneficiary], *, payment_month: YearMonth, params: SSAParameters, + deductions: Mapping[str, BenefitDeduction], + households: Mapping[str, str], standalone: bool, + worker_deductions: Mapping[str, Fraction] | None = None, ) -> FamilyBenefits ``` -It computes gross rates on the assumption that no deduction event has -changed available maximum room. Part (a) uses its monthly results and -refuses deduction-before-reduction cases. No G function is changed here. - -Part (b) needs an exact monthly entry point with the following proposed -contract, subject to the G lane's implementation: - -```python -family_benefits_after_deductions( - state, - beneficiaries, - *, - payment_month, - params, - deduction_events, - households, - standalone, -) -> FamilyBenefits -``` - -It must retain G's original metadata rather than accepting only reduced -rates: `RecordState` contains PIA, family maximum, worker/RIB-LIM and -eligibility facts; each `Beneficiary` retains original-share role, age -reduction, dual-entitlement and maximum-membership facts. The R2 input -rate alone cannot recover that information. - -For every deductee and month, `deduction_events` must identify the -beneficiary, reason, exact full or partial deduction and partial payable -amount, whether it is NH-wide or the beneficiary's own event, and -whether it is an estimated current-year suspension or an actual -closed-year permanent deduction. `households` must identify monthly -household membership, including any established historical configuration -needed for separate-household timing. `standalone` retains G's explicit -one-record assertion; two-record entitlement still needs the household -entry point rather than silent independent calculations. - -The new function must apply Act 203(a)(4)'s first sentence and GN -02603.050C/D, including the differing permanent and temporary formula -inputs, full and partial deductee treatment, capped readjusted original -benefits and retained G age/dual-entitlement order. It must return -recomputed rates for all beneficiaries and the room released by the -deductions, preserving exact arithmetic and G's refusal and validation -contracts. R2 then charges eligible workers against the appropriate -readjusted rates in the statutory order (RS 02501.130, .155). - -For separate households, increased amounts attributable to provisional -work deductions are delayed until the deductions become final, while -same-household increases can be paid sooner (RS 02501.160; GN -02603.090). The proposed contract must therefore preserve provisional -and final monthly states separately. Facility of payment itself ended -after December 1995 and is outside the supported payment years (GN -02603.075); it must not be restored from historical GN 02603.100 examples. +R2's `RecordYear.family_months` maps exact integer months to declared +`RETFamilyMonth(state, beneficiaries, params, households, standalone=True)` +values. Ordered beneficiaries accept tuple/list; household maps contain +nonempty built-in string identities. G/RET record kind, beneficiary IDs, +benefit types, original shares, rates and binding status must agree. +The nested declarations follow the shared single-validation boundary. +Computation uses G's private validated entry and privately constructs +owned `BenefitDeduction` declarations. G/RET provenance seals, canonical +enums, one refusal class per reason enum and denominator retention remain +in force. Evaluators still establish provenance, not attribution or freshness. + +Final own events use `OWN_EARNINGS_TEST`, their exact post-NH partial +payable and `permanent=True`. Provisional full-month suspensions use +`permanent=False`. `worker_deductions` carries deductions imposed on +auxiliaries for NH work: these amounts reserve maximum room and are not +redistributed. RS 02501.155B.3.c limits increases to the auxiliary's own +charge. G uses the pre-deduction allocated pool in this interaction so +preexisting dime-rounding slack cannot become an extra increase. + +NH charging is retained on fixed Parisi and outside-maximum beneficiaries. +The G adapter does not restore their pre-NH payables. Only subject NH +charges enter the maximum reserve, and a fixed dual payable reserves its +post-NH amount so the same charge is not counted twice. The NH property +also checks ordinary spouse $90/children $105/$105, then NH-partial +$60/$60/$60: one child's own $30 leaves it $30, the spouse $60 and the +other child $90. For an outside-maximum divorced spouse $300 and three +$100 children, NH excess $600 leaves $100 each; a child's own $30 leaves +it $70 and raises the other children to $115 while the divorced spouse +stays $100. Own work confined to the outside-maximum recipient changes +none of the children's rates. These explicit examples and generated own +excesses $1–$59 execute in the existing NH-reservation Hypothesis test. + +`BeneficiaryMonth` retains its prior declared shape for every previously +supported output. The new sealed `RedistributedBeneficiaryMonth` is used +only when final/provisional gross differs or reconstructed gross is an +exact non-dime amount after NH proration. It has an explicit +`provisional_gross`: final gross equals final net plus actual deduction; +provisional gross equals provisional net plus provisional deduction. +A delayed household increase is never mislabeled as a work deduction or +an ARF credit. Final credits alone flow to R3. + +### Worked cases and invariants + +RS 02501.160 gives PIA $213.10, maximum $396, original benefits $159.90, +four adjusted benefits $99 and C3 excess $555. Permanent charges are +$99 in January–May and $60 in June. C3 receives $0 then $39; the other +three receive $132 then $119. C2's January–May $33 increase is immediate +when it shares C3's household; E/C1's $33 increases wait for final +adjustment. Their final reconciliation is `5 * 33 + 20 = $185` each. +The source's original $159.90 is an upward dime rounding of its stated +PIA share; the capture does not date the example or establish why it used +that rounding. G's modern `floor_dime(213.10 * 3/4)` is $159.80. Both values are pinned +explicitly; equal original shares reproduce every listed payment exactly. +No altered PIA or unreported rounding override is used. + +`test_rs_02501_160_permanent_full_and_partial_months` and +`test_rs_02501_160_separate_household_increases_wait_for_final_deduction` +execute those results. Source quotes and figures are checked against the +listed capture in `test_track_b_ret_ledger_sources.py` and +`test_captured_original_rounding_and_worked_payment_figures_are_explicit`. +An invented .155A.2 case charges C1/C3 $99 each in January; February +partials are $48/$98 and the other two rates $125. An invented NH-partial +case has PIA $600/max $900, NH gross $600 and three $100 auxiliaries. +NH excess $600 leaves $120/$60/$60/$60; one auxiliary's own $30 charge +leaves $30 and raises the other two to $75 each, retaining their $40 NH +deductions (`test_rs_02501_155_nh_partial_month_preserves_nh_deductions`). + +The new executed invariants are: + +| Invariant | Executed test | +| --- | --- | +| No own deduction means identical old result fields/types, with or without G context | `test_property_unused_g_context_preserves_original_result_fields` | +| Actual and provisional deductions reconcile separately to charged/withheld worker totals | `test_property_readjustment_conserves_deductions_and_preserves_order` | +| In generated unreduced survivor families, nondeductees do not lose rates; they never exceed OB, gain deduction credits, or raise family payable over its maximum | Same property | +| Separate-household temporary amounts retain the original $99 rate | Same property and separate-household worked case | +| Result amounts are deterministic and beneficiary order independent | Same property | +| Actual positive deductions alone supply crediting months | Same property and `test_readjusted_deductions_flow_to_r3_without_household_delay_credits` | +| Multiple workers are charged before their common monthly redistribution | `test_rs_02501_155_multiple_workers_charge_before_redistribution` | +| NH work retains its charge and cannot release room | NH-partial worked case | +| Invalid later context precedes an earlier G coverage refusal | `test_later_family_input_error_precedes_earlier_g_coverage_refusal` | + +Absolute non-deductee monotonicity does not extend across GN .050A.1's +single-full-deduction exception: adding a second deductee restores the +age reserve required by GN .050C and can lower other rates. G's +`test_single_full_permanent_exception_disregards_age_reduction` pins the +minimized PIA $48/MAX $78 example, where the other children's rates fall +from $10 to $9.90 after a child's $0.10 deduction. The G note and final +report give the exact source conditions and derivation. + +### Reading taken: temporary partial payment wording + +This is the session's reading under Max's 2026-10-20 delegation, logged in +the source-conflict rulings as `us:oasdi-ret-temporary-partial-deduction`: +G follows RS 02501.160's explicit worked example (the specific case over +GN 02603.050D.2's general statement), and R2 keeps its full-month +provisional suspension, refusing the partial provisional path by name. + +GN 02603.050D.2 says: "The worker's rate will always be $0.00 because +there are no partial deductions for temporary work deductions." +RS 02501.160 Example 2 nevertheless gives June C3 "$ 39", C2 "$119" +and says the extra "$20" is immediate while E/C1 wait until permanent. +R2 retains its existing full-month estimated suspension (GN .050D.2): +June C3 provisional $0, same-household C2 $132; final C3 $39/C2 $119. +The .160 partial illustration instead pays C3 $39/C2 $119 provisionally, +a difference of +$39/−$13 for those two people. G directly reproduces the +published partial-payable illustration. Selecting an administrative +partial-suspension path in R2 remains a named +`protested_partial_work_suspension` refusal rather than silently changing +the existing estimated ledger. Admitting provisional partial payments +into R2 would be a further reading, not taken here. + +Facility of payment ended after December 1995 (GN 02603.075) and remains +outside supported R2 payment years. Two-record charging, combined maxima, +multiple auxiliary records and other deduction events remain refused. + +## Part (b) differential and mutation evidence + +`scripts/track_b_r2_cross_head.py --baseline-root ` +compares every declared field and result type at zero tolerance. The pinned +seed 53014 reproduces 240 previously supported R2 ledgers and their 240 +same-record R3 RIB computations byte for byte. Canonical output SHA-256 is +`799fc9e23a902ac1ca0c2563579ceb094d0dbcd631a912305c40062cf21a5f55`. +Six binding conformance inputs, with own excess $1/$60/$99/$100/$555/$1,188, +all move from `deduction_before_reduction_part_b` to supported; none move +to another refusal. Both source trees are local and both subprocesses set +the staged-data roots to nonexistent paths. + +Three isolated one-line R2 mutations were killed and then restored: +dropping the redistributed payable failed the .160 permanent example; +marking temporary events permanent failed separate-household timing; +dropping NH reservations failed the NH-partial example. Identical selected +tests passed after each restoration. The final lane verification artifact +records commands, counts, hashes and the back-to-back cost comparison. ## Build verification @@ -1738,7 +1839,7 @@ optimization (RS 02501.070). The ledger does not implement requested suspension prorating or deferral, protested partial current-year withholding, two-record excess -charging, deduction before reduction, household readjustment timing, +charging, other deduction-event readjustment, Medicare premiums, overpayment collection, ARF calculation, DRCs, recomputation, or monthly assembly I. It reports estimated-versus-actual check differences and actual deduction months so later milestones can diff --git a/scripts/track_b_r2_cross_head.py b/scripts/track_b_r2_cross_head.py new file mode 100644 index 000000000..fa3b1c3e7 --- /dev/null +++ b/scripts/track_b_r2_cross_head.py @@ -0,0 +1,297 @@ +"""Statutory conformance: exact R2/R3 cross-head invented-input diagnostic. + +No population, behavioral, or forecast claim. Compare every declared field +and type of 240 supported R2 ledgers and their same-record R3 RIB results. +Six separate binding survivor cases measure coverage movement. The baseline +is an existing local source tree; this script never fetches or edits it. + +Run with PYTHONPATH=src:. python scripts/track_b_r2_cross_head.py +--baseline-root --output . +""" + +from __future__ import annotations + +import argparse +import dataclasses +import hashlib +import json +import os +import random +import subprocess +import sys +import tempfile +from collections.abc import Mapping +from datetime import date +from enum import Enum +from fractions import Fraction as F +from pathlib import Path + +from populace_dynamics.track_b import arf as a +from populace_dynamics.track_b import gross_benefits as g +from populace_dynamics.track_b import ret_ledger as r +from populace_dynamics.track_b.ret_grace import BenefitType as T +from populace_dynamics.track_b.ret_params import load_ret_parameters +from tests.track_b_gross_benefit_support import ssa_params + + +def encode(value): + if dataclasses.is_dataclass(value): + return { + "type": type(value).__name__, + **{ + f.name: encode(getattr(value, f.name)) + for f in dataclasses.fields(value) + }, + } + if isinstance(value, F): + return [value.numerator, value.denominator] + if isinstance(value, Enum): + return [type(value).__name__, value.value] + if isinstance(value, Mapping): + return {str(k): encode(v) for k, v in sorted(value.items())} + if isinstance(value, (tuple, list)): + return [encode(v) for v in value] + if isinstance(value, (set, frozenset)): + return sorted( + (encode(v) for v in value), + key=lambda x: json.dumps(x, sort_keys=True), + ) + if isinstance(value, date): + return value.isoformat() + return value + + +def _dump(path): + params = load_ret_parameters() + ssa = ssa_params() + months = frozenset(range(1, 13)) + exempt = params.for_year(2026).lower_exempt_amount.value + random_source = random.Random(53014) + + def person(key, rate, original, kind, excess=0, estimate=None, fra=None): + def work(n): + annual = exempt + 2 * n if n else 0 + return r.WorkEarnings((F(annual),) + (F(0),) * 11) + + return r.RETBeneficiary( + key, + (kind,) * 12, + months, + (F(rate),) * 12, + (F(original),) * 12, + earnings=work(excess), + estimated_earnings=None if estimate is None else work(estimate), + fra_month=fra, + ) + + def evaluate(record): + try: + ledger = r.apply_ret_year(record, params) + except g.FamilyConfigurationUnsupported as error: + return {"refusal": error.reason.value} + if record.kind is r.RecordKind.DECEASED: + return {"ledger": encode(ledger)} + credits = frozenset( + g.YearMonth(2026, m) for m in ledger.crediting_months[record.nh_id] + ) + arf = a.apply_arf( + a.ARFClaim( + a.ARFBenefitKind.RIB, + date(1960, 1, 2), + g.YearMonth(2022, 1), + F(1300), + full_work_deduction_months=credits, + ), + payment_month=g.YearMonth(2027, 1), + params=ssa, + ) + return {"ledger": encode(ledger), "arf": encode(arf)} + + stable = [] + for index in range(240): + nh_rate = F(random_source.randint(1, 12000), 10) + people = [ + person( + "nh", + nh_rate, + nh_rate, + T.RIB, + random_source.randint(0, 15000), + random_source.randint(0, 15000), + fra=0 if index % 11 == 0 else None, + ) + ] + for aux in range(index % 4): + original = F(random_source.randint(1, 6000), 10) + rate = F(random_source.randint(0, int(original * 10)), 10) + kind = (T.SPOUSE, T.CHILD, T.CDB, T.DIVORCED_SPOUSE)[ + (index + aux) % 4 + ] + people.append( + person( + f"a{aux}", + rate, + original, + kind, + random_source.randint(0, 3000), + random_source.randint(0, 3000), + ) + ) + stable.append( + evaluate(r.RecordYear(2026, "nh", beneficiaries=tuple(people))) + ) + + transitions = [] + for excess in (1, 60, 99, 100, 555, 1188): + state = g.RecordState( + g.FamilyKind.SURVIVOR, F("213.10"), F(396), eligibility_year=2026 + ) + beneficiaries = (g.Beneficiary("e", g.Role.MOTHER_FATHER),) + tuple( + g.Beneficiary(k, g.Role.CHILD) for k in ("c1", "c2", "c3") + ) + family = g.family_benefits( + state, + beneficiaries, + payment_month=g.YearMonth(2026, 1), + params=ssa, + standalone=True, + ) + rows = {b.beneficiary_id: b for b in family.beneficiaries} + people = tuple( + person( + k, + rows[k].auxiliary_payable, + rows[k].original_benefit, + T.MOTHER_FATHER if k == "e" else T.CHILD, + excess if k == "c3" else 0, + ) + for k in rows + ) + keywords = {} + if hasattr(r, "RETFamilyMonth"): + context = r.RETFamilyMonth( + state, beneficiaries, ssa, {k: "one" for k in rows} + ) + keywords["family_months"] = {m: context for m in months} + record = r.RecordYear( + 2026, + "nh", + r.RecordKind.DECEASED, + people, + family_maximum_binding_months=months, + **keywords, + ) + transitions.append(evaluate(record)) + path.write_text( + json.dumps( + {"stable": stable, "transitions": transitions}, + sort_keys=True, + separators=(",", ":"), + ) + ) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--baseline-root", type=Path) + parser.add_argument("--output", type=Path) + parser.add_argument("--dump", type=Path, help=argparse.SUPPRESS) + args = parser.parse_args() + if args.dump is not None: + expected = Path(os.environ["TRACK_B_CROSS_HEAD_ROOT"]) + assert Path(r.__file__).is_relative_to(expected / "src") + _dump(args.dump) + return + if args.baseline_root is None: + parser.error("--baseline-root is required") + baseline = args.baseline_root.resolve() + root = Path(__file__).resolve().parents[1] + script = Path(__file__).resolve() + with tempfile.TemporaryDirectory( + prefix=".trackb-r2-cross-head-", dir=root + ) as temporary: + values = {} + for name, source_root in (("baseline", baseline), ("head", root)): + destination = Path(temporary) / f"{name}.json" + environment = { + **os.environ, + "PYTHONPATH": f"{source_root / 'src'}:{source_root}", + "POPULACE_DYNAMICS_PSID_DIR": str(root / ".no-real-data"), + "POPULACE_DYNAMICS_EPUF_DIR": str(root / ".no-real-data"), + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "TRACK_B_CROSS_HEAD_ROOT": str(source_root), + } + subprocess.run( + [sys.executable, str(script), "--dump", str(destination)], + cwd=source_root, + env=environment, + check=True, + ) + values[name] = json.loads(destination.read_text()) + + def canonical(value): + return json.dumps( + value, sort_keys=True, separators=(",", ":") + ).encode() + + before = canonical(values["baseline"]["stable"]) + after = canonical(values["head"]["stable"]) + if before != after: + raise AssertionError( + "Previously supported R2/R3 declared output bytes differ" + ) + transitions = {} + for name, document in values.items(): + rows = document["transitions"] + refused = {} + for row in rows: + if "refusal" in row: + refused[row["refusal"]] = refused.get(row["refusal"], 0) + 1 + transitions[name] = { + "rows": len(rows), + "supported": sum("ledger" in row for row in rows), + "refused_by_reason": refused, + } + report = { + "verification_class": "statutory conformance", + "scope": "invented cases only; no population, behavioral or forecast claim", + "seed": 53014, + "r2_stable_rows": len(values["head"]["stable"]), + "r3_stable_rows": sum( + "arf" in row for row in values["head"]["stable"] + ), + "identical_declared_output_bytes": True, + "stable_sha256": hashlib.sha256(after).hexdigest(), + "transitions": transitions, + "transition_rows": [ + { + "id": f"binding_survivor_own_excess_{excess}", + "own_excess": excess, + "baseline": ( + "supported" + if "ledger" in before_row + else before_row["refusal"] + ), + "head": ( + "supported" + if "ledger" in after_row + else after_row["refusal"] + ), + } + for excess, before_row, after_row in zip( + (1, 60, 99, 100, 555, 1188), + values["baseline"]["transitions"], + values["head"]["transitions"], + strict=True, + ) + ], + } + rendered = json.dumps(report, indent=2) + "\n" + if args.output is not None: + args.output.write_text(rendered) + print(rendered, end="") + + +if __name__ == "__main__": + main() diff --git a/src/populace_dynamics/track_b/gross_benefits.py b/src/populace_dynamics/track_b/gross_benefits.py index a0074b88e..16addf5c2 100644 --- a/src/populace_dynamics/track_b/gross_benefits.py +++ b/src/populace_dynamics/track_b/gross_benefits.py @@ -3,7 +3,9 @@ Verification class: statutory conformance (Track B design revision 3, §3.2 row G). Success admits gross monthly benefits for the supported family configurations below, and nothing else: no population claim, no payment -timing, no earnings-test deductions (R2), no ARF or recomputation (R3). +timing, no annual earnings or charge determination (R2), and no ARF or +recomputation (R3). The deduction entry points apply caller-declared monthly +deductions before redistributing the maximum (203(a)(4)). Max's ruling d515 (2026-09-28) adopted §10 question 9's default: a Python reference now, with Axiom differential checks as diagnostics once a pinned rule exists. At this module's creation rulespec-us had no 42 U.S.C. 403 @@ -106,10 +108,11 @@ dime multiple; 215(g) rounds each monthly benefit down to a whole dollar. Gross means before 203(b) earnings-test deductions and the 1840(a)(1) Medicare premium; 215(g) rounds after those, so the whole-dollar gross - here is not a net check. Gross rates assume no beneficiary on the record - has a deduction or suspension: 203(a)(4) makes the maximum reduction - after deductions, so a deduction can raise the others' rates (POMS RS - 00615.766). That ordering belongs to the RET ledger (R2). + here is not a net check. The ordinary entry points assume no declared + deduction or suspension. The after-deductions entry points implement + 203(a)(4): deductions can raise the other beneficiaries' rates (POMS + RS 00615.766; GN 02603.050C-D). R2 determines the monthly charges and + carries the resulting rates through its annual ledger. Which record and PIA to supply. The family maximum is computed once, from the PIA for the year of first eligibility before COLAs (RS 00615.736A.1), @@ -221,13 +224,16 @@ subject to the maximum, require the explicit False attestation or a known first-ever DIB date after May 1978, in both built and direct snapshots. -Not implemented, and refused rather than approximated: 403(a)(5). When two -or more persons are entitled for a month in which the maximum reduces -benefits, and the PIA rises for the next month, that month's total (after -403(a) and 402(q)) is protected for every later month. G computes one -month at a time. :class:`SavingsClauseGuard` carries the protected total -across one record's months and refuses any later governed month whose total -falls below it, and every governed month after that one. +The default 203(a)(5) reading follows SSA's operational procedure (d1338; +RS 00630.400): a qualifying prior month needs a binding maximum, two or +more entitled persons and an age reduction; the next month's PIA increase +must itself lower family payment. SavingsClauseGuard computes the protected +life-case rates, without changing formula FMAX, and carries the protection +under RS 00615.801B.2. Active-protection membership changes and payment +procedures not settled by the capture refuse by name. The explicit +SavingsClauseReading.LITERAL_REFUSAL switch retains the earlier broad +cross-month refusal reading. Both readings preserve unknown-history refusals. + """ from __future__ import annotations @@ -235,7 +241,7 @@ import math from collections import Counter from collections.abc import Callable, Iterable, Mapping, Sequence -from dataclasses import dataclass, field +from dataclasses import dataclass, field, fields from datetime import date from decimal import Decimal from enum import Enum @@ -282,6 +288,8 @@ "Beneficiary", "BeneficiaryBenefit", "BeneficiaryCondition", + "BenefitDeduction", + "DeductionReason", "FamilyBenefits", "FamilyConfigurationUnsupported", "FamilyDenominator", @@ -297,6 +305,7 @@ "RecordState", "Role", "SavingsClauseGuard", + "SavingsClauseReading", "StatutoryRates", "UnsupportedReason", "WorkerRecord", @@ -309,10 +318,12 @@ "disability_family_maximum", "evaluate_family", "family_benefits", + "family_benefits_after_deductions", "family_maximum_bend_points", "family_maximum_formula", "floor_dime", "household_benefits", + "household_benefits_after_deductions", "household_month_outcome", "increase_by_colas", "original_benefit", @@ -425,6 +436,8 @@ class UnsupportedReason(Enum): MULTIPLE_AUXILIARY_RECORDS = "multiple_auxiliary_records" SAVINGS_CLAUSE = "savings_clause_403a5" SAVINGS_CLAUSE_HISTORY_UNKNOWN = "savings_clause_history_unknown" + SAVINGS_CLAUSE_MEMBERSHIP_CHANGE = "savings_clause_membership_change" + SAVINGS_CLAUSE_RATE_PROCEDURE = "savings_clause_rate_procedure" WIDOW_DRC_SAVINGS_CLAUSE = "widow_drc_savings_clause" WIDOW_DRC_SAVINGS_CLAUSE_HISTORY_UNKNOWN = ( "widow_drc_savings_clause_history_unknown" @@ -437,6 +450,13 @@ class UnsupportedReason(Enum): DELAYED_CREDITS_BEFORE_1917 = "delayed_credits_born_before_1917" OWN_RIB_HISTORY_BEFORE_1978 = "own_rib_history_before_1978" REDUCED_BENEFIT_HISTORY_BEFORE_1978 = "reduced_benefit_history_before_1978" + PRISONER_SUSPENSION = "prisoner_suspension" + DRUG_ADDICTION_SUSPENSION = "drug_addiction_suspension" + FOREIGN_WORK_DEDUCTION = "foreign_work_deduction" + PENALTY_DEDUCTION = "penalty_deduction" + MARITIME_DEDUCTION = "maritime_deduction" + ELECTION_CERTIFICATE_SUSPENSION = "election_certificate_suspension" + DEDUCTION_AGE_WORK_INTERACTION = "deduction_age_work_interaction" @_sealed_refusal(UnsupportedReason) @@ -2212,6 +2232,57 @@ def record_state(record: WorkerRecord, params: SSAParameters) -> RecordState: ) +class DeductionReason(Enum): + """Canonical GN 02603.040 deduction events; unknown reasons are invalid.""" + + OWN_EARNINGS_TEST = "own_earnings_test" + NO_CHILD_IN_CARE = "no_child_in_care" + DUAL_ENTITLEMENT = "dual_entitlement" + WORKERS_COMPENSATION = "workers_compensation" + PRISONER_SUSPENSION = "prisoner_suspension" + DRUG_ADDICTION_SUSPENSION = "drug_addiction_suspension" + FOREIGN_WORK = "foreign_work" + PENALTY = "penalty" + MARITIME = "maritime" + ELECTION_CERTIFICATE_SUSPENSION = "election_certificate_suspension" + + +@_declared_input +@dataclass(frozen=True) +class BenefitDeduction: + """One month's deduction, keyed externally by beneficiary ID. + + ``payable`` is the exact nonnegative amount after deduction, not + earnings or the amount withheld. Zero means a full deduction. Estimated + own-work deductions have ``permanent=False``; all other supported events + are permanent. Dual entitlement is already declared by ``OwnBenefit``; + an explicit marker must agree with the ordinary G payable. + """ + + reason: DeductionReason + payable: Fraction = Fraction(0) + permanent: bool = True + + def __post_init__(self): + _input_type(self.reason, DeductionReason, "deduction reason") + _input_type(self.permanent, bool, "permanent") + object.__setattr__(self, "payable", _exact(self.payable, "payable")) + if self.payable < 0: + raise InvalidFamilyInput("payable must be nonnegative") + if self.reason is not DeductionReason.OWN_EARNINGS_TEST: + if not self.permanent: + raise InvalidFamilyInput( + "Only own-work deductions may be temporary" + ) + # Source conflict us:oasdi-ret-temporary-partial-deduction: a + # temporary own-work deduction may be partial (RS 02501.160 example + # 2), although GN 02603.050D.2 says temporary deductions never are. + if self.reason is DeductionReason.NO_CHILD_IN_CARE and self.payable: + raise InvalidFamilyInput( + "No-child-in-care deductions must be full" + ) + + # --------------------------------------------------------------------------- # Results # --------------------------------------------------------------------------- @@ -2235,6 +2306,12 @@ class BeneficiaryBenefit(_SealedResult): identifies it and the alternate care-exempt intermediate rate. * ``auxiliary_payable``: paid on this record after 402(k)(3)(A). * ``own_benefit``: the own RIB/DIB paid on the person's own record. + * ``reserved_work_deduction``: the NH charge, which releases no room. + Redistributed ordinary rates already reflect this charge. Fixed dual, + outside-maximum or nonbinding rates retain their dime gross amounts + and report the exact NH charge also as ``deduction``; its absent + ``deduction_reason`` marks a nonqualifying NH reservation. A nonzero + deduction without a qualifying reason must equal this reservation. """ beneficiary_id: str @@ -2251,6 +2328,10 @@ class BeneficiaryBenefit(_SealedResult): whole_dollar_auxiliary: int whole_dollar_own: int | None note: str = "" + deduction: Fraction = Fraction(0) + deduction_reason: DeductionReason | None = None + reserved_work_deduction: Fraction = Fraction(0) + age_reduction_factor: Fraction = Fraction(1) def __post_init__(self): _input_text(self.beneficiary_id, "beneficiary_id") @@ -2265,9 +2346,7 @@ def __post_init__(self): "original_benefit", "standard_rate", "family_maximum_rate", - "counted_against_maximum", "age_adjusted_rate", - "auxiliary_payable", ), ) _nonnegative_integer( @@ -2279,8 +2358,32 @@ def __post_init__(self): ) _optional_result_money(self, "own_benefit", "whole_dollar_own") _input_type(self.note, str, "note") + for name in ( + "deduction", + "reserved_work_deduction", + "counted_against_maximum", + "auxiliary_payable", + ): + value = getattr(self, name) + if type(value) is not Fraction or value < 0: + raise InvalidFamilyInput( + f"{name} must be a nonnegative Fraction" + ) + if self.deduction_reason is not None: + _input_type( + self.deduction_reason, DeductionReason, "deduction_reason" + ) + elif self.deduction and self.deduction != self.reserved_work_deduction: + raise InvalidFamilyInput( + "A deduction needs a qualifying reason or its exact NH reservation" + ) + factor = _exact(self.age_reduction_factor, "age_reduction_factor") + if not 0 <= factor <= 1: + raise InvalidFamilyInput("age_reduction_factor must be in [0, 1]") + object.__setattr__(self, "age_reduction_factor", factor) if self.auxiliary_payable != max( - Fraction(0), self.age_adjusted_rate - (self.own_benefit or 0) + Fraction(0), + self.age_adjusted_rate - (self.own_benefit or 0) - self.deduction, ): raise InvalidFamilyInput( "auxiliary_payable must offset age_adjusted_rate by own benefit" @@ -2288,7 +2391,8 @@ def __post_init__(self): if ( self.standard_rate > self.original_benefit or self.family_maximum_rate > self.original_benefit - or self.counted_against_maximum > self.family_maximum_rate + or self.counted_against_maximum + > self.family_maximum_rate + self.reserved_work_deduction ): raise InvalidFamilyInput( "Result rates exceed their original benefit" @@ -2348,6 +2452,8 @@ class FamilyBenefits(_SealedResult): state_source: str pe_us_revision: str version: str = GROSS_BENEFITS_VERSION + worker_reduced_for_age: bool = False + worker_age_reduction_factor: Fraction = Fraction(1) def __post_init__(self): _input_type(self.kind, FamilyKind, "kind") @@ -2363,13 +2469,25 @@ def __post_init__(self): "family_maximum", "available_for_auxiliaries", "total_original_benefits", - "record_total", - "subject_total", ), ) - for name in ("family_maximum_binding", "redistribution_applied"): + for name in ( + "family_maximum_binding", + "redistribution_applied", + "worker_reduced_for_age", + ): _input_type(getattr(self, name), bool, name) _optional_result_money(self, "worker_benefit", "whole_dollar_worker") + factor = _exact( + self.worker_age_reduction_factor, "worker_age_reduction_factor" + ) + if not 0 <= factor <= 1: + raise InvalidFamilyInput( + "worker_age_reduction_factor must be in [0, 1]" + ) + if self.worker_reduced_for_age != (factor < 1): + raise InvalidFamilyInput("Worker age metadata is inconsistent") + object.__setattr__(self, "worker_age_reduction_factor", factor) _nonnegative_integer( self.record_total_whole_dollars, "record_total_whole_dollars" ) @@ -2411,8 +2529,13 @@ def __post_init__(self): ) if self.redistribution_applied != bool( self.family_maximum_binding - and any(row.own_benefit is not None for row in subject) - and any(row.own_benefit is None for row in subject) + and ( + ( + any(row.own_benefit is not None for row in subject) + and any(row.own_benefit is None for row in subject) + ) + or any(row.deduction_reason is not None for row in subject) + ) ): raise InvalidFamilyInput( "Redistribution flag differs from subject rows" @@ -2451,7 +2574,11 @@ def __post_init__(self): and ( not self.redistribution_applied or row.own_benefit is None ) - and row.counted_against_maximum != row.family_maximum_rate + and row.deduction_reason is None + and row.counted_against_maximum + != row.family_maximum_rate + + row.reserved_work_deduction + - row.deduction ): raise InvalidFamilyInput( "Counted rate differs from maximum rate" @@ -3004,6 +3131,29 @@ def _refuse_historical_auxiliary( ) +def _beneficiary_age_factor( + beneficiary: Beneficiary, params: SSAParameters +) -> Fraction: + """Declared 402(q) factor, retained before dime rounding for 203(a)(5).""" + if beneficiary.role is Role.DIVORCED_SPOUSE and isinstance( + beneficiary.child_in_care, str + ): + return Fraction(1) + if beneficiary.role in _SPOUSE_ROLES: + return 1 - _spouse_reduction_fraction_validated( + beneficiary.reduction_months, params + ) + if beneficiary.role is Role.DISABLED_WIDOW: + return Fraction(715, 1000) + if beneficiary.role in _WIDOW_ROLES and beneficiary.reduction_months: + return 1 - _survivor_reduction_fraction_validated( + beneficiary.reduction_months, + beneficiary.reduction_period_months, + params, + ) + return Fraction(1) + + def _reduce_and_offset( row: _Row, state: RecordState, @@ -3557,6 +3707,9 @@ def _family_benefits( else _whole_dollars_validated(row.own_mba) ), note=row.note, + age_reduction_factor=_beneficiary_age_factor( + beneficiary, params + ), ) ) @@ -3598,7 +3751,396 @@ def _family_benefits( subject_total=subject_total, state_source=state.source, pe_us_revision=rates.pe_us_revision, + worker_reduced_for_age=bool( + worker_benefit is not None + and state.worker is not None + and state.worker.reduction_months + ), + worker_age_reduction_factor=( + 1 + - _worker_reduction_fraction_validated( + state.worker.reduction_months, params + ) + if worker_benefit is not None and state.worker is not None + else Fraction(1) + ), + ) + + +# GN 02603.040 event refusals deliberately retain distinct reason codes. +_DEDUCTION_REFUSALS = { + DeductionReason.WORKERS_COMPENSATION: UnsupportedReason.WORKERS_COMPENSATION_OFFSET, + DeductionReason.PRISONER_SUSPENSION: UnsupportedReason.PRISONER_SUSPENSION, + DeductionReason.DRUG_ADDICTION_SUSPENSION: UnsupportedReason.DRUG_ADDICTION_SUSPENSION, + DeductionReason.FOREIGN_WORK: UnsupportedReason.FOREIGN_WORK_DEDUCTION, + DeductionReason.PENALTY: UnsupportedReason.PENALTY_DEDUCTION, + DeductionReason.MARITIME: UnsupportedReason.MARITIME_DEDUCTION, + DeductionReason.ELECTION_CERTIFICATE_SUSPENSION: UnsupportedReason.ELECTION_CERTIFICATE_SUSPENSION, +} + + +def _check_deduction_inputs( + beneficiaries, deductions, households, worker_deductions +): + members = {b.beneficiary_id: b for b in beneficiaries} + for label, mapping in ( + ("deductions", deductions), + ("households", households), + ("worker_deductions", worker_deductions), + ): + if set(mapping) - set(members): + raise InvalidFamilyInput(f"{label} names an unknown beneficiary") + for key, value in households.items(): + _input_text(key, "household beneficiary ID") + _input_text(value, "household ID") + if any(not event.permanent for event in deductions.values()) and set( + households + ) != set(members): + raise InvalidFamilyInput( + "Temporary deductions require every beneficiary's household" + ) + for key, event in deductions.items(): + member = members[key] + if ( + event.reason is DeductionReason.DUAL_ENTITLEMENT + and member.own_benefit is None + ): + raise InvalidFamilyInput( + "A dual-entitlement marker needs an own benefit" + ) + if event.reason is DeductionReason.NO_CHILD_IN_CARE: + if member.role not in ( + Role.SPOUSE, + Role.SPOUSE_CHILD_IN_CARE, + Role.DIVORCED_SPOUSE, + Role.MOTHER_FATHER, + ): + raise InvalidFamilyInput( + "No-child-in-care deduction needs a spouse or mother/father" + ) + if isinstance(member.child_in_care, str): + raise InvalidFamilyInput( + "No-child-in-care deduction conflicts with current care" + ) + for value in worker_deductions.values(): + if value < 0: + raise InvalidFamilyInput("Worker deductions must be nonnegative") + + +def _check_deduction_amount_bounds( + state, beneficiaries, deductions, worker_deductions +): + """Reject impossible amounts before any statutory coverage refusal. + + The original benefit is an unconditional upper bound on a post-work + payable. For a parent, the one-parent OB is the conservative upper + bound until a supported computation resolves entitlement/count. + """ + for member in beneficiaries: + bid = member.beneficiary_id + original = _original_benefit_validated( + member.role, state.kind, state.pia, member.original_benefit_basis + ) + nh = worker_deductions.get(bid, Fraction(0)) + if nh > original: + raise InvalidFamilyInput( + "NH deduction exceeds the original benefit" + ) + event = deductions.get(bid) + if event is not None and event.payable + nh > original: + raise InvalidFamilyInput( + "Deductee payable and NH reservation exceed the original benefit" + ) + + +@_validated_entry +def family_benefits_after_deductions( + state: RecordState, + beneficiaries: Sequence[Beneficiary], + *, + payment_month: YearMonth, + params: SSAParameters, + deductions: Mapping[str, BenefitDeduction], + households: Mapping[str, str], + standalone: bool, + worker_deductions: Mapping[str, Fraction] | None = None, +) -> FamilyBenefits: + """203(a)(4), GN 02603.050C-D: deduct, then redistribute the maximum. + + Mappings preserve associations; beneficiaries is an ordered tuple/list. + Households are monthly membership IDs, required for all beneficiaries + whenever an own-work event is estimated. Empty deductions returns G's + ordinary result. ``worker_deductions`` reserves NH work deductions; + these never release room (GN 02603.040B; RS 02501.155B.3.c). + R2 owns earnings, charge order, grace years and permanent determinations. + """ + if standalone is not True: + raise InvalidFamilyInput( + "Use household_benefits_after_deductions unless standalone=True" + ) + beneficiaries = _check_family_inputs( + state, beneficiaries, payment_month, params + ) + worker_deductions = {} if worker_deductions is None else worker_deductions + _check_deduction_inputs( + beneficiaries, deductions, households, worker_deductions + ) + _check_deduction_amount_bounds( + state, beneficiaries, deductions, worker_deductions + ) + return _after_deductions( + state, + beneficiaries, + payment_month, + params, + deductions, + households, + worker_deductions, + ) + + +def _after_deductions( + state, + beneficiaries, + payment_month, + params, + deductions, + households, + worker_deductions, +): + baseline = _family_benefits(state, beneficiaries, payment_month, params) + by_id = {row.beneficiary_id: row for row in baseline.beneficiaries} + for bid, amount in worker_deductions.items(): + if amount > by_id[bid].auxiliary_payable: + raise InvalidFamilyInput( + "NH deduction exceeds the beneficiary's gross rate" + ) + for bid, event in deductions.items(): + gross = by_id[bid].auxiliary_payable - worker_deductions.get(bid, 0) + if not by_id[bid].entitled: + raise InvalidFamilyInput( + "A deduction needs an entitled beneficiary" + ) + if event.payable > gross: + raise InvalidFamilyInput( + "Deductee payable exceeds the pre-deduction rate" + ) + if ( + event.reason is DeductionReason.DUAL_ENTITLEMENT + and event.payable != gross + ): + raise InvalidFamilyInput( + "Dual-entitlement marker disagrees with the computed payable" + ) + for bid in sorted(deductions): + reason = _DEDUCTION_REFUSALS.get(deductions[bid].reason) + if reason is not None: + raise _computed( + FamilyConfigurationUnsupported, + reason, + "This GN 02603.040 event is outside the implemented deduction scope", + beneficiary_id=bid, + ) + events = { + bid: event + for bid, event in deductions.items() + if event.reason is not DeductionReason.DUAL_ENTITLEMENT + } + if not events: + return baseline + if any(worker_deductions.values()) and any( + row.age_reduction_factor != 1 for row in baseline.beneficiaries + ): + raise _computed( + FamilyConfigurationUnsupported, + UnsupportedReason.DEDUCTION_AGE_WORK_INTERACTION, + "Concurrent NH reservations and age reductions need a pinned allocation reading", + ) + subject = [ + row for row in baseline.beneficiaries if row.subject_to_family_maximum + ] + explicit = { + row.beneficiary_id for row in subject if row.beneficiary_id in events + } + # The existing Parisi result fixes which dual beneficiaries are deductees. + # In particular .050A.2 disregards a zero dual rate regardless of other events. + dual = { + row.beneficiary_id for row in subject if row.own_benefit is not None + } + permanent = dual | {bid for bid in explicit if events[bid].permanent} + members = {b.beneficiary_id: b for b in beneficiaries} + reserve = sum( + ( + worker_deductions.get(row.beneficiary_id, Fraction(0)) + for row in subject + ), + Fraction(0), + ) + # GN 02603.050A.1 expressly overrides the C formula for one full, + # permanent deduction and no other deduction event: disregard the row. + disregard_full = { + bid + for bid in explicit + if len(events) == 1 + and not dual + and not reserve + and events[bid].permanent + and events[bid].payable == 0 + } + results = [] + for old in baseline.beneficiaries: + bid = old.beneficiary_id + values = {item.name: getattr(old, item.name) for item in fields(old)} + if bid in events: + event = events[bid] + deduction = old.auxiliary_payable - event.payable + values.update( + auxiliary_payable=event.payable, + whole_dollar_auxiliary=_whole_dollars_validated(event.payable), + deduction=deduction, + deduction_reason=event.reason, + ) + if old.subject_to_family_maximum: + age_reserve = max( + Fraction(0), + old.counted_against_maximum - old.auxiliary_payable, + ) + if bid in disregard_full: + age_reserve = Fraction(0) + values["counted_against_maximum"] = ( + age_reserve + event.payable + worker_deductions.get(bid, 0) + ) + elif ( + old.subject_to_family_maximum + and bid not in dual + and baseline.family_maximum_binding + and explicit + ): + eligible = permanent | { + other + for other in explicit + if households.get(other) == households.get(bid) + } + remaining_ob = sum( + ( + row.original_benefit + for row in subject + if row.beneficiary_id not in eligible + ), + Fraction(0), + ) + reserved = Fraction(0) + for other in subject: + oid = other.beneficiary_id + if oid not in eligible: + continue + if oid in disregard_full: + continue + if oid in events: + reserved += events[oid].payable + max( + Fraction(0), + other.counted_against_maximum + - other.auxiliary_payable, + ) + else: + # A fixed Parisi rate still bears its NH deduction. + # The NH amount is already in the global reserve. + reserved += ( + other.counted_against_maximum + - worker_deductions.get(oid, Fraction(0)) + ) + pool = baseline.available_for_auxiliaries + if reserve: + # RS 02501.155B.3.c caps readjustment at the auxiliary's + # actual charge: NH partial months cannot release old slack. + pool = sum( + (other.counted_against_maximum for other in subject), + Fraction(0), + ) + available = max(Fraction(0), pool - reserve - reserved) + rate = ( + _floor_dime_validated( + min( + old.original_benefit - worker_deductions.get(bid, 0), + old.original_benefit * available / remaining_ob, + ) + ) + if remaining_ob + else old.family_maximum_rate + ) + member = members[bid] + row = _Row( + member, + old.entitled, + old.subject_to_family_maximum, + old.original_benefit, + None, + None, + standard=old.standard_rate, + rate=rate, + counted=rate, + ) + if ( + isinstance(member.child_in_care, str) + and member.role in _WIDOW_ROLES + ): + row.mother_father_rate = _mother_father_care_rate( + state, beneficiaries, member, payment_month, params + ) + age_adjusted, payable = _reduce_and_offset(row, state, params) + values.update( + family_maximum_rate=rate, + counted_against_maximum=rate + worker_deductions.get(bid, 0), + reserved_work_deduction=worker_deductions.get( + bid, Fraction(0) + ), + age_adjusted_rate=age_adjusted, + auxiliary_payable=payable, + whole_dollar_auxiliary=_whole_dollars_validated(payable), + ) + elif worker_deductions.get(bid, Fraction(0)): + # Fixed dual rates and outside-maximum rates do not receive + # redistribution, but NH work still reduces their cash. Keep + # dime gross rates and counted maximum room unchanged; the + # separate exact deduction supports fractional NH proration. + nh_deduction = worker_deductions[bid] + payable = old.auxiliary_payable - nh_deduction + values.update( + auxiliary_payable=payable, + whole_dollar_auxiliary=_whole_dollars_validated(payable), + deduction=nh_deduction, + reserved_work_deduction=nh_deduction, + ) + results.append(_computed(BeneficiaryBenefit, **values)) + family = { + item.name: getattr(baseline, item.name) for item in fields(baseline) + } + family.update( + beneficiaries=tuple(results), + redistribution_applied=bool( + baseline.redistribution_applied + or baseline.family_maximum_binding + and explicit + ), + record_total=(baseline.worker_benefit or Fraction(0)) + + sum((row.auxiliary_payable for row in results), Fraction(0)), + record_total_whole_dollars=(baseline.whole_dollar_worker or 0) + + sum(row.whole_dollar_auxiliary for row in results), + subject_total=( + baseline.pia + if baseline.worker_benefit is not None + else Fraction(0) + ) + + sum( + ( + row.counted_against_maximum + for row in results + if row.subject_to_family_maximum + ), + Fraction(0), + ), ) + return _computed(FamilyBenefits, **family) # --------------------------------------------------------------------------- @@ -3892,6 +4434,59 @@ def household_benefits( ) +@_validated_entry +def household_benefits_after_deductions( + records: Mapping[str, HouseholdRecord], + *, + payment_month: YearMonth, + params: SSAParameters, + deductions: Mapping[str, BenefitDeduction], + households: Mapping[str, str], + worker_deductions: Mapping[str, Fraction] | None = None, +) -> HouseholdBenefits: + """All records checked together; combined and multiple records refuse. + + Deduction and household dictionaries are keyed by person ID. All family + and deduction input checks precede household or statutory refusals. + """ + records, held = _check_household_inputs(records) + worker_deductions = {} if worker_deductions is None else worker_deductions + all_members = tuple( + b for record in records.values() for b in record.beneficiaries + ) + _check_deduction_inputs( + all_members, deductions, households, worker_deductions + ) + for record in records.values(): + _check_family_inputs( + record.state, record.beneficiaries, payment_month, params + ) + _check_deduction_amount_bounds( + record.state, record.beneficiaries, deductions, worker_deductions + ) + _refuse_household(held) + results = {} + for rid in sorted(records): + record = records[rid] + ids = {b.beneficiary_id for b in record.beneficiaries} + results[rid] = _after_deductions( + record.state, + record.beneficiaries, + payment_month, + params, + {bid: value for bid, value in deductions.items() if bid in ids}, + {bid: value for bid, value in households.items() if bid in ids}, + { + bid: value + for bid, value in worker_deductions.items() + if bid in ids + }, + ) + return _computed( + HouseholdBenefits, payment_month, MappingProxyType(results) + ) + + @_validated_entry def household_month_outcome( records: Mapping[str, HouseholdRecord], @@ -3972,7 +4567,7 @@ def household_month_outcome( # --------------------------------------------------------------------------- -# 403(a)(5): carried across a record's months, refused, never approximated +# 403(a)(5): operational payments or the explicit literal refusal reading # --------------------------------------------------------------------------- @_validated_entry def savings_clause_total(result: FamilyBenefits) -> Fraction: @@ -4039,68 +4634,182 @@ class _PriorMonth: pia: Fraction | None # None: unknown +class SavingsClauseReading(Enum): + """Canonical 203(a)(5) interpretations; d1338 selects SSA's procedure.""" + + SSA_OPERATIONAL = "ssa_operational" + LITERAL_REFUSAL = "literal_refusal" + + +def _savings_membership(result: FamilyBenefits) -> tuple: + """Membership is unordered; a change of record kind changes it too.""" + return ( + result.kind, + result.worker_benefit is not None, + frozenset( + (row.beneficiary_id, row.role) + for row in result.beneficiaries + if row.entitled + ), + ) + + +def _operational_age_reduced(result: FamilyBenefits) -> bool: + return result.worker_reduced_for_age or any( + row.entitled and row.age_reduction_factor < 1 + for row in result.beneficiaries + ) + + +def _savings_age_basis(result: FamilyBenefits) -> tuple: + """Do not attribute a simultaneous change of age factors to the PIA.""" + return ( + result.worker_age_reduction_factor, + frozenset( + (row.beneficiary_id, row.age_reduction_factor) + for row in result.beneficiaries + if row.entitled + ), + ) + + +def _savings_has_deductions(result: FamilyBenefits) -> bool: + """Deduction metadata changes the meaning of pre-offset age rates.""" + return any( + row.subject_to_family_maximum + and ( + row.deduction_reason is not None + or row.deduction + or row.reserved_work_deduction + ) + for row in result.beneficiaries + ) + + +def _savings_payment( + result: FamilyBenefits, protected: Fraction +) -> FamilyBenefits: + """RS 00630.400's two life-case procedures, retaining formula FMAX. + + The page says only 'rounded'. Equal auxiliary rates round upward to + the smallest dime that preserves 203(a)(5)'s protected family total; + a spouse's age reduction rounds down under RS 00615.201. The explicit + literal reading remains a refusal. The design records this rounding + interpretation and the procedures the capture does not settle. + """ + subject = [ + row for row in result.beneficiaries if row.subject_to_family_maximum + ] + reduced = [row for row in subject if row.age_reduction_factor < 1] + if ( + result.kind is FamilyKind.SURVIVOR + or any(row.own_benefit is not None for row in subject) + or _savings_has_deductions(result) + or len(reduced) > 1 + or any(row.role is not Role.SPOUSE for row in reduced) + or (reduced and len(subject) == 1) + ): + raise _computed( + FamilyConfigurationUnsupported, + UnsupportedReason.SAVINGS_CLAUSE_RATE_PROCEDURE, + "RS 00630.400 supplies the life-case procedure with no reduced " + "auxiliary or one reduced spouse plus other auxiliaries; " + "survivors, dual entitlement, deductions, and other reduced " + "auxiliary configurations need a captured payment procedure", + ) + # Source conflict us:oasdi-saving-clause-operational-rate-rounding: the + # least equal dime rates that keep the protected total (Act 203(a)(5)). + worker = result.worker_benefit or Fraction(0) + rates = {} + if reduced: + spouse = reduced[0] + increase = _ceil_dime_validated( + (protected - _savings_clause_total_validated(result)) + / len(subject) + ) + rates[spouse.beneficiary_id] = ( + spouse.age_adjusted_rate + + _floor_dime_validated(increase * spouse.age_reduction_factor) + ) + available = protected - worker - rates[spouse.beneficiary_id] + share = _ceil_dime_validated(available / (len(subject) - 1)) + else: + share = _ceil_dime_validated((protected - worker) / len(subject)) + for row in subject: + if row.beneficiary_id not in rates: + rates[row.beneficiary_id] = share + rows = [] + for row in result.beneficiaries: + if row.beneficiary_id not in rates: + rows.append(row) + continue + rate = rates[row.beneficiary_id] + if rate > row.original_benefit: + raise _computed( + FamilyConfigurationUnsupported, + UnsupportedReason.SAVINGS_CLAUSE_RATE_PROCEDURE, + "the protected rate would exceed the original benefit; " + "203(a)(4) only decreases benefits and RS 00630.400 does " + "not settle an above-OB carried payment", + beneficiary_id=row.beneficiary_id, + ) + values = {item.name: getattr(row, item.name) for item in fields(row)} + values.update( + age_adjusted_rate=rate, + auxiliary_payable=rate, + whole_dollar_auxiliary=_whole_dollars_validated(rate), + note=(row.note + "; " if row.note else "") + + "203(a)(5) operational protected payment; formula FMAX unchanged", + ) + rows.append(_computed(BeneficiaryBenefit, **values)) + values = {item.name: getattr(result, item.name) for item in fields(result)} + values.update( + beneficiaries=tuple(rows), + record_total=worker + + sum((row.auxiliary_payable for row in rows), Fraction(0)), + record_total_whole_dollars=(result.whole_dollar_worker or 0) + + sum(row.whole_dollar_auxiliary for row in rows), + ) + return _computed(FamilyBenefits, **values) + + @_checked_public_methods class SavingsClauseGuard: - """403(a)(5) for one insured worker's record, carried month to month. - - 403(a)(5): when two or more persons are entitled for a month in which - the maximum applies, and the PIA is increased for the following month, - that month's total is treated as increased by the smallest amount that - keeps "the total ... for any such subsequent month" from falling below - it (both totals after 403(a) and 402(q)). The guarantee is not limited - to the next month, and a saving clause, once established, "will - continue in effect until the table or formula maximum becomes larger" - and may become payable again (POMS RS 00615.801B.2). G computes one - month at a time and does not compute the raise, so it refuses. - - Create one guard per record at its first month and give it every - month in order, with :meth:`admit` (a result G computed), - :meth:`skip` (a month G refused for another reason) or - :meth:`evaluate` (which does either and returns a - :class:`FamilyOutcome` for the denominators). The guard: - - * **protects** the total of a *qualifying* month: two or more persons - entitled, the maximum reducing benefits (binding), and a higher PIA - in the next month. The highest protected total is carried forward - (:attr:`protected_total`); - * **refuses** (``savings_clause_403a5``) any later governed month whose total - falls below the protected total, whether or not the PIA rose into - it and whether or not the maximum binds in it, and every governed month after - the first such month, because the clause then stays in effect; - * **refuses** (``savings_clause_history_unknown``) every later governed month - once a protected total may exist that G cannot see: a path that does - not start at the record's first month of entitlement - (``earlier_months_unknown=True``), a skipped month while a protected - total is in force (its total may have fallen below it), or a skipped - month followed by a PIA increase or with no PIA given (it may have - qualified); - * **computes** a month in which no beneficiary is subject to the - maximum, whatever came before, because 403(a)(4) reduces only - benefits other than the worker's own and there is nothing to raise. - Its total still counts: one below the protected total puts the - clause into effect for later months. - - Known over-refusals, kept because they are conservative: a month in - which the maximum does not bind (403(a)(4) only decreases benefits, - so on the statute's text a larger maximum changes nothing there, but - SSA's procedure in RS 00630.400 divides the protected payment among - the auxiliaries without mentioning the OB cap); a total that falls - because a beneficiary left at any later time, even six months after - a December COLA; every later governed month is then refused (whether a - change of membership triggers the clause is not settled by any - captured source); and every governed month after a skipped one while a - protected total is in force. The guard follows the record across a - change of kind (a DIB converting to a RIB, or the worker's death), - because 403(a)(5) speaks of the total "on the basis of such wages". - - History holds private copies of admitted values. Every public calendar - or monetary accessor returns a fresh value, so altering a caller-held - input, result or snapshot cannot change a later decision. + """203(a)(5) for one insured worker's record, carried month to month. + + ``reading`` is an exact canonical SavingsClauseReading enum; its default + SSA_OPERATIONAL follows d1338 and POMS RS 00630.400. Protection starts + only after an age-reduced, maximum-reduced month with at least two + entitled persons, followed by a PIA increase that lowers payment with + unchanged membership. The two captured life-case procedures compute + protected auxiliary payments. Formula FMAX and its counted shares stay + unchanged. RS 00615.801B.2 carries the protected total, including a + period when the formula payment overtakes it and it later becomes + payable again. Membership changes during that carried protection refuse + with SAVINGS_CLAUSE_MEMBERSHIP_CHANGE. Survivor, dual-entitlement, + deduction and unspecified reduced-auxiliary procedures refuse with + SAVINGS_CLAUSE_RATE_PROCEDURE when protection would change money. + + LITERAL_REFUSAL retains G v2: every qualifying month followed by a PIA + increase protects its total, without an age condition or immediate fall. + Every later governed month below that total, and every governed month + after the first fall, refuses with SAVINGS_CLAUSE. This includes later + membership-driven declines that do not trigger SSA_OPERATIONAL. + + Both readings require every calendar month, via admit, skip or evaluate. + Earlier entitlement or skipped qualifying history that may hide a + protection retains SAVINGS_CLAUSE_HISTORY_UNKNOWN. Invalid public inputs + leave the guard unchanged. Prior results and snapshots are detached; + evaluations establish provenance, not freshness or attribution. """ @_validated_entry def __init__( - self, first_month: YearMonth, *, earlier_months_unknown: bool + self, + first_month: YearMonth, + *, + earlier_months_unknown: bool, + reading: SavingsClauseReading = SavingsClauseReading.SSA_OPERATIONAL, ): if type(self) is not SavingsClauseGuard: raise InvalidFamilyInput( @@ -4108,6 +4817,9 @@ def __init__( ) first_month = _checked_input(first_month, YearMonth, "first_month") _input_type(earlier_months_unknown, bool, "earlier_months_unknown") + _input_type(reading, SavingsClauseReading, "reading") + self._reading = reading + self._protected_membership: tuple | None = None self._next = first_month self._prior: _PriorMonth | None = ( _PriorMonth(_previous_month(first_month), None, None) @@ -4134,6 +4846,8 @@ def _check_initialized(self) -> None: "_floor_month", "_unknown_since", "_refused_since", + "_reading", + "_protected_membership", ) ): raise InvalidFamilyInput( @@ -4161,6 +4875,12 @@ def next_month(self) -> YearMonth: """The month the guard expects next.""" return _replace_declared(self._next) + @property + @_validated_entry + def reading(self) -> SavingsClauseReading: + """The canonical interpretation fixed when this guard was created.""" + return self._reading + @property @_validated_entry def protected_total(self) -> Fraction | None: @@ -4227,7 +4947,10 @@ def _carry(self, pia: Fraction | None) -> None: # A month G did not compute may have qualified, with a total # G never saw. self._unknown_since = self._unknown_since or prior.month - elif _qualifies(prior.result): + elif ( + self._reading is SavingsClauseReading.LITERAL_REFUSAL + and _qualifies(prior.result) + ): total = _savings_clause_total_validated(prior.result) if self._floor is None or total > self._floor: self._floor, self._floor_month = total, prior.month @@ -4247,8 +4970,11 @@ def admit(self, result: FamilyBenefits) -> FamilyBenefits: self._expect(month) total = _savings_clause_total_validated(result) self._carry(result.pia) + prior = self._prior self._prior = _PriorMonth(month, result, result.pia) self._next = _next_month(month) + if self._reading is SavingsClauseReading.SSA_OPERATIONAL: + return self._operational_admit(original, result, prior, total) # Source conflict us:oasdi-family-maximum-saving-clause below = self._floor is not None and total < self._floor first_fall = below and self._refused_since is None @@ -4286,6 +5012,90 @@ def admit(self, result: FamilyBenefits) -> FamilyBenefits: ) return original + def _operational_admit( + self, + original: FamilyBenefits, + result: FamilyBenefits, + prior: _PriorMonth | None, + total: Fraction, + ) -> FamilyBenefits: + membership = _savings_membership(result) + if ( + self._protected_membership is not None + and membership != self._protected_membership + ): + self._refused_since = self._refused_since or result.payment_month + if self._refused_since is not None: + raise _computed( + FamilyConfigurationUnsupported, + UnsupportedReason.SAVINGS_CLAUSE_MEMBERSHIP_CHANGE, + "membership changed while 203(a)(5) protection was active; " + "RS 00630.400 does not establish the successor protection", + ) + if self._unknown_since is not None and _governed(result): + raise _computed( + FamilyConfigurationUnsupported, + UnsupportedReason.SAVINGS_CLAUSE_HISTORY_UNKNOWN, + "a skipped or pre-entitlement month may carry an unknown " + "203(a)(5) protection", + ) + if self._floor is not None and ( + _savings_has_deductions(result) + or ( + prior is not None + and prior.result is not None + and _savings_has_deductions(prior.result) + ) + ): + self._unknown_since = self._unknown_since or result.payment_month + raise _computed( + FamilyConfigurationUnsupported, + UnsupportedReason.SAVINGS_CLAUSE_RATE_PROCEDURE, + "deductions in the current or prior month interact with " + "carried protection; pre-offset age rates do not establish " + "the protected payment under RS 00630.400", + ) + if ( + prior is not None + and prior.result is not None + and _qualifies(prior.result) + and _operational_age_reduced(prior.result) + and result.pia > prior.pia + and membership == _savings_membership(prior.result) + and total < _savings_clause_total_validated(prior.result) + ): + if ( + _savings_age_basis(result) != _savings_age_basis(prior.result) + or result.family_maximum < prior.result.family_maximum + or _savings_has_deductions(result) + or _savings_has_deductions(prior.result) + ): + self._unknown_since = ( + self._unknown_since or result.payment_month + ) + raise _computed( + FamilyConfigurationUnsupported, + UnsupportedReason.SAVINGS_CLAUSE_RATE_PROCEDURE, + "age factors changed, the formula maximum fell, or " + "either month has deductions, with a PIA increase and " + "lower pre-offset total; the snapshots do not isolate " + "the PIA's effect or establish the protected payment", + ) + protected = _savings_clause_total_validated(prior.result) + if self._floor is None or protected > self._floor: + self._floor = protected + self._floor_month = prior.month + self._protected_membership = membership + if self._floor is not None and total < self._floor: + # The protected total remains recorded when the formula payment + # overtakes it; .801B.2 permits it to become payable again. + protected = _savings_payment(result, self._floor) + self._prior = _PriorMonth( + result.payment_month, _detached_result(protected), result.pia + ) + return protected + return original + @_validated_entry def skip(self, month: YearMonth, *, pia: object = None) -> None: """Record a month of this record that G did not compute. @@ -4339,7 +5149,7 @@ def evaluate( f"pia {pia} disagrees with the computed PIA {result.pia}" ) try: - self._admit_validated(result) + result = self._admit_validated(result) except FamilyConfigurationUnsupported as error: return _computed(FamilyOutcome, key, weight, None, error) return _computed(FamilyOutcome, key, weight, result, None) @@ -4599,6 +5409,12 @@ def weighted_mean_record_total(outcomes: Sequence[FamilyOutcome]) -> Fraction: _disability_family_maximum_validated = disability_family_maximum.__wrapped__ _evaluate_family_validated = evaluate_family.__wrapped__ _family_benefits_validated = family_benefits.__wrapped__ +_family_benefits_after_deductions_validated = ( + family_benefits_after_deductions.__wrapped__ +) +_household_benefits_after_deductions_validated = ( + household_benefits_after_deductions.__wrapped__ +) _family_maximum_bend_points_validated = family_maximum_bend_points.__wrapped__ _family_maximum_formula_validated = family_maximum_formula.__wrapped__ _floor_dime_validated = floor_dime.__wrapped__ diff --git a/src/populace_dynamics/track_b/ret_ledger.py b/src/populace_dynamics/track_b/ret_ledger.py index 230763a04..2fe571868 100644 --- a/src/populace_dynamics/track_b/ret_ledger.py +++ b/src/populace_dynamics/track_b/ret_ledger.py @@ -1,4 +1,4 @@ -"""R2 part (a): an exact, single-record calendar-year RET ledger. +"""R2: an exact, single-record calendar-year RET ledger. Verification class: statutory conformance. Admitted scope: retirement earnings-test mechanics on invented cases and published statutory examples; @@ -16,8 +16,9 @@ Worker protections apply to that worker's excess, not another worker's excess charged against their benefit (Act 203(f)(1); RS 02501.140). In particular a deemed-entitled CDB recipient can be charged the NH's excess. -Auxiliary work that would free binding family-maximum room is refused for -part (b), as are other deduction events. No unsupported row is dropped +Auxiliary work readjusts binding family-maximum rates through G when the +caller supplies the monthly statutory and household facts. Other deduction +events remain refused. No unsupported row is dropped from an outcome denominator or silently computed as a single worker. Every raw month-set element must be an integer month before deduplication; malformed input raises before a coverage refusal can become an outcome. @@ -58,11 +59,13 @@ from math import ceil, floor from types import MappingProxyType +from populace_dynamics.track_b import gross_benefits as g from populace_dynamics.track_b._provenance import ( _check_refusal, _check_seal, _checked_result, _computed, + _construct_declared, _declared_input, _detached_result, _exact_number, @@ -99,7 +102,7 @@ class RETUnsupportedReason(Enum): PRORATED_SUSPENSION = "prorated_work_suspension" DEFERRED_SUSPENSION = "deferred_work_suspension" PROTEST_PARTIAL_SUSPENSION = "protested_partial_work_suspension" - DEDUCTION_BEFORE_REDUCTION = "deduction_before_reduction_part_b" + FAMILY_CONTEXT_REQUIRED = "deduction_readjustment_requires_family_context" TWO_RECORD_EARNINGS = "excess_earnings_on_two_records" FOREIGN_WORK = "noncovered_foreign_work" VOCATIONAL_REHABILITATION = "vocational_rehabilitation_refusal" @@ -366,6 +369,37 @@ def __post_init__(self): object.__setattr__(self, "original_rates", original) +@_declared_input +@dataclass(frozen=True) +class RETFamilyMonth: + """G's declared monthly inputs, including household memberships. + + Ordered beneficiaries accept tuple/list; household keys and values are + nonempty built-in strings. These are the same dated inputs used to + compute the RET beneficiary's gross/original rates, not inferred from + those rates. Household membership is the caller's GN 02603.090 fact. + """ + + state: g.RecordState + beneficiaries: tuple[g.Beneficiary, ...] + params: g.SSAParameters + households: Mapping[str, str] + standalone: bool = True + + def __post_init__(self): + ids = tuple(b.beneficiary_id for b in self.beneficiaries) + if len(set(ids)) != len(ids): + raise InvalidFamilyInput("Duplicate monthly family beneficiary") + if set(self.households) != set(ids): + raise InvalidFamilyInput( + "Households must identify every monthly family beneficiary" + ) + for key, household in self.households.items(): + _identity(key, "Household beneficiary") + _identity(household, "Household") + object.__setattr__(self, "households", dict(self.households)) + + @_declared_input @dataclass(frozen=True) class RecordYear: @@ -382,6 +416,7 @@ class RecordYear: suspension_method: SuspensionMethod = SuspensionMethod.FULL_MONTH foreign_work: bool = False vocational_rehabilitation_refusal: bool = False + family_months: Mapping[int, RETFamilyMonth] = field(default_factory=dict) def __post_init__(self): if type(self.year) is not int or self.year < 1: @@ -456,6 +491,44 @@ def __post_init__(self): ): raise InvalidFamilyInput("A living NH receives RIB or DIB") object.__setattr__(self, "beneficiaries", beneficiaries) + _months(self.family_months, "Family context months") + expected_kind = { + RecordKind.RETIREMENT: g.FamilyKind.RETIREMENT, + RecordKind.DISABILITY: g.FamilyKind.DISABILITY, + RecordKind.DECEASED: g.FamilyKind.SURVIVOR, + }[self.kind] + for month, context in self.family_months.items(): + if context.state.kind is not expected_kind: + raise InvalidFamilyInput("G and RET record kinds differ") + auxiliary_ids = { + b.beneficiary_id + for b in beneficiaries + if b.beneficiary_id != self.nh_id + and month in b.entitled_months + } + if { + b.beneficiary_id for b in context.beneficiaries + } != auxiliary_ids: + raise InvalidFamilyInput( + "G context must include every entitled RET auxiliary" + ) + role_types = { + g.Role.SPOUSE: (BenefitType.SPOUSE,), + g.Role.SPOUSE_CHILD_IN_CARE: (BenefitType.SPOUSE,), + g.Role.DIVORCED_SPOUSE: (BenefitType.DIVORCED_SPOUSE,), + g.Role.CHILD: (BenefitType.CHILD, BenefitType.CDB), + g.Role.WIDOW: (BenefitType.WIDOW,), + g.Role.SURVIVING_DIVORCED_SPOUSE: (BenefitType.WIDOW,), + g.Role.MOTHER_FATHER: (BenefitType.MOTHER_FATHER,), + g.Role.DISABLED_WIDOW: (BenefitType.DWB,), + } + ret_people = {b.beneficiary_id: b for b in beneficiaries} + for auxiliary in context.beneficiaries: + if ret_people[auxiliary.beneficiary_id].benefit_types[ + month - 1 + ] not in role_types.get(auxiliary.role, ()): + raise InvalidFamilyInput("G and RET benefit types differ") + object.__setattr__(self, "family_months", dict(self.family_months)) @_validated_entry @@ -675,6 +748,76 @@ def __post_init__(self): ) +@_sealed_result +@dataclass(frozen=True) +class RedistributedBeneficiaryMonth(_SealedResult): + """A month with separately determined final and provisional gross. + + GN 02603.050C/D and RS 02501.160 can give different final and + provisional gross rates. Delay of a household increase is not a work + deduction. NH partial shares can also make the reconstructed gross an + exact fraction of a dime. This separate sealed result preserves the + original BeneficiaryMonth serialization for previously supported rows. + """ + + beneficiary_id: str + month: int + gross: Fraction + net_due: Fraction + deduction: Fraction + payment: int + provisional_net: Fraction + provisional_deduction: Fraction + provisional_payment: int + nh_deduction: Fraction + own_deduction: Fraction + provisional_gross: Fraction + + def __post_init__(self): + _identity(self.beneficiary_id, "A monthly result") + _months((self.month,), "Result month") + for name in ( + "gross", + "net_due", + "deduction", + "provisional_gross", + "provisional_net", + "provisional_deduction", + "nh_deduction", + "own_deduction", + ): + value = _exact(getattr(self, name), name) + if value < 0: + raise InvalidFamilyInput("Monthly amounts must be nonnegative") + object.__setattr__(self, name, value) + if ( + self.gross != self.net_due + self.deduction + or self.provisional_gross + != self.provisional_net + self.provisional_deduction + or self.deduction != self.nh_deduction + self.own_deduction + ): + raise InvalidFamilyInput( + "Readjusted gross, net and deductions do not reconcile" + ) + for amount, payment in ( + (self.net_due, self.payment), + (self.provisional_net, self.provisional_payment), + ): + if type(payment) is not int or payment != _whole_dollars_validated( + amount + ): + raise InvalidFamilyInput( + "Monthly check must floor its exact net amount" + ) + + +def _checked_month(row): + if type(row) not in (BeneficiaryMonth, RedistributedBeneficiaryMonth): + raise InvalidFamilyInput("Expected a sealed RET monthly result") + _check_seal(row) + return row + + @_sealed_result @dataclass(frozen=True) class WorkerLedger(_SealedResult): @@ -744,7 +887,7 @@ def __post_init__(self): @dataclass(frozen=True) class RETLedger(_SealedResult): year: int - months: tuple[BeneficiaryMonth, ...] + months: tuple[BeneficiaryMonth | RedistributedBeneficiaryMonth, ...] workers: tuple[WorkerLedger, ...] crediting_months: Mapping[str, frozenset[int]] reconciliation: Mapping[str, int] @@ -755,7 +898,7 @@ def __post_init__(self): "RET results require a supported calendar year" ) months = tuple( - _checked_result(row, BeneficiaryMonth, "monthly result") + _checked_month(row) for row in _sequence(self.months, "Monthly results") ) workers = tuple( @@ -828,7 +971,7 @@ def __post_init__(self): @_validated_entry def for_beneficiary( self, beneficiary_id: str - ) -> tuple[BeneficiaryMonth, ...]: + ) -> tuple[BeneficiaryMonth | RedistributedBeneficiaryMonth, ...]: _check_seal(self) _identity(beneficiary_id, "Beneficiary lookup") return tuple( @@ -899,6 +1042,61 @@ def apply_ret_year( raise InvalidFamilyInput("Use an explicit NESE proration policy") if parameters is not None and not isinstance(parameters, RETParameters): raise InvalidFamilyInput("Use R1 RETParameters") + # Retain the G facts needed for money-changing readjustment. A caller's + # reduced rates cannot identify age reductions or dual entitlement. + held_family_refusals = [] + for month, context in sorted(record.family_months.items()): + try: + baseline = g._family_benefits_validated( + context.state, + context.beneficiaries, + payment_month=_construct_declared( + g.YearMonth, record.year, month + ), + params=context.params, + standalone=context.standalone, + ) + except FamilyConfigurationUnsupported as error: + held_family_refusals.append(error) + continue + baseline_rows = {b.beneficiary_id: b for b in baseline.beneficiaries} + if record.kind is not RecordKind.DECEASED: + nh = next( + b + for b in record.beneficiaries + if b.beneficiary_id == record.nh_id + ) + if (baseline.worker_benefit is not None) != ( + month in nh.entitled_months + ): + raise InvalidFamilyInput( + "G and RET NH entitlement facts differ" + ) + if baseline.family_maximum_binding != ( + month in record.family_maximum_binding_months + ): + raise InvalidFamilyInput("G and RET binding maximum facts differ") + for beneficiary in record.beneficiaries: + key = beneficiary.beneficiary_id + if month not in beneficiary.entitled_months: + continue + if key == record.nh_id: + gross = baseline.worker_benefit + original = baseline.pia + else: + if not baseline_rows[key].entitled: + raise InvalidFamilyInput( + "G and RET auxiliary entitlement facts differ" + ) + gross = baseline_rows[key].auxiliary_payable + original = baseline_rows[key].original_benefit + if ( + gross != beneficiary.gross_rates[month - 1] + or original != beneficiary.original_rates[month - 1] + ): + raise InvalidFamilyInput("G context does not match RET rates") + if held_family_refusals: + raise held_family_refusals[0] if record.year < 2000: raise _computed( RETConfigurationUnsupported, @@ -938,7 +1136,7 @@ def apply_ret_year( raise _computed( RETConfigurationUnsupported, reason, - "Outside R2 part (a)'s admitted scope", + "Outside R2's admitted scope", ) for b in record.beneficiaries: # Source conflict us:oasdi-ret-deemed-entitlement-basis @@ -1055,22 +1253,6 @@ def charge(provisional: bool): total = sum(caps.values(), Fraction(0)) if not total: continue - if ( - not is_nh - and m in record.family_maximum_binding_months - and any( - m in other.entitled_months - and other.original_rates[m - 1] > 0 - for k, other in people.items() - if k != key - ) - ): - raise _computed( - RETConfigurationUnsupported, - UnsupportedReason.DEDUCTION_BEFORE_REDUCTION, - "Auxiliary work frees binding maximum room; part (b) readjustment required", - beneficiary_id=key, - ) taken = min(remaining, total) if provisional or taken == total: payments = {k: Fraction(0) for k in caps} @@ -1092,28 +1274,104 @@ def charge(provisional: bool): if not provisional: charged[key] += taken remaining -= taken - return net, nh_deductions, own_deductions, charged, residuals - - final, nh, own, charged, residuals = charge(False) - provisional, _, _, suspended, _ = charge(True) - rows = tuple( - _computed( - BeneficiaryMonth, + gross = { + (k, m): b.gross_rates[m - 1] + for k, b in people.items() + for m in range(1, 13) + } + # RS 02501.155A.2: charge every worker against their own adjusted + # rate first. Redistribute only after all that month's workers have + # been charged, so changing beneficiary order cannot change excess. + for m in sorted(record.family_maximum_binding_months): + deductees = { + k: net[k, m] + for k in people + if k != record.nh_id and own_deductions[k, m] > 0 + } + if not deductees: + continue + if not any( + m in b.entitled_months and b.original_rates[m - 1] > 0 + for k, b in people.items() + if k not in deductees + ): + continue + if m not in record.family_months: + raise _computed( + RETConfigurationUnsupported, + UnsupportedReason.FAMILY_CONTEXT_REQUIRED, + "Deduction readjustment needs G age, dual-entitlement, " + "maximum and household facts for this month", + ) + context = record.family_months[m] + events = { + k: _construct_declared( + g.BenefitDeduction, + g.DeductionReason.OWN_EARNINGS_TEST, + payable, + not provisional, + ) + for k, payable in deductees.items() + } + worker_deductions = { + b.beneficiary_id: nh_deductions[b.beneficiary_id, m] + for b in context.beneficiaries + if nh_deductions[b.beneficiary_id, m] + } + adjusted = g._family_benefits_after_deductions_validated( + context.state, + context.beneficiaries, + payment_month=_construct_declared(g.YearMonth, record.year, m), + params=context.params, + deductions=events, + households=context.households, + standalone=context.standalone, + worker_deductions=worker_deductions, + ) + for row in adjusted.beneficiaries: + k = row.beneficiary_id + net[k, m] = row.auxiliary_payable + gross[k, m] = ( + net[k, m] + nh_deductions[k, m] + own_deductions[k, m] + ) + return net, nh_deductions, own_deductions, charged, residuals, gross + + final, nh, own, charged, residuals, gross = charge(False) + ( + provisional, + provisional_nh, + provisional_own, + suspended, + _, + provisional_gross, + ) = charge(True) + + def monthly_row(k, m): + values = ( k, m, - b.gross_rates[m - 1], + gross[k, m], final[k, m], - b.gross_rates[m - 1] - final[k, m], + nh[k, m] + own[k, m], _whole_dollars_validated(final[k, m]), provisional[k, m], - b.gross_rates[m - 1] - provisional[k, m], + provisional_nh[k, m] + provisional_own[k, m], _whole_dollars_validated(provisional[k, m]), nh[k, m], own[k, m], ) - for k, b in people.items() - for m in range(1, 13) - ) + if ( + gross[k, m] != provisional_gross[k, m] + or (gross[k, m] * 10).denominator != 1 + ): + return _computed( + RedistributedBeneficiaryMonth, + *values, + provisional_gross[k, m], + ) + return _computed(BeneficiaryMonth, *values) + + rows = tuple(monthly_row(k, m) for k in people for m in range(1, 13)) workers = tuple( _computed( WorkerLedger, diff --git a/tests/data/track_b/gross_benefit_examples.yaml b/tests/data/track_b/gross_benefit_examples.yaml index 7962448f6..75b23aecb 100644 --- a/tests/data/track_b/gross_benefit_examples.yaml +++ b/tests/data/track_b/gross_benefit_examples.yaml @@ -4,6 +4,9 @@ verification_class: statutory_conformance admitted_scope: Gross benefits for supported invented configurations and captured statutory examples only; no population, behavioral or forecast claim. tag_vocabulary: +- deduction:own_earnings +- deduction:no_child_in_care +- deduction:temporary - cola_path - credits:own_rib - credits:widow_basis @@ -52,6 +55,9 @@ tag_vocabulary: - ssfa:wep_regular_pia - widow:child_in_care supported_classes: +- deduction:own_earnings +- deduction:no_child_in_care +- deduction:temporary - cola_path - credits:own_rib - credits:widow_basis @@ -159,11 +165,6 @@ invented_only_classes: reason: RS 00209.001/.015 provide rules without a numerical example. tests: - tests/test_track_b_gross_benefits_parents_ieds.py::test_parent_hand_reference_one_or_two_entitled_parents - role:spouse_child_in_care: - reason: The captures give the exemption from age reduction but no worked-money - child-in-care dual-entitlement example. - tests: - - tests/test_track_b_gross_benefits.py::test_child_in_care_spouse_offset_uses_the_reduced_rib ssfa:gpo_ignored: reason: GN 02608.100 publishes the repeal boundary, not worked gross-family monetary figures. @@ -1365,7 +1366,7 @@ examples: inputs: scenarios: before: - operation: family + operation: family_after_deductions state: &id003 kind: retirement pia: '400.00' @@ -1383,7 +1384,7 @@ examples: - 2000 - 1 after: - operation: household + operation: household_after_deductions month: - 2000 - 1 @@ -1414,7 +1415,7 @@ examples: family_maximum: '150' worker: *id004 dual_reference: - operation: family + operation: family_after_deductions state: *id003 members: *id005 month: @@ -1497,7 +1498,7 @@ examples: inputs: scenarios: before: - operation: family + operation: family_after_deductions state: &id006 kind: retirement pia: '400.00' @@ -1515,7 +1516,7 @@ examples: - 2000 - 1 after: - operation: household + operation: household_after_deductions month: - 2000 - 1 @@ -1546,7 +1547,7 @@ examples: family_maximum: '150' worker: *id007 dual_reference: - operation: family + operation: family_after_deductions state: *id006 members: *id008 month: @@ -1628,7 +1629,7 @@ examples: inputs: scenarios: before: - operation: family + operation: family_after_deductions state: &id009 kind: retirement pia: '600.00' @@ -1646,7 +1647,7 @@ examples: - 2000 - 1 after: - operation: household + operation: household_after_deductions month: - 2000 - 1 @@ -1674,7 +1675,7 @@ examples: pia: '200.00' family_maximum: '300' dual_reference: - operation: family + operation: family_after_deductions state: *id009 members: *id010 month: @@ -1757,7 +1758,7 @@ examples: inputs: scenarios: before: - operation: family + operation: family_after_deductions state: &id011 kind: retirement pia: '500.00' @@ -1775,7 +1776,7 @@ examples: - 2000 - 1 after: - operation: household + operation: household_after_deductions month: - 2000 - 1 @@ -1806,7 +1807,7 @@ examples: family_maximum: '120' worker: *id012 dual_reference: - operation: family + operation: family_after_deductions state: *id011 members: *id013 month: @@ -2059,3 +2060,767 @@ examples: - path: caring.result.record_total_whole_dollars value: '1678' derivation: '215(g): $928 widow plus $750 child.' + +- id: gn-02603-060-a1 + capture_id: poms_gn_02603_060 + section: A.1 + tags: + - record:survivor + - role:mother_father + - role:child + - maximum:binding + - deduction:own_earnings + inputs: + scenarios: + case: + operation: family_after_deductions + month: + - 2026 + - 1 + state: + kind: survivor + pia: '300.40' + family_maximum: '548.40' + widow_drc_savings_clause: false + members: + - beneficiary_id: E + role: mother_father + - beneficiary_id: C3 + role: child + - beneficiary_id: C2 + role: child + - beneficiary_id: C1 + role: child + deductions: + E: + reason: own_earnings_test + payable: '0' + permanent: true + households: + E: home + C3: home + C2: home + C1: home + figure_count: 6 + expected: + - path: case.state.pia + value: '300.40' + literal: '300.40' + - path: case.state.family_maximum + value: '548.40' + literal: '548.40' + - path: case.rows.E.auxiliary_payable + value: '0' + literal: '0' + - path: case.rows.C3.auxiliary_payable + value: '182.80' + literal: '182.80' + - path: case.rows.C2.auxiliary_payable + value: '182.80' + literal: '182.80' + - path: case.rows.C1.auxiliary_payable + value: '182.80' + literal: '182.80' + derived_expected: + - path: case.rows.E.whole_dollar_auxiliary + value: '0' + derivation: '215(g): floor the published post-deduction dime rate.' + - path: case.rows.C3.whole_dollar_auxiliary + value: '182' + derivation: '215(g): floor the published post-deduction dime rate.' + - path: case.rows.C2.whole_dollar_auxiliary + value: '182' + derivation: '215(g): floor the published post-deduction dime rate.' + - path: case.rows.C1.whole_dollar_auxiliary + value: '182' + derivation: '215(g): floor the published post-deduction dime rate.' +- id: gn-02603-060-a2 + capture_id: poms_gn_02603_060 + section: A.2 + tags: + - record:survivor + - role:mother_father + - role:child + - maximum:binding + - deduction:own_earnings + inputs: + scenarios: + case: + operation: family_after_deductions + month: + - 2026 + - 1 + state: + kind: survivor + pia: '300.40' + family_maximum: '548.40' + widow_drc_savings_clause: false + members: + - beneficiary_id: E + role: mother_father + - beneficiary_id: C2 + role: child + - beneficiary_id: C1 + role: child + deductions: + C2: + reason: own_earnings_test + payable: '0' + permanent: true + households: + E: home + C2: home + C1: home + figure_count: 5 + expected: + - path: case.state.pia + value: '300.40' + literal: '300.40' + - path: case.state.family_maximum + value: '548.40' + literal: '548.40' + - path: case.rows.E.auxiliary_payable + value: '225.30' + literal: '225.30' + - path: case.rows.C2.auxiliary_payable + value: '0' + literal: '0' + - path: case.rows.C1.auxiliary_payable + value: '225.30' + literal: '225.30' + derived_expected: + - path: case.rows.E.whole_dollar_auxiliary + value: '225' + derivation: '215(g): floor the published post-deduction dime rate.' + - path: case.rows.C2.whole_dollar_auxiliary + value: '0' + derivation: '215(g): floor the published post-deduction dime rate.' + - path: case.rows.C1.whole_dollar_auxiliary + value: '225' + derivation: '215(g): floor the published post-deduction dime rate.' +- id: gn-02603-060-b1 + capture_id: poms_gn_02603_060 + section: B.1 + tags: + - record:survivor + - role:mother_father + - role:child + - maximum:binding + - deduction:own_earnings + inputs: + scenarios: + case: + operation: family_after_deductions + month: + - 2026 + - 1 + state: + kind: survivor + pia: '300.40' + family_maximum: '548.40' + widow_drc_savings_clause: false + members: + - beneficiary_id: E + role: mother_father + - beneficiary_id: C3 + role: child + - beneficiary_id: C2 + role: child + - beneficiary_id: C1 + role: child + deductions: + E: + reason: own_earnings_test + payable: '37.20' + permanent: true + households: + E: home + C3: home + C2: home + C1: home + figure_count: 6 + expected: + - path: case.state.pia + value: '300.40' + literal: '300.40' + - path: case.state.family_maximum + value: '548.40' + literal: '548.40' + - path: case.rows.E.auxiliary_payable + value: '37.20' + literal: '37.20' + - path: case.rows.C3.auxiliary_payable + value: '170.40' + literal: '170.40' + - path: case.rows.C2.auxiliary_payable + value: '170.40' + literal: '170.40' + - path: case.rows.C1.auxiliary_payable + value: '170.40' + literal: '170.40' + derived_expected: + - path: case.rows.E.whole_dollar_auxiliary + value: '37' + derivation: '215(g): floor the published post-deduction dime rate.' + - path: case.rows.C3.whole_dollar_auxiliary + value: '170' + derivation: '215(g): floor the published post-deduction dime rate.' + - path: case.rows.C2.whole_dollar_auxiliary + value: '170' + derivation: '215(g): floor the published post-deduction dime rate.' + - path: case.rows.C1.whole_dollar_auxiliary + value: '170' + derivation: '215(g): floor the published post-deduction dime rate.' +- id: gn-02603-060-c1 + capture_id: poms_gn_02603_060 + section: C.1 + tags: + - record:survivor + - role:mother_father + - role:child + - maximum:binding + - deduction:own_earnings + - deduction:temporary + inputs: + scenarios: + case: + operation: family_after_deductions + month: + - 2026 + - 1 + state: + kind: survivor + pia: '300.40' + family_maximum: '548.40' + widow_drc_savings_clause: false + members: + - beneficiary_id: E + role: mother_father + - beneficiary_id: C3 + role: child + - beneficiary_id: C2 + role: child + - beneficiary_id: C1 + role: child + deductions: + E: + reason: own_earnings_test + payable: '0' + permanent: false + households: + E: home + C3: home + C2: home + C1: other + figure_count: 6 + expected: + - path: case.state.pia + value: '300.40' + literal: '300.40' + - path: case.state.family_maximum + value: '548.40' + literal: '548.40' + - path: case.rows.E.auxiliary_payable + value: '0.00' + literal: '0.00' + - path: case.rows.C3.auxiliary_payable + value: '182.80' + literal: '182.80' + - path: case.rows.C2.auxiliary_payable + value: '182.80' + literal: '182.80' + - path: case.rows.C1.auxiliary_payable + value: '137.10' + literal: '137.10' + derived_expected: + - path: case.rows.E.whole_dollar_auxiliary + value: '0' + derivation: '215(g): floor the published post-deduction dime rate.' + - path: case.rows.C3.whole_dollar_auxiliary + value: '182' + derivation: '215(g): floor the published post-deduction dime rate.' + - path: case.rows.C2.whole_dollar_auxiliary + value: '182' + derivation: '215(g): floor the published post-deduction dime rate.' + - path: case.rows.C1.whole_dollar_auxiliary + value: '137' + derivation: '215(g): floor the published post-deduction dime rate.' +- id: gn-02603-060-c2 + capture_id: poms_gn_02603_060 + section: C.2 + tags: + - record:survivor + - role:mother_father + - role:child + - maximum:binding + - deduction:own_earnings + - deduction:temporary + - dual:child + inputs: + scenarios: + temporary: + operation: family_after_deductions + month: + - 2026 + - 1 + state: + kind: survivor + pia: '300.40' + family_maximum: '548.40' + widow_drc_savings_clause: false + members: + - beneficiary_id: E + role: mother_father + - beneficiary_id: C3 + role: child + - beneficiary_id: C2 + role: child + own_benefit: + kind: disability + pia: '280.00' + - beneficiary_id: C1 + role: child + deductions: + E: + reason: own_earnings_test + payable: '0' + permanent: false + households: + E: home + C3: home + C2: home + C1: other + permanent: + operation: family_after_deductions + month: + - 2026 + - 1 + state: + kind: survivor + pia: '300.40' + family_maximum: '548.40' + widow_drc_savings_clause: false + members: + - beneficiary_id: E + role: mother_father + - beneficiary_id: C3 + role: child + - beneficiary_id: C2 + role: child + own_benefit: + kind: disability + pia: '280.00' + - beneficiary_id: C1 + role: child + deductions: + E: + reason: own_earnings_test + payable: '0' + permanent: true + households: + E: home + C3: home + C2: home + C1: other + figure_count: 7 + expected: + - path: temporary.state.pia + value: '300.40' + literal: '300.40' + - path: temporary.state.family_maximum + value: '548.40' + literal: '548.40' + - path: temporary.rows.C2.own_benefit + value: '280.00' + literal: '280.00' + - path: temporary.rows.C2.auxiliary_payable + value: '0.00' + literal: '0.00' + - path: temporary.rows.C3.auxiliary_payable + value: '225.30' + literal: '225.30' + - path: temporary.rows.C1.auxiliary_payable + value: '182.80' + literal: '182.80' + - path: permanent.rows.C1.auxiliary_payable + value: '225.30' + literal: '225.30' + derived_expected: + - path: temporary.rows.C2.whole_dollar_auxiliary + value: '0' + derivation: '215(g): floor the published post-deduction dime rate.' + - path: temporary.rows.C3.whole_dollar_auxiliary + value: '225' + derivation: '215(g): floor the published post-deduction dime rate.' + - path: temporary.rows.C1.whole_dollar_auxiliary + value: '182' + derivation: '215(g): floor the published post-deduction dime rate.' + - path: permanent.rows.C1.whole_dollar_auxiliary + value: '225' + derivation: '215(g): floor the published post-deduction dime rate.' +- id: rs-02501-130-no-child-in-care + capture_id: poms_rs_02501_130 + section: B + tags: + - record:retirement + - role:spouse_child_in_care + - role:child + - maximum:binding + - deduction:no_child_in_care + inputs: + scenarios: + november: + operation: family_after_deductions + month: + - 2026 + - 11 + state: + kind: retirement + pia: '242.30' + family_maximum: '409.40' + members: + - beneficiary_id: B + role: spouse_child_in_care + - beneficiary_id: C2 + role: child + - beneficiary_id: C1 + role: child + deductions: + B: + reason: no_child_in_care + payable: '0' + permanent: true + households: + B: home + C2: home + C1: home + december: + operation: family_after_deductions + month: + - 2026 + - 12 + state: + kind: retirement + pia: '242.30' + family_maximum: '409.40' + members: + - beneficiary_id: B + role: spouse_child_in_care + - beneficiary_id: C2 + role: child + - beneficiary_id: C1 + role: child + deductions: + B: + reason: no_child_in_care + payable: '0' + permanent: true + households: + B: home + C2: home + C1: home + figure_count: 6 + expected: + - path: november.state.pia + value: '242.30' + literal: '242.30' + - path: november.state.family_maximum + value: '409.40' + literal: '409.40' + - path: november.rows.C2.auxiliary_payable + value: '83.50' + literal: '83.50' + - path: november.rows.C1.auxiliary_payable + value: '83.50' + literal: '83.50' + - path: december.rows.C2.auxiliary_payable + value: '83.50' + literal: '83.50' + - path: december.rows.C1.auxiliary_payable + value: '83.50' + literal: '83.50' + derived_expected: + - path: november.rows.C2.whole_dollar_auxiliary + value: '83' + derivation: '215(g): floor the published post-deduction dime rate.' + - path: november.rows.C1.whole_dollar_auxiliary + value: '83' + derivation: '215(g): floor the published post-deduction dime rate.' + - path: december.rows.C2.whole_dollar_auxiliary + value: '83' + derivation: '215(g): floor the published post-deduction dime rate.' + - path: december.rows.C1.whole_dollar_auxiliary + value: '83' + derivation: '215(g): floor the published post-deduction dime rate.' +- id: rs-02501-160-separate-households + capture_id: poms_rs_02501_160 + section: B.2 + tags: + - record:survivor + - role:mother_father + - role:child + - maximum:binding + - deduction:own_earnings + - deduction:temporary + inputs: + scenarios: + temporary: + operation: family_after_deductions + month: + - 2026 + - 1 + state: + kind: survivor + pia: '213.10' + family_maximum: '396' + widow_drc_savings_clause: false + members: + - beneficiary_id: E + role: mother_father + - beneficiary_id: C3 + role: child + - beneficiary_id: C2 + role: child + - beneficiary_id: C1 + role: child + deductions: + C3: + reason: own_earnings_test + payable: '0' + permanent: false + households: + C3: working + C2: working + E: other + C1: other + june: + operation: family_after_deductions + month: + - 2026 + - 6 + state: + kind: survivor + pia: '213.10' + family_maximum: '396' + widow_drc_savings_clause: false + members: + - beneficiary_id: E + role: mother_father + - beneficiary_id: C3 + role: child + - beneficiary_id: C2 + role: child + - beneficiary_id: C1 + role: child + deductions: + C3: + reason: own_earnings_test + payable: '39' + permanent: false + households: + C3: working + C2: working + E: other + C1: other + permanent: + operation: family_after_deductions + month: + - 2026 + - 1 + state: + kind: survivor + pia: '213.10' + family_maximum: '396' + widow_drc_savings_clause: false + members: + - beneficiary_id: E + role: mother_father + - beneficiary_id: C3 + role: child + - beneficiary_id: C2 + role: child + - beneficiary_id: C1 + role: child + deductions: + C3: + reason: own_earnings_test + payable: '0' + permanent: true + households: + C3: working + C2: working + E: other + C1: other + permanent_june: + operation: family_after_deductions + month: + - 2026 + - 6 + state: + kind: survivor + pia: '213.10' + family_maximum: '396' + widow_drc_savings_clause: false + members: + - beneficiary_id: E + role: mother_father + - beneficiary_id: C3 + role: child + - beneficiary_id: C2 + role: child + - beneficiary_id: C1 + role: child + deductions: + C3: + reason: own_earnings_test + payable: '39' + permanent: true + households: + C3: working + C2: working + E: other + C1: other + figure_count: 12 + expected: + - path: temporary.rows.E.auxiliary_payable + value: '99' + literal: '99' + - path: temporary.rows.C3.auxiliary_payable + value: '0' + literal: '0' + - path: temporary.rows.C2.auxiliary_payable + value: '132' + literal: '132' + - path: temporary.rows.C1.auxiliary_payable + value: '99' + literal: '99' + - path: june.rows.E.auxiliary_payable + value: '99' + literal: '99' + - path: june.rows.C3.auxiliary_payable + value: '39' + literal: '39' + - path: june.rows.C2.auxiliary_payable + value: '119' + literal: '119' + - path: june.rows.C1.auxiliary_payable + value: '99' + literal: '99' + - path: permanent.rows.E.auxiliary_payable + value: '132' + literal: '132' + - path: permanent.rows.C1.auxiliary_payable + value: '132' + literal: '132' + - path: permanent_june.rows.E.auxiliary_payable + value: '119' + literal: '119' + - path: permanent_june.rows.C1.auxiliary_payable + value: '119' + literal: '119' + derived_expected: + - path: temporary.rows.E.whole_dollar_auxiliary + value: '99' + derivation: '215(g): floor the published post-deduction dime rate.' + - path: temporary.rows.C3.whole_dollar_auxiliary + value: '0' + derivation: '215(g): floor the published post-deduction dime rate.' + - path: temporary.rows.C2.whole_dollar_auxiliary + value: '132' + derivation: '215(g): floor the published post-deduction dime rate.' + - path: temporary.rows.C1.whole_dollar_auxiliary + value: '99' + derivation: '215(g): floor the published post-deduction dime rate.' + - path: june.rows.E.whole_dollar_auxiliary + value: '99' + derivation: '215(g): floor the published post-deduction dime rate.' + - path: june.rows.C3.whole_dollar_auxiliary + value: '39' + derivation: '215(g): floor the published post-deduction dime rate.' + - path: june.rows.C2.whole_dollar_auxiliary + value: '119' + derivation: '215(g): floor the published post-deduction dime rate.' + - path: june.rows.C1.whole_dollar_auxiliary + value: '99' + derivation: '215(g): floor the published post-deduction dime rate.' + - path: permanent.rows.E.whole_dollar_auxiliary + value: '132' + derivation: '215(g): floor the published post-deduction dime rate.' + - path: permanent.rows.C1.whole_dollar_auxiliary + value: '132' + derivation: '215(g): floor the published post-deduction dime rate.' + - path: permanent_june.rows.E.whole_dollar_auxiliary + value: '119' + derivation: '215(g): floor the published post-deduction dime rate.' + - path: permanent_june.rows.C1.whole_dollar_auxiliary + value: '119' + derivation: '215(g): floor the published post-deduction dime rate.' +- id: rs-02501-160-basic + capture_id: poms_rs_02501_160 + section: B.1 + tags: + - record:survivor + - role:mother_father + - role:child + - maximum:binding + - deduction:own_earnings + inputs: + scenarios: + before: + operation: family_after_deductions + month: + - 2026 + - 1 + state: + kind: survivor + pia: '213.10' + family_maximum: '396' + widow_drc_savings_clause: false + members: + - beneficiary_id: E + role: mother_father + - beneficiary_id: C3 + role: child + - beneficiary_id: C2 + role: child + - beneficiary_id: C1 + role: child + deductions: {} + households: + C3: home + C2: home + E: home + C1: home + figure_count: 6 + expected: + - path: before.state.pia + value: '213.10' + literal: '213.10' + - path: before.state.family_maximum + value: '396' + literal: '396' + - path: before.rows.E.auxiliary_payable + value: '99' + literal: '99' + - path: before.rows.C3.auxiliary_payable + value: '99' + literal: '99' + - path: before.rows.C2.auxiliary_payable + value: '99' + literal: '99' + - path: before.rows.C1.auxiliary_payable + value: '99' + literal: '99' + derived_expected: + - path: before.rows.E.whole_dollar_auxiliary + value: '99' + derivation: '215(g): floor the published post-deduction dime rate.' + - path: before.rows.C3.whole_dollar_auxiliary + value: '99' + derivation: '215(g): floor the published post-deduction dime rate.' + - path: before.rows.C2.whole_dollar_auxiliary + value: '99' + derivation: '215(g): floor the published post-deduction dime rate.' + - path: before.rows.C1.whole_dollar_auxiliary + value: '99' + derivation: '215(g): floor the published post-deduction dime rate.' diff --git a/tests/data/track_b/gross_benefit_sources/README.md b/tests/data/track_b/gross_benefit_sources/README.md index ca3264c73..0a8b61bd6 100644 --- a/tests/data/track_b/gross_benefit_sources/README.md +++ b/tests/data/track_b/gross_benefit_sources/README.md @@ -99,3 +99,20 @@ These instructions pin the existing maximum, rounding, dual-entitlement and refusal boundaries. A completeness test requires all 58 retained captures to have a quoted rule or a registered worked figure as well as a byte-count and SHA-256 check. + +## Deduction-before-reduction source references + +The G part 2 manifest also references six existing captures in +`../ret_ledger_sources/`: GN 02603.020, .040 and .090 and RS 02501.130, +.155 and .160. Their original retrieval times, byte counts, hashes and +transmittals are preserved; bytes are not duplicated. The source tests +quote a rule from each and hash every relative reference. These establish +deduction priority, the number holder's work exception, household facts, +no-child-in-care deductions, full and partial auxiliary work deductions, +and the temporary/permanent separate-household distinction. The G manifest +now covers 64 captures, including these six shared references. + +The dispatch's `_new_*` capture logs and `lii_usc_402k_excerpt.txt` are not +present in this checkout. No uncaptured material is asserted or fetched. +Combined maximums and multiple auxiliary records remain refused under the +existing captured authorities. diff --git a/tests/data/track_b/gross_benefit_sources/manifest.json b/tests/data/track_b/gross_benefit_sources/manifest.json index 7440ec4e1..30fc872b6 100644 --- a/tests/data/track_b/gross_benefit_sources/manifest.json +++ b/tests/data/track_b/gross_benefit_sources/manifest.json @@ -742,6 +742,84 @@ "sha256": "2015c4840633e813391f43cb82324e5c46855a78c9459d78ad8003ed6340ffcd", "poms_transmittal": "TN 39 (11-23)", "page_date": "11/14/2023" + }, + { + "id": "poms_rs_02501_130", + "citation": "POMS RS 02501.130", + "url": "https://secure.ssa.gov/poms.nsf/lnx/0302501130", + "retrieved_at_utc": "2026-10-11T11:35:42Z", + "capture": "http_body", + "file": "../ret_ledger_sources/poms_rs_02501_130.html", + "bytes": 23095, + "sha256": "084beacc236c33fc88217486dccfeff7c23e564bf66717ebf8ab8d91818fbf82", + "poms_transmittal": "TN 40 (11-23)", + "page_date": "09/28/2011", + "title": "RS 02501.130 - Preclude Charging Excess Earnings When Individual Not Entitled to Benefits - 09/" + }, + { + "id": "poms_rs_02501_155", + "citation": "POMS RS 02501.155", + "url": "https://secure.ssa.gov/poms.nsf/lnx/0302501155", + "retrieved_at_utc": "2026-10-11T11:35:44Z", + "capture": "http_body", + "file": "../ret_ledger_sources/poms_rs_02501_155.html", + "bytes": 25236, + "sha256": "4bd6fc3e1485d5d9c8e89c50c08071abb23af8031893671339f4e0e44b6fb554", + "poms_transmittal": "TN 33 (11-23)", + "page_date": "11/01/2023", + "title": "RS 02501.155 - Adjustment for the Maximum Involving the Annual Earnings Test (AET) - 11/" + }, + { + "id": "poms_rs_02501_160", + "citation": "POMS RS 02501.160", + "url": "https://secure.ssa.gov/poms.nsf/lnx/0302501160", + "retrieved_at_utc": "2026-10-11T11:35:45Z", + "capture": "http_body", + "file": "../ret_ledger_sources/poms_rs_02501_160.html", + "bytes": 24146, + "sha256": "cd65f137741b83ba729b693f0c6f3fda118847b455c1c4d8ba33bbb1e404bca2", + "poms_transmittal": "TN 45 (11-23)", + "page_date": "11/15/2023", + "title": "RS 02501.160 - Adjusting for Family Maximum for Separate Households - 11/" + }, + { + "id": "poms_gn_02603_020", + "citation": "POMS GN 02603.020", + "url": "https://secure.ssa.gov/poms.nsf/lnx/0202603020", + "retrieved_at_utc": "2026-10-11T11:35:46Z", + "capture": "http_body", + "file": "../ret_ledger_sources/poms_gn_02603_020.html", + "bytes": 21454, + "sha256": "e397fd07d847f24c160e138de901dd89aca17e3fa7e06727de9a572f1c9eb508", + "poms_transmittal": "TN 6 (09-11)", + "page_date": "09/27/2011", + "title": "GN 02603.020 - Deduction before Reduction and Facility of Payment - 09/" + }, + { + "id": "poms_gn_02603_040", + "citation": "POMS GN 02603.040", + "url": "https://secure.ssa.gov/poms.nsf/lnx/0202603040", + "retrieved_at_utc": "2026-10-11T11:35:47Z", + "capture": "http_body", + "file": "../ret_ledger_sources/poms_gn_02603_040.html", + "bytes": 24924, + "sha256": "fec22e461e8cb1bb7829c717c5fbbc474b72ad7225e782a46b0f97c50b4bb16d", + "poms_transmittal": "TN 15 (09-25)", + "page_date": "09/27/2011", + "title": "GN 02603.040 - Events Subject to Deduction before Reduction - 09/" + }, + { + "id": "poms_gn_02603_090", + "citation": "POMS GN 02603.090", + "url": "https://secure.ssa.gov/poms.nsf/lnx/0202603090", + "retrieved_at_utc": "2026-10-11T11:35:51Z", + "capture": "http_body", + "file": "../ret_ledger_sources/poms_gn_02603_090.html", + "bytes": 30943, + "sha256": "fc544d57f3e2ec998a54b54ca4e7267dcd95b536463cabd94f00494c64f3269c", + "poms_transmittal": "TN 10 (07-23)", + "page_date": "12/16/2011", + "title": "GN 02603.090 - Same or Separate Household - 12/" } ] } diff --git a/tests/test_track_b_gross_benefits.py b/tests/test_track_b_gross_benefits.py index fefa3cb2c..1e126c56a 100644 --- a/tests/test_track_b_gross_benefits.py +++ b/tests/test_track_b_gross_benefits.py @@ -1397,7 +1397,11 @@ def test_households_stay_in_denominators(): def _guard(first=NOV, *, unknown=False): - return g.SavingsClauseGuard(first, earlier_months_unknown=unknown) + return g.SavingsClauseGuard( + first, + earlier_months_unknown=unknown, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) def _refusal(guard, result): @@ -1692,9 +1696,15 @@ def test_savings_clause_guard_needs_every_month_in_order(): ) ) with pytest.raises(TypeError): - g.SavingsClauseGuard(NOV, earlier_months_unknown=None) + g.SavingsClauseGuard( + NOV, + earlier_months_unknown=None, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) with pytest.raises(TypeError): - g.SavingsClauseGuard(NOV) + g.SavingsClauseGuard( + NOV, reading=g.SavingsClauseReading.LITERAL_REFUSAL + ) # Invalid inputs in a month still propagate out of evaluate. with pytest.raises(g.InvalidFamilyInput): guard.evaluate( @@ -1927,6 +1937,25 @@ def _unsupported_cases(): g.UnsupportedReason.SAVINGS_CLAUSE_HISTORY_UNKNOWN: lambda: ( _guard(NOV, unknown=True).admit(_review_m2_path()[0]) ), + **{ + reason: lambda reason=reason: _operational_savings_case(reason) + for reason in ( + g.UnsupportedReason.SAVINGS_CLAUSE_MEMBERSHIP_CHANGE, + g.UnsupportedReason.SAVINGS_CLAUSE_RATE_PROCEDURE, + ) + }, + **{ + reason: lambda reason=reason: _deduction_refusal_case(reason) + for reason in ( + g.UnsupportedReason.PRISONER_SUSPENSION, + g.UnsupportedReason.DRUG_ADDICTION_SUSPENSION, + g.UnsupportedReason.FOREIGN_WORK_DEDUCTION, + g.UnsupportedReason.PENALTY_DEDUCTION, + g.UnsupportedReason.MARITIME_DEDUCTION, + g.UnsupportedReason.ELECTION_CERTIFICATE_SUSPENSION, + g.UnsupportedReason.DEDUCTION_AGE_WORK_INTERACTION, + ) + }, g.UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE: lambda: _family( dataclasses.replace( _survivor_state(), widow_drc_savings_clause=True @@ -2024,6 +2053,42 @@ def _savings_clause_case(): guard.admit(after) +def _operational_savings_case(reason): + from tests.test_track_b_gross_benefits_savings import refusal_case + + return refusal_case(reason) + + +def _deduction_refusal_case(reason): + """Exercise every new event refusal through the public G computation.""" + events = { + g.UnsupportedReason.PRISONER_SUSPENSION: g.DeductionReason.PRISONER_SUSPENSION, + g.UnsupportedReason.DRUG_ADDICTION_SUSPENSION: g.DeductionReason.DRUG_ADDICTION_SUSPENSION, + g.UnsupportedReason.FOREIGN_WORK_DEDUCTION: g.DeductionReason.FOREIGN_WORK, + g.UnsupportedReason.PENALTY_DEDUCTION: g.DeductionReason.PENALTY, + g.UnsupportedReason.MARITIME_DEDUCTION: g.DeductionReason.MARITIME, + g.UnsupportedReason.ELECTION_CERTIFICATE_SUSPENSION: g.DeductionReason.ELECTION_CERTIFICATE_SUSPENSION, + g.UnsupportedReason.DEDUCTION_AGE_WORK_INTERACTION: g.DeductionReason.OWN_EARNINGS_TEST, + } + mixed = reason is g.UnsupportedReason.DEDUCTION_AGE_WORK_INTERACTION + return g.family_benefits_after_deductions( + _retired(400, 600), + ( + g.Beneficiary( + "B", g.Role.SPOUSE, reduction_months=12 if mixed else 0 + ), + g.Beneficiary("C1", g.Role.CHILD), + g.Beneficiary("C2", g.Role.CHILD), + ), + payment_month=NOW, + params=PARAMS, + deductions={"C1": g.BenefitDeduction(events[reason])}, + households={}, + standalone=True, + worker_deductions={"C1": F(1)} if mixed else None, + ) + + def test_every_unsupported_reason_has_a_refusal_case(): assert set(_unsupported_cases()) == set(g.UnsupportedReason) diff --git a/tests/test_track_b_gross_benefits_conformance_report.py b/tests/test_track_b_gross_benefits_conformance_report.py index 937a4c850..8ab0478bf 100644 --- a/tests/test_track_b_gross_benefits_conformance_report.py +++ b/tests/test_track_b_gross_benefits_conformance_report.py @@ -188,11 +188,11 @@ def test_every_retained_refusal_has_an_executed_named_witness(reason): def test_named_witness_denominator_is_separate_from_the_lattice(regenerated): witnesses = regenerated["supplemental_refusal_witnesses"] - assert len(g.UnsupportedReason) == 28 + assert len(g.UnsupportedReason) == 37 assert witnesses["denominator"] == { - "rows": 28, + "rows": 37, "supported": 0, - "refused": 28, + "refused": 37, "invalid": 0, } expected = {reason.value for reason in g.UnsupportedReason} @@ -225,6 +225,20 @@ def test_pre_1978_auxiliary_history_has_an_executed_refusal_witness(): assert caught.value.reason.value == "reduced_benefit_history_before_1978" +def test_deduction_extension_has_its_own_complete_denominator(): + extension = report.deduction_conformance() + assert extension["denominator"] == { + "rows": 16, + "supported": 16, + "refused": 0, + "invalid": 0, + } + assert len({row["id"] for row in extension["rows"]}) == 16 + assert all(row["status"] == "supported" for row in extension["rows"]) + assert "no historical lattice row" in extension["scope"] + assert report.deduction_conformance() == extension + + def test_pre_1978_own_rib_history_is_outside_the_1946_lattice(regenerated): lattice = regenerated["lattice"] assert lattice["refused_by_reason"]["own_rib_history_before_1978"] == 0 diff --git a/tests/test_track_b_gross_benefits_deductions.py b/tests/test_track_b_gross_benefits_deductions.py new file mode 100644 index 000000000..735ad8648 --- /dev/null +++ b/tests/test_track_b_gross_benefits_deductions.py @@ -0,0 +1,564 @@ +"""Statutory conformance for 203(a)(4) on invented and published cases. + +No population, behavioral or forecast claim. GN 02603.050C-D fixes the +formula; GN 02603.060 and RS 02501.130/.160 supply payment examples. +""" + +from dataclasses import fields, replace +from fractions import Fraction as F + +import pytest +from hypothesis import example, given, settings +from hypothesis import strategies as st + +from populace_dynamics.track_b import gross_benefits as g +from tests.track_b_gross_benefit_support import source_text, ssa_params + +PARAMS = ssa_params() +MONTH = g.YearMonth(2024, 1) + + +def survivor(pia=F("300.40"), maximum=F("548.40"), children=3, dual=False): + state = g.RecordState( + g.FamilyKind.SURVIVOR, pia, maximum, widow_drc_savings_clause=False + ) + members = [g.Beneficiary("E", g.Role.MOTHER_FATHER)] + members += [ + g.Beneficiary( + f"C{i}", + g.Role.CHILD, + own_benefit=( + g.OwnBenefit(g.OwnBenefitKind.DISABILITY, F(280)) + if dual and i == 2 + else None + ), + ) + for i in range(1, children + 1) + ] + return state, tuple(members) + + +def compute(state, members, deductions=None, households=None, **kwargs): + return g.family_benefits_after_deductions( + state, + members, + payment_month=MONTH, + params=PARAMS, + deductions={} if deductions is None else deductions, + households={} if households is None else households, + standalone=True, + **kwargs, + ) + + +def amounts(result): + return { + row.beneficiary_id: row.auxiliary_payable + for row in result.beneficiaries + } + + +@pytest.mark.parametrize( + "children,deductee,payable,expected", + [ + ( + 3, + "E", + F(0), + { + "E": F(0), + "C1": F("182.80"), + "C2": F("182.80"), + "C3": F("182.80"), + }, + ), + (2, "C2", F(0), {"E": F("225.30"), "C1": F("225.30"), "C2": F(0)}), + ( + 3, + "E", + F("37.20"), + { + "E": F("37.20"), + "C1": F("170.40"), + "C2": F("170.40"), + "C3": F("170.40"), + }, + ), + ], +) +def test_gn_02603_060_permanent_examples( + children, deductee, payable, expected +): + state, members = survivor(children=children) + result = compute( + state, + members, + { + deductee: g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST, payable + ) + }, + ) + assert amounts(result) == expected + if children == 2: + narrative = "That is $548.40 divided by 2 individuals = 225.30." + assert narrative in source_text("poms_gn_02603_060") + # A.2's narrative omits the OB cap; its displayed formula settles + # the actual quotient and cap separately. + assert F("548.40") / 2 == F("274.20") + assert min(F("274.20"), F("225.30")) == F("225.30") + assert { + r.beneficiary_id: r.whole_dollar_auxiliary + for r in result.beneficiaries + } == {k: int(v) for k, v in expected.items()} + + +@pytest.mark.parametrize( + "dual,expected", + [ + ( + False, + { + "E": F(0), + "C1": F("137.10"), + "C2": F("182.80"), + "C3": F("182.80"), + }, + ), + (True, {"E": F(0), "C1": F("182.80"), "C2": F(0), "C3": F("225.30")}), + ], +) +def test_gn_02603_060_temporary_examples(dual, expected): + state, members = survivor(dual=dual) + event = g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST, permanent=False + ) + households = {"E": "one", "C1": "two", "C2": "one", "C3": "one"} + assert ( + amounts(compute(state, members, {"E": event}, households)) == expected + ) + permanent = compute( + state, members, {"E": replace(event, permanent=True)}, households + ) + assert amounts(permanent)["C1"] == F("225.30" if dual else "182.80") + + +@pytest.mark.parametrize( + "payable,permanent,expected", + [ + (F(0), False, {"E": F(99), "C1": F(99), "C2": F(132), "C3": F(0)}), + (F(39), False, {"E": F(99), "C1": F(99), "C2": F(119), "C3": F(39)}), + (F(0), True, {"E": F(132), "C1": F(132), "C2": F(132), "C3": F(0)}), + (F(39), True, {"E": F(119), "C1": F(119), "C2": F(119), "C3": F(39)}), + ], +) +def test_rs_02501_160_separate_households(payable, permanent, expected): + state, members = survivor(F("213.10"), F(396)) + event = g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST, payable, permanent + ) + households = {"E": "one", "C1": "one", "C2": "two", "C3": "two"} + result = compute(state, members, {"C3": event}, households) + assert amounts(result) == expected + # The undated source OB rounds upward; modern G dime floors. Equal + # shares make every published actual payment identical without an override. + assert result.beneficiaries[0].original_benefit == F("159.80") + assert "$159.90" in source_text("poms_rs_02501_160") + + +def test_rs_02501_130_no_child_in_care(): + state = g.RecordState( + g.FamilyKind.RETIREMENT, + F("242.30"), + F("409.40"), + worker=g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, F("242.30")), + ) + members = ( + g.Beneficiary("B", g.Role.SPOUSE_CHILD_IN_CARE), + g.Beneficiary("C1", g.Role.CHILD), + g.Beneficiary("C2", g.Role.CHILD), + ) + event = g.BenefitDeduction(g.DeductionReason.NO_CHILD_IN_CARE) + result = compute(state, members, {"B": event}) + assert amounts(result) == {"B": F(0), "C1": F("83.50"), "C2": F("83.50")} + assert result.beneficiaries[0].original_benefit == F("121.10") + assert "$121.20" in source_text("poms_rs_02501_130") + + +@given(pia=st.integers(1, 20000), count=st.integers(1, 5), dual=st.booleans()) +@settings(max_examples=50, deadline=None) +def test_no_deductions_is_exact_family_and_household_differential( + pia, count, dual +): + state, members = survivor(F(pia), F(pia * 3, 2), count, dual) + old = g.family_benefits( + state, members, payment_month=MONTH, params=PARAMS, standalone=True + ) + assert compute(state, members) == old + records = {"record": g.HouseholdRecord("worker", state, members)} + assert g.household_benefits_after_deductions( + records, + payment_month=MONTH, + params=PARAMS, + deductions={}, + households={}, + ) == g.household_benefits(records, payment_month=MONTH, params=PARAMS) + + +@given( + pia=st.integers(2, 20000), + count=st.integers(2, 6), + partial=st.integers(0, 100), + temporary=st.booleans(), +) +@settings(max_examples=80, deadline=None) +def test_formula_bounds_monotonicity_households_order_and_determinism( + pia, count, partial, temporary +): + state, members = survivor(F(pia), F(pia * 3, 2), count) + old = compute(state, members) + before = old.by_id() + payable = g.floor_dime(before["E"].auxiliary_payable * partial / 100) + event = g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST, payable, not temporary + ) + households = { + b.beneficiary_id: ("elsewhere" if b.beneficiary_id == "C1" else "home") + for b in members + } + result = compute(state, members, {"E": event}, households) + again = compute( + state, + tuple(reversed(members)), + {"E": event}, + dict(reversed(tuple(households.items()))), + ) + assert amounts(result) == amounts(again) + assert compute(state, members, {"E": event}, households) == result + assert result.subject_total <= state.family_maximum + for row in result.beneficiaries: + assert row.family_maximum_rate <= row.original_benefit + if row.beneficiary_id == "E": + assert row.auxiliary_payable == payable + continue + assert ( + row.family_maximum_rate + >= before[row.beneficiary_id].family_maximum_rate + ) + if temporary and row.beneficiary_id == "C1": + assert row.auxiliary_payable == before["C1"].auxiliary_payable + else: + denominator = sum( + b.original_benefit + for b in old.beneficiaries + if b.beneficiary_id != "E" + ) + expected = g.floor_dime( + min( + row.original_benefit, + row.original_benefit + * (state.family_maximum - payable) + / denominator, + ) + ) + assert row.family_maximum_rate == expected + + +@pytest.mark.parametrize( + "reason,expected", + [ + ( + g.DeductionReason.WORKERS_COMPENSATION, + g.UnsupportedReason.WORKERS_COMPENSATION_OFFSET, + ), + ( + g.DeductionReason.PRISONER_SUSPENSION, + g.UnsupportedReason.PRISONER_SUSPENSION, + ), + ( + g.DeductionReason.DRUG_ADDICTION_SUSPENSION, + g.UnsupportedReason.DRUG_ADDICTION_SUSPENSION, + ), + ( + g.DeductionReason.FOREIGN_WORK, + g.UnsupportedReason.FOREIGN_WORK_DEDUCTION, + ), + (g.DeductionReason.PENALTY, g.UnsupportedReason.PENALTY_DEDUCTION), + (g.DeductionReason.MARITIME, g.UnsupportedReason.MARITIME_DEDUCTION), + ( + g.DeductionReason.ELECTION_CERTIFICATE_SUSPENSION, + g.UnsupportedReason.ELECTION_CERTIFICATE_SUSPENSION, + ), + ], +) +def test_unsupported_deductions_keep_named_denominator(reason, expected): + state, members = survivor() + outcome = g.evaluate_family( + "deduction", + 1, + lambda: compute(state, members, {"E": g.BenefitDeduction(reason)}), + ) + assert outcome.unsupported.reason is expected + assert g.count_family_outcomes((outcome,)).unsupported_rows == 1 + with pytest.raises(g.InvalidFamilyInput): + compute(state, members, {"missing": g.BenefitDeduction(reason)}) + + +def test_nh_partial_reservation_cannot_redistribute_original_rounding_slack(): + state = g.RecordState( + g.FamilyKind.RETIREMENT, + F(400), + F(600), + worker=g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, F(400)), + ) + members = tuple(g.Beneficiary(f"C{i}", g.Role.CHILD) for i in range(3)) + nh = dict.fromkeys(("C0", "C1", "C2"), F("46.64")) + result = compute( + state, + members, + { + "C0": g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST, F("9.96") + ) + }, + worker_deductions=nh, + ) + assert amounts(result) == { + "C0": F("9.96"), + "C1": F("24.90"), + "C2": F("24.90"), + } + assert amounts(result)["C1"] + amounts(result)["C2"] - F("19.96") * 2 <= 10 + + +def test_fields_remain_sealed_and_exact(): + state, members = survivor() + result = compute( + state, + members, + { + "E": g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST, F(1, 3) + ) + }, + ) + assert amounts(result)["E"] == F(1, 3) + with pytest.raises(g.InvalidFamilyInput): + g.FamilyBenefits( + **{ + item.name: getattr(result, item.name) + for item in fields(result) + } + ) + + +@pytest.mark.parametrize( + "source,figures", + [ + ( + "poms_gn_02603_060", + ( + "300.40", + "548.40", + "225.30", + "137.10", + "182.80", + "274.20", + "37.20", + "170.40", + "280.00", + ), + ), + ( + "poms_rs_02501_130", + ("242.30", "409.40", "121.20", "55.70", "83.50"), + ), + ( + "poms_rs_02501_160", + ("159.90", "213.10", "396", "99", "132", "119", "39"), + ), + ], +) +def test_worked_example_figures_are_quoted_from_the_captures(source, figures): + text = source_text(source) + for figure in figures: + assert figure in text + + +def test_temporary_partial_reading_is_explicit_in_captures(): + assert ( + "there are no partial deductions for temporary work deductions" + in source_text("poms_gn_02603_050") + ) + assert "C3 $ 39 C2 $119" in source_text("poms_rs_02501_160") + assert "C2 can receive the extra $20 for June immediately" in source_text( + "poms_rs_02501_160" + ) + + +def test_nh_age_interaction_is_named_refusal(): + for quote in ( + "Total amount of work deductions to be imposed against auxiliaries " + "or survivors due to the number holder's work", + "Age reduction amount for all workers or deductees", + ): + assert quote in source_text("poms_gn_02603_050") + assert ( + "The partial benefits of other auxiliaries cannot be readjusted " + "except to the extent to which we charge the auxiliary's excess " + "earnings against the benefits to which the auxiliary otherwise " + "was eligible." + ) in source_text("poms_rs_02501_155") + state = g.RecordState( + g.FamilyKind.RETIREMENT, + F(400), + F(600), + worker=g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, F(400)), + ) + members = ( + g.Beneficiary("B", g.Role.SPOUSE, reduction_months=12), + g.Beneficiary("C1", g.Role.CHILD), + g.Beneficiary("C2", g.Role.CHILD), + ) + with pytest.raises(g.FamilyConfigurationUnsupported) as error: + compute( + state, + members, + {"C1": g.BenefitDeduction(g.DeductionReason.OWN_EARNINGS_TEST)}, + worker_deductions={"C1": F(1)}, + ) + assert ( + error.value.reason + is g.UnsupportedReason.DEDUCTION_AGE_WORK_INTERACTION + ) + + +def test_all_dual_beneficiaries_do_not_gain_from_another_deduction(): + state = g.RecordState( + g.FamilyKind.SURVIVOR, F(300), F(450), widow_drc_savings_clause=False + ) + members = tuple( + g.Beneficiary( + f"C{i}", + g.Role.CHILD, + own_benefit=g.OwnBenefit(g.OwnBenefitKind.DISABILITY, F(200)), + ) + for i in range(3) + ) + result = compute( + state, + members, + {"C0": g.BenefitDeduction(g.DeductionReason.OWN_EARNINGS_TEST)}, + ) + assert amounts(result) == dict.fromkeys(("C0", "C1", "C2"), F(0)) + + +@given(scale=st.integers(1, 20)) +@example(scale=1) +@settings(max_examples=12, deadline=None) +def test_single_full_permanent_exception_disregards_age_reduction(scale): + state = g.RecordState( + g.FamilyKind.RETIREMENT, + F(400), + F(650), + worker=g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, F(400)), + ) + members = ( + g.Beneficiary("B", g.Role.SPOUSE, reduction_months=36), + g.Beneficiary("C1", g.Role.CHILD), + g.Beneficiary("C2", g.Role.CHILD), + ) + result = compute( + state, + members, + {"B": g.BenefitDeduction(g.DeductionReason.OWN_EARNINGS_TEST)}, + ) + assert amounts(result) == {"B": F(0), "C1": F(125), "C2": F(125)} + assert ( + "disregard that beneficiary when distributing the family maximum" + in source_text("poms_gn_02603_050") + ) + # Literal C reserves B age reduction20.90 and gives114.50, but A.1 + # explicitly calls this a full-permanent exception to that formula. + assert g.floor_dime((F(250) - F("20.90")) / 2) == F("114.50") + # A.1 applies only while there is no other deduction. Entering C by + # adding a second worker restores the age reserve and can LOWER the + # remaining children's payments: absolute monotonicity is not a rule. + state = g.RecordState( + g.FamilyKind.RETIREMENT, + F(48 * scale), + F(78 * scale), + worker=g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, F(48 * scale)), + ) + members = ( + g.Beneficiary("B", g.Role.SPOUSE, reduction_months=60), + ) + tuple(g.Beneficiary(f"C{i}", g.Role.CHILD) for i in range(1, 4)) + baseline = compute(state, members) + events = {"B": g.BenefitDeduction(g.DeductionReason.OWN_EARNINGS_TEST)} + single = compute(state, members, events) + child_payable = baseline.by_id()["C1"].auxiliary_payable - F("0.10") + multiple = compute( + state, + members, + { + **events, + "C1": g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST, child_payable + ), + }, + ) + spouse = baseline.by_id()["B"] + age_reserve = spouse.family_maximum_rate - spouse.age_adjusted_rate + expected = g.floor_dime((F(30 * scale) - age_reserve - child_payable) / 2) + assert amounts(single)["C2"] == amounts(single)["C3"] == 10 * scale + assert amounts(multiple)["C2"] == amounts(multiple)["C3"] == expected + assert expected < amounts(single)["C2"] + if scale == 1: + assert child_payable == F("7.40") + assert age_reserve == F("2.70") + assert expected == F("9.90") + # Extending A.1 despite the second worker would instead pay11.30. + assert g.floor_dime((F(30) - child_payable) / 2) == F("11.30") + text = source_text("poms_gn_02603_050") + assert "and no other deduction is involved for any beneficiary" in text + assert "Age reduction amount for all workers or deductees" in text + + +@pytest.mark.parametrize("household", (False, True)) +@given(excess=st.integers(1, 10000)) +@settings(max_examples=10, deadline=None) +def test_impossible_payable_precedes_statutory_refusal(household, excess): + state, members = survivor() + state = replace( + state, conditions={g.RecordCondition.WORKERS_COMPENSATION_OFFSET} + ) + event = g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST, F("225.30") + excess + ) + rows = [] + with pytest.raises(g.InvalidFamilyInput): + if household: + rows.append( + g.evaluate_family( + "invalid", + 1, + lambda: g.household_benefits_after_deductions( + { + "record": g.HouseholdRecord( + "worker", state, members + ) + }, + payment_month=MONTH, + params=PARAMS, + deductions={"E": event}, + households={}, + ), + ) + ) + else: + rows.append( + g.evaluate_family( + "invalid", 1, lambda: compute(state, members, {"E": event}) + ) + ) + assert g.count_family_outcomes(rows).rows == 0 diff --git a/tests/test_track_b_gross_benefits_fix_round_10_api.py b/tests/test_track_b_gross_benefits_fix_round_10_api.py index 23fb536af..ce056ab62 100644 --- a/tests/test_track_b_gross_benefits_fix_round_10_api.py +++ b/tests/test_track_b_gross_benefits_fix_round_10_api.py @@ -53,10 +53,12 @@ } ENUMS = { "BeneficiaryCondition", + "DeductionReason", "FamilyKind", "OwnBenefitKind", "RecordCondition", "Role", + "SavingsClauseReading", "UnsupportedReason", } MARKER_ERRORS = {"InvalidFamilyInput", "FamilyTargetBlocked"} @@ -82,6 +84,11 @@ "spouse_bracket_months": (True, "36", 0, -1), "pe_us_revision": TEXT, }, + "BenefitDeduction": { + "reason": (None, "own_earnings_test", g.FamilyKind.SURVIVOR), + "payable": MONEY, + "permanent": BOOL, + }, "BeneficiaryBenefit": { "beneficiary_id": TEXT, "role": (g.FamilyKind.SURVIVOR, "widow"), @@ -102,6 +109,10 @@ "whole_dollar_auxiliary": INTEGER, "whole_dollar_own": INTEGER, "note": (None, 1), + "deduction": MONEY, + "deduction_reason": (True, "own_earnings_test"), + "reserved_work_deduction": MONEY, + "age_reduction_factor": (True, None, F(-1), F(2)), }, "FamilyBenefits": { "kind": (g.OwnBenefitKind.OLD_AGE, "retirement"), @@ -119,6 +130,8 @@ }, "family_maximum_binding": BOOL, "redistribution_applied": BOOL, + "worker_reduced_for_age": BOOL, + "worker_age_reduction_factor": (True, None, F(-1), F(2)), "worker_benefit": OPTIONAL_DIMES, "whole_dollar_worker": INTEGER, "beneficiaries": (None, "invalid", (None,)), @@ -170,6 +183,7 @@ "SavingsClauseGuard": { "first_month": OBJECT, "earlier_months_unknown": BOOL, + "reading": (None, "ssa_operational", g.FamilyKind.RETIREMENT), }, } ) @@ -195,6 +209,24 @@ "params", "standalone", ), + "family_benefits_after_deductions": ( + "state", + "beneficiaries", + "payment_month", + "params", + "deductions", + "households", + "standalone", + "worker_deductions", + ), + "household_benefits_after_deductions": ( + "records", + "payment_month", + "params", + "deductions", + "households", + "worker_deductions", + ), "family_maximum_bend_points": ("eligibility_year", "params"), "family_maximum_formula": ("pia", "eligibility_year", "params"), "floor_dime": ("amount",), @@ -259,6 +291,7 @@ "FamilyOutcome": {"supported"}, "FamilyDenominator": {"supported_weight_share"}, "SavingsClauseGuard": { + "reading", "next_month", "protected_total", "protected_since", @@ -380,6 +413,12 @@ def _argument_errors(function, argument): {"auxiliary": float("inf")}, ) return values if optional else (None, *values) + if argument == "deductions": + return (None, [], {1: None}, {"auxiliary": None}) + if argument == "households": + return (None, [], {1: "h"}, {"auxiliary": 1}, {"auxiliary": ""}) + if argument == "worker_deductions": + return ([], {1: F(0)}, {"auxiliary": True}, {"auxiliary": F(-1)}) if argument == "outcomes": return (None, True, "outcome", (None,), (g.FamilyKind.RETIREMENT,)) if argument == "records": @@ -447,6 +486,9 @@ def _world(pia): "StatutoryRates": g.statutory_rates(PARAMS), "OwnBenefit": own, "Beneficiary": beneficiary, + "BenefitDeduction": g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST + ), "WorkerRecord": worker, "RecordState": state, "BeneficiaryBenefit": result.beneficiaries[0], @@ -456,7 +498,11 @@ def _world(pia): "FamilyOutcome": outcome, "FamilyDenominator": g.count_family_outcomes((outcome,)), } - guard = g.SavingsClauseGuard(NOW, earlier_months_unknown=False) + guard = g.SavingsClauseGuard( + NOW, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) arguments = { "amount": F(pia), "pia": F(pia), @@ -485,6 +531,9 @@ def _world(pia): "deductee_payables": {}, "age_reductions": {}, "other_deductions": {}, + "deductions": {}, + "households": {}, + "worker_deductions": None, "outcomes": (outcome,), "records": {"record": household_record}, "guards": {"record": guard}, diff --git a/tests/test_track_b_gross_benefits_fix_round_10_helpers.py b/tests/test_track_b_gross_benefits_fix_round_10_helpers.py index 9299266e8..88d6cf6b2 100644 --- a/tests/test_track_b_gross_benefits_fix_round_10_helpers.py +++ b/tests/test_track_b_gross_benefits_fix_round_10_helpers.py @@ -28,7 +28,11 @@ def _result(): def test_boolean_pia_is_invalid_before_historical_refusal_and_guard(): - guard = g.SavingsClauseGuard(NOW, earlier_months_unknown=False) + guard = g.SavingsClauseGuard( + NOW, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) before = vars(guard).copy() outcomes = [] with pytest.raises(g.InvalidFamilyInput): @@ -64,7 +68,11 @@ def test_guard_revalidates_entire_result_before_any_state_change( result = _result() # Bypass frozen construction to test defensive public consumption too. object.__setattr__(result, field, value) - guard = g.SavingsClauseGuard(NOW, earlier_months_unknown=False) + guard = g.SavingsClauseGuard( + NOW, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) before = vars(guard).copy() outcomes = [] with pytest.raises(g.InvalidFamilyInput): @@ -82,7 +90,11 @@ def test_guard_revalidates_refusal_before_skipping(): object.__setattr__( refusal, "reason", g.BeneficiaryCondition.GOVERNMENT_PENSION_OFFSET ) - guard = g.SavingsClauseGuard(NOW, earlier_months_unknown=False) + guard = g.SavingsClauseGuard( + NOW, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) before = vars(guard).copy() def compute(): diff --git a/tests/test_track_b_gross_benefits_fix_round_10_objects.py b/tests/test_track_b_gross_benefits_fix_round_10_objects.py index 072ae570a..457ccc0d9 100644 --- a/tests/test_track_b_gross_benefits_fix_round_10_objects.py +++ b/tests/test_track_b_gross_benefits_fix_round_10_objects.py @@ -69,6 +69,9 @@ def _declarations(): "StatutoryRates": g.statutory_rates(PARAMS), "OwnBenefit": own, "Beneficiary": g.Beneficiary("child", g.Role.CHILD), + "BenefitDeduction": g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST + ), "WorkerRecord": g.WorkerRecord(g.FamilyKind.RETIREMENT, 2023, F(0)), "RecordState": state, "HouseholdRecord": g.HouseholdRecord("worker", state), @@ -112,6 +115,7 @@ def test_constructor_corruption_is_an_input_error(case, corrupt): name, field = case if corrupt is True and field in { "entitled", + "permanent", "subject_to_family_maximum", "family_maximum_binding", "redistribution_applied", diff --git a/tests/test_track_b_gross_benefits_fix_round_10_parameters.py b/tests/test_track_b_gross_benefits_fix_round_10_parameters.py index e247ec907..d8e56f363 100644 --- a/tests/test_track_b_gross_benefits_fix_round_10_parameters.py +++ b/tests/test_track_b_gross_benefits_fix_round_10_parameters.py @@ -43,7 +43,11 @@ def _helper(field, bad_value, *, birth_year=1940): def _assert_atomic_rejection(field, bad_value, *, birth_year=1940): - guard = g.SavingsClauseGuard(MONTH, earlier_months_unknown=False) + guard = g.SavingsClauseGuard( + MONTH, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) before = deepcopy(vars(guard)) outcomes = [] @@ -143,7 +147,11 @@ def test_parameter_field_corruption_preserves_guard_and_denominator(case): def test_guard_admit_preserves_identity_but_stores_validated_history(): first = _valid_result() - guard = g.SavingsClauseGuard(MONTH, earlier_months_unknown=False) + guard = g.SavingsClauseGuard( + MONTH, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) # Numeric strings remain valid inputs, but changing even an equivalent # field on a computed result violates its round-11 provenance seal. before = vars(guard).copy() diff --git a/tests/test_track_b_gross_benefits_fix_round_11_seals.py b/tests/test_track_b_gross_benefits_fix_round_11_seals.py index 860b17d37..5d7869247 100644 --- a/tests/test_track_b_gross_benefits_fix_round_11_seals.py +++ b/tests/test_track_b_gross_benefits_fix_round_11_seals.py @@ -81,7 +81,11 @@ def test_review_altered_age_rate_cannot_lower_savings_clause_protection(): assert row.age_adjusted_rate == row.auxiliary_payable == F("0.40") with pytest.raises(g.InvalidFamilyInput): replace(row, age_adjusted_rate=F(0)) - guard = g.SavingsClauseGuard(JAN, earlier_months_unknown=False) + guard = g.SavingsClauseGuard( + JAN, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) outcomes = [ guard.evaluate("January", 1, lambda: january), guard.evaluate("February", 1, lambda: february), @@ -129,7 +133,11 @@ def test_every_consumer_rejects_unsealed_or_altered_results( for key, value in _values(result).items(): object.__setattr__(forged, key, value) result = forged - guard = g.SavingsClauseGuard(JAN, earlier_months_unknown=False) + guard = g.SavingsClauseGuard( + JAN, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) before = vars(guard).copy() with pytest.raises(g.InvalidFamilyInput): if consumer == "evaluate": @@ -195,7 +203,11 @@ def inconsistent(*args, **kwargs): def test_guard_history_is_detached_from_caller_result(extra): pia, maximum = F(11 + 2 * extra, 10), F(19 + 4 * extra, 10) january = _family(pia=pia, maximum=maximum) - guard = g.SavingsClauseGuard(JAN, earlier_months_unknown=False) + guard = g.SavingsClauseGuard( + JAN, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) assert guard.admit(january) is january object.__setattr__(january.beneficiaries[0], "age_adjusted_rate", F(0)) outcome = guard.evaluate( @@ -271,7 +283,11 @@ def test_property_changed_outcome_never_counts_or_advances(extra, weight): object.__setattr__(outcome, "weight", weight + extra) with pytest.raises(g.InvalidFamilyInput): g.count_family_outcomes([outcome]) - guard = g.SavingsClauseGuard(JAN, earlier_months_unknown=False) + guard = g.SavingsClauseGuard( + JAN, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) before = vars(guard).copy() object.__setattr__(family.beneficiaries[0], "age_adjusted_rate", F(0)) with pytest.raises(g.InvalidFamilyInput): diff --git a/tests/test_track_b_gross_benefits_fix_round_12_contract.py b/tests/test_track_b_gross_benefits_fix_round_12_contract.py index e2e326c26..1d2368c72 100644 --- a/tests/test_track_b_gross_benefits_fix_round_12_contract.py +++ b/tests/test_track_b_gross_benefits_fix_round_12_contract.py @@ -399,7 +399,11 @@ def invalid(): def test_g_money_consumers_reject_other_layer_results_and_outcomes(layer): result = COMPUTE[layer]() row = _outcome(layer) - guard = g.SavingsClauseGuard(JAN, earlier_months_unknown=False) + guard = g.SavingsClauseGuard( + JAN, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) with pytest.raises(g.InvalidFamilyInput): g.evaluate_family("wrong-result", 1, lambda: result) with pytest.raises(g.InvalidFamilyInput): @@ -420,7 +424,11 @@ def test_g_guard_and_report_reject_sibling_refusal_reasons(layer, monkeypatch): def refuse(): raise error - guard = g.SavingsClauseGuard(JAN, earlier_months_unknown=False) + guard = g.SavingsClauseGuard( + JAN, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) with pytest.raises(g.InvalidFamilyInput): guard.evaluate("wrong-reason", 1, refuse) monkeypatch.setattr( diff --git a/tests/test_track_b_gross_benefits_fix_round_13_audit.py b/tests/test_track_b_gross_benefits_fix_round_13_audit.py index fd66f39e0..cd8049468 100644 --- a/tests/test_track_b_gross_benefits_fix_round_13_audit.py +++ b/tests/test_track_b_gross_benefits_fix_round_13_audit.py @@ -71,12 +71,14 @@ "NESEProrationPolicy", "WorkEarnings", "RETBeneficiary", + "RETFamilyMonth", "RecordYear", "calculated_excess", "countable_earnings", "PartialPaymentAllocation", "partial_payments", "BeneficiaryMonth", + "RedistributedBeneficiaryMonth", "WorkerLedger", "RETLedger", "apply_ret_year", @@ -158,6 +160,8 @@ def test_cross_layer_public_names_and_members_have_explicit_audit_coverage(): "RecordCondition", "BeneficiaryCondition", "OwnBenefitKind", + "SavingsClauseReading", + "DeductionReason", } ) for module, names in PUBLIC_NAMES.items(): @@ -434,6 +438,8 @@ def test_object_new_declarations_do_not_hide_missing_fields(case): @cache def _sealed_samples(): + from tests.test_track_b_ret_ledger_deductions import family_record + objects, _, _ = _world(100) samples = { type(value).__name__: value @@ -458,6 +464,14 @@ def _sealed_samples(): ledger = COMPUTE["ret"]() samples["WorkerLedger"] = ledger.workers[0] samples["BeneficiaryMonth"] = ledger.months[0] + redistributed = ret.apply_ret_year( + family_record(separate=True), load_ret_parameters() + ) + samples["RedistributedBeneficiaryMonth"] = next( + row + for row in redistributed.months + if type(row) is ret.RedistributedBeneficiaryMonth + ) samples["PartialPaymentAllocation"] = ret.partial_payments( 1, {"nh": 2}, {"nh": 2} ) @@ -478,6 +492,7 @@ def _sealed_samples(): "RETConfigurationUnsupported", "PartialPaymentAllocation", "BeneficiaryMonth", + "RedistributedBeneficiaryMonth", "WorkerLedger", "RETLedger", "RETOutcome", diff --git a/tests/test_track_b_gross_benefits_fix_round_13_guard.py b/tests/test_track_b_gross_benefits_fix_round_13_guard.py index 63a69dd7e..3dad11d9d 100644 --- a/tests/test_track_b_gross_benefits_fix_round_13_guard.py +++ b/tests/test_track_b_gross_benefits_fix_round_13_guard.py @@ -89,7 +89,9 @@ def test_guard_rejects_uninitialized_instances_at_every_public_entry(entry): ) def test_guard_denies_copy_and_serialization(operation, populated): guard = g.SavingsClauseGuard( - g.YearMonth(2026, 1), earlier_months_unknown=False + g.YearMonth(2026, 1), + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, ) if populated: guard.admit(_family(1)) @@ -112,7 +114,9 @@ class OtherGuard(g.SavingsClauseGuard): def test_review_next_month_mutation_cannot_skip_qualifying_february(): guard = g.SavingsClauseGuard( - g.YearMonth(2026, 1), earlier_months_unknown=False + g.YearMonth(2026, 1), + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, ) january, february, march = ( _family(1, children=1), @@ -135,7 +139,9 @@ def test_review_next_month_mutation_cannot_skip_qualifying_february(): assert guard.protected_total == F("1.90") assert g.count_family_outcomes([outcome]).unsupported_rows == 1 skipped = g.SavingsClauseGuard( - g.YearMonth(2026, 1), earlier_months_unknown=False + g.YearMonth(2026, 1), + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, ) skipped.admit(january) skipped.skip(g.YearMonth(2026, 2), pia=F("1.10")) @@ -162,7 +168,9 @@ def test_review_next_month_mutation_cannot_skip_qualifying_february(): def test_guard_every_public_snapshot_is_detached(accessor, changed_month): guards = [ g.SavingsClauseGuard( - g.YearMonth(2026, 1), earlier_months_unknown=False + g.YearMonth(2026, 1), + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, ) for _ in range(2) ] @@ -206,9 +214,15 @@ def test_guard_admitted_objects_cannot_change_later_decisions( ): first_month = g.YearMonth(2026, 1) guards = [ - g.SavingsClauseGuard(first_month, earlier_months_unknown=False), g.SavingsClauseGuard( - g.YearMonth(2026, 1), earlier_months_unknown=False + first_month, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ), + g.SavingsClauseGuard( + g.YearMonth(2026, 1), + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, ), ] january = _family(1) @@ -256,7 +270,9 @@ def __gt__(self, other): return self.value > other control = g.SavingsClauseGuard( - g.YearMonth(2026, 1), earlier_months_unknown=False + g.YearMonth(2026, 1), + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, ) control.admit(_family(1)) assert _decision(control, _family(2, F("1.20")))[1] is ( @@ -269,7 +285,9 @@ def __gt__(self, other): except g.InvalidFamilyInput: return # Numeric subclasses may be rejected at the first boundary. guard = g.SavingsClauseGuard( - g.YearMonth(2026, 1), earlier_months_unknown=False + g.YearMonth(2026, 1), + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, ) guard.admit(january) pia.value = F("1.30") @@ -285,7 +303,9 @@ def __gt__(self, other): def test_guard_detaches_weight_before_calling_computation(numerator, changed): weight = F(numerator, 3) guard = g.SavingsClauseGuard( - g.YearMonth(2026, 1), earlier_months_unknown=False + g.YearMonth(2026, 1), + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, ) def compute(): diff --git a/tests/test_track_b_gross_benefits_fix_round_15_receivers.py b/tests/test_track_b_gross_benefits_fix_round_15_receivers.py index 5293cc7bf..6fba05ea3 100644 --- a/tests/test_track_b_gross_benefits_fix_round_15_receivers.py +++ b/tests/test_track_b_gross_benefits_fix_round_15_receivers.py @@ -415,7 +415,9 @@ def test_direct_post_init_revalidates_sealed_result_before_field_hooks(layer): def test_valid_guard_identity_and_month_membership_comparisons_stay_usable(): guard = g.SavingsClauseGuard( - g.YearMonth(2026, 1), earlier_months_unknown=False + g.YearMonth(2026, 1), + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, ) assert guard == guard assert not (guard != guard) @@ -879,7 +881,9 @@ def __eq__(self, other): own = g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, 100) result = COMPUTE["g"]() guard = g.SavingsClauseGuard( - g.YearMonth(2026, 1), earlier_months_unknown=False + g.YearMonth(2026, 1), + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, ) params = ssa_params() if kind == "statutory-input": diff --git a/tests/test_track_b_gross_benefits_fix_round_3_rates.py b/tests/test_track_b_gross_benefits_fix_round_3_rates.py index 2e5c71e67..ef7a76834 100644 --- a/tests/test_track_b_gross_benefits_fix_round_3_rates.py +++ b/tests/test_track_b_gross_benefits_fix_round_3_rates.py @@ -82,7 +82,11 @@ def household(): return household() if entry_point == "household-month-outcome": guards = { - key: g.SavingsClauseGuard(NOW, earlier_months_unknown=False) + key: g.SavingsClauseGuard( + NOW, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) for key in records } try: diff --git a/tests/test_track_b_gross_benefits_fix_round_5_cohorts.py b/tests/test_track_b_gross_benefits_fix_round_5_cohorts.py index 10ae3f108..422953546 100644 --- a/tests/test_track_b_gross_benefits_fix_round_5_cohorts.py +++ b/tests/test_track_b_gross_benefits_fix_round_5_cohorts.py @@ -87,7 +87,11 @@ def household(): return g.household_benefits(records, payment_month=NOW, params=PARAMS) if entry == "household-month-outcome": - guard = g.SavingsClauseGuard(NOW, earlier_months_unknown=False) + guard = g.SavingsClauseGuard( + NOW, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) try: result = g.household_month_outcome( records, diff --git a/tests/test_track_b_gross_benefits_fix_round_6_cohorts.py b/tests/test_track_b_gross_benefits_fix_round_6_cohorts.py index 216a028fd..09bab1e2f 100644 --- a/tests/test_track_b_gross_benefits_fix_round_6_cohorts.py +++ b/tests/test_track_b_gross_benefits_fix_round_6_cohorts.py @@ -93,7 +93,11 @@ def _run( ): original = deepcopy(records) guards = { - key: g.SavingsClauseGuard(NOW, earlier_months_unknown=False) + key: g.SavingsClauseGuard( + NOW, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) for key in records } try: diff --git a/tests/test_track_b_gross_benefits_fix_round_7_cohorts.py b/tests/test_track_b_gross_benefits_fix_round_7_cohorts.py index d7172e925..71a67d7ec 100644 --- a/tests/test_track_b_gross_benefits_fix_round_7_cohorts.py +++ b/tests/test_track_b_gross_benefits_fix_round_7_cohorts.py @@ -70,7 +70,11 @@ def _records(months, *, cohort=1935, gpo=False, explicit=False, style="built"): def _run(records, entry): original = deepcopy(records) guards = { - key: g.SavingsClauseGuard(NOW, earlier_months_unknown=False) + key: g.SavingsClauseGuard( + NOW, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) for key in records } try: diff --git a/tests/test_track_b_gross_benefits_fix_round_7_history.py b/tests/test_track_b_gross_benefits_fix_round_7_history.py index d168b69c9..883abe045 100644 --- a/tests/test_track_b_gross_benefits_fix_round_7_history.py +++ b/tests/test_track_b_gross_benefits_fix_round_7_history.py @@ -46,7 +46,11 @@ def _case(cohort=1912, months=1, *, own_pia=F(1000), placement="own"): def _outcome(state, member, entry, *, weight=F(7, 3)): records = {"record": g.HouseholdRecord("worker", state, (member,))} if entry == "household-month-outcome": - guard = g.SavingsClauseGuard(NOW, earlier_months_unknown=False) + guard = g.SavingsClauseGuard( + NOW, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) try: outcome = g.household_month_outcome( records, diff --git a/tests/test_track_b_gross_benefits_fix_round_8_entries.py b/tests/test_track_b_gross_benefits_fix_round_8_entries.py index 7333be748..8adbc9155 100644 --- a/tests/test_track_b_gross_benefits_fix_round_8_entries.py +++ b/tests/test_track_b_gross_benefits_fix_round_8_entries.py @@ -47,7 +47,11 @@ def _gpo_divorced_spouse(): @pytest.mark.parametrize("route", ROUTES) @pytest.mark.parametrize("pia", (F(0), F(1000))) def test_review_unclaimed_eligibility_error_precedes_gpo_and_guard(route, pia): - guard = g.SavingsClauseGuard(NOW, earlier_months_unknown=False) + guard = g.SavingsClauseGuard( + NOW, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) with pytest.raises( g.InvalidFamilyInput, match="eligibility_year exceeds birth year" ): @@ -83,7 +87,11 @@ def test_review_unclaimed_eligibility_error_precedes_gpo_and_guard(route, pia): @pytest.mark.parametrize("built", (False, True)) def test_valid_unclaimed_eligibility_gpo_stays_in_denominator(built): state = _unclaimed(eligibility=1997, built=built) - guard = g.SavingsClauseGuard(NOW, earlier_months_unknown=False) + guard = g.SavingsClauseGuard( + NOW, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) outcome = g.household_month_outcome( { "record": g.HouseholdRecord( @@ -254,7 +262,11 @@ def _capture(compute): def _guarded(records, month): guards = { - key: g.SavingsClauseGuard(month, earlier_months_unknown=False) + key: g.SavingsClauseGuard( + month, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) for key in records } try: diff --git a/tests/test_track_b_gross_benefits_fix_round_8_history.py b/tests/test_track_b_gross_benefits_fix_round_8_history.py index acc1814a7..251aed08c 100644 --- a/tests/test_track_b_gross_benefits_fix_round_8_history.py +++ b/tests/test_track_b_gross_benefits_fix_round_8_history.py @@ -58,7 +58,11 @@ def _case(role, cohort=1912, months=1, pia=F(1000)): def _outcome(state, members, entry, weight=F(7, 3)): records = {"record": g.HouseholdRecord("worker", state, tuple(members))} if entry == "household-month-outcome": - guard = g.SavingsClauseGuard(NOW, earlier_months_unknown=False) + guard = g.SavingsClauseGuard( + NOW, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) try: outcome = g.household_month_outcome( records, diff --git a/tests/test_track_b_gross_benefits_fix_round_9_outcomes.py b/tests/test_track_b_gross_benefits_fix_round_9_outcomes.py index b4a0bbb4e..bd29ef654 100644 --- a/tests/test_track_b_gross_benefits_fix_round_9_outcomes.py +++ b/tests/test_track_b_gross_benefits_fix_round_9_outcomes.py @@ -40,7 +40,11 @@ def _benefits(): def _guard(): - return g.SavingsClauseGuard(NOW, earlier_months_unknown=False) + return g.SavingsClauseGuard( + NOW, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) @pytest.mark.parametrize("guarded", (False, True)) diff --git a/tests/test_track_b_gross_benefits_fix_round_9_validation.py b/tests/test_track_b_gross_benefits_fix_round_9_validation.py index d342d09d3..be771562f 100644 --- a/tests/test_track_b_gross_benefits_fix_round_9_validation.py +++ b/tests/test_track_b_gross_benefits_fix_round_9_validation.py @@ -77,7 +77,11 @@ def test_review_malformed_inputs_precede_refusal_and_guard( route, malformation ): guards = { - "record": g.SavingsClauseGuard(NOW, earlier_months_unknown=False), + "record": g.SavingsClauseGuard( + NOW, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ), } def compute(): @@ -341,7 +345,9 @@ def test_malformed_field_never_counts_or_advances_any_entry( for route in _applicable_routes(cls): guards = { "record": g.SavingsClauseGuard( - NOW, earlier_months_unknown=False + NOW, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, ), } _assert_invalid( @@ -392,7 +398,11 @@ def test_guard_constructor_rejects_malformed_public_arguments( first_month, unknown ): with pytest.raises(g.InvalidFamilyInput): - g.SavingsClauseGuard(first_month, earlier_months_unknown=unknown) + g.SavingsClauseGuard( + first_month, + earlier_months_unknown=unknown, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) @pytest.mark.parametrize("name,bad", (("year", True), ("month", 13))) @@ -400,7 +410,11 @@ def test_guard_revalidates_nested_first_month(name, bad): first = g.YearMonth(2023, 12) object.__setattr__(first, name, bad) with pytest.raises(g.InvalidFamilyInput): - g.SavingsClauseGuard(first, earlier_months_unknown=False) + g.SavingsClauseGuard( + first, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) CROSS_FIELD_CASES = ( @@ -508,7 +522,11 @@ def test_cross_field_errors_precede_refusal_in_every_entry(case, pia, cohort): ) for route in routes: guards = { - "record": g.SavingsClauseGuard(NOW, earlier_months_unknown=False), + "record": g.SavingsClauseGuard( + NOW, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ), } _assert_invalid( partial( @@ -525,7 +543,11 @@ def test_terminal_calendar_month_errors_leave_every_guard_unchanged( refusing, route ): month = g.YearMonth(9999, 12) - guard = g.SavingsClauseGuard(month, earlier_months_unknown=False) + guard = g.SavingsClauseGuard( + month, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) _, state, beneficiary = _valid_inputs(1000, 1940, refusing) guards = {"record": guard} diff --git a/tests/test_track_b_gross_benefits_properties.py b/tests/test_track_b_gross_benefits_properties.py index bcdfb9c05..dbce8bd34 100644 --- a/tests/test_track_b_gross_benefits_properties.py +++ b/tests/test_track_b_gross_benefits_properties.py @@ -848,7 +848,11 @@ def test_savings_clause_contract_across_a_cola(family, tenths): except g.FamilyConfigurationUnsupported: assume(False) total = g.savings_clause_total - guard = g.SavingsClauseGuard(COLA_MONTHS[0], earlier_months_unknown=False) + guard = g.SavingsClauseGuard( + COLA_MONTHS[0], + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) assert guard.admit(before) is before try: guard.admit(after) @@ -914,7 +918,11 @@ def state(increases): after = _compute(after_state, raised_members, COLA_MONTHS[1]) except g.FamilyConfigurationUnsupported: assume(False) - guard = g.SavingsClauseGuard(COLA_MONTHS[0], earlier_months_unknown=False) + guard = g.SavingsClauseGuard( + COLA_MONTHS[0], + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) assert after.available_for_auxiliaries >= before.available_for_auxiliaries total = g.savings_clause_total qualifying_increase = after.pia > before.pia and _qualifies(before) @@ -1002,7 +1010,9 @@ def test_savings_clause_guard_along_month_paths(path): * a path whose PIA never rises is never refused. """ guard = g.SavingsClauseGuard( - path[0].payment_month, earlier_months_unknown=False + path[0].payment_month, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, ) total = g.savings_clause_total protected = [] @@ -1091,7 +1101,9 @@ def test_a_reduced_joiner_after_a_cola_is_refused_iff_the_total_falls( assume(False) total = g.savings_clause_total guard = g.SavingsClauseGuard( - g.YearMonth(2026, 10), earlier_months_unknown=False + g.YearMonth(2026, 10), + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, ) guard.admit(path[0]) prior_refused = False diff --git a/tests/test_track_b_gross_benefits_registry.py b/tests/test_track_b_gross_benefits_registry.py index 4819f65b5..2bbf1f64c 100644 --- a/tests/test_track_b_gross_benefits_registry.py +++ b/tests/test_track_b_gross_benefits_registry.py @@ -90,9 +90,24 @@ def _worker_record(raw): return g.record_state(g.WorkerRecord(**raw), PARAMS) -def _family_output(state, members, month): - result = g.family_benefits( - state, members, payment_month=month, params=PARAMS, standalone=True +def _family_output(state, members, month, *, deductions=None, households=None): + compute = ( + g.family_benefits + if deductions is None + else g.family_benefits_after_deductions + ) + extra = ( + {} + if deductions is None + else {"deductions": deductions, "households": households or {}} + ) + result = compute( + state, + members, + payment_month=month, + params=PARAMS, + standalone=True, + **extra, ) rows = result.by_id() own = sum((row.own_benefit or F(0) for row in rows.values()), F(0)) @@ -157,14 +172,27 @@ def _family_output(state, members, month): def _scenario(raw): operation = raw["operation"] month = g.YearMonth(*raw.get("month", [2026, 1])) - if operation == "family": + if operation in ("family", "family_after_deductions"): state = ( _worker_record(raw["worker_record"]) if "worker_record" in raw else _state(raw["state"]) ) - return _family_output(state, _members(raw["members"]), month) - if operation == "household": + extra = {} + if operation == "family_after_deductions": + extra = { + "deductions": { + key: g.BenefitDeduction( + g.DeductionReason(value["reason"]), + F(value.get("payable", "0")), + value.get("permanent", True), + ) + for key, value in raw.get("deductions", {}).items() + }, + "households": raw.get("households", {}), + } + return _family_output(state, _members(raw["members"]), month, **extra) + if operation in ("household", "household_after_deductions"): records = { key: g.HouseholdRecord( record["worker_id"], @@ -173,9 +201,17 @@ def _scenario(raw): ) for key, record in raw["records"].items() } - result = g.household_benefits( - records, payment_month=month, params=PARAMS + compute = ( + g.household_benefits + if operation == "household" + else g.household_benefits_after_deductions ) + extra = ( + {} + if operation == "household" + else {"deductions": {}, "households": raw.get("households", {})} + ) + result = compute(records, payment_month=month, params=PARAMS, **extra) return { "result": result, "records": { @@ -423,6 +459,21 @@ def _rounded(value, rule): ), }, "poms_gn_02603_060": { + "A.1": (("1. Full deduction", "2. Full deduction and"),), + "A.2": (("2. Full deduction and", "3. Full work deduction"),), + "B.1": ( + ( + "B. Examples of permanent partial deductions", + "C. Examples of temporary deductions", + ), + ("1. Partial deduction", "2. Partial deduction and"), + ), + "C.1": ( + ("1. Temporary work deduction", "2. Temporary work deduction and"), + ), + "C.2": ( + ("2. Temporary work deduction and", "To Link to this section"), + ), "A.5": ( ( "A. Examples of permanent full deductions", @@ -468,6 +519,13 @@ def _rounded(value, rule): ("b. No Increase in Amount", None), ), }, + "poms_rs_02501_130": { + "B": (("B. Example of excess earnings", "To Link to this section"),), + }, + "poms_rs_02501_160": { + "B.1": (("EXAMPLE 1:", "EXAMPLE 2:"),), + "B.2": (("EXAMPLE 2:", "To Link to this section"),), + }, } @@ -658,6 +716,11 @@ def test_survivor_snapshot_attestations_are_supported_by_capture_facts(): for name, raw in example["inputs"]["scenarios"].items() if raw.get("state", {}).get("kind") == "survivor" } + for key, (example, _) in snapshots.items(): + if example["id"].startswith("gn-02603-060-"): + facts[key] = "A parent (E)" + elif example["id"].startswith("rs-02501-160-"): + facts[key] = "A widow and three children are entitled in January" assert set(snapshots) == set(facts) for key, (example, state) in snapshots.items(): assert state["widow_drc_savings_clause"] is False, key @@ -686,6 +749,9 @@ def test_registry_schema_and_declared_figures_are_complete(): FEATURE_CLASSES = { + "deduction:own_earnings", + "deduction:no_child_in_care", + "deduction:temporary", "reduction:worker", "reduction:spouse", "reduction:widow", diff --git a/tests/test_track_b_gross_benefits_review.py b/tests/test_track_b_gross_benefits_review.py index 1846c2e57..9d6eab0c5 100644 --- a/tests/test_track_b_gross_benefits_review.py +++ b/tests/test_track_b_gross_benefits_review.py @@ -372,7 +372,9 @@ def test_review_child_departure_six_months_after_cola_refuses_later_widow(): g.Beneficiary("c2", g.Role.CHILD), ] guard = g.SavingsClauseGuard( - g.YearMonth(2020, 1), earlier_months_unknown=False + g.YearMonth(2020, 1), + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, ) for month in _months_between(g.YearMonth(2020, 1), g.YearMonth(2025, 11)): guard.admit(_family(state, members, month)) @@ -429,7 +431,11 @@ def test_review_guarded_household_keeps_refused_record_and_denominator( if reverse: records = dict(reversed(list(records.items()))) guards = { - key: g.SavingsClauseGuard(first, earlier_months_unknown=False) + key: g.SavingsClauseGuard( + first, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) for key in records } admitted = g.household_month_outcome( @@ -476,7 +482,11 @@ def test_review_guarded_household_input_error_does_not_advance_guards(reverse): if reverse: records = dict(reversed(list(records.items()))) guards = { - key: g.SavingsClauseGuard(month, earlier_months_unknown=False) + key: g.SavingsClauseGuard( + month, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) for key in records } with pytest.raises(g.InvalidFamilyInput): @@ -499,7 +509,11 @@ def test_review_guard_aliases_are_input_errors_before_any_advance( } if reverse: records = dict(reversed(list(records.items()))) - shared = g.SavingsClauseGuard(month, earlier_months_unknown=False) + shared = g.SavingsClauseGuard( + month, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) with pytest.raises(g.InvalidFamilyInput): g.household_month_outcome( records, @@ -514,7 +528,11 @@ def test_review_guard_aliases_are_input_errors_before_any_advance( child = g.Beneficiary("c", g.Role.CHILD) records["second"] = g.HouseholdRecord("b", _retired(), [child, child]) distinct_guards = { - key: g.SavingsClauseGuard(month, earlier_months_unknown=False) + key: g.SavingsClauseGuard( + month, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) for key in records } with pytest.raises(g.InvalidFamilyInput): diff --git a/tests/test_track_b_gross_benefits_savings.py b/tests/test_track_b_gross_benefits_savings.py new file mode 100644 index 000000000..c35c22f8e --- /dev/null +++ b/tests/test_track_b_gross_benefits_savings.py @@ -0,0 +1,552 @@ +"""Statutory conformance: operational 203(a)(5), invented families only. + +No population, behavioral or forecast claim. Captures pin RS 00630.400's +conditions and two life-case procedures; invented arithmetic pins dimes. +""" + +import os +import subprocess +import sys +from dataclasses import replace +from fractions import Fraction as F +from pathlib import Path + +import pytest +from hypothesis import example, given, settings +from hypothesis import strategies as st + +from populace_dynamics.track_b import gross_benefits as g +from tests.track_b_gross_benefit_support import source_text, ssa_params + +PARAMS = ssa_params() +JAN = g.YearMonth(2026, 1) +OPERATIONAL = g.SavingsClauseReading.SSA_OPERATIONAL +LITERAL = g.SavingsClauseReading.LITERAL_REFUSAL + + +def family( + month=1, + pia=F(1000), + maximum=F(1500), + *, + reduction=60, + spouse=False, + spouse_months=60, + children=2, + reverse=False, +): + state = g.RecordState( + g.FamilyKind.RETIREMENT, + pia, + maximum, + worker=g.OwnBenefit( + g.OwnBenefitKind.OLD_AGE, pia, reduction_months=reduction + ), + ) + rows = [g.Beneficiary(f"C{i}", g.Role.CHILD) for i in range(children)] + if spouse: + rows.append( + g.Beneficiary("S", g.Role.SPOUSE, reduction_months=spouse_months) + ) + return g.family_benefits( + state, + rows[::-1] if reverse else rows, + payment_month=g.YearMonth(2026, month), + params=PARAMS, + standalone=True, + ) + + +def guard(reading=OPERATIONAL): + return g.SavingsClauseGuard( + JAN, earlier_months_unknown=False, reading=reading + ) + + +def refusal_case(reason): + """Public-computation witnesses used by the complete refusal catalog.""" + value = guard() + value.admit(family()) + if reason is g.UnsupportedReason.SAVINGS_CLAUSE_RATE_PROCEDURE: + # One reduced spouse alone has no remaining auxiliaries for .400's + # final division. A deliberately falling formula MAX exposes it. + value = guard() + value.admit(family(spouse=True, children=0, maximum=F(1400))) + return value.admit( + family(2, F(1010), F(1300), spouse=True, children=0) + ) + value.admit(family(2, F(1010))) + return value.admit(family(3, F(1010), children=1)) + + +def test_operational_source_rules_are_quoted_from_captures(): + text = source_text("poms_rs_00630_400") + for quote in ( + "Two or more persons are entitled to monthly benefits;", + "Benefits for that month are reduced for the MAX and at least one beneficiary is reduced for age;", + "PIA is increased the following month;", + "Total family payment is less after the PIA increase than it was before.", + "Family Payments Before PIA Increase, less Reduced Rate After Increase = Difference.", + "Difference ÷ By the Number of Auxiliaries (rounded) = Auxiliary Rate;", + "Reduce Increase by spouse appropriate reduction factor (RF).", + "Difference ÷ the Number of Auxiliaries Rounded = Increase.", + "Difference ÷ the Number of Remaining Auxiliaries (rounded).", + "The established FMAX will not change—only total benefits payable are affected.", + ): + assert quote in text + assert ( + "Once a saving clause is established, it will continue in effect " + "until the table or formula maximum becomes larger." + ) in source_text("poms_rs_00615_801") + assert ( + "it is possible that the savings clause maximum may again become " + "payable if the total payable under the savings clause exceeds " + "that payable using the table or formula maximum." + ) in source_text("poms_rs_00615_801") + assert ( + "smallest amount that would have been required in order to assure " + "that the total of monthly benefits payable on the basis of such " + "wages and self-employment income for any such subsequent month " + "will not be less" + ) in source_text("ssa_act_203") + + +def test_default_is_operational_and_literal_is_explicit(): + assert ( + g.SavingsClauseGuard(JAN, earlier_months_unknown=False).reading + is OPERATIONAL + ) + assert guard(LITERAL).reading is LITERAL + for bad in ("ssa_operational", None, True, g.FamilyKind.RETIREMENT): + with pytest.raises(g.InvalidFamilyInput): + guard(bad) + + +def test_first_guard_constructor_registers_its_enum_in_fresh_process(): + script = """ +from populace_dynamics.track_b import gross_benefits as g +value = g.SavingsClauseGuard(g.YearMonth(2026, 1), + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL) +assert value.reading is g.SavingsClauseReading.LITERAL_REFUSAL +""" + result = subprocess.run( + [sys.executable, "-c", script], + cwd=Path(__file__).parents[1], + env=os.environ.copy(), + text=True, + capture_output=True, + ) + assert result.returncode == 0, result.stderr + + +def test_operational_worker_reduction_protects_payment_not_maximum(): + before, after = family(), family(2, F(1010)) + assert before.record_total == F(1200) + assert after.record_total == F(1197) + value = guard() + assert value.admit(before) is before + outcome = value.evaluate("February", F(3), lambda: after) + paid = outcome.benefits + assert paid.record_total == F(1200) + assert paid.worker_benefit == F(707) + assert [row.auxiliary_payable for row in paid.beneficiaries] == [ + F("246.50") + ] * 2 + assert [row.family_maximum_rate for row in paid.beneficiaries] == [ + F(245) + ] * 2 + assert paid.family_maximum == after.family_maximum == F(1500) + assert paid.subject_total == after.subject_total == F(1500) + assert paid.record_total_whole_dollars == 1199 + assert value.protected_total == F(1200) + assert value.protected_since == JAN + assert g.count_family_outcomes([outcome]).supported_weight == F(3) + with pytest.raises(g.InvalidFamilyInput): + replace(paid, record_total=F(1201)) + + +def test_operational_spouse_procedure_uses_unrounded_declared_factor(): + before = family(spouse=True) + after = family(2, F(1010), spouse=True) + assert before.record_total == F("1141.40") + assert after.record_total == F("1139.70") + assert after.by_id()["S"].age_reduction_factor == F(65, 100) + value = guard() + value.admit(before) + paid = value.admit(after) + # 1.70 / 3 -> .60; spouse increase floor(.60*.65)=.30. + # Children: (1141.40 - 707 - 106.40)/2 = 164 each. + assert paid.by_id()["S"].auxiliary_payable == F("106.40") + assert paid.by_id()["C0"].auxiliary_payable == F(164) + assert paid.by_id()["C1"].auxiliary_payable == F(164) + assert paid.record_total == F("1141.40") + assert paid.record_total_whole_dollars == 1141 + + +def test_operational_rounding_is_minimum_equal_dime_that_preserves_total(): + value = guard() + value.admit(family()) + paid = value.admit(family(2, F(1001))) + # 1200 - 700.70 = 499.30; equal rates 249.65 round up to 249.70. + # Rounding down to 249.60 would pay 1199.90, below 1200. + assert paid.record_total == F("1200.10") + assert paid.by_id()["C0"].auxiliary_payable == F("249.70") + assert paid.record_total - F("0.20") < F(1200) + + +def test_operational_carries_and_can_become_payable_again(): + value = guard() + value.admit(family()) + assert value.admit(family(2, F(1010))).record_total == F(1200) + assert value.admit(family(3, F(1010))).record_total == F(1200) + above = family(4, F(1010), F(1600)) + assert value.admit(above) is above + assert value.protected_total == F(1200) + assert value.admit(family(5, F(1010))).record_total == F(1200) + + +@pytest.mark.parametrize( + "reason", + [ + g.UnsupportedReason.SAVINGS_CLAUSE_MEMBERSHIP_CHANGE, + g.UnsupportedReason.SAVINGS_CLAUSE_RATE_PROCEDURE, + ], +) +def test_operational_named_refusals_stay_in_denominator(reason): + outcome = g.evaluate_family("refused", F(7), lambda: refusal_case(reason)) + assert outcome.unsupported.reason is reason + counts = g.count_family_outcomes([outcome]) + assert counts.unsupported_by_reason == {reason: (1, F(7))} + + +def test_operational_child_departure_never_starts_without_pia_increase(): + value = guard() + value.admit(family()) + after = family(2, children=1) + assert value.admit(after) is after + assert value.protected_total is None + + +def test_round_11_cola_fall_requires_age_reduction_operationally(): + # Actual formula/COLA witness from #530 round 11: unequal survivor + # shares change from 2.40 + 2.40 + 1.80 to 2.40 + 2.40 + 1.70. + members = [ + g.Beneficiary(f"W{i}", g.Role.WIDOW, child_in_care=False) + for i in range(2) + ] + [g.Beneficiary("M", g.Role.MOTHER_FATHER)] + results = [] + for month, colas in ((1, ()), (2, (F("2.3"),))): + state = replace( + g.record_state( + g.WorkerRecord( + g.FamilyKind.SURVIVOR, + 2026, + F("4.40"), + cola_percents=colas, + ), + PARAMS, + ), + widow_drc_savings_clause=False, + ) + results.append( + g.family_benefits( + state, + members, + payment_month=g.YearMonth(2026, month), + params=PARAMS, + standalone=True, + ) + ) + before, after = results + assert (before.pia, after.pia) == (F("4.40"), F("4.50")) + assert (before.family_maximum, after.family_maximum) == ( + F("6.60"), + F("6.70"), + ) + assert (before.record_total, after.record_total) == (F("6.60"), F("6.50")) + value = guard() + value.admit(before) + assert value.admit(after) is after + assert value.protected_total is None + literal = guard(LITERAL) + literal.admit(before) + with pytest.raises(g.FamilyConfigurationUnsupported) as caught: + literal.admit(after) + assert caught.value.reason is g.UnsupportedReason.SAVINGS_CLAUSE + + +@settings(max_examples=60, deadline=None, derandomize=True) +@given( + st.integers(100, 2000), + st.integers(0, 60), + st.integers(0, 20), + st.sampled_from((OPERATIONAL, LITERAL)), +) +def test_both_readings_start_exactly_on_their_conditions( + pia, reduction, rise, reading +): + before = family(pia=F(pia), maximum=F(3 * pia, 2), reduction=reduction) + after = family(2, F(pia) + F(rise, 10), F(3 * pia, 2), reduction=reduction) + value = guard(reading) + value.admit(before) + falls = after.record_total < before.record_total + if reading is LITERAL and rise and falls: + with pytest.raises(g.FamilyConfigurationUnsupported) as caught: + value.admit(after) + assert caught.value.reason is g.UnsupportedReason.SAVINGS_CLAUSE + else: + paid = value.admit(after) + starts = ( + bool(rise and reduction and falls) + if reading is OPERATIONAL + else bool(rise) + ) + assert (value.protected_total is not None) is starts + if starts and reading is OPERATIONAL: + assert paid.record_total >= before.record_total + assert paid.family_maximum == after.family_maximum + assert paid.subject_total == after.subject_total + assert paid.record_total - before.record_total < F("0.20") + else: + assert paid is after + + +@settings(max_examples=30, deadline=None, derandomize=True) +@given(st.integers(100, 2000), st.booleans()) +def test_operational_is_deterministic_order_independent_and_sealed( + pia, spouse +): + outputs = [] + for reverse in (False, True, False): + value = guard() + value.admit( + family( + pia=F(pia), + maximum=F(3 * pia, 2), + spouse=spouse, + reverse=reverse, + ) + ) + paid = value.admit( + family( + 2, F(pia + 1), F(3 * pia, 2), spouse=spouse, reverse=reverse + ) + ) + outputs.append( + (paid.by_id(), paid.record_total, value.protected_total) + ) + if value.protected_total is not None: + assert paid.record_total >= value.protected_total + assert paid.record_total - value.protected_total < F("0.20") + assert paid.family_maximum == F(3 * pia, 2) + assert paid.subject_total <= paid.family_maximum + assert paid.record_total == (paid.worker_benefit or 0) + sum( + row.auxiliary_payable for row in paid.beneficiaries + ) + assert all( + row.auxiliary_payable <= row.original_benefit + for row in paid.beneficiaries + ) + assert outputs[0] == outputs[1] == outputs[2] + + +@settings(max_examples=20, deadline=None, derandomize=True) +@example(pia=1000, weight=1) +@given(st.integers(100, 2000), st.integers(1, 9)) +def test_operational_carry_membership_refusal_and_denominator_properties( + pia, weight +): + value = guard() + before = family(pia=F(pia), maximum=F(3 * pia, 2)) + value.admit(before) + paid = value.admit(family(2, F(pia + 1), F(3 * pia, 2))) + assert value.protected_total is not None + carried = value.admit(family(3, F(pia + 1), F(3 * pia, 2))) + assert carried.record_total == paid.record_total + outcome = value.evaluate( + "changed membership", + F(weight), + lambda: family(4, F(pia + 1), F(3 * pia, 2), children=1), + ) + reason = g.UnsupportedReason.SAVINGS_CLAUSE_MEMBERSHIP_CHANGE + assert outcome.unsupported.reason is reason + counts = g.count_family_outcomes([outcome]) + assert counts.rows == counts.unsupported_rows == 1 + assert counts.unsupported_by_reason == {reason: (1, F(weight))} + + dormant = guard() + dormant.admit(before) + protected = dormant.admit(family(2, F(pia + 1), F(3 * pia, 2))) + established_total = dormant.protected_total + established_month = dormant.protected_since + expanded_maximum = F(3 * pia, 2) + 100 + ordinary = family(3, F(pia + 1), expanded_maximum) + assert ordinary.record_total > established_total + assert dormant.admit(ordinary) is ordinary + assert dormant.protected_total == established_total + assert dormant.protected_since == established_month == JAN + membership_change = family(4, F(pia + 1), expanded_maximum, children=1) + assert membership_change.record_total > established_total + dormant_outcome = dormant.evaluate( + "changed membership during dormant protection", + F(weight), + lambda: membership_change, + ) + assert dormant_outcome.unsupported.reason is reason + dormant_counts = g.count_family_outcomes([dormant_outcome]) + assert dormant_counts.rows == dormant_counts.unsupported_rows == 1 + assert dormant_counts.unsupported_by_reason == {reason: (1, F(weight))} + if pia == 1000 and weight == 1: + assert ( + before.record_total, + protected.record_total, + ordinary.record_total, + membership_change.record_total, + established_total, + ) == (F(1200), F("1200.10"), F("1299.70"), F("1201.20"), F(1200)) + + lower = guard() + lower.admit(before) + lower.admit(family(2, F(pia + 1), F(3 * pia, 2))) + with pytest.raises(g.FamilyConfigurationUnsupported) as caught: + lower.admit(family(3, F(pia, 2), g.floor_dime(F(3 * pia, 4)))) + assert ( + caught.value.reason + is g.UnsupportedReason.SAVINGS_CLAUSE_RATE_PROCEDURE + ) + + def deducted(month, current_pia): + return g.family_benefits_after_deductions( + g.RecordState( + g.FamilyKind.RETIREMENT, + current_pia, + F(3 * pia, 2), + worker=g.OwnBenefit( + g.OwnBenefitKind.OLD_AGE, + current_pia, + reduction_months=60, + ), + ), + [g.Beneficiary(f"C{i}", g.Role.CHILD) for i in range(2)], + payment_month=g.YearMonth(2026, month), + params=PARAMS, + standalone=True, + households={}, + deductions={ + "C0": g.BenefitDeduction(g.DeductionReason.OWN_EARNINGS_TEST) + }, + ) + + earlier_deduction = deducted(1, F(pia)) + history = guard() + # A first month with no candidate protection preserves its result. + assert history.admit(earlier_deduction) is earlier_deduction + assert history.unknown_since is None + assert ( + g.savings_clause_total(earlier_deduction) + > earlier_deduction.record_total + ) + with pytest.raises(g.FamilyConfigurationUnsupported) as caught: + history.admit(family(2, F(pia + 1), F(3 * pia, 2))) + assert ( + caught.value.reason + is g.UnsupportedReason.SAVINGS_CLAUSE_RATE_PROCEDURE + ) + assert history.protected_total is None + assert history.unknown_since == g.YearMonth(2026, 2) + + active = guard() + active.admit(before) + active.admit(family(2, F(pia + 1), F(3 * pia, 2))) + current_deduction = deducted(3, F(pia + 1)) + # An inflated pre-offset sum must not bypass an active protection's + # unsupported deduction interaction just because the sum exceeds it. + assert g.savings_clause_total(current_deduction) > active.protected_total + with pytest.raises(g.FamilyConfigurationUnsupported) as caught: + active.admit(current_deduction) + assert ( + caught.value.reason + is g.UnsupportedReason.SAVINGS_CLAUSE_RATE_PROCEDURE + ) + assert active.unknown_since == g.YearMonth(2026, 3) + + +@settings(max_examples=20, deadline=None, derandomize=True) +@given(st.integers(100, 2000), st.integers(1, 60)) +def test_membership_declines_without_pia_increases_never_start_protection( + pia, months +): + value = guard() + value.admit(family(pia=F(pia), maximum=F(3 * pia, 2), reduction=months)) + after = family(2, F(pia), F(3 * pia, 2), reduction=months, children=0) + assert value.admit(after) is after + assert value.protected_total is None + + +@pytest.mark.parametrize("changed", ("worker", "spouse")) +@settings(max_examples=20, deadline=None, derandomize=True) +@example(pia=100, months=37) +@example(pia=100, months=59) +@given(st.integers(100, 2000), st.integers(1, 59)) +def test_simultaneous_basis_change_refuses_ambiguous_fall( + changed, pia, months +): + options = ( + {"reduction": months} + if changed == "worker" + else {"spouse": True, "spouse_months": months} + ) + after_options = { + **options, + "reduction" if changed == "worker" else "spouse_months": months + 1, + } + for before_options, new_options, rise in ( + (options, after_options, F(1, 10)), + (after_options, options, F(2)), + ): + before = family(pia=F(pia), maximum=F(3 * pia, 2), **before_options) + after = family(2, F(pia) + rise, F(3 * pia, 2), **new_options) + # Both worsening and improving age factors can accompany a fall. + # PIA100/RF60 -> PIA102/RF59: 120 ->119.80; the improved age + # factor alone raises payment, so ignoring that fall underprotects. + value = guard() + value.admit(before) + if after.record_total < before.record_total: + with pytest.raises(g.FamilyConfigurationUnsupported) as caught: + value.admit(after) + assert ( + caught.value.reason + is g.UnsupportedReason.SAVINGS_CLAUSE_RATE_PROCEDURE + ) + assert value.unknown_since == g.YearMonth(2026, 2) + else: + assert value.admit(after) is after + assert value.protected_total is None + if changed == "worker" and pia == 100 and months == 59: + before = family( + pia=F(100), + maximum=F(150), + reduction=0, + spouse=True, + spouse_months=36, + ) + after = family( + 2, F(101), F(140), reduction=0, spouse=True, spouse_months=36 + ) + pia_only = family( + 2, F(101), F(150), reduction=0, spouse=True, spouse_months=36 + ) + assert ( + before.record_total, + after.record_total, + pia_only.record_total, + ) == (F("145.60"), F("136.70"), F("145.80")) + value = guard() + value.admit(before) + with pytest.raises(g.FamilyConfigurationUnsupported) as caught: + value.admit(after) + assert ( + caught.value.reason + is g.UnsupportedReason.SAVINGS_CLAUSE_RATE_PROCEDURE + ) diff --git a/tests/test_track_b_gross_benefits_sources_20261011.py b/tests/test_track_b_gross_benefits_sources_20261011.py index 9eb3f99cc..1fd7a4f79 100644 --- a/tests/test_track_b_gross_benefits_sources_20261011.py +++ b/tests/test_track_b_gross_benefits_sources_20261011.py @@ -19,6 +19,35 @@ ) RULE_QUOTES = ( + ( + "poms_gn_02603_020", + "Take the reduction for the family maximum after making the " + "deductions listed on GN 02603.040 .", + ), + ( + "poms_gn_02603_040", + "Work deductions for the number holder that apply to the auxiliaries", + ), + ( + "poms_gn_02603_090", + "Determine household status using the configuration that exists " + "when the beneficiary files the annual report.", + ), + ( + "poms_rs_02501_130", + "Readjust auxiliary benefit rates up to the family maximum when " + "an individual is deemed not entitled to benefits for a month", + ), + ( + "poms_rs_02501_155", + "Reduce the maximum applicable to the other beneficiaries by " + "the amount of the partial benefit due the beneficiary.", + ), + ( + "poms_rs_02501_160", + "E and C1 will receive the extra $33 per month only when the " + "deductions become permanent.", + ), ( "poms_gn_02603_045", "Only pay this increase to others who are not dually entitled. " @@ -374,7 +403,7 @@ def test_every_new_capture_has_a_rule_and_pinned_bytes(): ("2026-10-11T", "2026-10-12T") ) } - assert len(sources) == 22 + assert len(sources) == 28 assert set(sources) == {source_id for source_id, _ in RULE_QUOTES} for source_id, source in sources.items(): data = (SOURCES / source["file"]).read_bytes() diff --git a/tests/test_track_b_input_schema.py b/tests/test_track_b_input_schema.py index 2e2d30586..cb5caf22f 100644 --- a/tests/test_track_b_input_schema.py +++ b/tests/test_track_b_input_schema.py @@ -830,7 +830,14 @@ def test_every_public_argument_and_declaration_field_declares_a_schema(seed): guard = g.SavingsClauseGuard( g.YearMonth(2026, 1), earlier_months_unknown=False ) - assert len(GUARD_PROPERTIES) == 5 + assert set(GUARD_PROPERTIES) == { + "next_month", + "reading", + "protected_total", + "protected_since", + "refused_since", + "unknown_since", + } for name in GUARD_PROPERTIES: getter = getattr(g.SavingsClauseGuard, name).fget schemas = provenance._argument_schemas(inspect.unwrap(getter)) @@ -1160,7 +1167,11 @@ def counted(original): result = check( getattr(g.SavingsClauseGuard, name).fget, {"self": guard} ) - assert result == (month if name == "next_month" else None) + expected = { + "next_month": month, + "reading": g.SavingsClauseReading.SSA_OPERATIONAL, + }.get(name) + assert result == expected ledger = world[ret]["outcomes"][0].ledger selected = check( ret.RETLedger.for_beneficiary, diff --git a/tests/test_track_b_r3_fix_round_13.py b/tests/test_track_b_r3_fix_round_13.py index 48940af30..c8ef10ae4 100644 --- a/tests/test_track_b_r3_fix_round_13.py +++ b/tests/test_track_b_r3_fix_round_13.py @@ -151,6 +151,33 @@ def add(label, factory, consumer, values): "suspension_method": "full_month", "foreign_work": 1, "vocational_rehabilitation_refusal": 1, + "family_months": {13: object()}, + }, + ) + add( + "family_month", + lambda: r.RETFamilyMonth( + g.RecordState( + g.FamilyKind.RETIREMENT, + F(600), + F(900), + worker=g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, F(600)), + eligibility_year=2026, + ), + (), + PARAMS, + {}, + ), + lambda value: r.apply_ret_year( + record(beneficiary(), foreign_work=True, family_months={1: value}), + RET_PARAMS, + ), + { + "state": object(), + "beneficiaries": ("unknown",), + "params": object(), + "households": {"unknown": "household"}, + "standalone": 1, }, ) add( diff --git a/tests/test_track_b_ret_ledger.py b/tests/test_track_b_ret_ledger.py index 9d05e6753..a8763ae26 100644 --- a/tests/test_track_b_ret_ledger.py +++ b/tests/test_track_b_ret_ledger.py @@ -879,12 +879,12 @@ def test_entitled_zero_rate_auxiliary_keeps_its_original_partial_share(): @pytest.mark.parametrize("child_in_care", [False, "cdb"]) -def test_binding_survivor_maximum_with_zero_rate_cdb_is_deferred_to_part_b( +def test_binding_survivor_maximum_with_zero_rate_cdb_computes_part_b( child_in_care, ): - # A zero auxiliary rate after dual entitlement does not remove that - # beneficiary from the family-maximum computation. Widow own work - # can release room for the entitled CDB recipient. + # Retain technical entitlement and the original share, while applying + # GN 02603.050A.2: a zero Parisi payable remains excluded even when + # another beneficiary has an own-work deduction. params = ssa_params() state = g.RecordState( g.FamilyKind.SURVIVOR, @@ -892,22 +892,23 @@ def test_binding_survivor_maximum_with_zero_rate_cdb_is_deferred_to_part_b( g.retirement_survivor_family_maximum(F(1000), YEAR, params), eligibility_year=YEAR, ) + family_members = ( + g.Beneficiary( + "widow", + g.Role.WIDOW, + reduction_months=60, + reduction_period_months=84, + child_in_care=child_in_care, + ), + g.Beneficiary( + "cdb", + g.Role.CHILD, + own_benefit=g.OwnBenefit(g.OwnBenefitKind.DISABILITY, F(650)), + ), + ) family = g.family_benefits( state, - [ - g.Beneficiary( - "widow", - g.Role.WIDOW, - reduction_months=60, - reduction_period_months=84, - child_in_care=child_in_care, - ), - g.Beneficiary( - "cdb", - g.Role.CHILD, - own_benefit=g.OwnBenefit(g.OwnBenefitKind.DISABILITY, F(650)), - ), - ], + family_members, payment_month=g.YearMonth(YEAR, 1), params=params, standalone=True, @@ -935,10 +936,25 @@ def test_binding_survivor_maximum_with_zero_rate_cdb_is_deferred_to_part_b( ), kind=r.RecordKind.DECEASED, family_maximum_binding_months=MONTHS, + family_months={ + month: r.RETFamilyMonth( + state, + family_members, + params, + {"widow": "household", "cdb": "household"}, + ) + for month in MONTHS + }, ) - with pytest.raises(r.RETConfigurationUnsupported) as error: - r.apply_ret_year(case, PARAMS) - assert error.value.reason is r.UnsupportedReason.DEDUCTION_BEFORE_REDUCTION + result = r.apply_ret_year(case, PARAMS) + assert by_month(result, "widow")[1].net_due == F("696.40") + assert by_month(result, "widow")[1].payment == 696 + assert by_month(result, "widow")[1].provisional_payment == 0 + # GN 02603.050A.2 excludes a zero dual-entitlement rate regardless + # of other deductions; work does not revive the CDB's $0 payable. + assert all(row.net_due == 0 for row in result.for_beneficiary("cdb")) + assert result.crediting_months["widow"] == frozenset({1}) + assert result.crediting_months["cdb"] == frozenset() @pytest.mark.parametrize( @@ -976,7 +992,7 @@ def test_requested_suspension_methods_are_refused(method, reason): assert error.value.reason is r.UnsupportedReason[reason] -def test_auxiliary_excess_with_binding_family_maximum_is_deferred_to_part_b(): +def test_binding_auxiliary_work_needs_declared_g_family_context(): spouse = beneficiary( "spouse", rate=200, @@ -987,7 +1003,7 @@ def test_auxiliary_excess_with_binding_family_maximum_is_deferred_to_part_b(): ledger( beneficiary(), spouse, family_maximum_binding_months=frozenset({1}) ) - assert error.value.reason is r.UnsupportedReason.DEDUCTION_BEFORE_REDUCTION + assert error.value.reason is r.UnsupportedReason.FAMILY_CONTEXT_REQUIRED def test_nonbinding_number_holder_partial_deduction_precedes_auxiliary_own(): diff --git a/tests/test_track_b_ret_ledger_deductions.py b/tests/test_track_b_ret_ledger_deductions.py new file mode 100644 index 000000000..bc3d3ccc2 --- /dev/null +++ b/tests/test_track_b_ret_ledger_deductions.py @@ -0,0 +1,602 @@ +"""R2 part (b), statutory conformance on invented/captured examples only. + +No population, behavioral, or forecast claim. GN 02603.050 and RS +02501.155-.160 govern the monthly readjustment and household timing. +""" + +from dataclasses import fields, replace +from datetime import date +from fractions import Fraction as F + +import pytest +from hypothesis import example, given, settings +from hypothesis import strategies as st + +from populace_dynamics.track_b import arf as a +from populace_dynamics.track_b import gross_benefits as g +from populace_dynamics.track_b import ret_ledger as r +from populace_dynamics.track_b.ret_grace import BenefitType as T +from populace_dynamics.track_b.ret_params import load_ret_parameters +from tests.track_b_gross_benefit_support import ssa_params +from tests.track_b_ret_ledger_support import source_text + +YEAR = 2026 +MONTHS = frozenset(range(1, 13)) +PARAMS = load_ret_parameters() + + +def family_record(*, excess=555, separate=False, other_excess=0, nh_excess=0): + """Published .160 family, or an invented living-worker interaction.""" + params = ssa_params() + if nh_excess: + state = g.RecordState( + g.FamilyKind.RETIREMENT, + F(600), + F(900), + worker=g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, F(600)), + eligibility_year=YEAR, + ) + members = tuple( + g.Beneficiary(k, g.Role.CHILD) for k in ("c1", "c2", "c3") + ) + else: + state = g.RecordState( + g.FamilyKind.SURVIVOR, + F("213.10"), + F(396), + eligibility_year=YEAR, + ) + members = (g.Beneficiary("e", g.Role.MOTHER_FATHER),) + tuple( + g.Beneficiary(k, g.Role.CHILD) for k in ("c1", "c2", "c3") + ) + family = g.family_benefits( + state, + members, + payment_month=g.YearMonth(YEAR, 1), + params=params, + standalone=True, + ) + households = { + b.beneficiary_id: ( + "other" + if separate and b.beneficiary_id in ("e", "c1") + else "worker" + ) + for b in members + } + context = r.RETFamilyMonth(state, members, params, households) + own_excess = {"c3": excess, "c1": other_excess, "nh": nh_excess} + people = [] + rates = [ + (b.beneficiary_id, b.auxiliary_payable, b.original_benefit) + for b in family.beneficiaries + ] + if nh_excess: + rates.append(("nh", family.worker_benefit, family.pia)) + for key, rate, original in rates: + annual = own_excess.get(key, 0) + wages = ( + PARAMS.for_year(YEAR).lower_exempt_amount.value + 2 * annual + if annual + else 0 + ) + people.append( + r.RETBeneficiary( + key, + ( + ( + T.RIB + if key == "nh" + else T.MOTHER_FATHER if key == "e" else T.CHILD + ), + ) + * 12, + MONTHS, + (rate,) * 12, + (original,) * 12, + earnings=r.WorkEarnings((F(wages),) + (F(0),) * 11), + ) + ) + return r.RecordYear( + YEAR, + "nh", + r.RecordKind.RETIREMENT if nh_excess else r.RecordKind.DECEASED, + tuple(people), + family_maximum_binding_months=MONTHS, + family_months={month: context for month in MONTHS}, + ) + + +def month(result, key, number=1): + return result.for_beneficiary(key)[number - 1] + + +def payload(value): + """All declared fields, without private process-specific seal metadata.""" + return {field.name: getattr(value, field.name) for field in fields(value)} + + +def fixed_nh_record(excess, *, dual): + """NH partial charges on a fixed Parisi/outside-maximum auxiliary.""" + params = ssa_params() + state = g.RecordState( + g.FamilyKind.RETIREMENT, + F(600), + F(900), + worker=g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, F(600)), + eligibility_year=YEAR, + ) + fixed = ( + g.Beneficiary( + "fixed", + g.Role.SPOUSE, + own_benefit=g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, F(10)), + own_benefit_first=True, + ) + if dual + else g.Beneficiary( + "fixed", + g.Role.DIVORCED_SPOUSE, + child_in_care=False, + first_entitlement_child_in_care=False, + ) + ) + members = (fixed,) + tuple( + g.Beneficiary(f"c{n}", g.Role.CHILD) + for n in range(1, 3 if dual else 4) + ) + baseline = g.family_benefits( + state, + members, + payment_month=g.YearMonth(YEAR, 1), + params=params, + standalone=True, + ) + rates = [("nh", F(600), F(600), T.RIB)] + [ + ( + row.beneficiary_id, + row.auxiliary_payable, + row.original_benefit, + ( + T.SPOUSE + if dual and row.beneficiary_id == "fixed" + else ( + T.DIVORCED_SPOUSE + if row.beneficiary_id == "fixed" + else T.CHILD + ) + ), + ) + for row in baseline.beneficiaries + ] + people = [] + for key, rate, original, kind in rates: + deduction = 600 if key == "nh" else excess if key == "c1" else 0 + annual = ( + PARAMS.for_year(YEAR).lower_exempt_amount.value + 2 * deduction + if deduction + else 0 + ) + people.append( + r.RETBeneficiary( + key, + (kind,) * 12, + MONTHS, + (rate,) * 12, + (original,) * 12, + earnings=r.WorkEarnings((F(annual),) + (F(0),) * 11), + ) + ) + context = r.RETFamilyMonth( + state, members, params, {b.beneficiary_id: "one" for b in members} + ) + return r.RecordYear( + YEAR, + "nh", + beneficiaries=tuple(people), + family_maximum_binding_months=MONTHS, + family_months={1: context, 2: context}, + ) + + +def test_rs_02501_160_permanent_full_and_partial_months(): + result = r.apply_ret_year(family_record(), PARAMS) + assert [month(result, "c3", n).net_due for n in range(1, 8)] == [0] * 5 + [ + 39, + 99, + ] + assert ( + sum(row.own_deduction for row in result.for_beneficiary("c3")) == 555 + ) + for key in ("e", "c1", "c2"): + assert [month(result, key, n).net_due for n in range(1, 8)] == [ + 132 + ] * 5 + [119, 99] + assert month(result, key, 6).payment == 119 + assert result.crediting_months[key] == frozenset() + assert result.crediting_months["c3"] == frozenset(range(1, 7)) + + +def test_rs_02501_160_separate_household_increases_wait_for_final_deduction(): + result = r.apply_ret_year(family_record(separate=True), PARAMS) + for key in ("e", "c1"): + row = month(result, key) + assert type(row) is r.RedistributedBeneficiaryMonth + assert row.gross == row.net_due == 132 + assert row.provisional_gross == row.provisional_net == 99 + assert row.deduction == row.provisional_deduction == 0 + assert result.reconciliation[key] == 5 * 33 + 20 + assert month(result, "c2").provisional_net == 132 + # R2 retains full-month estimated suspension, GN .050D.2. The .160 + # partial June example is a different operational reading covered by G. + assert month(result, "c3", 6).provisional_net == 0 + assert month(result, "c2", 6).provisional_net == 132 + + +def test_rs_02501_155_multiple_workers_charge_before_redistribution(): + result = r.apply_ret_year( + family_record(excess=100, other_excess=150), PARAMS + ) + assert month(result, "c3").own_deduction == 99 + assert month(result, "c1").own_deduction == 99 + assert month(result, "e").net_due == F("159.80") + assert month(result, "c3", 2).net_due == 98 + assert month(result, "c1", 2).net_due == 48 + assert month(result, "e", 2).net_due == 125 + assert month(result, "c2", 2).net_due == 125 + + +@settings(max_examples=12, deadline=None) +@example(excess=30) +@given(excess=st.integers(1, 59)) +def test_rs_02501_155_nh_partial_month_preserves_nh_deductions(excess): + result = r.apply_ret_year( + family_record(excess=excess, nh_excess=600), PARAMS + ) + assert month(result, "nh").net_due == 120 + assert month(result, "c3").net_due == 60 - excess + assert month(result, "c3").nh_deduction == 40 + assert month(result, "c3").own_deduction == excess + for key in ("c1", "c2"): + assert month(result, key).net_due == 60 + F(excess, 2) + assert month(result, key).nh_deduction == 40 + assert month(result, key).own_deduction == 0 + assert month(result, key).gross == 100 + F(excess, 2) + dual = r.apply_ret_year(fixed_nh_record(excess, dual=True), PARAMS) + assert month(dual, "fixed").net_due == 60 + assert month(dual, "fixed").nh_deduction == 30 + assert month(dual, "fixed").gross == 90 + assert month(dual, "c1").net_due == 60 - excess + assert month(dual, "c2").net_due == 60 + excess + outside = r.apply_ret_year(fixed_nh_record(excess, dual=False), PARAMS) + assert month(outside, "fixed").net_due == 100 + assert month(outside, "fixed").nh_deduction == 200 + assert month(outside, "fixed").gross == 300 + assert month(outside, "c1").net_due == 100 - excess + for key in ("c2", "c3"): + assert month(outside, key).net_due == 100 + F(excess, 2) + case = fixed_nh_record(excess, dual=False) + own_work = next( + b.earnings for b in case.beneficiaries if b.beneficiary_id == "c1" + ) + case = replace( + case, + beneficiaries=tuple( + ( + replace( + b, + earnings=( + own_work + if b.beneficiary_id == "fixed" + else r.WorkEarnings() + ), + ) + if b.beneficiary_id in ("fixed", "c1") + else b + ) + for b in case.beneficiaries + ), + ) + outside_worker = r.apply_ret_year(case, PARAMS) + assert month(outside_worker, "fixed").net_due == 100 - excess + assert month(outside_worker, "fixed").nh_deduction == 200 + for key in ("c1", "c2", "c3"): + assert month(outside_worker, key).net_due == 100 + + +def test_readjusted_deductions_flow_to_r3_without_household_delay_credits(): + params = ssa_params() + state = g.RecordState( + g.FamilyKind.SURVIVOR, F(1000), F(1500), eligibility_year=YEAR + ) + members = ( + g.Beneficiary( + "widow", + g.Role.WIDOW, + reduction_months=60, + reduction_period_months=84, + child_in_care=False, + ), + g.Beneficiary( + "cdb", + g.Role.CHILD, + own_benefit=g.OwnBenefit(g.OwnBenefitKind.DISABILITY, F(650)), + ), + ) + family = g.family_benefits( + state, + members, + payment_month=g.YearMonth(YEAR, 1), + params=params, + standalone=True, + ) + rows = {row.beneficiary_id: row for row in family.beneficiaries} + annual = PARAMS.for_year(YEAR).lower_exempt_amount.value + 200 + people = tuple( + r.RETBeneficiary( + key, + (T.WIDOW if key == "widow" else T.CDB,) * 12, + MONTHS, + (rows[key].auxiliary_payable,) * 12, + (rows[key].original_benefit,) * 12, + earnings=r.WorkEarnings( + (F(annual if key == "widow" else 0),) + (F(0),) * 11 + ), + ) + for key in ("widow", "cdb") + ) + context = r.RETFamilyMonth( + state, members, params, {"widow": "one", "cdb": "two"} + ) + record = r.RecordYear( + YEAR, + "nh", + r.RecordKind.DECEASED, + people, + family_maximum_binding_months=MONTHS, + family_months={m: context for m in MONTHS}, + ) + result = r.apply_ret_year(record, PARAMS) + credits = frozenset( + g.YearMonth(YEAR, m) for m in result.crediting_months["widow"] + ) + claim = a.ARFClaim( + a.ARFBenefitKind.WIDOW, + date(1962, 1, 2), + g.YearMonth(2024, 1), + F(1000), + partial_work_deduction_months=credits, + ) + adjusted = a.apply_arf( + claim, payment_month=g.YearMonth(2029, 1), params=params + ) + assert ( + adjusted.crediting_months + == credits + == frozenset({g.YearMonth(YEAR, 1)}) + ) + assert adjusted.adjusted_reduction_months == 59 + assert adjusted.benefit == F("799.80") + assert result.crediting_months["cdb"] == frozenset() + + +@settings(max_examples=30, deadline=None) +@given( + excess=st.integers(1, 1600), + other_excess=st.integers(0, 500), + separate=st.booleans(), +) +def test_property_readjustment_conserves_deductions_and_preserves_order( + excess, other_excess, separate +): + case = family_record( + excess=excess, other_excess=other_excess, separate=separate + ) + result = r.apply_ret_year(case, PARAMS) + reverse = r.apply_ret_year( + replace(case, beneficiaries=tuple(reversed(case.beneficiaries))), + PARAMS, + ) + repeated = r.apply_ret_year(case, PARAMS) + assert [payload(v) for v in result.months] == [ + payload(v) for v in reverse.months + ] + assert [payload(v) for v in result.months] == [ + payload(v) for v in repeated.months + ] + assert sum(v.deduction for v in result.months) == sum( + v.charged for v in result.workers + ) + assert sum(v.provisional_deduction for v in result.months) == sum( + v.provisional_withheld for v in result.workers + ) + workers = {row.beneficiary_id: row for row in result.workers} + assert workers["c3"].charged == min(excess, 12 * 99) + assert workers["c1"].charged == min(other_excess, 12 * 99) + for n in range(1, 13): + assert ( + sum(month(result, k, n).net_due for k in ("e", "c1", "c2", "c3")) + <= 396 + ) + for key in ("e", "c1", "c2"): + row = month(result, key, n) + if not row.own_deduction: + assert 99 <= row.net_due <= F("159.80") + assert row.deduction == 0 + if ( + separate + and key != "c2" + and not month(result, "c1", n).provisional_deduction + ): + assert row.provisional_net == 99 + row = month(result, "c3", n) + assert (n in result.crediting_months["c3"]) == (row.own_deduction > 0) + + +@settings(max_examples=20, deadline=None) +@given(separate=st.booleans(), amount=st.integers(0, 20)) +def test_property_unused_g_context_preserves_original_result_fields( + separate, amount +): + case = family_record(excess=0, separate=separate) + # Earnings below the exempt amount create no deduction event. + people = tuple( + replace(b, earnings=r.WorkEarnings((F(amount),) * 12)) + for b in case.beneficiaries + ) + with_context = r.apply_ret_year( + replace(case, beneficiaries=people), PARAMS + ) + without_context = r.apply_ret_year( + replace(case, beneficiaries=people, family_months={}), PARAMS + ) + assert all(type(row) is r.BeneficiaryMonth for row in with_context.months) + assert [payload(row) for row in with_context.months] == [ + payload(row) for row in without_context.months + ] + + +def test_family_context_invalidity_precedes_record_refusal(): + case = family_record(excess=100) + b = case.beneficiaries[0] + case = replace( + case, + fiscal_year=True, + beneficiaries=(replace(b, gross_rates=(F(1),) * 12),) + + case.beneficiaries[1:], + ) + with pytest.raises(g.InvalidFamilyInput, match="does not match"): + r.apply_ret_year(case, PARAMS) + + living = fixed_nh_record(30, dual=True) + no_nh_entitlement = replace( + living, + fiscal_year=True, + beneficiaries=tuple( + ( + replace( + b, entitled_months=frozenset(), gross_rates=(F(0),) * 12 + ) + if b.beneficiary_id == "nh" + else b + ) + for b in living.beneficiaries + ), + ) + with pytest.raises(g.InvalidFamilyInput, match="NH entitlement"): + r.apply_ret_year(no_nh_entitlement, PARAMS) + + context = living.family_months[1] + not_entitled = replace( + context.beneficiaries[0], + own_benefit=g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, F(300)), + ) + context = replace( + context, beneficiaries=(not_entitled,) + context.beneficiaries[1:] + ) + baseline = g.family_benefits( + context.state, + context.beneficiaries, + payment_month=g.YearMonth(YEAR, 1), + params=context.params, + standalone=True, + ) + rows = {row.beneficiary_id: row for row in baseline.beneficiaries} + assert rows["fixed"].entitled is False + declared_entitled = replace( + living, + fiscal_year=True, + family_months={1: context, 2: context}, + beneficiaries=tuple( + ( + replace( + b, + gross_rates=(rows[b.beneficiary_id].auxiliary_payable,) + * 12, + original_rates=(rows[b.beneficiary_id].original_benefit,) + * 12, + ) + if b.beneficiary_id != "nh" + else b + ) + for b in living.beneficiaries + ), + ) + with pytest.raises(g.InvalidFamilyInput, match="auxiliary entitlement"): + r.apply_ret_year(declared_entitled, PARAMS) + + +def test_later_family_input_error_precedes_earlier_g_coverage_refusal(): + case = family_record(excess=100) + contexts = dict(case.family_months) + context = contexts[1] + child = replace( + context.beneficiaries[-1], + conditions=frozenset( + {g.BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD} + ), + ) + contexts[1] = replace( + context, beneficiaries=context.beneficiaries[:-1] + (child,) + ) + person = case.beneficiaries[0] + person = replace(person, gross_rates=person.gross_rates[:11] + (F(1),)) + case = replace( + case, + family_months=contexts, + beneficiaries=(person,) + case.beneficiaries[1:], + ) + with pytest.raises(g.InvalidFamilyInput, match="does not match"): + r.apply_ret_year(case, PARAMS) + + +@pytest.mark.parametrize( + "field,value", + [ + ("households", {"e": "only"}), + ("standalone", 1), + ("beneficiaries", frozenset()), + ], +) +def test_family_context_schema_rejects_invalid_fields(field, value): + context = family_record().family_months[1] + with pytest.raises(g.InvalidFamilyInput): + replace(context, **{field: value}) + + +@pytest.mark.parametrize( + "field", + ("gross", "provisional_gross", "deduction", "provisional_deduction"), +) +def test_redistributed_month_tampering_cannot_enter_ret_denominator(field): + result = r.apply_ret_year(family_record(separate=True), PARAMS) + row = next( + row + for row in result.months + if type(row) is r.RedistributedBeneficiaryMonth + ) + object.__setattr__(row, field, F(-1)) + with pytest.raises(g.InvalidFamilyInput): + r.evaluate_ret("altered", 1, lambda: result) + + +def test_captured_original_rounding_and_worked_payment_figures_are_explicit(): + text = source_text("poms_rs_02501_160") + for figure in ( + "$159.90", + "$213.10", + "$396", + "$99", + "$555", + "$60", + "$132", + "$119", + "$33", + "$20", + "$ 39", + ): + assert figure in text + # Modern floor differs from this undated example's upward-rounded + # original benefit. Equal shares make every published payment identical. + case = family_record() + assert all(b.original_rates[0] == F("159.80") for b in case.beneficiaries) diff --git a/tests/test_track_b_ret_ledger_sources.py b/tests/test_track_b_ret_ledger_sources.py index e5f3660cc..35edf916d 100644 --- a/tests/test_track_b_ret_ledger_sources.py +++ b/tests/test_track_b_ret_ledger_sources.py @@ -177,6 +177,8 @@ def test_manifest_pins_every_capture(): "poms_rs_02501_155": [ "treat the beneficiary as not being on the benefit rolls in applying the maximum provisions", "Reduce the maximum applicable to the other beneficiaries by the amount of the partial benefit due the beneficiary.", + "charge each auxiliary's or survivor's excess earnings against their own benefit.", + "The partial benefits of other auxiliaries cannot be readjusted except to the extent to which we charge the auxiliary's excess earnings against the benefits to which the auxiliary otherwise was eligible.", ], "poms_rs_02501_160": [ "Withhold any increased amounts due beneficiaries outside the household of the working beneficiary until after the close of the year" @@ -194,7 +196,9 @@ def test_manifest_pins_every_capture(): "we will consider only the benefit actually payable when reducing the benefits of dually entitled auxiliaries or survivors" ], "poms_gn_02603_050": [ - "Deductions based on the annual earnings test become permanent deductions based on a closed year work report" + "Deductions based on the annual earnings test become permanent deductions based on a closed year work report", + "regardless of other deductions that may apply for any other beneficiary on record disregard the dually entitled beneficiary", + "The worker's rate will always be $0.00 because there are no partial deductions for temporary work deductions.", ], "poms_gn_02603_055": [ "Apply WC or PDB offset to determine the amount of offset that applies to each beneficiary." @@ -282,6 +286,19 @@ def test_manifest_pins_every_capture(): WORKED_EXAMPLE_QUOTES = { + "poms_rs_02501_160": [ + "$159.90", + "$213.10", + "$396", + "$99", + "$555", + "$60", + "$132", + "$119", + "$33", + "$20", + "$ 39", + ], "poms_rs_02501_080": [ "Beneficiary is age 64 in TY 1999", "$12,121", diff --git a/tests/track_b_gross_benefit_support.py b/tests/track_b_gross_benefit_support.py index 10f7ad248..d5755c7cc 100644 --- a/tests/track_b_gross_benefit_support.py +++ b/tests/track_b_gross_benefit_support.py @@ -122,7 +122,11 @@ def computed_refusal(reason): ), ) if reason is g.UnsupportedReason.SAVINGS_CLAUSE: - guard = g.SavingsClauseGuard(month, earlier_months_unknown=False) + guard = g.SavingsClauseGuard( + month, + earlier_months_unknown=False, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) members = tuple( g.Beneficiary(f"child-{index}", g.Role.CHILD) for index in range(3) ) From f3b9a71999733ab92111576e42a6198daa00b096 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Fri, 23 Oct 2026 11:05:35 -0400 Subject: [PATCH 03/17] Regenerate the G conformance report with the deduction denominator; record mutations and verification; recount tiers The 356,400-row lattice is unchanged. A separate 16-row invented deduction denominator is added, and every one of the 37 G refusal reasons has an executed witness. The mutation and verification records pin the 13 one-line mutations and the lane's commands. Co-Authored-By: Claude Opus 5.5 --- docs/design/track_b_g2_r2b_mutations.json | 599 ++++++++ docs/design/track_b_g2_r2b_verification.json | 1350 +++++++++++++++++ docs/design/track_b_g_conformance_report.json | 263 +++- scripts/track_b_g_conformance_report.py | 171 ++- tests/README-tiers.md | 4 +- tests/tier_counts.json | 2 +- 6 files changed, 2367 insertions(+), 22 deletions(-) create mode 100644 docs/design/track_b_g2_r2b_mutations.json create mode 100644 docs/design/track_b_g2_r2b_verification.json diff --git a/docs/design/track_b_g2_r2b_mutations.json b/docs/design/track_b_g2_r2b_mutations.json new file mode 100644 index 000000000..427be4fd0 --- /dev/null +++ b/docs/design/track_b_g2_r2b_mutations.json @@ -0,0 +1,599 @@ +{ + "schema_version": 1, + "verification_class": "statutory_conformance", + "admitted_scope": "Mutation sensitivity of statutory rules on invented and captured worked cases only; no population, behavioral or forecast claim.", + "confirmed_mutation_count": 13, + "counts_by_layer": { + "shared_provenance": 1, + "g_deductions": 5, + "r2": 3, + "g_savings": 4 + }, + "environment_contract": { + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "microdata": "Both POPULACE_DYNAMICS_PSID_DIR and POPULACE_DYNAMICS_EPUF_DIR pointed to nonexistent paths.", + "imports": "PYTHONPATH selected the isolated mutated source copy before the assigned workspace.", + "pytest_plugins_disabled": [ + "xdist", + "cacheprovider" + ] + }, + "excluded_attempts": [ + { + "id": "discard_causal_age_basis", + "reason": "Interrupted fifth savings mutation; no completed failing-test log. Not counted among the 13 confirmed mutations." + } + ], + "mutations": [ + { + "id": "notes_assignment_only", + "layer": "shared_provenance", + "source": "src/populace_dynamics/track_b/_provenance.py", + "change": { + "before": "if name == \"__notes__\" and args:", + "after": "if name == \"__notes__\":" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_refusal_notes.py", + "-k", + "deletion_preserves" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_refusal_notes.py::test_refusal_note_deletion_preserves_provenance_and_denominator[g]", + "tests/test_track_b_refusal_notes.py::test_refusal_note_deletion_preserves_provenance_and_denominator[ret]", + "tests/test_track_b_refusal_notes.py::test_refusal_note_deletion_preserves_provenance_and_denominator[arf]", + "tests/test_track_b_refusal_notes.py::test_refusal_note_deletion_preserves_provenance_and_denominator[recompute]" + ], + "log": { + "path": "scratch/trackb_lane/note_mutation.log", + "sha256": "161dc26aaf05b4e2ce6d5d79fa257e302ff9ec1922a7fd9cdf7bf3a85c98c89c", + "failure_summary": "4 failed, 16 deselected in 114.45s (0:01:54)", + "failed_tests": [ + "tests/test_track_b_refusal_notes.py::test_refusal_note_deletion_preserves_provenance_and_denominator[g]", + "tests/test_track_b_refusal_notes.py::test_refusal_note_deletion_preserves_provenance_and_denominator[ret]", + "tests/test_track_b_refusal_notes.py::test_refusal_note_deletion_preserves_provenance_and_denominator[arf]", + "tests/test_track_b_refusal_notes.py::test_refusal_note_deletion_preserves_provenance_and_denominator[recompute]" + ] + }, + "restoration": { + "reverted": true, + "isolated_source_restored": true, + "production_guard_present": true, + "restored_test_exit_code": null, + "verification": "Reverted flag in note_mutation.json; assignment-only guard present in both isolated and production modules." + }, + "metadata_reference": "scratch/trackb_lane/note_mutation.json" + }, + { + "id": "deductions_omit_partial_payable", + "layer": "g_deductions", + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": "reserved += events[oid].payable + max(", + "after": "reserved += Fraction(0) + max(" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_deductions.py", + "-k", + "test_gn_02603_060_permanent_examples", + "--tb=short" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_gross_benefits_deductions.py::test_gn_02603_060_permanent_examples[3-E-payable2-expected2]" + ], + "log": { + "path": "scratch/trackb_lane/deduction_mutation_results.json", + "entry": "omit_partial_payable", + "sha256": "94f0cb00124743e933ec9c99e43d11d07e553c2ffeb56965d4805e2b44136fa2", + "failure_summary": "1 failed, 2 passed, 23 deselected in 6.89s" + }, + "restoration": { + "reverted": true, + "temporary_source_copy_removed": true, + "production_guard_present": true, + "production_restoration_marker": "reserved += events[oid].payable + max(", + "restored_test_exit_code": null, + "verification": "Runner rewrote its saved original after each failure, then TemporaryDirectory removed the isolated source tree. No .deduction-mutations-* tree remains; original production rule is present. Production implementation was never mutated." + } + }, + { + "id": "deductions_release_separate_household_early", + "layer": "g_deductions", + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": "if households.get(other) == households.get(bid)", + "after": "if True" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_deductions.py", + "-k", + "test_gn_02603_060_temporary_examples", + "--tb=short" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_gross_benefits_deductions.py::test_gn_02603_060_temporary_examples[False-expected0]", + "tests/test_track_b_gross_benefits_deductions.py::test_gn_02603_060_temporary_examples[True-expected1]" + ], + "log": { + "path": "scratch/trackb_lane/deduction_mutation_results.json", + "entry": "release_separate_household_early", + "sha256": "94f0cb00124743e933ec9c99e43d11d07e553c2ffeb56965d4805e2b44136fa2", + "failure_summary": "2 failed, 24 deselected in 3.98s" + }, + "restoration": { + "reverted": true, + "temporary_source_copy_removed": true, + "production_guard_present": true, + "production_restoration_marker": "if households.get(other) == households.get(bid)", + "restored_test_exit_code": null, + "verification": "Runner rewrote its saved original after each failure, then TemporaryDirectory removed the isolated source tree. No .deduction-mutations-* tree remains; original production rule is present. Production implementation was never mutated." + } + }, + { + "id": "deductions_do_not_release_original_share", + "layer": "g_deductions", + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": "if row.beneficiary_id not in eligible), Fraction(0))", + "after": "if True), Fraction(0))" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_deductions.py", + "-k", + "test_gn_02603_060_permanent_examples", + "--tb=short" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_gross_benefits_deductions.py::test_gn_02603_060_permanent_examples[3-E-payable0-expected0]", + "tests/test_track_b_gross_benefits_deductions.py::test_gn_02603_060_permanent_examples[2-C2-payable1-expected1]", + "tests/test_track_b_gross_benefits_deductions.py::test_gn_02603_060_permanent_examples[3-E-payable2-expected2]" + ], + "log": { + "path": "scratch/trackb_lane/deduction_mutation_results.json", + "entry": "do_not_release_original_share", + "sha256": "94f0cb00124743e933ec9c99e43d11d07e553c2ffeb56965d4805e2b44136fa2", + "failure_summary": "3 failed, 23 deselected in 4.53s" + }, + "restoration": { + "reverted": true, + "temporary_source_copy_removed": true, + "production_guard_present": true, + "production_restoration_marker": "if row.beneficiary_id not in eligible", + "restored_test_exit_code": null, + "verification": "Runner rewrote its saved original after each failure, then TemporaryDirectory removed the isolated source tree. No .deduction-mutations-* tree remains; original production rule is present. Production implementation was never mutated." + } + }, + { + "id": "deductions_reverse_own_deduction", + "layer": "g_deductions", + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": "deduction = old.auxiliary_payable - event.payable", + "after": "deduction = old.auxiliary_payable + event.payable" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_deductions.py", + "-k", + "test_gn_02603_060_permanent_examples", + "--tb=short" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_gross_benefits_deductions.py::test_gn_02603_060_permanent_examples[3-E-payable2-expected2]" + ], + "log": { + "path": "scratch/trackb_lane/deduction_mutation_results.json", + "entry": "reverse_own_deduction", + "sha256": "94f0cb00124743e933ec9c99e43d11d07e553c2ffeb56965d4805e2b44136fa2", + "failure_summary": "1 failed, 2 passed, 23 deselected in 10.75s" + }, + "restoration": { + "reverted": true, + "temporary_source_copy_removed": true, + "production_guard_present": true, + "production_restoration_marker": "deduction = old.auxiliary_payable - event.payable", + "restored_test_exit_code": null, + "verification": "Runner rewrote its saved original after each failure, then TemporaryDirectory removed the isolated source tree. No .deduction-mutations-* tree remains; original production rule is present. Production implementation was never mutated." + } + }, + { + "id": "deductions_extend_single_full_exception", + "layer": "g_deductions", + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": "if len(events) == 1", + "after": "if True" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_deductions.py::test_single_full_permanent_exception_disregards_age_reduction", + "--tb=short" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_gross_benefits_deductions.py::test_single_full_permanent_exception_disregards_age_reduction" + ], + "log": { + "path": "scratch/discontinuity_mutation/mutated.log", + "sha256": "5e0bd09cd9cab4c6d4af58757622754383fe86edebd6eb72bd8ed18500f56d04", + "failure_summary": "1 failed in 6.41s" + }, + "restoration": { + "reverted": true, + "isolated_source_restored": true, + "production_unchanged": true, + "production_sha256": "e1e6b35c3b547e4dc597235b2d395c49bd906ab29c4b06e682cc36de9f310a1f", + "restored_test_exit_code": 0, + "restored_log": "scratch/discontinuity_mutation/restored.log", + "restored_log_sha256": "9ad5f31eebb9204c2c34f70ebd9f5ef6de8bc91e8097893eb9bccf6b7b1ae63a", + "restored_test_summary": "1 passed in 6.04s", + "verification": "Saved original bytes restored in isolated copy, exact production-source equality verified, and the same property test passed on the restored isolated source. Production was never mutated." + }, + "metadata_reference": "scratch/discontinuity_mutation/result.json" + }, + { + "id": "r2_drop_redistribution", + "layer": "r2", + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": { + "before": "net[k, m] = row.auxiliary_payable", + "after": "net[k, m] = net[k, m]" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_ret_ledger_deductions.py::test_rs_02501_160_permanent_full_and_partial_months" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_deductions.py::test_rs_02501_160_permanent_full_and_partial_months" + ], + "log": { + "path": "scratch/g2-r2b-r2/drop_redistribution.txt", + "sha256": "c4ac2678418bf8361a61f98f8e796b29142b3d8f6aa6415deacdfc03f79cf020", + "failure_summary": "1 failed in 8.85s", + "failed_tests": [ + "tests/test_track_b_ret_ledger_deductions.py::test_rs_02501_160_permanent_full_and_partial_months" + ] + }, + "restoration": { + "reverted": true, + "restored_test_exit_code": 0, + "restored_log": "scratch/g2-r2b-r2/drop_redistribution_restored.txt", + "restored_log_sha256": "6c3ef9ae319bd6dcce4d2df6a5c8f2e12df6c0d10d769deeabba4403eefd36a8", + "restored_test_summary": "1 passed in 7.63s", + "isolated_source_sha256": "27568b175af5acf16c83012ae151584a237886723b3946e55539e07639131d50", + "production_guard_present": true, + "verification": "Each identical test passed after source restoration. Current isolated-source SHA-256 matches the saved original; production rule is present." + }, + "metadata_reference": "scratch/g2-r2b-r2/mutations.json" + }, + { + "id": "r2_temporary_as_permanent", + "layer": "r2", + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": { + "before": " not provisional,", + "after": " True," + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_ret_ledger_deductions.py::test_rs_02501_160_separate_household_increases_wait_for_final_deduction" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_deductions.py::test_rs_02501_160_separate_household_increases_wait_for_final_deduction" + ], + "log": { + "path": "scratch/g2-r2b-r2/temporary_as_permanent.txt", + "sha256": "4e0f770db21f42f139904f5c69795edba587f8f428ad0c8937b6a241c54ba637", + "failure_summary": "1 failed in 8.36s", + "failed_tests": [ + "tests/test_track_b_ret_ledger_deductions.py::test_rs_02501_160_separate_household_increases_wait_for_final_deduction" + ] + }, + "restoration": { + "reverted": true, + "restored_test_exit_code": 0, + "restored_log": "scratch/g2-r2b-r2/temporary_as_permanent_restored.txt", + "restored_log_sha256": "f832f1e1e84adbb268c3e95231944d298493e7c3ef9d4f47544b6103699e803c", + "restored_test_summary": "1 passed in 3.47s", + "isolated_source_sha256": "27568b175af5acf16c83012ae151584a237886723b3946e55539e07639131d50", + "production_guard_present": true, + "verification": "Each identical test passed after source restoration. Current isolated-source SHA-256 matches the saved original; production rule is present." + }, + "metadata_reference": "scratch/g2-r2b-r2/mutations.json" + }, + { + "id": "r2_drop_nh_reservation", + "layer": "r2", + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": { + "before": "worker_deductions=worker_deductions,", + "after": "worker_deductions={}," + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_ret_ledger_deductions.py::test_rs_02501_155_nh_partial_month_preserves_nh_deductions" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_deductions.py::test_rs_02501_155_nh_partial_month_preserves_nh_deductions" + ], + "log": { + "path": "scratch/g2-r2b-r2/drop_nh_reservation.txt", + "sha256": "527075276827ccee4e7bafb4e9f2e95020a51f9e0be05c0fa6e14cb74ad58d19", + "failure_summary": "1 failed in 6.61s", + "failed_tests": [ + "tests/test_track_b_ret_ledger_deductions.py::test_rs_02501_155_nh_partial_month_preserves_nh_deductions" + ] + }, + "restoration": { + "reverted": true, + "restored_test_exit_code": 0, + "restored_log": "scratch/g2-r2b-r2/drop_nh_reservation_restored.txt", + "restored_log_sha256": "f36b7145c79a5eea7791442b7fba5e4fe618372de67209c296c0e69d79250b90", + "restored_test_summary": "1 passed in 15.50s", + "isolated_source_sha256": "27568b175af5acf16c83012ae151584a237886723b3946e55539e07639131d50", + "production_guard_present": true, + "verification": "Each identical test passed after source restoration. Current isolated-source SHA-256 matches the saved original; production rule is present." + }, + "metadata_reference": "scratch/g2-r2b-r2/mutations.json" + }, + { + "id": "savings_remove_age_condition", + "layer": "g_savings", + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": "and _operational_age_reduced(prior.result)", + "after": "and True" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_savings.py", + "-k", + "test_round_11_cola_fall_requires_age_reduction_operationally" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_gross_benefits_savings.py::test_round_11_cola_fall_requires_age_reduction_operationally" + ], + "log": { + "path": "scratch/savings_mutations/remove_age_condition.log", + "sha256": "719585948db1e459ab15bbff971d628b31e7f9b40939306c09c85ffb98c3b921", + "failure_summary": "1 failed, 12 deselected in 10.49s", + "failed_tests": [ + "tests/test_track_b_gross_benefits_savings.py::test_round_11_cola_fall_requires_age_reduction_operationally" + ] + }, + "restoration": { + "reverted": true, + "isolated_source_restored": true, + "production_guard_present": true, + "restored_test_exit_code": null, + "verification": "run_mutations.py restores original text after every run and asserts final equality. All four original fragments are currently present in isolated and production modules." + }, + "runner_reference": "scratch/savings_mutations/run_mutations.py" + }, + { + "id": "savings_floor_protected_equal_rates", + "layer": "g_savings", + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": "share = _ceil_dime_validated((protected - worker) / len(subject))", + "after": "share = _floor_dime_validated((protected - worker) / len(subject))" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_savings.py", + "-k", + "test_operational_rounding_is_minimum_equal_dime_that_preserves_total" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_gross_benefits_savings.py::test_operational_rounding_is_minimum_equal_dime_that_preserves_total" + ], + "log": { + "path": "scratch/savings_mutations/floor_protected_equal_rates.log", + "sha256": "5deae2bca548f2f2a43c9ad5bca5e13e463b0db63d0ca61b2dc6ade7f57fed57", + "failure_summary": "1 failed, 12 deselected in 9.81s", + "failed_tests": [ + "tests/test_track_b_gross_benefits_savings.py::test_operational_rounding_is_minimum_equal_dime_that_preserves_total" + ] + }, + "restoration": { + "reverted": true, + "isolated_source_restored": true, + "production_guard_present": true, + "restored_test_exit_code": null, + "verification": "run_mutations.py restores original text after every run and asserts final equality. All four original fragments are currently present in isolated and production modules." + }, + "runner_reference": "scratch/savings_mutations/run_mutations.py" + }, + { + "id": "savings_discard_active_membership_check", + "layer": "g_savings", + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": "and membership != self._protected_membership", + "after": "and False" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_savings.py", + "-k", + "test_operational_named_refusals_stay_in_denominator" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_gross_benefits_savings.py::test_operational_named_refusals_stay_in_denominator[UnsupportedReason.SAVINGS_CLAUSE_MEMBERSHIP_CHANGE]" + ], + "log": { + "path": "scratch/savings_mutations/discard_active_membership_check.log", + "sha256": "6ab05a0fc835552644e465b72fd18990d38075ef2ab3309cafb63a2aa96cfb3d", + "failure_summary": "1 failed, 1 passed, 11 deselected in 4.48s", + "failed_tests": [ + "tests/test_track_b_gross_benefits_savings.py::test_operational_named_refusals_stay_in_denominator[UnsupportedReason.SAVINGS_CLAUSE_MEMBERSHIP_CHANGE]" + ] + }, + "restoration": { + "reverted": true, + "isolated_source_restored": true, + "production_guard_present": true, + "restored_test_exit_code": null, + "verification": "run_mutations.py restores original text after every run and asserts final equality. All four original fragments are currently present in isolated and production modules." + }, + "runner_reference": "scratch/savings_mutations/run_mutations.py" + }, + { + "id": "savings_discard_spouse_age_factor", + "layer": "g_savings", + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": "_floor_dime_validated(increase * spouse.age_reduction_factor)", + "after": "_floor_dime_validated(increase)" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_savings.py", + "-k", + "test_operational_spouse_procedure_uses_unrounded_declared_factor" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_gross_benefits_savings.py::test_operational_spouse_procedure_uses_unrounded_declared_factor" + ], + "log": { + "path": "scratch/savings_mutations/discard_spouse_age_factor.log", + "sha256": "379658dc64df8c6ed176b29289b6aec1bfc923adef6b9448a92b9ea885844446", + "failure_summary": "1 failed, 14 deselected in 9.77s", + "failed_tests": [ + "tests/test_track_b_gross_benefits_savings.py::test_operational_spouse_procedure_uses_unrounded_declared_factor" + ] + }, + "restoration": { + "reverted": true, + "isolated_source_restored": true, + "production_guard_present": true, + "restored_test_exit_code": null, + "verification": "run_mutations.py restores original text after every run and asserts final equality. All four original fragments are currently present in isolated and production modules." + }, + "runner_reference": "scratch/savings_mutations/run_mutations.py" + } + ], + "restoration_verification_snapshot": { + "provenance": { + "path": "src/populace_dynamics/track_b/_provenance.py", + "sha256_at_verification": "886cbd14bb6461eed6761fee8185b330d71550cb27c53ee5283c785077828404" + }, + "g": { + "path": "src/populace_dynamics/track_b/gross_benefits.py", + "sha256_at_verification": "cab28ea4748876f8604cfcaf8c1adfa004d5ee18d50b3413a9f41d31c483aa81" + }, + "r2": { + "path": "src/populace_dynamics/track_b/ret_ledger.py", + "sha256_at_verification": "27568b175af5acf16c83012ae151584a237886723b3946e55539e07639131d50" + } + }, + "restoration_snapshot_note": "These hashes identify the source state checked when mutations were consolidated. Subsequent reviewed fixes are separately hashed in the final verification artifact; mutation rules remain restored." +} diff --git a/docs/design/track_b_g2_r2b_verification.json b/docs/design/track_b_g2_r2b_verification.json new file mode 100644 index 000000000..0aeecd4f4 --- /dev/null +++ b/docs/design/track_b_g2_r2b_verification.json @@ -0,0 +1,1350 @@ +{ + "schema_version": 1, + "verification_class": "statutory_conformance", + "admitted_scope": "Invented cases and captured published examples only; no population, behavioral or forecast claim.", + "workspace": "/Users/maxghenis/.subfleet/worktrees/20261023-090920-trackb-g2-r2b", + "head": "6967142aada78870fdf9c414b371d5e2b7d63352", + "environment": { + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "$PWD/scratch/no-microdata", + "POPULACE_DYNAMICS_EPUF_DIR": "$PWD/scratch/no-microdata", + "PYTHONPATH": "$PWD/src:$PWD" + }, + "preservation": { + "uncommitted": true, + "no_push": true, + "no_network": true, + "no_real_data": true, + "protected_files_unchanged": true, + "checks": { + "head": { + "command": [ + "git", + "--no-optional-locks", + "-c", + "core.fsmonitor=false", + "rev-parse", + "HEAD" + ], + "exit_code": 0, + "stdout": "6967142aada78870fdf9c414b371d5e2b7d63352\n", + "stderr": "" + }, + "log_since_origin_master": { + "command": [ + "git", + "--no-optional-locks", + "-c", + "core.fsmonitor=false", + "log", + "--oneline", + "origin/master..HEAD" + ], + "exit_code": 0, + "stdout": "", + "stderr": "" + }, + "committed_changed_paths": { + "command": [ + "git", + "--no-optional-locks", + "-c", + "core.fsmonitor=false", + "diff", + "--name-only", + "origin/master...HEAD" + ], + "exit_code": 0, + "stdout": "", + "stderr": "" + }, + "working_tree_changed_paths": { + "command": [ + "git", + "--no-optional-locks", + "-c", + "core.fsmonitor=false", + "diff", + "--name-only" + ], + "exit_code": 0, + "stdout": "docs/design/track_b_g_conformance_report.json\ndocs/design/track_b_g_gross_benefits.md\ndocs/design/track_b_r2_ret_ledger.md\nscripts/track_b_g_conformance_report.py\nsrc/populace_dynamics/track_b/_provenance.py\nsrc/populace_dynamics/track_b/gross_benefits.py\nsrc/populace_dynamics/track_b/ret_ledger.py\ntests/README-tiers.md\ntests/data/track_b/gross_benefit_examples.yaml\ntests/data/track_b/gross_benefit_sources/README.md\ntests/data/track_b/gross_benefit_sources/manifest.json\ntests/test_track_b_gross_benefits.py\ntests/test_track_b_gross_benefits_conformance_report.py\ntests/test_track_b_gross_benefits_fix_round_10_api.py\ntests/test_track_b_gross_benefits_fix_round_10_helpers.py\ntests/test_track_b_gross_benefits_fix_round_10_objects.py\ntests/test_track_b_gross_benefits_fix_round_10_parameters.py\ntests/test_track_b_gross_benefits_fix_round_11_seals.py\ntests/test_track_b_gross_benefits_fix_round_12_contract.py\ntests/test_track_b_gross_benefits_fix_round_13_audit.py\ntests/test_track_b_gross_benefits_fix_round_13_guard.py\ntests/test_track_b_gross_benefits_fix_round_15_receivers.py\ntests/test_track_b_gross_benefits_fix_round_3_rates.py\ntests/test_track_b_gross_benefits_fix_round_5_cohorts.py\ntests/test_track_b_gross_benefits_fix_round_6_cohorts.py\ntests/test_track_b_gross_benefits_fix_round_7_cohorts.py\ntests/test_track_b_gross_benefits_fix_round_7_history.py\ntests/test_track_b_gross_benefits_fix_round_8_entries.py\ntests/test_track_b_gross_benefits_fix_round_8_history.py\ntests/test_track_b_gross_benefits_fix_round_9_outcomes.py\ntests/test_track_b_gross_benefits_fix_round_9_validation.py\ntests/test_track_b_gross_benefits_properties.py\ntests/test_track_b_gross_benefits_registry.py\ntests/test_track_b_gross_benefits_review.py\ntests/test_track_b_gross_benefits_sources_20261011.py\ntests/test_track_b_r3_fix_round_13.py\ntests/test_track_b_ret_ledger.py\ntests/test_track_b_ret_ledger_sources.py\ntests/tier_counts.json\ntests/track_b_gross_benefit_support.py\n", + "stderr": "" + }, + "status": { + "command": [ + "git", + "--no-optional-locks", + "-c", + "core.fsmonitor=false", + "status", + "--short" + ], + "exit_code": 0, + "stdout": " M docs/design/track_b_g_conformance_report.json\n M docs/design/track_b_g_gross_benefits.md\n M docs/design/track_b_r2_ret_ledger.md\n M scripts/track_b_g_conformance_report.py\n M src/populace_dynamics/track_b/_provenance.py\n M src/populace_dynamics/track_b/gross_benefits.py\n M src/populace_dynamics/track_b/ret_ledger.py\n M tests/README-tiers.md\n M tests/data/track_b/gross_benefit_examples.yaml\n M tests/data/track_b/gross_benefit_sources/README.md\n M tests/data/track_b/gross_benefit_sources/manifest.json\n M tests/test_track_b_gross_benefits.py\n M tests/test_track_b_gross_benefits_conformance_report.py\n M tests/test_track_b_gross_benefits_fix_round_10_api.py\n M tests/test_track_b_gross_benefits_fix_round_10_helpers.py\n M tests/test_track_b_gross_benefits_fix_round_10_objects.py\n M tests/test_track_b_gross_benefits_fix_round_10_parameters.py\n M tests/test_track_b_gross_benefits_fix_round_11_seals.py\n M tests/test_track_b_gross_benefits_fix_round_12_contract.py\n M tests/test_track_b_gross_benefits_fix_round_13_audit.py\n M tests/test_track_b_gross_benefits_fix_round_13_guard.py\n M tests/test_track_b_gross_benefits_fix_round_15_receivers.py\n M tests/test_track_b_gross_benefits_fix_round_3_rates.py\n M tests/test_track_b_gross_benefits_fix_round_5_cohorts.py\n M tests/test_track_b_gross_benefits_fix_round_6_cohorts.py\n M tests/test_track_b_gross_benefits_fix_round_7_cohorts.py\n M tests/test_track_b_gross_benefits_fix_round_7_history.py\n M tests/test_track_b_gross_benefits_fix_round_8_entries.py\n M tests/test_track_b_gross_benefits_fix_round_8_history.py\n M tests/test_track_b_gross_benefits_fix_round_9_outcomes.py\n M tests/test_track_b_gross_benefits_fix_round_9_validation.py\n M tests/test_track_b_gross_benefits_properties.py\n M tests/test_track_b_gross_benefits_registry.py\n M tests/test_track_b_gross_benefits_review.py\n M tests/test_track_b_gross_benefits_sources_20261011.py\n M tests/test_track_b_r3_fix_round_13.py\n M tests/test_track_b_ret_ledger.py\n M tests/test_track_b_ret_ledger_sources.py\n M tests/tier_counts.json\n M tests/track_b_gross_benefit_support.py\n?? docs/design/track_b_g2_r2b_mutations.json\n?? docs/design/track_b_g2_r2b_report.md\n?? docs/design/track_b_g2_r2b_verification.json\n?? scripts/track_b_r2_cross_head.py\n?? tests/test_track_b_gross_benefits_deductions.py\n?? tests/test_track_b_gross_benefits_savings.py\n?? tests/test_track_b_refusal_notes.py\n?? tests/test_track_b_ret_ledger_deductions.py\n", + "stderr": "" + }, + "diff_check": { + "command": [ + "git", + "--no-optional-locks", + "-c", + "core.fsmonitor=false", + "diff", + "--check" + ], + "exit_code": 0, + "stdout": "", + "stderr": "" + } + } + }, + "changed_files": [ + "docs/design/track_b_g2_r2b_mutations.json", + "docs/design/track_b_g2_r2b_report.md", + "docs/design/track_b_g2_r2b_verification.json", + "docs/design/track_b_g_conformance_report.json", + "docs/design/track_b_g_gross_benefits.md", + "docs/design/track_b_r2_ret_ledger.md", + "scripts/track_b_g_conformance_report.py", + "scripts/track_b_r2_cross_head.py", + "src/populace_dynamics/track_b/_provenance.py", + "src/populace_dynamics/track_b/gross_benefits.py", + "src/populace_dynamics/track_b/ret_ledger.py", + "tests/README-tiers.md", + "tests/data/track_b/gross_benefit_examples.yaml", + "tests/data/track_b/gross_benefit_sources/README.md", + "tests/data/track_b/gross_benefit_sources/manifest.json", + "tests/test_track_b_gross_benefits.py", + "tests/test_track_b_gross_benefits_conformance_report.py", + "tests/test_track_b_gross_benefits_deductions.py", + "tests/test_track_b_gross_benefits_fix_round_10_api.py", + "tests/test_track_b_gross_benefits_fix_round_10_helpers.py", + "tests/test_track_b_gross_benefits_fix_round_10_objects.py", + "tests/test_track_b_gross_benefits_fix_round_10_parameters.py", + "tests/test_track_b_gross_benefits_fix_round_11_seals.py", + "tests/test_track_b_gross_benefits_fix_round_12_contract.py", + "tests/test_track_b_gross_benefits_fix_round_13_audit.py", + "tests/test_track_b_gross_benefits_fix_round_13_guard.py", + "tests/test_track_b_gross_benefits_fix_round_15_receivers.py", + "tests/test_track_b_gross_benefits_fix_round_3_rates.py", + "tests/test_track_b_gross_benefits_fix_round_5_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_6_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_history.py", + "tests/test_track_b_gross_benefits_fix_round_8_entries.py", + "tests/test_track_b_gross_benefits_fix_round_8_history.py", + "tests/test_track_b_gross_benefits_fix_round_9_outcomes.py", + "tests/test_track_b_gross_benefits_fix_round_9_validation.py", + "tests/test_track_b_gross_benefits_properties.py", + "tests/test_track_b_gross_benefits_registry.py", + "tests/test_track_b_gross_benefits_review.py", + "tests/test_track_b_gross_benefits_savings.py", + "tests/test_track_b_gross_benefits_sources_20261011.py", + "tests/test_track_b_r3_fix_round_13.py", + "tests/test_track_b_refusal_notes.py", + "tests/test_track_b_ret_ledger.py", + "tests/test_track_b_ret_ledger_deductions.py", + "tests/test_track_b_ret_ledger_sources.py", + "tests/tier_counts.json", + "tests/track_b_gross_benefit_support.py" + ], + "final_source_sha256": { + "src/populace_dynamics/track_b/_provenance.py": "886cbd14bb6461eed6761fee8185b330d71550cb27c53ee5283c785077828404", + "src/populace_dynamics/track_b/gross_benefits.py": "e1e6b35c3b547e4dc597235b2d395c49bd906ab29c4b06e682cc36de9f310a1f", + "src/populace_dynamics/track_b/ret_ledger.py": "62b896c508de879a4429961331e51f8af8162fef019a15c1804ce9df7b03c4e0", + "scripts/track_b_g_conformance_report.py": "3cb5cf9b27b1019daf224040554ea707a0dc96c4962bae8dc2cbaaa8f48ca2e4", + "scripts/track_b_r2_cross_head.py": "4f2a1bea264d906ea0fb4cec08a2b233b458bb3a0ca0d09dbe580d6cc78e8178" + }, + "validation_runs": [ + { + "environment": { + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "$PWD/scratch/no-microdata", + "POPULACE_DYNAMICS_EPUF_DIR": "$PWD/scratch/no-microdata", + "PYTHONPATH": "$PWD/src:$PWD" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits.py", + "tests/test_track_b_gross_benefits_deductions.py" + ], + "path": "scratch/trackb_lane/g_core_final.log", + "sha256": "be6fd18c848dd32e9e383350b1ec79a544c22b0d7af79c3627efe2f6553db013", + "summary": "346 passed in 64.90s (0:01:04)" + }, + { + "environment": { + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "$PWD/scratch/no-microdata", + "POPULACE_DYNAMICS_EPUF_DIR": "$PWD/scratch/no-microdata", + "PYTHONPATH": "$PWD/src:$PWD" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_dwb.py", + "tests/test_track_b_gross_benefits_fix_round_1.py", + "tests/test_track_b_gross_benefits_fix_round_10_api.py", + "tests/test_track_b_gross_benefits_fix_round_10_helpers.py" + ], + "path": "scratch/trackb_lane/g_prefix_final.log", + "sha256": "34a349d03d004d7a9d741639ea8429c0a48bd032275c5fcf05068f622dcad581", + "summary": "988 passed in 188.93s (0:03:08)", + "actual_launcher": "Python stdin invoked pytest.main with this argument list; paths selected by filename as recorded here." + }, + { + "environment": { + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "$PWD/scratch/no-microdata", + "POPULACE_DYNAMICS_EPUF_DIR": "$PWD/scratch/no-microdata", + "PYTHONPATH": "$PWD/src:$PWD" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "-o", + "faulthandler_timeout=120", + "tests/test_track_b_gross_benefits_fix_round_10_objects.py", + "tests/test_track_b_gross_benefits_fix_round_10_parameters.py", + "tests/test_track_b_gross_benefits_fix_round_11_roles.py", + "tests/test_track_b_gross_benefits_fix_round_11_seals.py", + "tests/test_track_b_gross_benefits_fix_round_12_contract.py", + "tests/test_track_b_gross_benefits_fix_round_13_audit.py", + "tests/test_track_b_gross_benefits_fix_round_13_boundary.py", + "tests/test_track_b_gross_benefits_fix_round_13_guard.py", + "tests/test_track_b_gross_benefits_fix_round_15_arguments.py", + "tests/test_track_b_gross_benefits_fix_round_15_collections.py", + "tests/test_track_b_gross_benefits_fix_round_15_receivers.py", + "tests/test_track_b_gross_benefits_fix_round_2_care.py", + "tests/test_track_b_gross_benefits_fix_round_2_history.py", + "tests/test_track_b_gross_benefits_fix_round_2_periods.py", + "tests/test_track_b_gross_benefits_fix_round_3_rates.py", + "tests/test_track_b_gross_benefits_fix_round_4_care_floor.py", + "tests/test_track_b_gross_benefits_fix_round_4_divorced_care.py", + "tests/test_track_b_gross_benefits_fix_round_5_care_history.py", + "tests/test_track_b_gross_benefits_fix_round_5_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_6_care_note.py", + "tests/test_track_b_gross_benefits_fix_round_6_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_boundary.py", + "tests/test_track_b_gross_benefits_fix_round_7_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_history.py", + "tests/test_track_b_gross_benefits_fix_round_8_entries.py", + "tests/test_track_b_gross_benefits_fix_round_8_history.py", + "tests/test_track_b_gross_benefits_fix_round_9_citations.py", + "tests/test_track_b_gross_benefits_fix_round_9_outcomes.py", + "tests/test_track_b_gross_benefits_fix_round_9_validation.py", + "tests/test_track_b_gross_benefits_oracle.py", + "tests/test_track_b_gross_benefits_own_input_order.py", + "tests/test_track_b_gross_benefits_parents_ieds.py", + "tests/test_track_b_gross_benefits_parisi.py", + "tests/test_track_b_gross_benefits_payment_review.py", + "tests/test_track_b_gross_benefits_properties.py", + "tests/test_track_b_gross_benefits_registry.py", + "tests/test_track_b_gross_benefits_review.py", + "tests/test_track_b_gross_benefits_savings.py", + "tests/test_track_b_gross_benefits_sources_20261011.py", + "tests/test_track_b_gross_benefits_ssfa.py" + ], + "path": "scratch/trackb_lane/g_remaining_final.log", + "sha256": "6f375fea82b61b5628e553be6aacf483642ec9be1c31dd4c6cdfd6184e423f3c", + "summary": "2 failed, 6612 passed in 1831.16s (0:30:31)", + "actual_launcher": "Python stdin invoked pytest.main; this process imported the audit inventories before their final update.", + "known_failures": [ + "test_cross_layer_public_names_and_members_have_explicit_audit_coverage", + "test_every_declared_sealed_class_has_an_adversarial_sample" + ], + "corrected_by": "final_inventory_files.log; both complete inventory files rerun after updating new-class declarations" + }, + { + "environment": { + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "$PWD/scratch/no-microdata", + "POPULACE_DYNAMICS_EPUF_DIR": "$PWD/scratch/no-microdata", + "PYTHONPATH": "$PWD/src:$PWD" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_fix_round_10_objects.py", + "tests/test_track_b_gross_benefits_fix_round_13_audit.py" + ], + "path": "scratch/trackb_lane/final_inventory_files.log", + "sha256": "9d155fdfacd01b11d6184e1effaa087a669b1db1455b9c885d99ec4d3656de36", + "summary": "1239 passed in 49.92s" + }, + { + "environment": { + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "$PWD/scratch/no-microdata", + "POPULACE_DYNAMICS_EPUF_DIR": "$PWD/scratch/no-microdata", + "PYTHONPATH": "$PWD/src:$PWD" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "-o", + "faulthandler_timeout=120", + "tests/test_track_b_gross_benefits_conformance_report.py" + ], + "path": "scratch/trackb_lane/g_report_tests.log", + "sha256": "7bbb05e509da76f0c8acc201f90a2eb3e611afaf2028c467580b4c0fb6be83ed", + "summary": "53 passed in 1336.87s (0:22:16)" + }, + { + "environment": { + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "$PWD/scratch/no-microdata", + "POPULACE_DYNAMICS_EPUF_DIR": "$PWD/scratch/no-microdata", + "PYTHONPATH": "$PWD/src:$PWD" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "-x", + "-o", + "faulthandler_timeout=120", + "tests/test_track_b_r3_fix_round_13.py", + "tests/test_track_b_r3_provenance.py", + "tests/test_track_b_r3_sources.py", + "tests/test_track_b_r3_validation_once.py", + "tests/test_track_b_arf.py", + "tests/test_track_b_arf_properties.py", + "tests/test_track_b_recompute.py", + "tests/test_track_b_recompute_properties.py", + "tests/test_track_b_refusal_notes.py", + "tests/estimates/test_birth_evidence_artifact.py" + ], + "path": "scratch/trackb_lane/r3_notes_birth.log", + "sha256": "dffe3b56ceb79ab92dd5efdc5ecfa6de5375babc5dfb8bb245e152d612b06cb9", + "summary": "1482 passed in 384.01s (0:06:24)" + }, + { + "environment": { + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "$PWD/scratch/no-microdata", + "POPULACE_DYNAMICS_EPUF_DIR": "$PWD/scratch/no-microdata", + "PYTHONPATH": "$PWD/src:$PWD" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_deductions.py", + "-k", + "test_nh_age_interaction_is_named_refusal or test_temporary_partial_reading_is_explicit_in_captures" + ], + "path": "scratch/trackb_lane/final_quotes.log", + "sha256": "e4590294c75fdec0ff06151e1cdd4f1eab424095c0ac566b30284e6acbab385a", + "summary": "2 passed, 28 deselected in 15.64s" + }, + { + "environment": { + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "$PWD/scratch/no-microdata", + "POPULACE_DYNAMICS_EPUF_DIR": "$PWD/scratch/no-microdata", + "PYTHONPATH": "$PWD/src:$PWD" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_fix_round_13_audit.py", + "-k", + "RedistributedBeneficiaryMonth or test_cross_layer_public_names_and_members_have_explicit_audit_coverage or test_every_declared_sealed_class_has_an_adversarial_sample" + ], + "path": "scratch/trackb_lane/final_audit.log", + "sha256": "224477f8a38ef7053f03f4c12aa1f7d890c597fac96ee940c02faa109570996d", + "summary": "13 passed, 1097 deselected in 15.03s" + }, + { + "environment": { + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "$PWD/scratch/no-microdata", + "POPULACE_DYNAMICS_EPUF_DIR": "$PWD/scratch/no-microdata", + "PYTHONPATH": "$PWD/src:$PWD" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests", + "-k", + "test__given_collected_suite__then_tiers_match_policy_manifest" + ], + "path": "scratch/trackb_lane/final_tier_policy.log", + "sha256": "7044e477a6f0bd8a854372800841f1bffe8eb1198e81fc84d460033e3f65ccba", + "summary": "1 passed, 25159 deselected in 189.39s (0:03:09)" + } + ], + "r2_final_review": { + "verification_class": "statutory conformance", + "scope": "invented cases only", + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "$PWD/.no-real-data", + "POPULACE_DYNAMICS_EPUF_DIR": "$PWD/.no-real-data", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "PYTHONPATH": "$PWD/src:$PWD" + }, + "python": "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "tests": [ + { + "arguments": [ + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_ret_ledger_deductions.py::test_rs_02501_155_nh_partial_month_preserves_nh_deductions", + "tests/test_track_b_gross_benefits_deductions.py" + ], + "passed": 31, + "seconds": 58.0 + }, + { + "arguments": [ + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_ret_ledger_deductions.py::test_rs_02501_155_nh_partial_month_preserves_nh_deductions" + ], + "passed": 1, + "seconds": 29.64 + }, + { + "arguments": [ + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_ret_ledger_deductions.py::test_family_context_invalidity_precedes_record_refusal", + "tests/test_track_b_ret_ledger.py::test_binding_survivor_maximum_with_zero_rate_cdb_computes_part_b" + ], + "passed": 3, + "seconds": 6.94 + } + ], + "cross_head_arguments": [ + "scripts/track_b_r2_cross_head.py", + "--baseline-root", + "scratch/trackb_lane/baseline", + "--output", + "scratch/g2-r2b-r2/cross_head_report.json" + ], + "cross_head": { + "verification_class": "statutory conformance", + "scope": "invented cases only; no population, behavioral or forecast claim", + "seed": 53014, + "r2_stable_rows": 240, + "r3_stable_rows": 240, + "identical_declared_output_bytes": true, + "stable_sha256": "799fc9e23a902ac1ca0c2563579ceb094d0dbcd631a912305c40062cf21a5f55", + "transitions": { + "baseline": { + "rows": 6, + "supported": 0, + "refused_by_reason": { + "deduction_before_reduction_part_b": 6 + } + }, + "head": { + "rows": 6, + "supported": 6, + "refused_by_reason": {} + } + }, + "transition_rows": [ + { + "id": "binding_survivor_own_excess_1", + "own_excess": 1, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_60", + "own_excess": 60, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_99", + "own_excess": 99, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_100", + "own_excess": 100, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_555", + "own_excess": 555, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_1188", + "own_excess": 1188, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + } + ] + }, + "collected_test_count_change": 0, + "formatting": "Black -l 79 and Ruff clean on changed source/tests/script" + }, + "savings_final_review": { + "environment": { + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "$PWD/__nonexistent_data__", + "POPULACE_DYNAMICS_EPUF_DIR": "$PWD/__nonexistent_data__", + "PYTHONPATH": "$PWD/src:$PWD" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_savings.py", + "tests/test_track_b_gross_benefits_fix_round_13_guard.py" + ], + "summary": "63 passed in 133.91s", + "log": "scratch/savings_deduction_history.log" + }, + "savings_dormant_review": { + "environment": { + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "$PWD/__nonexistent_data__", + "POPULACE_DYNAMICS_EPUF_DIR": "$PWD/__nonexistent_data__", + "PYTHONPATH": "$PWD/src:$PWD" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_savings.py", + "-k", + "test_operational_source_rules_are_quoted_from_captures or test_operational_carry_membership_refusal_and_denominator_properties" + ], + "summary": "2 passed, 15 deselected in 10.20s", + "log": "scratch/savings_dormant.log", + "log_sha256": "37e66382b2785c29b5758520c010f4bd584eb61c0dae6adb6360db8ee8bc5874" + }, + "tier_recount": { + "unit": { + "path": "scratch/trackb_lane/final_tier_unit.log", + "sha256": "ba1351844e26133240cae46fd1443ff6c2dcf4a1bf8682f18fc5e8b40438602c", + "summary": "18629/25160 tests collected (6531 deselected) in 255.82s (0:04:15)", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "--collect-only", + "-q", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-m", + "unit" + ], + "count": 18629 + }, + "artifact": { + "path": "scratch/trackb_lane/final_tier_artifact.log", + "sha256": "db437e3b8b92697ea44c2a4f04a75a38baf7a725e5b7c2b08507af9ffdc15cf4", + "summary": "4253/25160 tests collected (20907 deselected) in 275.01s (0:04:35)", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "--collect-only", + "-q", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-m", + "artifact" + ], + "count": 4253 + }, + "integration_psid": { + "path": "scratch/trackb_lane/final_tier_integration_psid.log", + "sha256": "27a9b1f8a2a1f2507f30d5228bcd0d93e486028620dc6a394501d240f332fe46", + "summary": "1450/25160 tests collected (23710 deselected) in 232.67s (0:03:52)", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "--collect-only", + "-q", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-m", + "integration_psid" + ], + "count": 1450 + }, + "reproduction_legacy": { + "path": "scratch/trackb_lane/final_tier_reproduction_legacy.log", + "sha256": "b7591a79416b50a266204faf0f24268ad1765e1f21c4cae3eca5bc6d2808278e", + "summary": "520/25160 tests collected (24640 deselected) in 304.57s (0:05:04)", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "--collect-only", + "-q", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-m", + "reproduction_legacy" + ], + "count": 520 + }, + "oracle_policyengine": { + "path": "scratch/trackb_lane/final_tier_oracle_policyengine.log", + "sha256": "d9d75e51747669bcc1faad83ef67916b34eb50432fb560a825170577fd21db20", + "summary": "308/25160 tests collected (24852 deselected) in 208.57s (0:03:28)", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "--collect-only", + "-q", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-m", + "oracle_policyengine" + ], + "count": 308 + } + }, + "formatting": [ + { + "argv": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "black", + "-l", + "79", + "scripts/track_b_g_conformance_report.py", + "scripts/track_b_r2_cross_head.py", + "src/populace_dynamics/track_b/_provenance.py", + "src/populace_dynamics/track_b/gross_benefits.py", + "src/populace_dynamics/track_b/ret_ledger.py", + "tests/test_track_b_gross_benefits.py", + "tests/test_track_b_gross_benefits_conformance_report.py", + "tests/test_track_b_gross_benefits_deductions.py", + "tests/test_track_b_gross_benefits_fix_round_10_api.py", + "tests/test_track_b_gross_benefits_fix_round_10_helpers.py", + "tests/test_track_b_gross_benefits_fix_round_10_objects.py", + "tests/test_track_b_gross_benefits_fix_round_10_parameters.py", + "tests/test_track_b_gross_benefits_fix_round_11_seals.py", + "tests/test_track_b_gross_benefits_fix_round_12_contract.py", + "tests/test_track_b_gross_benefits_fix_round_13_audit.py", + "tests/test_track_b_gross_benefits_fix_round_13_guard.py", + "tests/test_track_b_gross_benefits_fix_round_15_receivers.py", + "tests/test_track_b_gross_benefits_fix_round_3_rates.py", + "tests/test_track_b_gross_benefits_fix_round_5_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_6_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_history.py", + "tests/test_track_b_gross_benefits_fix_round_8_entries.py", + "tests/test_track_b_gross_benefits_fix_round_8_history.py", + "tests/test_track_b_gross_benefits_fix_round_9_outcomes.py", + "tests/test_track_b_gross_benefits_fix_round_9_validation.py", + "tests/test_track_b_gross_benefits_properties.py", + "tests/test_track_b_gross_benefits_registry.py", + "tests/test_track_b_gross_benefits_review.py", + "tests/test_track_b_gross_benefits_savings.py", + "tests/test_track_b_gross_benefits_sources_20261011.py", + "tests/test_track_b_r3_fix_round_13.py", + "tests/test_track_b_refusal_notes.py", + "tests/test_track_b_ret_ledger.py", + "tests/test_track_b_ret_ledger_deductions.py", + "tests/test_track_b_ret_ledger_sources.py", + "tests/track_b_gross_benefit_support.py" + ], + "exit_code": 0, + "output": "All done! \u2728 \ud83c\udf70 \u2728\n37 files left unchanged.\n" + }, + { + "argv": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "ruff", + "check", + "scripts/track_b_g_conformance_report.py", + "scripts/track_b_r2_cross_head.py", + "src/populace_dynamics/track_b/_provenance.py", + "src/populace_dynamics/track_b/gross_benefits.py", + "src/populace_dynamics/track_b/ret_ledger.py", + "tests/test_track_b_gross_benefits.py", + "tests/test_track_b_gross_benefits_conformance_report.py", + "tests/test_track_b_gross_benefits_deductions.py", + "tests/test_track_b_gross_benefits_fix_round_10_api.py", + "tests/test_track_b_gross_benefits_fix_round_10_helpers.py", + "tests/test_track_b_gross_benefits_fix_round_10_objects.py", + "tests/test_track_b_gross_benefits_fix_round_10_parameters.py", + "tests/test_track_b_gross_benefits_fix_round_11_seals.py", + "tests/test_track_b_gross_benefits_fix_round_12_contract.py", + "tests/test_track_b_gross_benefits_fix_round_13_audit.py", + "tests/test_track_b_gross_benefits_fix_round_13_guard.py", + "tests/test_track_b_gross_benefits_fix_round_15_receivers.py", + "tests/test_track_b_gross_benefits_fix_round_3_rates.py", + "tests/test_track_b_gross_benefits_fix_round_5_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_6_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_history.py", + "tests/test_track_b_gross_benefits_fix_round_8_entries.py", + "tests/test_track_b_gross_benefits_fix_round_8_history.py", + "tests/test_track_b_gross_benefits_fix_round_9_outcomes.py", + "tests/test_track_b_gross_benefits_fix_round_9_validation.py", + "tests/test_track_b_gross_benefits_properties.py", + "tests/test_track_b_gross_benefits_registry.py", + "tests/test_track_b_gross_benefits_review.py", + "tests/test_track_b_gross_benefits_savings.py", + "tests/test_track_b_gross_benefits_sources_20261011.py", + "tests/test_track_b_r3_fix_round_13.py", + "tests/test_track_b_refusal_notes.py", + "tests/test_track_b_ret_ledger.py", + "tests/test_track_b_ret_ledger_deductions.py", + "tests/test_track_b_ret_ledger_sources.py", + "tests/track_b_gross_benefit_support.py" + ], + "exit_code": 0, + "output": "All checks passed!\n" + } + ], + "final_conformance_regeneration": { + "path": "docs/design/track_b_g_conformance_report.json", + "sha256": "ee8ef3247a700b4cec92dfc27bbb98b071deaba5566b092cb9c3df4f762be972", + "final_sha256": "ee8ef3247a700b4cec92dfc27bbb98b071deaba5566b092cb9c3df4f762be972", + "byte_identical": true + }, + "mutations": { + "artifact": "docs/design/track_b_g2_r2b_mutations.json", + "confirmed": 13, + "all_reverted": true + }, + "cost": { + "measurements": [ + { + "workload": "g_conformance", + "head": "origin_master", + "cwd": "/Users/maxghenis/.subfleet/worktrees/20261023-090920-trackb-g2-r2b/scratch/trackb_lane/baseline", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "scripts/track_b_g_conformance_report.py" + ], + "wall_seconds": 1499.654013249994, + "user_cpu_seconds": 144.122114, + "system_cpu_seconds": 8.243347, + "exit_code": 0, + "last_lines": [ + "Wrote /Users/maxghenis/.subfleet/worktrees/20261023-090920-trackb-g2-r2b/scratch/trackb_lane/baseline/docs/design/track_b_g_conformance_report.json: 356400 invented configurations" + ], + "total_cpu_seconds": 152.365461, + "environment": { + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261023-090920-trackb-g2-r2b/scratch/no-microdata", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261023-090920-trackb-g2-r2b/scratch/no-microdata", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261023-090920-trackb-g2-r2b/scratch/trackb_lane/baseline/src:/Users/maxghenis/.subfleet/worktrees/20261023-090920-trackb-g2-r2b/scratch/trackb_lane/baseline" + } + }, + { + "workload": "g_conformance", + "head": "working_tree", + "cwd": "/Users/maxghenis/.subfleet/worktrees/20261023-090920-trackb-g2-r2b", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "scripts/track_b_g_conformance_report.py" + ], + "wall_seconds": 796.099722333005, + "user_cpu_seconds": 163.88692700000001, + "system_cpu_seconds": 8.626982000000002, + "exit_code": 0, + "last_lines": [ + "Wrote /Users/maxghenis/.subfleet/worktrees/20261023-090920-trackb-g2-r2b/docs/design/track_b_g_conformance_report.json: 356400 invented configurations" + ], + "total_cpu_seconds": 172.513909, + "environment": { + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261023-090920-trackb-g2-r2b/scratch/no-microdata", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261023-090920-trackb-g2-r2b/scratch/no-microdata", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261023-090920-trackb-g2-r2b/src:/Users/maxghenis/.subfleet/worktrees/20261023-090920-trackb-g2-r2b" + } + }, + { + "workload": "r2_tests", + "head": "origin_master", + "cwd": "/Users/maxghenis/.subfleet/worktrees/20261023-090920-trackb-g2-r2b/scratch/trackb_lane/baseline", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_ret_differential.py", + "tests/test_track_b_ret_grace.py", + "tests/test_track_b_ret_grace_differential.py", + "tests/test_track_b_ret_grace_provenance.py", + "tests/test_track_b_ret_ledger.py", + "tests/test_track_b_ret_ledger_properties.py", + "tests/test_track_b_ret_ledger_readings.py", + "tests/test_track_b_ret_ledger_sources.py" + ], + "wall_seconds": 868.5359836249991, + "user_cpu_seconds": 81.33624600000002, + "system_cpu_seconds": 5.500299999999999, + "exit_code": 0, + "last_lines": [ + "........................................................................ [ 73%]", + "........................................................................ [ 82%]", + "........................................................................ [ 91%]", + ".................................................................. [100%]", + "786 passed in 861.05s (0:14:21)" + ], + "total_cpu_seconds": 86.83654600000001, + "environment": { + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261023-090920-trackb-g2-r2b/scratch/no-microdata", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261023-090920-trackb-g2-r2b/scratch/no-microdata", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261023-090920-trackb-g2-r2b/scratch/trackb_lane/baseline/src:/Users/maxghenis/.subfleet/worktrees/20261023-090920-trackb-g2-r2b/scratch/trackb_lane/baseline" + } + }, + { + "workload": "r2_tests", + "head": "working_tree", + "cwd": "/Users/maxghenis/.subfleet/worktrees/20261023-090920-trackb-g2-r2b", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_ret_differential.py", + "tests/test_track_b_ret_grace.py", + "tests/test_track_b_ret_grace_differential.py", + "tests/test_track_b_ret_grace_provenance.py", + "tests/test_track_b_ret_ledger.py", + "tests/test_track_b_ret_ledger_deductions.py", + "tests/test_track_b_ret_ledger_properties.py", + "tests/test_track_b_ret_ledger_readings.py", + "tests/test_track_b_ret_ledger_sources.py" + ], + "wall_seconds": 911.7418719999987, + "user_cpu_seconds": 107.79183, + "system_cpu_seconds": 6.463436999999999, + "exit_code": 0, + "last_lines": [ + "........................................................................ [ 79%]", + "........................................................................ [ 88%]", + "........................................................................ [ 96%]", + ".......................... [100%]", + "818 passed in 902.52s (0:15:02)" + ], + "total_cpu_seconds": 114.255267, + "environment": { + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261023-090920-trackb-g2-r2b/scratch/no-microdata", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261023-090920-trackb-g2-r2b/scratch/no-microdata", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261023-090920-trackb-g2-r2b/src:/Users/maxghenis/.subfleet/worktrees/20261023-090920-trackb-g2-r2b" + } + } + ], + "caveat": "Single back-to-back observations under concurrent validation load; CPU and wall times are reported separately. The final G pair was rerun after production source freeze. R2 current-head tests also ran after freeze. Baseline R2 has fewer tests; both exact command lists and counts are retained.", + "superseded_initial_g_pair": [ + { + "workload": "g_conformance", + "head": "origin_master", + "cwd": "/Users/maxghenis/.subfleet/worktrees/20261023-090920-trackb-g2-r2b/scratch/trackb_lane/baseline", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "scripts/track_b_g_conformance_report.py" + ], + "wall_seconds": 1483.483369417001, + "user_cpu_seconds": 133.246797, + "system_cpu_seconds": 4.74792, + "exit_code": 0, + "last_lines": [ + "Wrote /Users/maxghenis/.subfleet/worktrees/20261023-090920-trackb-g2-r2b/scratch/trackb_lane/baseline/docs/design/track_b_g_conformance_report.json: 356400 invented configurations" + ] + }, + { + "workload": "g_conformance", + "head": "working_tree", + "cwd": "/Users/maxghenis/.subfleet/worktrees/20261023-090920-trackb-g2-r2b", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "scripts/track_b_g_conformance_report.py" + ], + "wall_seconds": 1183.0418077079958, + "user_cpu_seconds": 134.834483, + "system_cpu_seconds": 5.831826, + "exit_code": 0, + "last_lines": [ + "Wrote /Users/maxghenis/.subfleet/worktrees/20261023-090920-trackb-g2-r2b/docs/design/track_b_g_conformance_report.json: 356400 invented configurations" + ] + } + ] + }, + "coverage": { + "g_unique_tests": 8004, + "g_lattice": { + "invalid": 286794, + "refused": 60775, + "rows": 356400, + "supported": 8831 + }, + "g_registry_examples": 37, + "g_refusal_witnesses": { + "denominator": { + "invalid": 0, + "refused": 37, + "rows": 37, + "supported": 0 + }, + "refused_by_reason": { + "administrative_finality": 1, + "combined_family_maximum": 1, + "deduction_age_work_interaction": 1, + "deemed_or_putative_spouse": 1, + "delayed_credits_born_before_1917": 1, + "di_entitlement_before_july_1980": 1, + "dib_after_reduced_rib": 1, + "dib_guarantee_pia": 1, + "disabled_widow_before_1984": 1, + "divorced_spouse_care_history": 1, + "divorced_spouse_child_in_care_unknown": 1, + "drug_addiction_suspension": 1, + "dual_entitlement_sequence": 1, + "election_certificate_suspension": 1, + "eligibility_before_1983": 1, + "foreign_work_deduction": 1, + "government_pension_offset": 1, + "independently_entitled_divorced_spouse": 1, + "maritime_deduction": 1, + "multiple_auxiliary_records": 1, + "non_aime_formula_pia": 1, + "own_rib_history_before_1978": 1, + "parent_benefit": 1, + "parisi_before_october_1999": 1, + "parisi_redistribution_ambiguous": 1, + "payment_month_before_1983": 1, + "penalty_deduction": 1, + "prisoner_suspension": 1, + "reduced_benefit_history_before_1978": 1, + "savings_clause_403a5": 1, + "savings_clause_history_unknown": 1, + "savings_clause_membership_change": 1, + "savings_clause_rate_procedure": 1, + "widow_child_in_care_unknown": 1, + "widow_drc_savings_clause": 1, + "widow_drc_savings_clause_history_unknown": 1, + "workers_compensation_offset": 1 + }, + "scope": "Named invented witnesses outside the finite lattice; separate denominator, one valid refusal for every retained UnsupportedReason.", + "witnesses": [ + { + "description": "Declared finality protection", + "id": "administrative_finality", + "reason": "administrative_finality", + "status": "refused" + }, + { + "description": "One child on retirement and survivor records", + "id": "combined_family_maximum", + "reason": "combined_family_maximum", + "status": "refused" + }, + { + "description": "Concurrent number-holder reservations and age reduction need a captured allocation", + "id": "deduction_age_work_interaction", + "reason": "deduction_age_work_interaction", + "status": "refused" + }, + { + "description": "Declared deemed spouse", + "id": "deemed_or_putative_spouse", + "reason": "deemed_or_putative_spouse", + "status": "refused" + }, + { + "description": "Own RIB has 12 credit months for a 1916 birth", + "id": "delayed_credits_born_before_1917", + "reason": "delayed_credits_born_before_1917", + "status": "refused" + }, + { + "description": "Initial DIB entitlement June 1980", + "id": "di_entitlement_before_july_1980", + "reason": "di_entitlement_before_july_1980", + "status": "refused" + }, + { + "description": "Own DIB reduced for prior reduced RIB", + "id": "dib_after_reduced_rib", + "reason": "dib_after_reduced_rib", + "status": "refused" + }, + { + "description": "Declared DIB guarantee PIA", + "id": "dib_guarantee_pia", + "reason": "dib_guarantee_pia", + "status": "refused" + }, + { + "description": "DWB benefit month December 1983", + "id": "disabled_widow_before_1984", + "reason": "disabled_widow_before_1984", + "status": "refused" + }, + { + "description": "An aged divorced spouse lacks first-entitlement care history that can change the amount", + "id": "divorced_spouse_care_history", + "reason": "divorced_spouse_care_history", + "status": "refused" + }, + { + "description": "A divorced spouse and an entitled child lack a current care attestation", + "id": "divorced_spouse_child_in_care_unknown", + "reason": "divorced_spouse_child_in_care_unknown", + "status": "refused" + }, + { + "description": "GN 02603.040 event requires an unimplemented deduction procedure: drug_addiction_suspension", + "id": "drug_addiction_suspension", + "reason": "drug_addiction_suspension", + "status": "refused" + }, + { + "description": "Widow also entitled to own DIB", + "id": "dual_entitlement_sequence", + "reason": "dual_entitlement_sequence", + "status": "refused" + }, + { + "description": "GN 02603.040 event requires an unimplemented deduction procedure: election_certificate_suspension", + "id": "election_certificate_suspension", + "reason": "election_certificate_suspension", + "status": "refused" + }, + { + "description": "1982 eligibility with otherwise valid survivor inputs", + "id": "eligibility_before_1983", + "reason": "eligibility_before_1983", + "status": "refused" + }, + { + "description": "GN 02603.040 event requires an unimplemented deduction procedure: foreign_work", + "id": "foreign_work_deduction", + "reason": "foreign_work_deduction", + "status": "refused" + }, + { + "description": "Widow GPO before repeal in December 2023", + "id": "government_pension_offset", + "reason": "government_pension_offset", + "status": "refused" + }, + { + "description": "IEDS benefit month December 1984", + "id": "independently_entitled_divorced_spouse", + "reason": "independently_entitled_divorced_spouse", + "status": "refused" + }, + { + "description": "GN 02603.040 event requires an unimplemented deduction procedure: maritime", + "id": "maritime_deduction", + "reason": "maritime_deduction", + "status": "refused" + }, + { + "description": "One person is divorced spouse and mother/father on two records", + "id": "multiple_auxiliary_records", + "reason": "multiple_auxiliary_records", + "status": "refused" + }, + { + "description": "Declared PIA outside the AIME formula", + "id": "non_aime_formula_pia", + "reason": "non_aime_formula_pia", + "status": "refused" + }, + { + "description": "Spouse born in 1912 has own RIB PIA 1000 and RF1 but no pre-January-1978 reduction or PIA history", + "id": "own_rib_history_before_1978", + "reason": "own_rib_history_before_1978", + "status": "refused" + }, + { + "description": "Two potential parents; one own RIB 780 lies between 75% and 82.5% of PIA 1000", + "id": "parent_benefit", + "reason": "parent_benefit", + "status": "refused" + }, + { + "description": "Binding mixed dual/non-dual family in September 1999", + "id": "parisi_before_october_1999", + "reason": "parisi_before_october_1999", + "status": "refused" + }, + { + "description": "Binding maximum with credited own RIB and a non-dual child", + "id": "parisi_redistribution_ambiguous", + "reason": "parisi_redistribution_ambiguous", + "status": "refused" + }, + { + "description": "December 1982 benefit month", + "id": "payment_month_before_1983", + "reason": "payment_month_before_1983", + "status": "refused" + }, + { + "description": "GN 02603.040 event requires an unimplemented deduction procedure: penalty", + "id": "penalty_deduction", + "reason": "penalty_deduction", + "status": "refused" + }, + { + "description": "GN 02603.040 event requires an unimplemented deduction procedure: prisoner_suspension", + "id": "prisoner_suspension", + "reason": "prisoner_suspension", + "status": "refused" + }, + { + "description": "Spouse born in 1912 has RF1 on an unreduced 500 benefit but no pre-January-1978 money reduction or unreduced-rate history", + "id": "reduced_benefit_history_before_1978", + "reason": "reduced_benefit_history_before_1978", + "status": "refused" + }, + { + "description": "Protected total 1500 falls to 1499.90 after a PIA increase", + "id": "savings_clause_403a5", + "reason": "savings_clause_403a5", + "status": "refused" + }, + { + "description": "Governed month begins with unknown prior entitlement months", + "id": "savings_clause_history_unknown", + "reason": "savings_clause_history_unknown", + "status": "refused" + }, + { + "description": "One child leaves while operational protection is active", + "id": "savings_clause_membership_change", + "reason": "savings_clause_membership_change", + "status": "refused" + }, + { + "description": "A reduced spouse alone has no captured allocation procedure", + "id": "savings_clause_rate_procedure", + "reason": "savings_clause_rate_procedure", + "status": "refused" + }, + { + "description": "A widow and an entitled child lack a current care attestation", + "id": "widow_child_in_care_unknown", + "reason": "widow_child_in_care_unknown", + "status": "refused" + }, + { + "description": "May 1978 survivor protected from widow deceased-worker DRCs", + "id": "widow_drc_savings_clause", + "reason": "widow_drc_savings_clause", + "status": "refused" + }, + { + "description": "Direct survivor snapshot has widow DRCs and a child but lacks May 1978 attestation", + "id": "widow_drc_savings_clause_history_unknown", + "reason": "widow_drc_savings_clause_history_unknown", + "status": "refused" + }, + { + "description": "Disability record with declared workers compensation offset", + "id": "workers_compensation_offset", + "reason": "workers_compensation_offset", + "status": "refused" + } + ] + }, + "g_deduction_extension": { + "invalid": 0, + "refused": 0, + "rows": 16, + "supported": 16 + }, + "r2_r3_cross_head": { + "verification_class": "statutory conformance", + "scope": "invented cases only; no population, behavioral or forecast claim", + "seed": 53014, + "r2_stable_rows": 240, + "r3_stable_rows": 240, + "identical_declared_output_bytes": true, + "stable_sha256": "799fc9e23a902ac1ca0c2563579ceb094d0dbcd631a912305c40062cf21a5f55", + "transitions": { + "baseline": { + "rows": 6, + "supported": 0, + "refused_by_reason": { + "deduction_before_reduction_part_b": 6 + } + }, + "head": { + "rows": 6, + "supported": 6, + "refused_by_reason": {} + } + }, + "transition_rows": [ + { + "id": "binding_survivor_own_excess_1", + "own_excess": 1, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_60", + "own_excess": 60, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_99", + "own_excess": 99, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_100", + "own_excess": 100, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_555", + "own_excess": 555, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_1188", + "own_excess": 1188, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + } + ] + } + }, + "validation_notes": [ + "Full G/R3 combined attempts were interrupted after stalled progress; the requested file surface was verified in smaller groups.", + "The broad G remainder run passed 6612 tests and failed two explicit audit inventories imported before their updates. Both entire affected inventory files passed after the updates. Counts in separate runs overlap and must not be summed as unique coverage.", + "Four concurrent final tier collection attempts were interrupted to reduce contention and rerun sequentially. No full-suite execution was performed.", + "The requested absolute non-deductee monotonicity invariant conflicts with the captured single-full-deduction exception. The executed minimized counterexample and qualified invariant are recorded in the design and report; the existing property has no collection-count change." + ] +} diff --git a/docs/design/track_b_g_conformance_report.json b/docs/design/track_b_g_conformance_report.json index 805ce6e5c..6dc5b3927 100644 --- a/docs/design/track_b_g_conformance_report.json +++ b/docs/design/track_b_g_conformance_report.json @@ -1,5 +1,160 @@ { "admitted_scope": "Gross benefits for supported invented configurations only; no population, behavioral, payment-timing or forecast claim.", + "deduction_conformance": { + "denominator": { + "invalid": 0, + "refused": 0, + "rows": 16, + "supported": 16 + }, + "rows": [ + { + "id": "retirement-estimated-full-same", + "payables": { + "a": "0", + "b": "250", + "c": "250" + }, + "status": "supported" + }, + { + "id": "retirement-estimated-full-separate", + "payables": { + "a": "0", + "b": "250", + "c": "833/5" + }, + "status": "supported" + }, + { + "id": "retirement-estimated-partial-same", + "payables": { + "a": "50", + "b": "225", + "c": "225" + }, + "status": "supported" + }, + { + "id": "retirement-estimated-partial-separate", + "payables": { + "a": "50", + "b": "225", + "c": "833/5" + }, + "status": "supported" + }, + { + "id": "retirement-permanent-full-same", + "payables": { + "a": "0", + "b": "250", + "c": "250" + }, + "status": "supported" + }, + { + "id": "retirement-permanent-full-separate", + "payables": { + "a": "0", + "b": "250", + "c": "250" + }, + "status": "supported" + }, + { + "id": "retirement-permanent-partial-same", + "payables": { + "a": "50", + "b": "225", + "c": "225" + }, + "status": "supported" + }, + { + "id": "retirement-permanent-partial-separate", + "payables": { + "a": "50", + "b": "225", + "c": "225" + }, + "status": "supported" + }, + { + "id": "survivor-estimated-full-same", + "payables": { + "a": "0", + "b": "750", + "c": "750" + }, + "status": "supported" + }, + { + "id": "survivor-estimated-full-separate", + "payables": { + "a": "0", + "b": "750", + "c": "5833/10" + }, + "status": "supported" + }, + { + "id": "survivor-estimated-partial-same", + "payables": { + "a": "50", + "b": "750", + "c": "750" + }, + "status": "supported" + }, + { + "id": "survivor-estimated-partial-separate", + "payables": { + "a": "50", + "b": "750", + "c": "5833/10" + }, + "status": "supported" + }, + { + "id": "survivor-permanent-full-same", + "payables": { + "a": "0", + "b": "750", + "c": "750" + }, + "status": "supported" + }, + { + "id": "survivor-permanent-full-separate", + "payables": { + "a": "0", + "b": "750", + "c": "750" + }, + "status": "supported" + }, + { + "id": "survivor-permanent-partial-same", + "payables": { + "a": "50", + "b": "750", + "c": "750" + }, + "status": "supported" + }, + { + "id": "survivor-permanent-partial-separate", + "payables": { + "a": "50", + "b": "750", + "c": "750" + }, + "status": "supported" + } + ], + "scope": "Separate invented monthly deduction denominator. G v2 had no deduction entry point; no historical lattice row is reclassified." + }, "denominator_kind": "finite invented configuration lattice; no population data or population weights", "gross_benefits_version": "track-b-g-v2", "lattice": { @@ -161,6 +316,7 @@ "refused_by_reason": { "administrative_finality": 9831, "combined_family_maximum": 4860, + "deduction_age_work_interaction": 0, "deemed_or_putative_spouse": 9720, "delayed_credits_born_before_1917": 0, "di_entitlement_before_july_1980": 0, @@ -169,10 +325,14 @@ "disabled_widow_before_1984": 0, "divorced_spouse_care_history": 0, "divorced_spouse_child_in_care_unknown": 196, + "drug_addiction_suspension": 0, "dual_entitlement_sequence": 6844, + "election_certificate_suspension": 0, "eligibility_before_1983": 0, + "foreign_work_deduction": 0, "government_pension_offset": 3240, "independently_entitled_divorced_spouse": 0, + "maritime_deduction": 0, "multiple_auxiliary_records": 0, "non_aime_formula_pia": 4971, "own_rib_history_before_1978": 0, @@ -180,9 +340,13 @@ "parisi_before_october_1999": 832, "parisi_redistribution_ambiguous": 340, "payment_month_before_1983": 0, + "penalty_deduction": 0, + "prisoner_suspension": 0, "reduced_benefit_history_before_1978": 0, "savings_clause_403a5": 0, "savings_clause_history_unknown": 0, + "savings_clause_membership_change": 0, + "savings_clause_rate_procedure": 0, "widow_child_in_care_unknown": 168, "widow_drc_savings_clause": 4860, "widow_drc_savings_clause_history_unknown": 0, @@ -195,8 +359,11 @@ "credits:own_rib": 1, "credits:widow_basis": 2, "credits:worker": 1, + "deduction:no_child_in_care": 1, + "deduction:own_earnings": 7, + "deduction:temporary": 3, "dual:all_dual": 0, - "dual:child": 2, + "dual:child": 3, "dual:method_b": 1, "dual:method_c": 7, "dual:parent": 0, @@ -205,7 +372,7 @@ "formula:maximum": 5, "historical:refused": 4, "ieds": 0, - "maximum:binding": 15, + "maximum:binding": 23, "maximum:disability_aime": 0, "maximum:disability_cap": 4, "maximum:disability_floor": 0, @@ -216,8 +383,8 @@ "parent:one": 0, "parent:two": 0, "record:disability": 5, - "record:retirement": 10, - "record:survivor": 9, + "record:retirement": 11, + "record:survivor": 16, "redistribution:own_age_reduced": 2, "redistribution:partial": 4, "redistribution:zero": 4, @@ -225,13 +392,13 @@ "reduction:widow": 4, "reduction:worker": 1, "rib_lim": 1, - "role:child": 17, + "role:child": 25, "role:disabled_widow": 0, "role:divorced_spouse": 0, - "role:mother_father": 2, + "role:mother_father": 9, "role:parent": 0, "role:spouse": 11, - "role:spouse_child_in_care": 0, + "role:spouse_child_in_care": 1, "role:surviving_divorced_spouse": 1, "role:widow": 7, "source:erratum": 1, @@ -239,8 +406,8 @@ "ssfa:wep_regular_pia": 0, "widow:child_in_care": 2 }, - "examples": 29, - "figures": 216, + "examples": 37, + "figures": 270, "file": "tests/data/track_b/gross_benefit_examples.yaml", "invented_only_classes": { "cola_path": { @@ -327,12 +494,6 @@ "tests/test_track_b_gross_benefits_parents_ieds.py::test_parent_hand_reference_one_or_two_entitled_parents" ] }, - "role:spouse_child_in_care": { - "reason": "The captures give the exemption from age reduction but no worked-money child-in-care dual-entitlement example.", - "tests": [ - "tests/test_track_b_gross_benefits.py::test_child_in_care_spouse_offset_uses_the_reduced_rib" - ] - }, "ssfa:gpo_ignored": { "reason": "GN 02608.100 publishes the repeal boundary, not worked gross-family monetary figures.", "tests": [ @@ -347,12 +508,15 @@ ] } }, - "sha256": "9595c8ec4f19b164faef26faadf90649fbf40fc2b18a7639d7deaa8aba3a8da9", + "sha256": "a06a3f7158b6b5e4ce6901fd8de94bdf30e485ebbc3e967cdb9422ebd955abb6", "supported_classes": [ "cola_path", "credits:own_rib", "credits:widow_basis", "credits:worker", + "deduction:no_child_in_care", + "deduction:own_earnings", + "deduction:temporary", "dual:all_dual", "dual:child", "dual:method_b", @@ -398,13 +562,14 @@ "supplemental_refusal_witnesses": { "denominator": { "invalid": 0, - "refused": 28, - "rows": 28, + "refused": 37, + "rows": 37, "supported": 0 }, "refused_by_reason": { "administrative_finality": 1, "combined_family_maximum": 1, + "deduction_age_work_interaction": 1, "deemed_or_putative_spouse": 1, "delayed_credits_born_before_1917": 1, "di_entitlement_before_july_1980": 1, @@ -413,10 +578,14 @@ "disabled_widow_before_1984": 1, "divorced_spouse_care_history": 1, "divorced_spouse_child_in_care_unknown": 1, + "drug_addiction_suspension": 1, "dual_entitlement_sequence": 1, + "election_certificate_suspension": 1, "eligibility_before_1983": 1, + "foreign_work_deduction": 1, "government_pension_offset": 1, "independently_entitled_divorced_spouse": 1, + "maritime_deduction": 1, "multiple_auxiliary_records": 1, "non_aime_formula_pia": 1, "own_rib_history_before_1978": 1, @@ -424,9 +593,13 @@ "parisi_before_october_1999": 1, "parisi_redistribution_ambiguous": 1, "payment_month_before_1983": 1, + "penalty_deduction": 1, + "prisoner_suspension": 1, "reduced_benefit_history_before_1978": 1, "savings_clause_403a5": 1, "savings_clause_history_unknown": 1, + "savings_clause_membership_change": 1, + "savings_clause_rate_procedure": 1, "widow_child_in_care_unknown": 1, "widow_drc_savings_clause": 1, "widow_drc_savings_clause_history_unknown": 1, @@ -446,6 +619,12 @@ "reason": "combined_family_maximum", "status": "refused" }, + { + "description": "Concurrent number-holder reservations and age reduction need a captured allocation", + "id": "deduction_age_work_interaction", + "reason": "deduction_age_work_interaction", + "status": "refused" + }, { "description": "Declared deemed spouse", "id": "deemed_or_putative_spouse", @@ -494,18 +673,36 @@ "reason": "divorced_spouse_child_in_care_unknown", "status": "refused" }, + { + "description": "GN 02603.040 event requires an unimplemented deduction procedure: drug_addiction_suspension", + "id": "drug_addiction_suspension", + "reason": "drug_addiction_suspension", + "status": "refused" + }, { "description": "Widow also entitled to own DIB", "id": "dual_entitlement_sequence", "reason": "dual_entitlement_sequence", "status": "refused" }, + { + "description": "GN 02603.040 event requires an unimplemented deduction procedure: election_certificate_suspension", + "id": "election_certificate_suspension", + "reason": "election_certificate_suspension", + "status": "refused" + }, { "description": "1982 eligibility with otherwise valid survivor inputs", "id": "eligibility_before_1983", "reason": "eligibility_before_1983", "status": "refused" }, + { + "description": "GN 02603.040 event requires an unimplemented deduction procedure: foreign_work", + "id": "foreign_work_deduction", + "reason": "foreign_work_deduction", + "status": "refused" + }, { "description": "Widow GPO before repeal in December 2023", "id": "government_pension_offset", @@ -518,6 +715,12 @@ "reason": "independently_entitled_divorced_spouse", "status": "refused" }, + { + "description": "GN 02603.040 event requires an unimplemented deduction procedure: maritime", + "id": "maritime_deduction", + "reason": "maritime_deduction", + "status": "refused" + }, { "description": "One person is divorced spouse and mother/father on two records", "id": "multiple_auxiliary_records", @@ -560,6 +763,18 @@ "reason": "payment_month_before_1983", "status": "refused" }, + { + "description": "GN 02603.040 event requires an unimplemented deduction procedure: penalty", + "id": "penalty_deduction", + "reason": "penalty_deduction", + "status": "refused" + }, + { + "description": "GN 02603.040 event requires an unimplemented deduction procedure: prisoner_suspension", + "id": "prisoner_suspension", + "reason": "prisoner_suspension", + "status": "refused" + }, { "description": "Spouse born in 1912 has RF1 on an unreduced 500 benefit but no pre-January-1978 money reduction or unreduced-rate history", "id": "reduced_benefit_history_before_1978", @@ -578,6 +793,18 @@ "reason": "savings_clause_history_unknown", "status": "refused" }, + { + "description": "One child leaves while operational protection is active", + "id": "savings_clause_membership_change", + "reason": "savings_clause_membership_change", + "status": "refused" + }, + { + "description": "A reduced spouse alone has no captured allocation procedure", + "id": "savings_clause_rate_procedure", + "reason": "savings_clause_rate_procedure", + "status": "refused" + }, { "description": "A widow and an entitled child lack a current care attestation", "id": "widow_child_in_care_unknown", diff --git a/scripts/track_b_g_conformance_report.py b/scripts/track_b_g_conformance_report.py index b2424730c..55cc6ffba 100644 --- a/scripts/track_b_g_conformance_report.py +++ b/scripts/track_b_g_conformance_report.py @@ -246,7 +246,11 @@ def classify_configuration(case: Configuration) -> tuple[str, str | None]: def _savings_witness(*, unknown=False): month = g.YearMonth(2025, 11) children = [g.Beneficiary(c, g.Role.CHILD) for c in ("c1", "c2")] - guard = g.SavingsClauseGuard(month, earlier_months_unknown=unknown) + guard = g.SavingsClauseGuard( + month, + earlier_months_unknown=unknown, + reading=g.SavingsClauseReading.LITERAL_REFUSAL, + ) guard.admit(_family(_retired(), children, month)) guard.admit( _family( @@ -257,6 +261,69 @@ def _savings_witness(*, unknown=False): ) +def _deduction_witness(reason, *, age_worker=False): + members = [ + g.Beneficiary("c1", g.Role.CHILD), + g.Beneficiary("c2", g.Role.CHILD), + ] + if age_worker: + members[0] = g.Beneficiary( + "c1", g.Role.SPOUSE, reduction_months=36, birth_year=1960 + ) + return g.family_benefits_after_deductions( + _retired(), + members, + payment_month=NOW, + params=PARAMS, + deductions={"c1": g.BenefitDeduction(reason)}, + households={"c1": "home", "c2": "home"}, + worker_deductions={"c2": F(1)} if age_worker else None, + standalone=True, + ) + + +def _operational_savings_witness(*, membership): + month = g.YearMonth(2026, 1) + guard = g.SavingsClauseGuard(month, earlier_months_unknown=False) + members = ( + [g.Beneficiary("c1", g.Role.CHILD), g.Beneficiary("c2", g.Role.CHILD)] + if membership + else [ + g.Beneficiary( + "s", g.Role.SPOUSE, reduction_months=60, birth_year=1960 + ) + ] + ) + + def state(pia, maximum): + return g.RecordState( + g.FamilyKind.RETIREMENT, + F(pia), + F(maximum), + worker=g.OwnBenefit( + g.OwnBenefitKind.OLD_AGE, + F(pia), + reduction_months=60, + birth_year=1960, + ), + ) + + guard.admit( + _family(state(1000, 1500 if membership else 1400), members, month) + ) + guard.admit( + _family( + state(1010, 1500 if membership else 1300), + members, + g.YearMonth(2026, 2), + ) + ) + if membership: + guard.admit( + _family(state(1010, 1500), members[:1], g.YearMonth(2026, 3)) + ) + + def refusal_witnesses() -> dict[g.UnsupportedReason, tuple[str, Callable]]: """One independently constructed witness for every retained reason.""" rib, dib = g.OwnBenefitKind.OLD_AGE, g.OwnBenefitKind.DISABILITY @@ -485,6 +552,47 @@ def multiple_records(child): "Governed month begins with unknown prior entitlement months", lambda: _savings_witness(unknown=True), ), + reasons.SAVINGS_CLAUSE_MEMBERSHIP_CHANGE: ( + "One child leaves while operational protection is active", + lambda: _operational_savings_witness(membership=True), + ), + reasons.SAVINGS_CLAUSE_RATE_PROCEDURE: ( + "A reduced spouse alone has no captured allocation procedure", + lambda: _operational_savings_witness(membership=False), + ), + **{ + refusal: ( + "GN 02603.040 event requires an unimplemented deduction procedure: " + + event.value, + lambda event=event: _deduction_witness(event), + ) + for refusal, event in ( + ( + reasons.PRISONER_SUSPENSION, + g.DeductionReason.PRISONER_SUSPENSION, + ), + ( + reasons.DRUG_ADDICTION_SUSPENSION, + g.DeductionReason.DRUG_ADDICTION_SUSPENSION, + ), + ( + reasons.FOREIGN_WORK_DEDUCTION, + g.DeductionReason.FOREIGN_WORK, + ), + (reasons.PENALTY_DEDUCTION, g.DeductionReason.PENALTY), + (reasons.MARITIME_DEDUCTION, g.DeductionReason.MARITIME), + ( + reasons.ELECTION_CERTIFICATE_SUSPENSION, + g.DeductionReason.ELECTION_CERTIFICATE_SUSPENSION, + ), + ) + }, + reasons.DEDUCTION_AGE_WORK_INTERACTION: ( + "Concurrent number-holder reservations and age reduction need a captured allocation", + lambda: _deduction_witness( + g.DeductionReason.OWN_EARNINGS_TEST, age_worker=True + ), + ), reasons.WIDOW_DRC_SAVINGS_CLAUSE: ( "May 1978 survivor protected from widow deceased-worker DRCs", lambda: _family(_survivor(widow_drc_savings_clause=True)), @@ -658,6 +766,66 @@ def _registry_summary(path: Path) -> dict: } +def deduction_conformance() -> dict: + """Separate invented monthly cases; the original lattice is unchanged.""" + rows = [] + for kind, permanent, partial, separate in itertools.product( + (g.FamilyKind.RETIREMENT, g.FamilyKind.SURVIVOR), + (False, True), + (False, True), + (False, True), + ): + state = _retired() if kind is g.FamilyKind.RETIREMENT else _survivor() + members = [g.Beneficiary(key, g.Role.CHILD) for key in ("a", "b", "c")] + key = f"{kind.value}-{'permanent' if permanent else 'estimated'}-{'partial' if partial else 'full'}-{'separate' if separate else 'same'}" + outcome = g.evaluate_family( + key, + 1, + lambda state=state, members=members, partial=partial, permanent=permanent, separate=separate: g.family_benefits_after_deductions( + state, + members, + payment_month=NOW, + params=PARAMS, + deductions={ + "a": g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST, + F(50) if partial else F(0), + permanent, + ) + }, + households={ + "a": "home", + "b": "home", + "c": "other" if separate else "home", + }, + standalone=True, + ), + ) + row = { + "id": key, + "status": "supported" if outcome.supported else "refused", + } + if outcome.supported: + row["payables"] = { + member.beneficiary_id: str(member.auxiliary_payable) + for member in outcome.benefits.beneficiaries + } + else: + row["reason"] = outcome.unsupported.reason.value + rows.append(row) + counts = Counter(row["status"] for row in rows) + return { + "scope": "Separate invented monthly deduction denominator. G v2 had no deduction entry point; no historical lattice row is reclassified.", + "denominator": { + "rows": len(rows), + "supported": counts["supported"], + "refused": counts["refused"], + "invalid": 0, + }, + "rows": rows, + } + + def build_report(registry_path: Path = DEFAULT_REGISTRY) -> dict: """Exhaustively classify each cell once, preserving every denominator.""" statuses = Counter() @@ -683,6 +851,7 @@ def build_report(registry_path: Path = DEFAULT_REGISTRY) -> dict: "admitted_scope": "Gross benefits for supported invented configurations only; no population, behavioral, payment-timing or forecast claim.", "denominator_kind": "finite invented configuration lattice; no population data or population weights", "gross_benefits_version": g.GROSS_BENEFITS_VERSION, + "deduction_conformance": deduction_conformance(), "lattice": { "definition": { "record_kinds": [kind.value for kind in g.FamilyKind], diff --git a/tests/README-tiers.md b/tests/README-tiers.md index e2715c124..18367b687 100644 --- a/tests/README-tiers.md +++ b/tests/README-tiers.md @@ -39,9 +39,9 @@ pytest --collect-only -q -m oracle_policyengine | tail -1 | Tier | Tests at HEAD | |---|---:| -| `unit` | 18,088 | +| `unit` | 18,629 | | `artifact` | 4,253 | | `integration_psid` | 1,450 | | `reproduction_legacy` | 520 | | `oracle_policyengine` | 308 | -| **Total** | **24,619** | +| **Total** | **25,160** | diff --git a/tests/tier_counts.json b/tests/tier_counts.json index 0303dc6ab..1d08b5c15 100644 --- a/tests/tier_counts.json +++ b/tests/tier_counts.json @@ -1,7 +1,7 @@ { "schema_version": 1, "counts": { - "unit": 18088, + "unit": 18629, "artifact": 4253, "integration_psid": 1450, "reproduction_legacy": 520, From 2f88f07e30177ac5a6076606d68124e28fa50a89 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 31 Oct 2026 07:52:40 -0400 Subject: [PATCH 04/17] Refuse uncovered G2 and R2 part (b) paths (#563 fix round 2, part 1) Sol's round-1 review of #563 found seven issues. This part derives two-record entitlement from G's facts, adds the savings-clause membership refusal, checks own benefits in both months and looks up the R1 year before releasing held refusals. Part 2 finishes and verifies the round. Subfleet job 20261025-031318-trackb-fix-g2-2 (a1) wrote this part. Co-Authored-By: Claude Opus 5.5 --- docs/design/track_b_g2_r2b_mutations.json | 580 +++++++++++++++++- docs/design/track_b_g_gross_benefits.md | 107 +++- docs/design/track_b_r2_ret_ledger.md | 25 +- .../track_b/gross_benefits.py | 201 ++++-- src/populace_dynamics/track_b/ret_ledger.py | 52 +- .../test_track_b_gross_benefits_deductions.py | 22 +- ...b_gross_benefits_deductions_fix_round_2.py | 322 ++++++++++ ...ck_b_gross_benefits_savings_fix_round_2.py | 275 +++++++++ tests/test_track_b_ret_ledger_fix_round_2.py | 369 +++++++++++ 9 files changed, 1881 insertions(+), 72 deletions(-) create mode 100644 tests/test_track_b_gross_benefits_deductions_fix_round_2.py create mode 100644 tests/test_track_b_gross_benefits_savings_fix_round_2.py create mode 100644 tests/test_track_b_ret_ledger_fix_round_2.py diff --git a/docs/design/track_b_g2_r2b_mutations.json b/docs/design/track_b_g2_r2b_mutations.json index 427be4fd0..12db8e659 100644 --- a/docs/design/track_b_g2_r2b_mutations.json +++ b/docs/design/track_b_g2_r2b_mutations.json @@ -2,12 +2,12 @@ "schema_version": 1, "verification_class": "statutory_conformance", "admitted_scope": "Mutation sensitivity of statutory rules on invented and captured worked cases only; no population, behavioral or forecast claim.", - "confirmed_mutation_count": 13, + "confirmed_mutation_count": 24, "counts_by_layer": { "shared_provenance": 1, - "g_deductions": 5, - "r2": 3, - "g_savings": 4 + "g_deductions": 8, + "r2": 7, + "g_savings": 8 }, "environment_contract": { "OMP_NUM_THREADS": "1", @@ -579,6 +579,570 @@ "verification": "run_mutations.py restores original text after every run and asserts final equality. All four original fragments are currently present in isolated and production modules." }, "runner_reference": "scratch/savings_mutations/run_mutations.py" + }, + { + "id": "round2_no_care_discard_age_exclusion", + "layer": "g_deductions", + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": " if member.reduction_months:\n", + "after": " if False:\n" + }, + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/deduction-mutation-tree/src:/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2", + "PYTHONDONTWRITEBYTECODE": "1", + "OMP_NUM_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/hypothesis-deductions" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-c", + "import sys; from populace_dynamics.track_b import gross_benefits as g; assert \"deduction-mutation-tree/src\" in g.__file__, g.__file__; import pytest; sys.exit(pytest.main(sys.argv[1:]))", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", + "-k", + "test_under_fra_attestation_cannot_admit_an_age_reduced_spouse", + "--tb=short" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_under_fra_attestation_cannot_admit_an_age_reduced_spouse[False]", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_under_fra_attestation_cannot_admit_an_age_reduced_spouse[True]" + ], + "restoration": { + "reverted": true, + "restored_test_exit_code": 0, + "isolated_source_sha256": "83a73585b57ae29a036e7c013f64662dea019aa60605a0a1cd9f917d20273dd0", + "restored_test_summary": "2 passed, 22 deselected in 36.89s", + "restored_log": "scratch/review/round2_no_care_discard_age_exclusion-restored.log", + "restored_log_sha256": "ff762baf0580e3ce57472a9d12d3c212d9752d0655465eb3ce3c30735a76447e" + }, + "log": { + "path": "scratch/review/round2_no_care_discard_age_exclusion-mutated.log", + "sha256": "0c4c1b4e90f441d62e21453dbe495182459cef0f78a2133287f24c88fccd4ebf", + "failure_summary": "2 failed, 22 deselected in 39.92s" + } + }, + { + "id": "round2_no_care_discard_under_fra_requirement", + "layer": "g_deductions", + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": " if event.under_full_retirement_age is not True:\n", + "after": " if False:\n" + }, + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/deduction-mutation-tree/src:/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2", + "PYTHONDONTWRITEBYTECODE": "1", + "OMP_NUM_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/hypothesis-deductions" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-c", + "import sys; from populace_dynamics.track_b import gross_benefits as g; assert \"deduction-mutation-tree/src\" in g.__file__, g.__file__; import pytest; sys.exit(pytest.main(sys.argv[1:]))", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", + "-k", + "test_no_care_spouse_requires_unreduced_under_fra_attestation", + "--tb=short" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_no_care_spouse_requires_unreduced_under_fra_attestation[None-False]", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_no_care_spouse_requires_unreduced_under_fra_attestation[None-True]", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_no_care_spouse_requires_unreduced_under_fra_attestation[False-False]", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_no_care_spouse_requires_unreduced_under_fra_attestation[False-True]" + ], + "restoration": { + "reverted": true, + "restored_test_exit_code": 0, + "isolated_source_sha256": "83a73585b57ae29a036e7c013f64662dea019aa60605a0a1cd9f917d20273dd0", + "restored_test_summary": "6 passed, 18 deselected in 39.65s", + "restored_log": "scratch/review/round2_no_care_discard_under_fra_requirement-restored.log", + "restored_log_sha256": "8b635cf4d038f8abfb943060dae521d03dbf05e4060f95c61aed147d5a6f4838" + }, + "log": { + "path": "scratch/review/round2_no_care_discard_under_fra_requirement-mutated.log", + "sha256": "defd78c73d3771a3d58eaea369e05c80ba764e0545cb251d22f272d149c14eff", + "failure_summary": "4 failed, 2 passed, 18 deselected in 31.05s" + } + }, + { + "id": "round2_admit_zero_earnings_event", + "layer": "g_deductions", + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": " and event.payable == gross\n", + "after": " and event.payable > gross\n" + }, + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/deduction-mutation-tree/src:/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2", + "PYTHONDONTWRITEBYTECODE": "1", + "OMP_NUM_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/hypothesis-deductions" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-c", + "import sys; from populace_dynamics.track_b import gross_benefits as g; assert \"deduction-mutation-tree/src\" in g.__file__, g.__file__; import pytest; sys.exit(pytest.main(sys.argv[1:]))", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", + "-k", + "test_reviewed_zero_deduction_cases_are_input_errors", + "--tb=short" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_reviewed_zero_deduction_cases_are_input_errors[small-False]", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_reviewed_zero_deduction_cases_are_input_errors[small-True]", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_reviewed_zero_deduction_cases_are_input_errors[large-False]", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_reviewed_zero_deduction_cases_are_input_errors[large-True]", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_reviewed_zero_deduction_cases_are_input_errors[survivor-False]", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_reviewed_zero_deduction_cases_are_input_errors[survivor-True]" + ], + "restoration": { + "reverted": true, + "restored_test_exit_code": 0, + "isolated_source_sha256": "83a73585b57ae29a036e7c013f64662dea019aa60605a0a1cd9f917d20273dd0", + "restored_test_summary": "6 passed, 18 deselected in 67.60s (0:01:07)", + "restored_log": "scratch/review/round2_admit_zero_earnings_event-restored.log", + "restored_log_sha256": "b9e70fbf6cd777507c544b0a778e5eb1d3b8d5a1f2e7d96cf7c3420f6f12741c" + }, + "log": { + "path": "scratch/review/round2_admit_zero_earnings_event-mutated.log", + "sha256": "49271283243cf25456e27795171a47a1c72166a7472f1dfdb3e268e82bbd96f2", + "failure_summary": "6 failed, 18 deselected in 45.39s" + } + }, + { + "id": "round2_r2_contextual_two_record_detection_removed", + "layer": "r2", + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": { + "before": "if (b.two_record_entitlement or key in contextual_two_records) and (", + "after": "if b.two_record_entitlement and (" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-c", + "import sys; from populace_dynamics.track_b import ret_ledger as r; assert r.__file__.startswith('/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/r2-mutation-tree'),r.__file__; import pytest; sys.exit(pytest.main(sys.argv[1:]))", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_ret_ledger_fix_round_2.py", + "-k", + "contextual_own_rib_requires_two_record_refusal and None" + ], + "environment": { + "OMP_NUM_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/hypothesis-r2", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/r2-mutation-tree/src:/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "FAILED tests/test_track_b_ret_ledger_fix_round_2.py::test_contextual_own_rib_requires_two_record_refusal[None-False-10-1]", + "FAILED tests/test_track_b_ret_ledger_fix_round_2.py::test_contextual_own_rib_requires_two_record_refusal[None-False-1000-100]", + "FAILED tests/test_track_b_ret_ledger_fix_round_2.py::test_contextual_own_rib_requires_two_record_refusal[None-True-10-1]", + "FAILED tests/test_track_b_ret_ledger_fix_round_2.py::test_contextual_own_rib_requires_two_record_refusal[None-True-1000-100]" + ], + "log": { + "failure_summary": "4 failed, 16 deselected in 50.80s" + }, + "restoration": { + "reverted": true, + "isolated_source_restored": true, + "restored_test_exit_code": 0, + "restored_test_summary": "4 passed, 16 deselected in 45.32s", + "isolated_source_sha256": "0e3f19edfbe36571718fac2559972132db3ac8efbd282262ffbfc28dc366c64d" + }, + "metadata_reference": "scratch/review/r2-mutations.json" + }, + { + "id": "round2_r2_contextual_two_record_consistency_removed", + "layer": "r2", + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": { + "before": "key in contextual_people\n", + "after": "False\n" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-c", + "import sys; from populace_dynamics.track_b import ret_ledger as r; assert r.__file__.startswith('/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/r2-mutation-tree'),r.__file__; import pytest; sys.exit(pytest.main(sys.argv[1:]))", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_ret_ledger_fix_round_2.py", + "-k", + "declared_two_record_contradiction_is_input_error" + ], + "environment": { + "OMP_NUM_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/hypothesis-r2", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/r2-mutation-tree/src:/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "FAILED tests/test_track_b_ret_ledger_fix_round_2.py::test_declared_two_record_contradiction_is_input_error[False-True-False]", + "FAILED tests/test_track_b_ret_ledger_fix_round_2.py::test_declared_two_record_contradiction_is_input_error[False-False-True]", + "FAILED tests/test_track_b_ret_ledger_fix_round_2.py::test_declared_two_record_contradiction_is_input_error[True-True-False]", + "FAILED tests/test_track_b_ret_ledger_fix_round_2.py::test_declared_two_record_contradiction_is_input_error[True-False-True]" + ], + "log": { + "failure_summary": "4 failed, 16 deselected in 29.01s" + }, + "restoration": { + "reverted": true, + "isolated_source_restored": true, + "restored_test_exit_code": 0, + "restored_test_summary": "4 passed, 16 deselected in 38.60s", + "isolated_source_sha256": "0e3f19edfbe36571718fac2559972132db3ac8efbd282262ffbfc28dc366c64d" + }, + "metadata_reference": "scratch/review/r2-mutations.json" + }, + { + "id": "round2_r2_missing_parameter_hidden_by_held_g_refusal", + "layer": "r2", + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": { + "before": "if record.year >= 2000:\n", + "after": "if record.year >= 2000 and not held_family_refusals:\n" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-c", + "import sys; from populace_dynamics.track_b import ret_ledger as r; assert r.__file__.startswith('/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/r2-mutation-tree'),r.__file__; import pytest; sys.exit(pytest.main(sys.argv[1:]))", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_ret_ledger_fix_round_2.py", + "-k", + "missing_r1_parameter_precedes_held_g_refusal" + ], + "environment": { + "OMP_NUM_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/hypothesis-r2", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/r2-mutation-tree/src:/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "FAILED tests/test_track_b_ret_ledger_fix_round_2.py::test_missing_r1_parameter_precedes_held_g_refusal[False]", + "FAILED tests/test_track_b_ret_ledger_fix_round_2.py::test_missing_r1_parameter_precedes_held_g_refusal[True]" + ], + "log": { + "failure_summary": "2 failed, 18 deselected in 36.59s" + }, + "restoration": { + "reverted": true, + "isolated_source_restored": true, + "restored_test_exit_code": 0, + "restored_test_summary": "2 passed, 18 deselected in 30.77s", + "isolated_source_sha256": "0e3f19edfbe36571718fac2559972132db3ac8efbd282262ffbfc28dc366c64d" + }, + "metadata_reference": "scratch/review/r2-mutations.json" + }, + { + "id": "round2_r2_zero_excess_emits_a_g_deduction_event", + "layer": "r2", + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": { + "before": "if k != record.nh_id and own_deductions[k, m] > 0\n", + "after": "if k != record.nh_id and own_deductions[k, m] >= 0\n" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-c", + "import sys; from populace_dynamics.track_b import ret_ledger as r; assert r.__file__.startswith('/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/r2-mutation-tree'),r.__file__; import pytest; sys.exit(pytest.main(sys.argv[1:]))", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_ret_ledger_fix_round_2.py", + "-k", + "r2_emits_only_positive_actual_deduction_events" + ], + "environment": { + "OMP_NUM_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/hypothesis-r2", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/r2-mutation-tree/src:/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "FAILED tests/test_track_b_ret_ledger_fix_round_2.py::test_r2_emits_only_positive_actual_deduction_events" + ], + "log": { + "failure_summary": "1 failed, 19 deselected in 13.46s" + }, + "restoration": { + "reverted": true, + "isolated_source_restored": true, + "restored_test_exit_code": 0, + "restored_test_summary": "1 passed, 19 deselected in 31.97s", + "isolated_source_sha256": "0e3f19edfbe36571718fac2559972132db3ac8efbd282262ffbfc28dc366c64d" + }, + "metadata_reference": "scratch/review/r2-mutations.json" + }, + { + "id": "round2_savings_skip_first_membership_trigger", + "layer": "g_savings", + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": " and result.pia > prior.pia\n", + "after": " and result.pia > prior.pia and membership == _savings_membership(prior.result)\n" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-c", + "from populace_dynamics.track_b import gross_benefits as g; assert 'savings-mutation-tree/src' in g.__file__, g.__file__; import pytest,sys; sys.exit(pytest.main(sys.argv[1:]))", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py", + "-k", + "first_trigger_membership_change" + ], + "environment": { + "PYTHONDONTWRITEBYTECODE": "1", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/savings-mutation-tree/src:/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2", + "OMP_NUM_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/hypothesis-savings-mutation" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_first_trigger_membership_change_refuses_and_retains_denominator[pia0-new_pia0-maximum0-names0-ordinary_total0]", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_first_trigger_membership_change_refuses_and_retains_denominator[pia1-new_pia1-maximum1-names1-ordinary_total1]", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_first_trigger_membership_change_refuses_and_retains_denominator[pia2-new_pia2-maximum2-names2-ordinary_total2]", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_first_trigger_membership_change_refuses_and_retains_denominator[pia3-new_pia3-maximum3-names3-ordinary_total3]" + ], + "log": { + "path": "scratch/review/round2_savings_skip_first_membership_trigger.log", + "sha256": "d381b9f01739b7c37580e37d5f95a0fb49bafa1c8427fae4fff562e5e5b23f4f", + "failure_summary": "4 failed, 14 deselected in 32.75s" + }, + "restoration": { + "reverted": true, + "isolated_source_restored": true, + "restored_test_exit_code": 0, + "isolated_source_sha256": "c5885aa63592f76e50867daa454bb9aee3f16a30abacbf3f3c487a27443aad6d", + "restored_log": "scratch/review/round2_savings_skip_first_membership_trigger-restored.log", + "restored_log_sha256": "3a701ed247406c521ef142c3e2c435dde7715e8db30275e1556f20cfb5c329f7", + "restored_test_summary": "4 passed, 14 deselected in 9.74s" + } + }, + { + "id": "round2_savings_ignore_prior_own_benefit", + "layer": "g_savings", + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": " or _savings_has_own_benefits(prior.result)\n", + "after": " or False\n" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-c", + "from populace_dynamics.track_b import gross_benefits as g; assert 'savings-mutation-tree/src' in g.__file__, g.__file__; import pytest,sys; sys.exit(pytest.main(sys.argv[1:]))", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py", + "-k", + "prior_own_benefit_cessation_refuses_before" + ], + "environment": { + "PYTHONDONTWRITEBYTECODE": "1", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/savings-mutation-tree/src:/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2", + "OMP_NUM_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/hypothesis-savings-mutation" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_prior_own_benefit_cessation_refuses_before_setting_protection[pia0-new_pia0-maximum0-own0-before_total0-prior_diagnostic0-after_total0-Role.SPOUSE]", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_prior_own_benefit_cessation_refuses_before_setting_protection[pia0-new_pia0-maximum0-own0-before_total0-prior_diagnostic0-after_total0-Role.CHILD]", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_prior_own_benefit_cessation_refuses_before_setting_protection[pia1-new_pia1-maximum1-own1-before_total1-prior_diagnostic1-after_total1-Role.SPOUSE]", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_prior_own_benefit_cessation_refuses_before_setting_protection[pia1-new_pia1-maximum1-own1-before_total1-prior_diagnostic1-after_total1-Role.CHILD]" + ], + "log": { + "path": "scratch/review/round2_savings_ignore_prior_own_benefit.log", + "sha256": "efd32d1f9fdfec0f08e63bdab91a1ac74779f6ea7c111f5b385df5503965acfa", + "failure_summary": "4 failed, 14 deselected in 15.70s" + }, + "restoration": { + "reverted": true, + "isolated_source_restored": true, + "restored_test_exit_code": 0, + "isolated_source_sha256": "c5885aa63592f76e50867daa454bb9aee3f16a30abacbf3f3c487a27443aad6d", + "restored_log": "scratch/review/round2_savings_ignore_prior_own_benefit-restored.log", + "restored_log_sha256": "fe284da226dee5ded0ee8c4c435163c913cac30f2dacb20f08ce98f36ea3ba76", + "restored_test_summary": "4 passed, 14 deselected in 4.58s" + } + }, + { + "id": "round2_savings_ignore_current_own_benefit_on_carried_floor", + "layer": "g_savings", + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": " or _savings_has_own_benefits(result)\n", + "after": " or False\n" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-c", + "from populace_dynamics.track_b import gross_benefits as g; assert 'savings-mutation-tree/src' in g.__file__, g.__file__; import pytest,sys; sys.exit(pytest.main(sys.argv[1:]))", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py", + "-k", + "current_own_benefit_refuses_carried_and_dormant" + ], + "environment": { + "PYTHONDONTWRITEBYTECODE": "1", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/savings-mutation-tree/src:/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2", + "OMP_NUM_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/hypothesis-savings-mutation" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_current_own_benefit_refuses_carried_and_dormant_protection[False-Role.SPOUSE]", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_current_own_benefit_refuses_carried_and_dormant_protection[False-Role.CHILD]", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_current_own_benefit_refuses_carried_and_dormant_protection[True-Role.SPOUSE]", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_current_own_benefit_refuses_carried_and_dormant_protection[True-Role.CHILD]" + ], + "log": { + "path": "scratch/review/round2_savings_ignore_current_own_benefit_on_carried_floor.log", + "sha256": "35c9170f75474a850df211acc14fa9eae34c53c1bff1d311be330ade5a555ee0", + "failure_summary": "4 failed, 14 deselected in 13.50s" + }, + "restoration": { + "reverted": true, + "isolated_source_restored": true, + "restored_test_exit_code": 0, + "isolated_source_sha256": "c5885aa63592f76e50867daa454bb9aee3f16a30abacbf3f3c487a27443aad6d", + "restored_log": "scratch/review/round2_savings_ignore_current_own_benefit_on_carried_floor-restored.log", + "restored_log_sha256": "6e082ef7797e0df3a9d26ec51f623546720d30a1b9cba581735579b3881b215b", + "restored_test_summary": "4 passed, 14 deselected in 22.11s" + } + }, + { + "id": "round2_savings_ignore_current_own_benefit_at_trigger", + "layer": "g_savings", + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": " or _savings_has_own_benefits(result)\n", + "after": " or False\n" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-c", + "from populace_dynamics.track_b import gross_benefits as g; assert 'savings-mutation-tree/src' in g.__file__, g.__file__; import pytest,sys; sys.exit(pytest.main(sys.argv[1:]))", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py", + "-k", + "current_own_benefit_refuses_before_setting" + ], + "environment": { + "PYTHONDONTWRITEBYTECODE": "1", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/savings-mutation-tree/src:/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2", + "OMP_NUM_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/hypothesis-savings-mutation" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_current_own_benefit_refuses_before_setting_protection[Role.SPOUSE]", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_current_own_benefit_refuses_before_setting_protection[Role.CHILD]" + ], + "log": { + "path": "scratch/review/round2_savings_ignore_current_own_benefit_at_trigger.log", + "sha256": "bb7b92f25f39815bbaf21e0edd073a73d73777195ccfc43e951e6dcd2a0ac1d0", + "failure_summary": "2 failed, 16 deselected in 18.00s" + }, + "restoration": { + "reverted": true, + "isolated_source_restored": true, + "restored_test_exit_code": 0, + "isolated_source_sha256": "c5885aa63592f76e50867daa454bb9aee3f16a30abacbf3f3c487a27443aad6d", + "restored_log": "scratch/review/round2_savings_ignore_current_own_benefit_at_trigger-restored.log", + "restored_log_sha256": "77e10f90c4b2ae97c372f4f6b02ae7fffdd2ba526591f813fb4f53ff98c9f310", + "restored_test_summary": "2 passed, 16 deselected in 20.72s" + } } ], "restoration_verification_snapshot": { @@ -595,5 +1159,11 @@ "sha256_at_verification": "27568b175af5acf16c83012ae151584a237886723b3946e55539e07639131d50" } }, - "restoration_snapshot_note": "These hashes identify the source state checked when mutations were consolidated. Subsequent reviewed fixes are separately hashed in the final verification artifact; mutation rules remain restored." + "restoration_snapshot_note": "These hashes identify the source state checked when mutations were consolidated. Subsequent reviewed fixes are separately hashed in the final verification artifact; mutation rules remain restored.", + "round_2_head": "0ccf66ff63874167ffff0eca34b15c5eca57b3ad", + "round_2_note": "Eleven new isolated one-line mutations caught and restored; no production mutation was retained. Exact commands, environments, failing names and restored counts are in each new record.", + "round_2_restoration_snapshot": { + "src/populace_dynamics/track_b/gross_benefits.py": "43ac51f6dc0a38c08f858521d8e2074d2466a87efaac3e0462db5d81404e7a86", + "src/populace_dynamics/track_b/ret_ledger.py": "0e3f19edfbe36571718fac2559972132db3ac8efbd282262ffbfc28dc366c64d" + } } diff --git a/docs/design/track_b_g_gross_benefits.md b/docs/design/track_b_g_gross_benefits.md index 4b5270722..81a846665 100644 --- a/docs/design/track_b_g_gross_benefits.md +++ b/docs/design/track_b_g_gross_benefits.md @@ -5,7 +5,7 @@ benefits for supported invented or published statutory cases only; no population, behavioral or forecast claim.** **Status: build-only, 2026-09-29; statutory delayed-credit convention -(#494), 2026-10-11; review fixes through 2026-10-18. No real-data +(#494), 2026-10-11; review fixes through 2026-10-25. No real-data computation.** Inputs are invented families and SSA's published worked examples. @@ -2624,6 +2624,22 @@ dictionaries retain associations. Types, enum identities and every raw container entry follow the existing public schema. `worker_deductions` optionally reserves the number holder's charges against auxiliaries; those charges do not release room (GN 02603.040B; RS 02501.155B.3.c). +For a spouse's `NO_CHILD_IN_CARE` event, `under_full_retirement_age=True` +is required and the supplied spouse benefit must be unreduced for age. +Act 203(c)(2) limits this deduction to a spouse "under retirement age" +whose benefit "was not reduced under the provisions of section 202(q)"; +20 CFR 404.421(a) likewise excludes the reduced-benefit election month. +Missing or false age attestation, age-reduced spouse benefits and declared +current care are `InvalidFamilyInput` before a family or household refusal. +The attestation must also agree with a supplied birth cohort. SSA cohorts +run from January 2 through January 1 of the following year, with age +attained the day before the birthday (RS 00615.003/.010). If the payment +month is at or after even that cohort's latest possible FRA month, an +under-FRA attestation is impossible and invalid; an unknown birthday inside +the cohort's FRA interval remains a caller-attested fact. A 1950-cohort +spouse in January 2024 therefore cannot lose its $2 ordinary benefit under +a falsely attested no-care event on PIA $4/MAX $6. +Mother/father deductions under 203(c)(3)-(4) have no spouse age condition. | Configuration | Result | |---|---| @@ -2631,7 +2647,7 @@ charges do not release room (GN 02603.040B; RS 02501.155B.3.c). | Auxiliary or survivor own earnings deduction, full or partial | Supported | | Permanent deduction | GN 02603.050C redistribution | | Estimated own earnings deduction | Same-household increase; other households retain their previous rate | -| No child in care, full deduction | Supported for spouse or mother/father | +| No child in care, full deduction | Supported for an unreduced spouse with an explicit under-FRA attestation, or a mother/father | | Dual entitlement | Existing Parisi computation, including zero technical rates | | Workers' compensation offset | `workers_compensation_offset` | | Prisoner suspension | `prisoner_suspension` | @@ -2652,6 +2668,19 @@ capped at the original benefit and dime-floored before age reduction. A zero dual rate remains disregarded regardless of another deduction (GN 02603.050A.2). Explicit dual markers must match the existing own-benefit declaration and computed payable; they do not apply a second offset. +An `OWN_EARNINGS_TEST` event must withhold a strictly positive amount after +NH reservations. R2 selects events only where its actual own deduction is +positive, including when annual excess is zero. A zero-amount event is +therefore `InvalidFamilyInput` in both public G forms, before event coverage +refusals. It produces no result or denominator row and cannot freeze a +rate, release rounding slack or disable A.1's single-full-deduction rule. +Household and family coverage refusals are held until amount-dependent +input checks finish on every computable record. In the invented survivor +PIA $4/MAX $6 case, a shared child and a unique child each have OB/gross $3 +on one record; the shared child also appears on a second record. A unique +child's zero-withholding $3 event is invalid before the household's combined +maximum refusal. The shared child's unsettled maximum cannot mask a +separately derivable input error. `BeneficiaryBenefit.deduction` records the amount withheld from that row's age-adjusted gross amount after its own-benefit offset, and @@ -2724,7 +2753,7 @@ identical; tests pin both quoted OBs and modern OBs rather than overriding the arithmetic or claiming historical rounding coverage. The captures do not date these examples or establish why they used upward rounding. -### Readings needing judgment +### Settled reading and deferred coverage GN 02603.050D.2 says "there are no partial deductions for temporary work deductions". RS 02501.160 Example 2 nevertheless instructs immediate @@ -2735,10 +2764,12 @@ amounts. The literal GN sentence would refuse that temporary partial case; it would withhold C2's $20 June increase. The source assertions pin both sentences. No switch invents a different benefit amount. -The interaction of NH reservations and age reductions is not established -by a captured worked example. The implementation refuses that new mixed -configuration by name; ordinary G/R2 age-reduced supported inputs remain -unchanged. No population processing, combined maximum determination, +The interaction of NH reservations and age reductions is deferred coverage: +no allocation procedure has been derived for the combined configuration. +This is not a conflict between authoritative algorithms, and missing worked +examples alone do not establish an ambiguous reading. The implementation +refuses the mixed configuration as `deduction_age_work_interaction`. +No population processing, combined maximum determination, multiple auxiliary-record selection or annual earnings determination is in scope here. @@ -2782,8 +2813,12 @@ Under `SSA_OPERATIONAL`, the prior month must have two or more entitled persons, a binding maximum, and at least one age-reduced beneficiary. The next month's PIA must rise and its family total must fall. These are the four requirements in RS 00630.400's "1972 Family Payment Saving Clause". -Membership and exact worker/auxiliary age factors must be unchanged for the supported -payment computation. A membership-driven decline starts no protection. +Membership and exact worker/auxiliary age factors must be unchanged for the +supported payment computation. The four source conditions are evaluated +before this coverage boundary. A qualifying PIA increase and fall with +changed membership refuses as `savings_clause_membership_change` and retains +uncertain history. A membership-only decline without a PIA increase starts +no protection. A simultaneous change of age factors or a declining formula maximum with a qualifying overall fall refuses by name because the snapshots do not isolate the PIA effect. For example, PIA/FMAX $100/$150 with an unreduced @@ -2804,7 +2839,7 @@ carried protection refuses, including later months after the change. | Life case, one reduced spouse and at least one other auxiliary | Divide the family-payment loss by the auxiliary count; apply the spouse's exact RF to that increase and add it to the spouse's ordinary reduced rate; divide the remaining protected amount after the new worker and spouse rates among the other auxiliaries (RS 00630.400) | | No qualifying age reduction, no PIA increase, or no immediate fall | No operational protection starts | | Later raw payment is below an established protection | Reapply the captured procedure without changing formula FMAX (RS 00615.801B.2) | -| Entitlement membership changes during carried protection | `savings_clause_membership_change`; the captured 1972 procedure does not say how protection survives the change | +| Entitlement membership changes at the first qualifying fall or during carried protection | `savings_clause_membership_change`; the captured 1972 procedure does not establish successor protection | | Survivor, own-benefit offset, deduction, multiple reduced auxiliaries, lone reduced spouse, simultaneous age-factor change or declining FMAX with a qualifying fall, or a protected rate above OB | `savings_clause_rate_procedure`; the captured life-case allocation does not settle these rates | | Prior history is unknown or a skipped month may hide protection | `savings_clause_history_unknown`, retained in every denominator | | Explicit literal alternative reaches any later lower governed total | Existing `savings_clause_403a5` refusal; the original broad interpretation remains testable | @@ -2931,6 +2966,11 @@ maximum shares. Those rates therefore cannot establish an operational family payment without an additional captured rule. Numeric `deduction` and `reserved_work_deduction` count even when `deduction_reason` is absent for an NH-only reservation. These fields remain part of each sealed result. +Subject own-benefit facts are likewise checked in both months before +establishing or extending protection, even while a carried floor is dormant. +An own benefit ceasing at the trigger cannot turn the prior pre-offset +diagnostic total into a payment floor. These unsettled procedures refuse +as `savings_clause_rate_procedure` and retain the uncertain history. Executed counterexample: January PIA $1,000, FMAX $1,500, a worker reduced 60 months to $700, and two children. One child's full permanent own-work @@ -2953,6 +2993,53 @@ with GN 02603.050, not to input validity. No protected amount is inferred from a diagnostic pre-offset total, and every refusal retains its row and weight. Completing this combined payment procedure remains outside scope. +### Round-2 input and history regressions + +The following are invented calculations, not published SSA examples. + +| Inputs | Ordinary calculation and resulting boundary | +|---|---| +| January 2024 PIA $4/MAX $6, spouse reduced 60 months | Spouse $1.30, whole dollars $1; a no-care declaration is invalid and cannot replace this with $0 | +| Same record, plus two children and a full spouse own-work deduction | Children $1 each, whole dollars $1 each; a child event payable $.60 withholds zero and is invalid | +| PIA $48/MAX $78, spouse reduced 60 months and three children | A full spouse deduction leaves children $10 each; adding a child's zero-withholding $7.50 marker is invalid | +| Survivor PIA $1/MAX $1.10, three children | $.30 each and $.90 total; a $.30 own-work marker is invalid and cannot raise siblings to $.40 | +| PIA $.40/MAX $.60 rises to $.50 with unchanged MAX and worker RF60; children C0/C1 become C0/C2 | Ordinary totals $.40 then $.30; the qualifying membership change refuses, whereas stable membership protects $.50 | +| PIA $1,000/MAX $1,500 rises to $1,010, worker RF60 | January $1,200; replacement/removal gives ordinary $1,197 and addition $1,196.90; all qualifying membership changes refuse | +| Spouse or child own benefit $.10 ceases as PIA $1 rises to $1.10, MAX $1.50, worker RF60 | Prior actual total $1.20, pre-offset diagnostic $1.30; current ordinary $1.10 cannot establish a $1.30 floor and refuses | + +The new files `test_track_b_gross_benefits_deductions_fix_round_2.py` and +`test_track_b_gross_benefits_savings_fix_round_2.py` execute these boundaries. +Every new invariant has a Hypothesis property beside the examples: + +- `test_under_fra_attestation_cannot_admit_an_age_reduced_spouse` and + `test_no_care_spouse_requires_unreduced_under_fra_attestation` enforce + the spouse age exclusion and required eligibility fact in both public + forms. `test_age_reduced_no_care_is_input_error_before_refusal` keeps + invalid declarations out of the denominator even with a held refusal. +- `test_zero_event_cannot_change_existing_full_deduction_output` rejects + permanent and temporary no-op events without any result or denominator + change, preserving exact and whole-dollar controls, determinism and the + existing full age-reduced deductee. R2's Hypothesis property + `test_r2_emits_only_positive_actual_deduction_events` differentially + checks every emitted final/provisional G event against actual deductions. +- `test_qualifying_membership_change_is_order_independent_refusal` keeps + first-trigger membership changes in the weighted denominator and retains + uncertain history independently of beneficiary order. + `test_membership_decline_without_pia_increase_stays_admitted` preserves + the supported no-PIA-increase control. +- `test_prior_own_benefit_cessation_always_preserves_uncertain_history` + and `test_current_own_benefit_never_certifies_candidate_or_carried_protection` + prohibit a diagnostic pre-offset own-benefit rate from establishing or + extending protection, including dormant protection. Every legal refusal + retains its full weight; input errors retain no denominator row. + +These implement the orchestrator's settled readings under Max's +2026-10-20 delegation. First-trigger membership and prior-month own-benefit +cessation add deferred procedure coverage, with the named reasons above; +they do not assert an alternative supported payment algorithm. The existing +temporary-partial reading, least-sufficient-dime rounding, qualified +monotonicity, A.1 exception and deduction-history refusal remain in force. + ### Not in scope No combined family maximum, multiple auxiliary records, survivor allocation diff --git a/docs/design/track_b_r2_ret_ledger.md b/docs/design/track_b_r2_ret_ledger.md index fdfeaa7f8..397237d57 100644 --- a/docs/design/track_b_r2_ret_ledger.md +++ b/docs/design/track_b_r2_ret_ledger.md @@ -457,7 +457,15 @@ Each beneficiary also supplies actual earnings, optional estimated earnings, the RIB FRA month, the actual grace-helper decision and an optional `estimated_grace` decision for the current-year forecast, death and divorced-spouse facts, and flags for established statutory -own-work protections or entitlement on two records. For ledger inputs, +own-work protections or entitlement on two records. The optional +`two_record_entitlement` declaration defaults to `None`: supplied G +monthly own-benefit facts establish two-record entitlement, while an +explicit boolean must agree with the contextual facts for that person +over the year. With no supplied G context, `None` retains the absence of +a declared second entitlement. An own benefit present in any supplied +month establishes the annual exposure; a later cessation does not erase +it. Own actual or estimated excess remains refused because RS +02501.145-.150 require charging across both records. For ledger inputs, `fra_month=None` means FRA after the year, `0` means FRA before the year, and `1` through `12` identifies the attainment month. Survivors use the RIB FRA, even when their survivor-benefit FRA is earlier (RS @@ -529,10 +537,13 @@ prior year's amount or relabelled as a statutory coverage refusal. 404.415(b), .420, .434; RS 02501.021B.5.b, .095B.2 and .140). 5. **Other workers' charging.** After NH charging, charge each auxiliary or survivor's excess against that person's remaining benefit only. - Do not charge an already exhausted month again. If this would free - binding family-maximum room for another beneficiary, refuse the - record for part (b) (20 CFR 404.434(b)(2)-(3); RS 02501.095B.3-4, - .155A.3-4; GN 02603.020-.050). + Do not charge an already exhausted month again. When this frees + binding family-maximum room for another beneficiary, readjust through + G using that month's declared `RETFamilyMonth` statutory and household + facts. Without those facts, retain the named refusal + `deduction_readjustment_requires_family_context` (20 CFR + 404.434(b)(2)-(3); RS 02501.095B.3-4, .155A.3-4; + GN 02603.020-.050). 6. **Protected months.** A worker's own excess cannot be charged in an unentitled month, a protected grace-year NSM, the FRA month or later, a DIB/DWB/CDB payment month, or an explicitly established own-work @@ -891,6 +902,10 @@ In the table, unqualified property test names are in | R1 annual amounts and exact rates match every supported bundled year, with zero tolerance | `test_r1_differential_matches_every_supported_year_exactly`; `test_r1_differential_statutory_default_is_exactly_one_twelfth` | | The default statutory monthly limit is exactly annual/12, with zero tolerance; wages above it cannot protect a grace month | `test_r1_differential_statutory_default_is_exactly_one_twelfth`; readings `test_property_default_monthly_limit_is_exact_twelfth_and_controls_grace_wages`; unit `test_act_203_f_8_d_vi_exact_limit_is_not_chart_ceiling`; source `test_act_203_f_8_d_v_vi_monthly_amounts_are_quoted_and_equal_annual_twelfths` | | Missing R1 years raise rather than substitute | `test_r1_differential_missing_year_raises_without_substitution`; unit `test_missing_parameter_year_is_not_carried_forward` | +| G monthly own-benefit facts establish annual two-record exposure, independently of beneficiary and household order; an omitted flag cannot admit actual or estimated excess | review `test_contextual_own_rib_requires_two_record_refusal`; property `test_two_record_derivation_is_order_independent` | +| A declared two-record flag contradicting supplied G facts is an input error and creates no outcome or denominator row | review `test_declared_two_record_contradiction_is_input_error` | +| Missing supported R1 years precede held G coverage refusals and create no outcome or denominator row | review `test_missing_r1_parameter_precedes_held_g_refusal`; property `test_unavailable_supported_r1_year_is_never_a_coverage_row` | +| R2 emits G own-work events only for positive actual deductions; a person with zero excess never becomes a deductee in either actual or estimated runs | review property `test_r2_emits_only_positive_actual_deduction_events` | | Every outcome row and weight stays in the coverage denominator; any refusal blocks an aggregate | `test_coverage_denominators_keep_every_supported_or_refused_row`; unit `test_coverage_denominator_keeps_refusals_and_blocks_aggregate` | | Exact 1/2 and 1/3 excess rates use an integer floor: excess is nonnegative and differs from the unrounded amount by less than $1 | readings `test_property_excess_uses_exact_statutory_rate_and_dollar_floor`; unit `test_lower_threshold_and_whole_dollar_floor`; unit `test_fra_threshold_uses_one_third_and_floors`; R1 differential above | | Invalid input is never counted as a statutory coverage gap | `test_coverage_denominators_keep_every_supported_or_refused_row`; unit `test_invalid_wage_inputs_raise_before_coverage_refusal`; `test_invalid_rates_raise_before_coverage_refusal`; `test_duplicate_identity_is_invalid_even_in_an_unsupported_record`; `test_invalid_inputs_are_not_counted_as_coverage_gaps` | diff --git a/src/populace_dynamics/track_b/gross_benefits.py b/src/populace_dynamics/track_b/gross_benefits.py index 16addf5c2..f2083d5ef 100644 --- a/src/populace_dynamics/track_b/gross_benefits.py +++ b/src/populace_dynamics/track_b/gross_benefits.py @@ -6,6 +6,10 @@ timing, no annual earnings or charge determination (R2), and no ARF or recomputation (R3). The deduction entry points apply caller-declared monthly deductions before redistributing the maximum (203(a)(4)). +No-care spouse deductions require an unreduced benefit and an explicit +under-full-retirement-age attestation (203(c)(2); 20 CFR 404.421(a)). +Own-work events must withhold a positive amount; a zero deduction is an +input error and never changes the family-maximum computation. Max's ruling d515 (2026-09-28) adopted §10 question 9's default: a Python reference now, with Axiom differential checks as diagnostics once a pinned rule exists. At this module's creation rulespec-us had no 42 U.S.C. 403 @@ -229,8 +233,10 @@ more entitled persons and an age reduction; the next month's PIA increase must itself lower family payment. SavingsClauseGuard computes the protected life-case rates, without changing formula FMAX, and carries the protection -under RS 00615.801B.2. Active-protection membership changes and payment -procedures not settled by the capture refuse by name. The explicit +under RS 00615.801B.2. Membership changes at the first qualifying fall or +during carried protection, and payment procedures not settled by the +capture, refuse by name. Prior and current subject own-benefit or deduction +facts are checked before establishing or extending protection. The explicit SavingsClauseReading.LITERAL_REFUSAL switch retains the earlier broad cross-month refusal reading. Both readings preserve unknown-history refusals. @@ -456,6 +462,8 @@ class UnsupportedReason(Enum): PENALTY_DEDUCTION = "penalty_deduction" MARITIME_DEDUCTION = "maritime_deduction" ELECTION_CERTIFICATE_SUSPENSION = "election_certificate_suspension" + #: Deferred coverage: no NH-reservation/age-reduction allocation + #: procedure has been derived; no competing authoritative algorithms. DEDUCTION_AGE_WORK_INTERACTION = "deduction_age_work_interaction" @@ -2257,15 +2265,30 @@ class BenefitDeduction: own-work deductions have ``permanent=False``; all other supported events are permanent. Dual entitlement is already declared by ``OwnBenefit``; an explicit marker must agree with the ordinary G payable. + ``under_full_retirement_age`` must be True for a spouse no-care + deduction (203(c)(2); 20 CFR 404.421(a)); None does not establish age. + Own-work payables must be strictly below the ordinary rate after NH + reservations. R2 emits only strictly positive own-work deductions. """ reason: DeductionReason payable: Fraction = Fraction(0) permanent: bool = True + under_full_retirement_age: bool | None = None def __post_init__(self): _input_type(self.reason, DeductionReason, "deduction reason") _input_type(self.permanent, bool, "permanent") + if self.under_full_retirement_age is not None: + _input_type( + self.under_full_retirement_age, + bool, + "under_full_retirement_age", + ) + if self.reason is not DeductionReason.NO_CHILD_IN_CARE: + raise InvalidFamilyInput( + "Under-FRA attestation describes a no-child-in-care deduction" + ) object.__setattr__(self, "payable", _exact(self.payable, "payable")) if self.payable < 0: raise InvalidFamilyInput("payable must be nonnegative") @@ -3780,7 +3803,12 @@ def _family_benefits( def _check_deduction_inputs( - beneficiaries, deductions, households, worker_deductions + beneficiaries, + deductions, + households, + worker_deductions, + payment_month, + params, ): members = {b.beneficiary_id: b for b in beneficiaries} for label, mapping in ( @@ -3818,6 +3846,31 @@ def _check_deduction_inputs( raise InvalidFamilyInput( "No-child-in-care deduction needs a spouse or mother/father" ) + if member.role in _SPOUSE_ROLES: + if member.reduction_months: + raise InvalidFamilyInput( + "No-child-in-care deduction excludes age-reduced spouses" + ) + if event.under_full_retirement_age is not True: + raise InvalidFamilyInput( + "No-child-in-care spouse deduction requires under-FRA status" + ) + if member.birth_year is not None: + # SSA cohorts run Jan 2 through Jan 1 of the next + # year; the latest possible Jan 1 birth attains FRA + # in the preceding month (RS 00615.003/.010). + latest_fra = ( + (member.birth_year + 1) * 12 + + _fra_months(member.birth_year, params) + - 1 + ) + if ( + payment_month.year * 12 + payment_month.month - 1 + >= latest_fra + ): + raise InvalidFamilyInput( + "Under-FRA attestation contradicts the birth cohort" + ) if isinstance(member.child_in_care, str): raise InvalidFamilyInput( "No-child-in-care deduction conflicts with current care" @@ -3872,6 +3925,9 @@ def family_benefits_after_deductions( whenever an own-work event is estimated. Empty deductions returns G's ordinary result. ``worker_deductions`` reserves NH work deductions; these never release room (GN 02603.040B; RS 02501.155B.3.c). + Concurrent NH reservations and auxiliary age reductions have deferred + allocation coverage and refuse as ``deduction_age_work_interaction``; + no procedure has been derived for that combination. R2 owns earnings, charge order, grace years and permanent determinations. """ if standalone is not True: @@ -3883,7 +3939,12 @@ def family_benefits_after_deductions( ) worker_deductions = {} if worker_deductions is None else worker_deductions _check_deduction_inputs( - beneficiaries, deductions, households, worker_deductions + beneficiaries, + deductions, + households, + worker_deductions, + payment_month, + params, ) _check_deduction_amount_bounds( state, beneficiaries, deductions, worker_deductions @@ -3925,6 +3986,13 @@ def _after_deductions( raise InvalidFamilyInput( "Deductee payable exceeds the pre-deduction rate" ) + if ( + event.reason is DeductionReason.OWN_EARNINGS_TEST + and event.payable == gross + ): + raise InvalidFamilyInput( + "Own-earnings-test event must withhold a positive amount" + ) if ( event.reason is DeductionReason.DUAL_ENTITLEMENT and event.payable != gross @@ -3954,7 +4022,7 @@ def _after_deductions( raise _computed( FamilyConfigurationUnsupported, UnsupportedReason.DEDUCTION_AGE_WORK_INTERACTION, - "Concurrent NH reservations and age reductions need a pinned allocation reading", + "Concurrent NH reservations and age reductions have deferred allocation coverage", ) subject = [ row for row in baseline.beneficiaries if row.subject_to_family_maximum @@ -4455,7 +4523,12 @@ def household_benefits_after_deductions( b for record in records.values() for b in record.beneficiaries ) _check_deduction_inputs( - all_members, deductions, households, worker_deductions + all_members, + deductions, + households, + worker_deductions, + payment_month, + params, ) for record in records.values(): _check_family_inputs( @@ -4464,24 +4537,40 @@ def household_benefits_after_deductions( _check_deduction_amount_bounds( record.state, record.beneficiaries, deductions, worker_deductions ) - _refuse_household(held) results = {} + family_refusals = [] for rid in sorted(records): record = records[rid] ids = {b.beneficiary_id for b in record.beneficiaries} - results[rid] = _after_deductions( - record.state, - record.beneficiaries, - payment_month, - params, - {bid: value for bid, value in deductions.items() if bid in ids}, - {bid: value for bid, value in households.items() if bid in ids}, - { - bid: value - for bid, value in worker_deductions.items() - if bid in ids - }, - ) + try: + results[rid] = _after_deductions( + record.state, + record.beneficiaries, + payment_month, + params, + { + bid: value + for bid, value in deductions.items() + if bid in ids + }, + { + bid: value + for bid, value in households.items() + if bid in ids + }, + { + bid: value + for bid, value in worker_deductions.items() + if bid in ids + }, + ) + except FamilyConfigurationUnsupported as error: + family_refusals.append(error) + # Amount-dependent errors on every computable record precede either + # household coverage or a different record's held coverage refusal. + _refuse_household(held) + if family_refusals: + raise family_refusals[0] return _computed( HouseholdBenefits, payment_month, MappingProxyType(results) ) @@ -4686,6 +4775,14 @@ def _savings_has_deductions(result: FamilyBenefits) -> bool: ) +def _savings_has_own_benefits(result: FamilyBenefits) -> bool: + """Subject own benefits need an uncaptured dual-entitlement procedure.""" + return any( + row.subject_to_family_maximum and row.own_benefit is not None + for row in result.beneficiaries + ) + + def _savings_payment( result: FamilyBenefits, protected: Fraction ) -> FamilyBenefits: @@ -4780,15 +4877,18 @@ class SavingsClauseGuard: ``reading`` is an exact canonical SavingsClauseReading enum; its default SSA_OPERATIONAL follows d1338 and POMS RS 00630.400. Protection starts only after an age-reduced, maximum-reduced month with at least two - entitled persons, followed by a PIA increase that lowers payment with - unchanged membership. The two captured life-case procedures compute - protected auxiliary payments. Formula FMAX and its counted shares stay - unchanged. RS 00615.801B.2 carries the protected total, including a - period when the formula payment overtakes it and it later becomes - payable again. Membership changes during that carried protection refuse - with SAVINGS_CLAUSE_MEMBERSHIP_CHANGE. Survivor, dual-entitlement, - deduction and unspecified reduced-auxiliary procedures refuse with - SAVINGS_CLAUSE_RATE_PROCEDURE when protection would change money. + entitled persons, followed by a PIA increase that lowers payment. The + two captured life-case procedures compute protected auxiliary payments. + Formula FMAX and its counted shares stay unchanged. RS 00615.801B.2 + carries the protected total, including a period when the formula payment + overtakes it and it later becomes payable again. Membership changes at + that first qualifying fall or during carried protection refuse with + SAVINGS_CLAUSE_MEMBERSHIP_CHANGE. + Subject own benefits or deductions in either the prior or current + month refuse with SAVINGS_CLAUSE_RATE_PROCEDURE before establishing or + extending protection, retaining uncertain history. Survivor and + unspecified reduced-auxiliary procedures also refuse when protection + would change money. LITERAL_REFUSAL retains G v2: every qualifying month followed by a PIA increase protects its total, without an age condition or immediate fall. @@ -4904,7 +5004,7 @@ def protected_since(self) -> YearMonth | None: @property @_validated_entry def refused_since(self) -> YearMonth | None: - """The first month whose total fell below the protected total.""" + """The first refused fall or membership change in this history.""" return ( None if self._refused_since is None @@ -5029,8 +5129,9 @@ def _operational_admit( raise _computed( FamilyConfigurationUnsupported, UnsupportedReason.SAVINGS_CLAUSE_MEMBERSHIP_CHANGE, - "membership changed while 203(a)(5) protection was active; " - "RS 00630.400 does not establish the successor protection", + "membership changed at a qualifying fall or while " + "203(a)(5) protection was active; RS 00630.400 does not " + "establish the successor protection", ) if self._unknown_since is not None and _governed(result): raise _computed( @@ -5041,19 +5142,23 @@ def _operational_admit( ) if self._floor is not None and ( _savings_has_deductions(result) + or _savings_has_own_benefits(result) or ( prior is not None and prior.result is not None - and _savings_has_deductions(prior.result) + and ( + _savings_has_deductions(prior.result) + or _savings_has_own_benefits(prior.result) + ) ) ): self._unknown_since = self._unknown_since or result.payment_month raise _computed( FamilyConfigurationUnsupported, UnsupportedReason.SAVINGS_CLAUSE_RATE_PROCEDURE, - "deductions in the current or prior month interact with " - "carried protection; pre-offset age rates do not establish " - "the protected payment under RS 00630.400", + "own benefits or deductions in the current or prior month " + "interact with carried protection; pre-offset age rates " + "do not establish the protected payment under RS 00630.400", ) if ( prior is not None @@ -5061,14 +5166,29 @@ def _operational_admit( and _qualifies(prior.result) and _operational_age_reduced(prior.result) and result.pia > prior.pia - and membership == _savings_membership(prior.result) and total < _savings_clause_total_validated(prior.result) ): + if membership != _savings_membership(prior.result): + self._unknown_since = ( + self._unknown_since or result.payment_month + ) + self._refused_since = ( + self._refused_since or result.payment_month + ) + raise _computed( + FamilyConfigurationUnsupported, + UnsupportedReason.SAVINGS_CLAUSE_MEMBERSHIP_CHANGE, + "membership changed with a qualifying PIA increase " + "and lower payment; RS 00630.400 does not establish " + "the successor protection", + ) if ( _savings_age_basis(result) != _savings_age_basis(prior.result) or result.family_maximum < prior.result.family_maximum or _savings_has_deductions(result) or _savings_has_deductions(prior.result) + or _savings_has_own_benefits(result) + or _savings_has_own_benefits(prior.result) ): self._unknown_since = ( self._unknown_since or result.payment_month @@ -5077,9 +5197,10 @@ def _operational_admit( FamilyConfigurationUnsupported, UnsupportedReason.SAVINGS_CLAUSE_RATE_PROCEDURE, "age factors changed, the formula maximum fell, or " - "either month has deductions, with a PIA increase and " - "lower pre-offset total; the snapshots do not isolate " - "the PIA's effect or establish the protected payment", + "either month has own benefits or deductions, with a " + "PIA increase and lower pre-offset total; the snapshots " + "do not isolate the PIA's effect or establish the " + "protected payment", ) protected = _savings_clause_total_validated(prior.result) if self._floor is None or protected > self._floor: diff --git a/src/populace_dynamics/track_b/ret_ledger.py b/src/populace_dynamics/track_b/ret_ledger.py index 2fe571868..98a4abef3 100644 --- a/src/populace_dynamics/track_b/ret_ledger.py +++ b/src/populace_dynamics/track_b/ret_ledger.py @@ -20,6 +20,9 @@ caller supplies the monthly statutory and household facts. Other deduction events remain refused. No unsupported row is dropped from an outcome denominator or silently computed as a single worker. +G's declared monthly own-benefit facts establish two-record entitlement; +an optional annual declaration must agree with those facts. Actual or +estimated excess on two records remains refused (RS 02501.145-.150). Every raw month-set element must be an integer month before deduplication; malformed input raises before a coverage refusal can become an outcome. @@ -243,6 +246,9 @@ class RETBeneficiary: ``deemed_child_age_18_months``; that Act/CFR coverage difference is refused pending judgment. Broader unmarried-child wording in RS 02501.140 is also refused. Own two-record excess is still refused. + ``two_record_entitlement=None`` derives entitlement from supplied G + monthly own-benefit facts, or asserts no known two-record entitlement + without context. An explicit boolean must agree with those G facts. ``own_work_exempt_months`` supplies other Act 203(f)(1)(C)-(D) protections (entitled child who has attained 18 / widow(er) entitled before 60). It defaults to empty under the CFR's @@ -270,7 +276,7 @@ class RETBeneficiary: ) death_month: int | None = None own_work_exempt_months: frozenset[int] = field(default_factory=frozenset) - two_record_entitlement: bool = False + two_record_entitlement: bool | None = None def __post_init__(self): _identity(self.beneficiary_id, "A beneficiary") @@ -292,10 +298,16 @@ def __post_init__(self): "nh_entitled_before_divorce", "deemed_entitled", "deemed_married_to_nh", - "two_record_entitlement", ): if type(getattr(self, name)) is not bool: raise InvalidFamilyInput(f"{name} must be boolean") + if ( + self.two_record_entitlement is not None + and type(self.two_record_entitlement) is not bool + ): + raise InvalidFamilyInput( + "two_record_entitlement must be boolean or None" + ) _fra(self.fra_month) if not isinstance(self.earnings, WorkEarnings) or ( self.estimated_earnings is not None @@ -497,6 +509,8 @@ def __post_init__(self): RecordKind.DISABILITY: g.FamilyKind.DISABILITY, RecordKind.DECEASED: g.FamilyKind.SURVIVOR, }[self.kind] + contextual_people = set() + contextual_two_records = set() for month, context in self.family_months.items(): if context.state.kind is not expected_kind: raise InvalidFamilyInput("G and RET record kinds differ") @@ -524,10 +538,24 @@ def __post_init__(self): } ret_people = {b.beneficiary_id: b for b in beneficiaries} for auxiliary in context.beneficiaries: + contextual_people.add(auxiliary.beneficiary_id) + if auxiliary.own_benefit is not None: + contextual_two_records.add(auxiliary.beneficiary_id) if ret_people[auxiliary.beneficiary_id].benefit_types[ month - 1 ] not in role_types.get(auxiliary.role, ()): raise InvalidFamilyInput("G and RET benefit types differ") + for beneficiary in beneficiaries: + key = beneficiary.beneficiary_id + if ( + key in contextual_people + and beneficiary.two_record_entitlement is not None + and beneficiary.two_record_entitlement + != (key in contextual_two_records) + ): + raise InvalidFamilyInput( + "G and RET two-record entitlement facts differ" + ) object.__setattr__(self, "family_months", dict(self.family_months)) @@ -1095,6 +1123,13 @@ def apply_ret_year( or original != beneficiary.original_rates[month - 1] ): raise InvalidFamilyInput("G context does not match RET rates") + # R1 availability is an input requirement, so a held G coverage + # refusal cannot turn a missing supported year into a denominator row. + year = None + if record.year >= 2000: + year = ( + parameters if parameters is not None else load_ret_parameters() + ).for_year(record.year) if held_family_refusals: raise held_family_refusals[0] if record.year < 2000: @@ -1103,9 +1138,6 @@ def apply_ret_year( UnsupportedReason.YEAR_BEFORE_2000, "FRA-year rules in this form start in 2000", ) - year = ( - parameters if parameters is not None else load_ret_parameters() - ).for_year(record.year) refusals = ( (record.fiscal_year, UnsupportedReason.FISCAL_YEAR), (record.short_taxable_year, UnsupportedReason.SHORT_TAXABLE_YEAR), @@ -1163,6 +1195,12 @@ def apply_ret_year( for b in sorted(record.beneficiaries, key=lambda b: b.beneficiary_id) } facts = {} + contextual_two_records = { + b.beneficiary_id + for context in record.family_months.values() + for b in context.beneficiaries + if b.own_benefit is not None + } for key, b in people.items(): higher = b.fra_month is not None and b.fra_month > 0 exempt = ( @@ -1195,7 +1233,9 @@ def apply_ret_year( exempt, rate, ) - if b.two_record_entitlement and (excess or estimate): + if (b.two_record_entitlement or key in contextual_two_records) and ( + excess or estimate + ): raise _computed( RETConfigurationUnsupported, UnsupportedReason.TWO_RECORD_EARNINGS, diff --git a/tests/test_track_b_gross_benefits_deductions.py b/tests/test_track_b_gross_benefits_deductions.py index 735ad8648..0cc0a02ee 100644 --- a/tests/test_track_b_gross_benefits_deductions.py +++ b/tests/test_track_b_gross_benefits_deductions.py @@ -178,7 +178,9 @@ def test_rs_02501_130_no_child_in_care(): g.Beneficiary("C1", g.Role.CHILD), g.Beneficiary("C2", g.Role.CHILD), ) - event = g.BenefitDeduction(g.DeductionReason.NO_CHILD_IN_CARE) + event = g.BenefitDeduction( + g.DeductionReason.NO_CHILD_IN_CARE, under_full_retirement_age=True + ) result = compute(state, members, {"B": event}) assert amounts(result) == {"B": F(0), "C1": F("83.50"), "C2": F("83.50")} assert result.beneficiaries[0].original_benefit == F("121.10") @@ -226,6 +228,10 @@ def test_formula_bounds_monotonicity_households_order_and_determinism( b.beneficiary_id: ("elsewhere" if b.beneficiary_id == "C1" else "home") for b in members } + if payable == before["E"].auxiliary_payable: + with pytest.raises(g.InvalidFamilyInput): + compute(state, members, {"E": event}, households) + return result = compute(state, members, {"E": event}, households) again = compute( state, @@ -445,12 +451,16 @@ def test_all_dual_beneficiaries_do_not_gain_from_another_deduction(): ) for i in range(3) ) - result = compute( - state, - members, - {"C0": g.BenefitDeduction(g.DeductionReason.OWN_EARNINGS_TEST)}, - ) + result = compute(state, members) assert amounts(result) == dict.fromkeys(("C0", "C1", "C2"), F(0)) + # R2 never emits an own-work event for zero actual withholding. + # A zero-rate dual beneficiary cannot have a further earnings deduction. + with pytest.raises(g.InvalidFamilyInput): + compute( + state, + members, + {"C0": g.BenefitDeduction(g.DeductionReason.OWN_EARNINGS_TEST)}, + ) @given(scale=st.integers(1, 20)) diff --git a/tests/test_track_b_gross_benefits_deductions_fix_round_2.py b/tests/test_track_b_gross_benefits_deductions_fix_round_2.py new file mode 100644 index 000000000..40b587b10 --- /dev/null +++ b/tests/test_track_b_gross_benefits_deductions_fix_round_2.py @@ -0,0 +1,322 @@ +"""Statutory conformance: invented deduction-input counterexamples. + +Act 203(c)(2) excludes age-reduced spouse benefits. GN 02603.050A.1/B.3 +redistributes actual deductions only. No population or forecast claim. +""" + +from dataclasses import replace +from fractions import Fraction as F + +import pytest +from hypothesis import example, given, settings +from hypothesis import strategies as st + +from populace_dynamics.track_b import gross_benefits as g +from tests.track_b_gross_benefit_support import source_text as g_source_text +from tests.track_b_gross_benefit_support import ssa_params +from tests.track_b_ret_ledger_support import source_text as r2_source_text + +PARAMS = ssa_params() +MONTH = g.YearMonth(2024, 1) + + +def retirement(pia=4, maximum=6, children=2, reduction=60): + state = g.RecordState( + g.FamilyKind.RETIREMENT, + F(pia), + F(maximum), + worker=g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, F(pia)), + ) + members = (g.Beneficiary("B", g.Role.SPOUSE, reduction_months=reduction),) + members += tuple( + g.Beneficiary(f"C{i}", g.Role.CHILD) for i in range(1, children + 1) + ) + return state, members + + +def compute(state, members, deductions, household=False): + kwargs = dict( + payment_month=MONTH, + params=PARAMS, + deductions=deductions, + households={member.beneficiary_id: "home" for member in members}, + ) + if household: + return g.household_benefits_after_deductions( + {"record": g.HouseholdRecord("worker", state, members)}, + **kwargs, + ) + return g.family_benefits_after_deductions( + state, members, standalone=True, **kwargs + ) + + +@pytest.mark.parametrize("household", (False, True)) +@pytest.mark.parametrize("held_refusal", (False, True)) +def test_age_reduced_no_care_is_input_error_before_refusal( + household, held_refusal +): + state, members = retirement(children=0) + baseline = compute(state, members, {}, household) + family = baseline.records["record"] if household else baseline + assert family.by_id()["B"].auxiliary_payable == F("1.30") + assert family.by_id()["B"].whole_dollar_auxiliary == 1 + if held_refusal: + state = replace( + state, conditions={g.RecordCondition.ADMINISTRATIVE_FINALITY} + ) + with pytest.raises(g.FamilyConfigurationUnsupported) as held: + compute(state, members, {}, household) + assert held.value.reason is g.UnsupportedReason.ADMINISTRATIVE_FINALITY + outcomes = [] + with pytest.raises(g.InvalidFamilyInput): + outcomes.append( + g.evaluate_family( + "invalid", + 7, + lambda: compute( + state, + members, + { + "B": g.BenefitDeduction( + g.DeductionReason.NO_CHILD_IN_CARE + ) + }, + household, + ), + ) + ) + assert g.count_family_outcomes(outcomes).rows == 0 + + +@pytest.mark.parametrize("household", (False, True)) +@pytest.mark.parametrize("case", ("small", "large", "survivor")) +def test_reviewed_zero_deduction_cases_are_input_errors(case, household): + if case == "survivor": + state = g.RecordState( + g.FamilyKind.SURVIVOR, + F(1), + F("1.10"), + widow_drc_savings_clause=False, + ) + members = tuple(g.Beneficiary(f"C{i}", g.Role.CHILD) for i in range(3)) + events = {} + zero_id, zero_payable = "C0", F(".30") + expected = {f"C{i}": F(".30") for i in range(3)} + else: + state, members = retirement( + 4 if case == "small" else 48, + 6 if case == "small" else 78, + 2 if case == "small" else 3, + ) + events = {"B": g.BenefitDeduction(g.DeductionReason.OWN_EARNINGS_TEST)} + zero_id, zero_payable = "C1", F(".60" if case == "small" else "7.50") + expected = {"B": F(0)} | { + member.beneficiary_id: F(1 if case == "small" else 10) + for member in members[1:] + } + baseline = compute(state, members, events, household) + family = baseline.records["record"] if household else baseline + assert { + b.beneficiary_id: b.auxiliary_payable for b in family.beneficiaries + } == expected + assert { + b.beneficiary_id: b.whole_dollar_auxiliary + for b in family.beneficiaries + } == {bid: int(amount) for bid, amount in expected.items()} + outcomes = [] + with pytest.raises(g.InvalidFamilyInput): + outcomes.append( + g.evaluate_family( + "zero", + 3, + lambda: compute( + state, + members, + events + | { + zero_id: g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST, zero_payable + ) + }, + household, + ), + ) + ) + assert g.count_family_outcomes(outcomes).rows == 0 + assert compute(state, members, events, household) == baseline + + +@pytest.mark.parametrize("household", (False, True)) +@given( + scale=st.integers(1, 100), + reduction=st.integers(1, 60), + permanent=st.booleans(), +) +@settings(max_examples=15, deadline=None) +def test_zero_event_cannot_change_existing_full_deduction_output( + household, scale, reduction, permanent +): + state, members = retirement(48 * scale, 78 * scale, 3, reduction) + ordinary = compute(state, members, {}, household) + ordinary_family = ordinary.records["record"] if household else ordinary + events = {"B": g.BenefitDeduction(g.DeductionReason.OWN_EARNINGS_TEST)} + baseline = compute(state, members, events, household) + zero = g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST, + ordinary_family.by_id()["C1"].auxiliary_payable, + permanent, + ) + outcomes = [] + with pytest.raises(g.InvalidFamilyInput): + outcomes.append( + g.evaluate_family( + "zero", + 5, + lambda: compute( + state, members, events | {"C1": zero}, household + ), + ) + ) + assert g.count_family_outcomes(outcomes).rows == 0 + assert compute(state, members, events, household) == baseline + + +@pytest.mark.parametrize("household", (False, True)) +@pytest.mark.parametrize("under_fra", (None, False, True)) +@given(pia=st.integers(2, 1000), birth_year=st.integers(1930, 1950)) +@example(pia=4, birth_year=1950) +@settings(max_examples=8, deadline=None) +def test_no_care_spouse_requires_unreduced_under_fra_attestation( + household, under_fra, pia, birth_year +): + state, members = retirement(pia, 2 * pia, 0, 0) + event = g.BenefitDeduction( + g.DeductionReason.NO_CHILD_IN_CARE, + under_full_retirement_age=under_fra, + ) + if under_fra is True: + result = compute(state, members, {"B": event}, household) + family = result.records["record"] if household else result + assert family.by_id()["B"].auxiliary_payable == 0 + # A supplied cohort can make the separate age attestation impossible. + older = (replace(members[0], birth_year=birth_year),) + with pytest.raises(g.InvalidFamilyInput, match="birth cohort"): + compute(state, older, {"B": event}, household) + younger = (replace(members[0], birth_year=1960),) + result = compute(state, younger, {"B": event}, household) + family = result.records["record"] if household else result + assert family.by_id()["B"].auxiliary_payable == 0 + else: + outcomes = [] + with pytest.raises(g.InvalidFamilyInput): + outcomes.append( + g.evaluate_family( + "missing-age", + 3, + lambda: compute(state, members, {"B": event}, household), + ) + ) + assert g.count_family_outcomes(outcomes).rows == 0 + + +@pytest.mark.parametrize("household", (False, True)) +@given(reduction=st.integers(1, 60)) +@example(reduction=60) +@settings(max_examples=8, deadline=None) +def test_under_fra_attestation_cannot_admit_an_age_reduced_spouse( + household, reduction +): + state, members = retirement(reduction=reduction) + event = g.BenefitDeduction( + g.DeductionReason.NO_CHILD_IN_CARE, + under_full_retirement_age=True, + ) + with pytest.raises(g.InvalidFamilyInput, match="age-reduced"): + compute(state, members, {"B": event}, household) + + +def test_zero_event_is_measured_after_nh_reservation(): + state, members = retirement() + with pytest.raises(g.InvalidFamilyInput, match="positive amount"): + g.family_benefits_after_deductions( + state, + members, + payment_month=MONTH, + params=PARAMS, + deductions={ + "C1": g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST, F(".50") + ) + }, + households={}, + worker_deductions={"C1": F(".10")}, + standalone=True, + ) + + +def test_no_care_age_exclusion_is_quoted_from_existing_captures(): + text = g_source_text("ssa_act_203") + assert "if a wife or husband under retirement age" in text + assert ( + "and such wife's or husband's insurance benefit for such month " + "was not reduced under the provisions of section 202(q)" + ) in text + text = r2_source_text("ecfr_20cfr404_subpart_e") + assert "if he or she is under full retirement age" in text + assert ( + "there is in effect a certificate of election for him or her to " + "receive actuarially reduced wife's or husband's benefits for such month" + ) in text + + +@pytest.mark.parametrize("household", (False, True)) +@given(scale=st.integers(1, 100)) +@example(scale=1) +@settings(max_examples=8, deadline=None) +def test_zero_event_validation_precedes_an_unsupported_deduction( + household, scale +): + state, members = retirement(4 * scale, 6 * scale) + ordinary = compute(state, members, {}, household) + family = ordinary.records["record"] if household else ordinary + with pytest.raises(g.InvalidFamilyInput): + compute( + state, + members, + { + "B": g.BenefitDeduction(g.DeductionReason.PRISONER_SUSPENSION), + "C1": g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST, + family.by_id()["C1"].auxiliary_payable, + ), + }, + household, + ) + if household: + # The unique child's zero deduction is computable independently of + # the shared child's combined-maximum coverage refusal. + state = g.RecordState( + g.FamilyKind.SURVIVOR, + F(4 * scale), + F(6 * scale), + widow_drc_savings_clause=False, + ) + shared = g.Beneficiary("shared", g.Role.CHILD) + unique = g.Beneficiary("unique", g.Role.CHILD) + records = { + "a": g.HouseholdRecord("deceased-a", state, (shared, unique)), + "b": g.HouseholdRecord("deceased-b", state, (shared,)), + } + with pytest.raises(g.InvalidFamilyInput, match="positive amount"): + g.household_benefits_after_deductions( + records, + payment_month=MONTH, + params=PARAMS, + deductions={ + "unique": g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST, F(3 * scale) + ) + }, + households={}, + ) diff --git a/tests/test_track_b_gross_benefits_savings_fix_round_2.py b/tests/test_track_b_gross_benefits_savings_fix_round_2.py new file mode 100644 index 000000000..70d2b6ebb --- /dev/null +++ b/tests/test_track_b_gross_benefits_savings_fix_round_2.py @@ -0,0 +1,275 @@ +"""Statutory conformance: saving-clause coverage, invented families only. + +RS 00630.400's four conditions do not exempt a concurrent membership +change. Its captured payment procedures do not establish protection from +prior or current dual-entitlement rates. No population or forecast claim. +""" + +from fractions import Fraction as F + +import pytest +from hypothesis import given, settings +from hypothesis import strategies as st + +from populace_dynamics.track_b import gross_benefits as g +from tests.track_b_gross_benefit_support import ssa_params + +PARAMS = ssa_params() +JAN = g.YearMonth(2026, 1) +FEB = g.YearMonth(2026, 2) + + +def family( + month, + pia, + maximum, + *, + names=("C0", "C1"), + own=None, + own_role=g.Role.CHILD, + reverse=False, +): + state = g.RecordState( + g.FamilyKind.RETIREMENT, + F(pia), + F(maximum), + worker=g.OwnBenefit( + g.OwnBenefitKind.OLD_AGE, F(pia), reduction_months=60 + ), + ) + rows = [ + g.Beneficiary( + name, + own_role if index == 0 else g.Role.CHILD, + own_benefit=( + g.OwnBenefit(g.OwnBenefitKind.DISABILITY, F(own)) + if own is not None and index == 0 + else None + ), + own_benefit_first=( + True if own is not None and index == 0 else None + ), + ) + for index, name in enumerate(names) + ] + return g.family_benefits( + state, + rows[::-1] if reverse else rows, + payment_month=g.YearMonth(2026, month), + params=PARAMS, + standalone=True, + ) + + +def guard(): + return g.SavingsClauseGuard(JAN, earlier_months_unknown=False) + + +def assert_refused_with_history(value, after, reason, *, protected=None): + outcome = value.evaluate("concurrent change", F(7), lambda: after) + assert outcome.benefits is None + assert outcome.unsupported.reason is reason + counts = g.count_family_outcomes([outcome]) + assert counts.rows == counts.unsupported_rows == 1 + assert counts.weight == counts.unsupported_weight == F(7) + assert counts.unsupported_by_reason == {reason: (1, F(7))} + assert value.protected_total == protected + assert value.unknown_since == after.payment_month + assert value.next_month == g.YearMonth(2026, after.payment_month.month + 1) + return outcome + + +@pytest.mark.parametrize( + "pia,new_pia,maximum,names,ordinary_total", + ( + (F(".40"), F(".50"), F(".60"), ("C0", "C2"), F(".30")), + (F(1000), F(1010), F(1500), ("C0", "C2"), F(1197)), + (F(1000), F(1010), F(1500), ("C0", "C1", "C2"), F("1196.90")), + (F(1000), F(1010), F(1500), ("C0",), F(1197)), + ), +) +def test_first_trigger_membership_change_refuses_and_retains_denominator( + pia, new_pia, maximum, names, ordinary_total +): + before = family(1, pia, maximum) + after = family(2, new_pia, maximum, names=names) + assert before.record_total == (F(".40") if pia < 1 else F(1200)) + assert after.record_total == ordinary_total < before.record_total + value = guard() + assert value.admit(before) is before + assert_refused_with_history( + value, after, g.UnsupportedReason.SAVINGS_CLAUSE_MEMBERSHIP_CHANGE + ) + # Once a possible protection is lost, a later ordinary month cannot + # certify that the unseen successor protection has disappeared. + later = family(3, new_pia, maximum, names=names) + with pytest.raises(g.FamilyConfigurationUnsupported) as caught: + value.admit(later) + assert ( + caught.value.reason + is g.UnsupportedReason.SAVINGS_CLAUSE_MEMBERSHIP_CHANGE + ) + assert value.unknown_since == FEB + + +@pytest.mark.parametrize("role", (g.Role.SPOUSE, g.Role.CHILD)) +@pytest.mark.parametrize( + "pia,new_pia,maximum,own,before_total,prior_diagnostic,after_total", + ( + ( + F(1), + F("1.10"), + F("1.50"), + F(".10"), + F("1.20"), + F("1.30"), + F("1.10"), + ), + (F(1000), F(1010), F(1500), F(100), F(1200), F(1300), F(1197)), + ), +) +def test_prior_own_benefit_cessation_refuses_before_setting_protection( + role, + pia, + new_pia, + maximum, + own, + before_total, + prior_diagnostic, + after_total, +): + before = family(1, pia, maximum, own=own, own_role=role) + after = family(2, new_pia, maximum, own_role=role) + assert before.record_total == before_total + assert g.savings_clause_total(before) == prior_diagnostic + assert after.record_total == after_total + value = guard() + assert value.admit(before) is before + assert_refused_with_history( + value, after, g.UnsupportedReason.SAVINGS_CLAUSE_RATE_PROCEDURE + ) + later = family(3, new_pia, maximum, own_role=role) + with pytest.raises(g.FamilyConfigurationUnsupported) as caught: + value.admit(later) + assert ( + caught.value.reason + is g.UnsupportedReason.SAVINGS_CLAUSE_HISTORY_UNKNOWN + ) + + +@pytest.mark.parametrize("role", (g.Role.SPOUSE, g.Role.CHILD)) +def test_current_own_benefit_refuses_before_setting_protection(role): + before = family(1, 1000, 1500, own_role=role) + after = family(2, 1010, 1500, own=1, own_role=role) + assert g.savings_clause_total(after) < before.record_total + value = guard() + value.admit(before) + assert_refused_with_history( + value, after, g.UnsupportedReason.SAVINGS_CLAUSE_RATE_PROCEDURE + ) + + +@pytest.mark.parametrize("role", (g.Role.SPOUSE, g.Role.CHILD)) +@pytest.mark.parametrize("dormant", (False, True)) +def test_current_own_benefit_refuses_carried_and_dormant_protection( + role, dormant +): + value = guard() + value.admit(family(1, 1000, 1500, own_role=role)) + assert ( + value.admit(family(2, 1010, 1500, own_role=role)).record_total == 1200 + ) + after = family(3, 1010, 1600 if dormant else 1500, own=100, own_role=role) + assert (after.record_total >= F(1200)) is dormant + assert_refused_with_history( + value, + after, + g.UnsupportedReason.SAVINGS_CLAUSE_RATE_PROCEDURE, + protected=F(1200), + ) + + +@settings(max_examples=20, deadline=None, derandomize=True) +@given( + st.integers(100, 2000), + st.sampled_from((("C0", "C2"), ("C0", "C1", "C2"), ("C0",))), + st.booleans(), +) +def test_qualifying_membership_change_is_order_independent_refusal( + pia, names, reverse +): + maximum = F(3 * pia, 2) + before = family(1, pia, maximum, reverse=reverse) + after = family(2, pia + 10, maximum, names=names, reverse=reverse) + assert after.record_total < before.record_total + value = guard() + value.admit(before) + assert_refused_with_history( + value, after, g.UnsupportedReason.SAVINGS_CLAUSE_MEMBERSHIP_CHANGE + ) + + +@settings(max_examples=20, deadline=None, derandomize=True) +@given( + st.integers(100, 2000), + st.sampled_from((g.Role.SPOUSE, g.Role.CHILD)), + st.booleans(), +) +def test_prior_own_benefit_cessation_always_preserves_uncertain_history( + pia, role, reverse +): + maximum = F(3 * pia, 2) + before = family( + 1, pia, maximum, own=F(pia, 10), own_role=role, reverse=reverse + ) + after = family(2, pia + 10, maximum, own_role=role, reverse=reverse) + assert after.record_total < g.savings_clause_total(before) + value = guard() + value.admit(before) + assert_refused_with_history( + value, after, g.UnsupportedReason.SAVINGS_CLAUSE_RATE_PROCEDURE + ) + + +@settings(max_examples=20, deadline=None, derandomize=True) +@given( + st.integers(100, 2000), + st.sampled_from((g.Role.SPOUSE, g.Role.CHILD)), + st.booleans(), +) +def test_current_own_benefit_never_certifies_candidate_or_carried_protection( + pia, role, carried +): + maximum = F(3 * pia, 2) + before = family(1, pia, maximum, own_role=role) + value = guard() + value.admit(before) + if carried: + value.admit(family(2, pia + 10, maximum, own_role=role)) + after = family( + 3 if carried else 2, + pia + 10, + maximum + (100 if carried else 0), + own=F(".10"), + own_role=role, + ) + assert_refused_with_history( + value, + after, + g.UnsupportedReason.SAVINGS_CLAUSE_RATE_PROCEDURE, + protected=before.record_total if carried else None, + ) + + +@settings(max_examples=20, deadline=None, derandomize=True) +@given(st.integers(100, 2000), st.booleans()) +def test_membership_decline_without_pia_increase_stays_admitted(pia, reverse): + maximum = F(3 * pia, 2) + before = family(1, pia, maximum, reverse=reverse) + after = family(2, pia, maximum, names=(), reverse=reverse) + assert after.record_total < before.record_total + value = guard() + value.admit(before) + assert value.admit(after) is after + assert value.protected_total is None + assert value.unknown_since is None diff --git a/tests/test_track_b_ret_ledger_fix_round_2.py b/tests/test_track_b_ret_ledger_fix_round_2.py new file mode 100644 index 000000000..fea4add0d --- /dev/null +++ b/tests/test_track_b_ret_ledger_fix_round_2.py @@ -0,0 +1,369 @@ +"""R2 review regressions: statutory conformance on invented cases only. + +No population, behavioral, or forecast claim. RS 02501.145-.150 require +coordinated charging when a beneficiary has entitlement on two records. +""" + +from dataclasses import replace +from fractions import Fraction as F +from pathlib import Path + +import pytest +from hypothesis import example, given, settings +from hypothesis import strategies as st + +from populace_dynamics.track_b import gross_benefits as g +from populace_dynamics.track_b import ret_ledger as r +from populace_dynamics.track_b.ret_grace import BenefitType as T +from populace_dynamics.track_b.ret_params import load_ret_parameters +from tests.test_track_b_ret_ledger_deductions import family_record +from tests.track_b_gross_benefit_support import ssa_params + +YEAR = 2026 +MONTHS = frozenset(range(1, 13)) +PARAMS = load_ret_parameters() + + +def dual_record(pia=10, *, estimated=False, declared=None, own=True, excess=1): + """The reviewer's PIA 10/MAX 15 and PIA 1000/MAX 1500 cases.""" + params = ssa_params() + state = g.RecordState( + g.FamilyKind.RETIREMENT, + F(pia), + F(3 * pia, 2), + worker=g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, F(pia)), + eligibility_year=YEAR, + ) + spouse = g.Beneficiary( + "spouse", + g.Role.SPOUSE, + **( + { + "own_benefit": g.OwnBenefit( + g.OwnBenefitKind.OLD_AGE, F(pia, 10) + ), + "own_benefit_first": True, + } + if own + else {} + ), + ) + members = (spouse, g.Beneficiary("child", g.Role.CHILD)) + baseline = g.family_benefits( + state, + members, + payment_month=g.YearMonth(YEAR, 1), + params=params, + standalone=True, + ) + baseline_rows = baseline.by_id() + assert baseline.worker_benefit == pia + assert baseline_rows["spouse"].original_benefit == F(pia, 2) + assert baseline_rows["child"].original_benefit == F(pia, 2) + assert baseline_rows["spouse"].auxiliary_payable == ( + F(3 * pia, 20) if own else F(pia, 4) + ) + assert baseline_rows["child"].auxiliary_payable == ( + F(7 * pia, 20) if own else F(pia, 4) + ) + rates = [("nh", F(pia), F(pia), T.RIB)] + [ + ( + row.beneficiary_id, + row.auxiliary_payable, + row.original_benefit, + T.SPOUSE if row.beneficiary_id == "spouse" else T.CHILD, + ) + for row in baseline.beneficiaries + ] + wages = ( + PARAMS.for_year(YEAR).lower_exempt_amount.value + 2 * excess + if excess + else 0 + ) + earnings = r.WorkEarnings((F(wages),) + (F(0),) * 11) + people = [] + for key, rate, original, kind in rates: + kwargs = {} + if key == "spouse": + kwargs["estimated_earnings" if estimated else "earnings"] = ( + earnings + ) + if declared is not None: + kwargs["two_record_entitlement"] = declared + people.append( + r.RETBeneficiary( + key, + (kind,) * 12, + MONTHS, + (rate,) * 12, + (original,) * 12, + **kwargs, + ) + ) + return r.RecordYear( + YEAR, + "nh", + beneficiaries=tuple(people), + family_maximum_binding_months=MONTHS, + family_months={ + 1: r.RETFamilyMonth( + state, members, params, {"spouse": "h", "child": "h"} + ) + }, + ) + + +@pytest.mark.parametrize("pia,excess", [(10, 1), (1000, 100)]) +@pytest.mark.parametrize("estimated", [False, True]) +@pytest.mark.parametrize("declared", [None, True]) +def test_contextual_own_rib_requires_two_record_refusal( + pia, excess, estimated, declared +): + case = dual_record( + pia, estimated=estimated, declared=declared, excess=excess + ) + outcome = r.evaluate_ret("dual", 3, lambda: r.apply_ret_year(case, PARAMS)) + assert not outcome.supported + assert ( + outcome.unsupported.reason + is r.RETUnsupportedReason.TWO_RECORD_EARNINGS + ) + assert outcome.unsupported.beneficiary_id == "spouse" + denominator = g.count_family_outcomes([outcome]) + assert denominator.rows == denominator.unsupported_rows == 1 + assert denominator.weight == denominator.unsupported_weight == 3 + + +@pytest.mark.parametrize("own,declared", [(True, False), (False, True)]) +@pytest.mark.parametrize("estimated", [False, True]) +@settings(max_examples=6, deadline=None, derandomize=True) +@example(scale=1, excess=0, g_refusal=True) +@example(scale=1, excess=1, g_refusal=False) +@given( + scale=st.integers(1, 100), + excess=st.integers(0, 2), + g_refusal=st.booleans(), +) +def test_declared_two_record_contradiction_is_input_error( + own, declared, estimated, scale, excess, g_refusal +): + def contradictory_record(): + case = dual_record( + 10 * scale, own=own, estimated=estimated, excess=excess + ) + people = tuple( + ( + replace(person, two_record_entitlement=declared) + if person.beneficiary_id == "spouse" + else person + ) + for person in case.beneficiaries + ) + contexts = case.family_months + if g_refusal: + contexts = { + month: replace( + context, + beneficiaries=tuple( + ( + replace( + member, + conditions=frozenset( + { + g.BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD + } + ), + ) + if member.beneficiary_id == "spouse" + else member + ) + for member in context.beneficiaries + ), + ) + for month, context in contexts.items() + } + return replace(case, beneficiaries=people, family_months=contexts) + + outcomes = [] + with pytest.raises(r.InvalidFamilyInput, match="two.record"): + outcomes.append( + r.evaluate_ret( + "contradiction", + 1, + lambda: r.apply_ret_year(contradictory_record(), PARAMS), + ) + ) + assert outcomes == [] + assert g.count_family_outcomes(outcomes).rows == 0 + + +@settings(max_examples=12, deadline=None, derandomize=True) +@given(pia=st.integers(1, 100).map(lambda n: 10 * n), estimated=st.booleans()) +def test_two_record_derivation_is_order_independent(pia, estimated): + case = dual_record(pia, estimated=estimated) + reordered = replace( + case, + beneficiaries=tuple(reversed(case.beneficiaries)), + family_months={ + month: replace( + context, + beneficiaries=tuple(reversed(context.beneficiaries)), + households=dict(reversed(tuple(context.households.items()))), + ) + for month, context in reversed(tuple(case.family_months.items())) + }, + ) + outcomes = [ + r.evaluate_ret( + "dual", 1, lambda case=case: r.apply_ret_year(case, PARAMS) + ) + for case in (case, reordered) + ] + assert all(not outcome.supported for outcome in outcomes) + assert all( + outcome.unsupported.reason + is r.RETUnsupportedReason.TWO_RECORD_EARNINGS + for outcome in outcomes + ) + assert all( + outcome.unsupported.beneficiary_id == "spouse" for outcome in outcomes + ) + + +def test_contextual_own_rib_without_excess_remains_supported(): + result = r.apply_ret_year(dual_record(excess=0), PARAMS) + assert all( + row.deduction == row.provisional_deduction == 0 + for row in result.months + ) + + +@settings(max_examples=10, deadline=None, derandomize=True) +@example(excess=0) +@example(excess=1) +@example(excess=555) +@given(excess=st.integers(0, 600)) +def test_r2_emits_only_positive_actual_deduction_events(excess): + """Zero-excess people never become G deductees in either run.""" + original = g._family_benefits_after_deductions_validated + calls = [] + + def capture(state, beneficiaries, **kwargs): + baseline = g._family_benefits_validated( + state, + beneficiaries, + payment_month=kwargs["payment_month"], + params=kwargs["params"], + standalone=kwargs["standalone"], + ).by_id() + for key, event in kwargs["deductions"].items(): + assert event.reason is g.DeductionReason.OWN_EARNINGS_TEST + assert event.payable < baseline[key].auxiliary_payable + assert key == "c3" + calls.append(kwargs["deductions"]) + return original(state, beneficiaries, **kwargs) + + with pytest.MonkeyPatch.context() as monkeypatch: + monkeypatch.setattr( + g, "_family_benefits_after_deductions_validated", capture + ) + result = r.apply_ret_year(family_record(excess=excess), PARAMS) + assert bool(calls) is bool(excess) + if not excess: + assert all(row.deduction == 0 for row in result.months) + + +def missing_parameter_case(year=2027): + member = g.Beneficiary( + "c", + g.Role.CHILD, + conditions=frozenset( + {g.BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD} + ), + ) + context = r.RETFamilyMonth( + g.RecordState( + g.FamilyKind.SURVIVOR, F(100), F(100), eligibility_year=year + ), + (member,), + ssa_params(), + {"c": "h"}, + ) + beneficiary = r.RETBeneficiary( + "c", + (T.CHILD,) * 12, + frozenset({1}), + (F(75),) + (F(0),) * 11, + (F(75),) * 12, + ) + return r.RecordYear( + year, + "nh", + r.RecordKind.DECEASED, + (beneficiary,), + family_months={1: context}, + ) + + +@pytest.mark.parametrize("fiscal_year", [False, True]) +def test_missing_r1_parameter_precedes_held_g_refusal(fiscal_year): + outcomes = [] + with pytest.raises( + KeyError, match="RET parameters unavailable for year 2027" + ): + outcomes.append( + r.evaluate_ret( + "missing", + 1, + lambda: r.apply_ret_year( + replace(missing_parameter_case(), fiscal_year=fiscal_year), + PARAMS, + ), + ) + ) + assert outcomes == [] + assert g.count_family_outcomes(outcomes).rows == 0 + + +@settings(max_examples=10, deadline=None, derandomize=True) +@given(year=st.integers(2027, 2100), fiscal_year=st.booleans()) +def test_unavailable_supported_r1_year_is_never_a_coverage_row( + year, fiscal_year +): + outcomes = [] + with pytest.raises(KeyError, match=f"year {year}"): + outcomes.append( + r.evaluate_ret( + "missing", + 1, + lambda: r.apply_ret_year( + replace( + missing_parameter_case(year), fiscal_year=fiscal_year + ), + PARAMS, + ), + ) + ) + assert g.count_family_outcomes(outcomes).rows == 0 + + +def test_pre_2000_legal_refusal_does_not_request_an_r1_year(): + case = replace(missing_parameter_case(1999), family_months={}) + outcome = r.evaluate_ret( + "historical", 1, lambda: r.apply_ret_year(case, PARAMS) + ) + assert ( + outcome.unsupported.reason is r.RETUnsupportedReason.YEAR_BEFORE_2000 + ) + + +def test_r2_statutory_order_describes_contextual_g_readjustment(): + note = ( + Path(__file__).parents[1] / "docs/design/track_b_r2_ret_ledger.md" + ).read_text() + step = note.split("5. **Other workers' charging.**", 1)[1].split( + "6. **Protected months.**", 1 + )[0] + assert "RETFamilyMonth" in step + assert "deduction_readjustment_requires_family_context" in step + assert "refuse the\n record for part (b)" not in step From 1a9c8b7eae779dbe5d4094c1162e06af8094a8cf Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 31 Oct 2026 07:52:40 -0400 Subject: [PATCH 05/17] Finish and verify #563 fix round 2 (part 2) This part adds the no-child-in-care age checks under Act 203(c)(2) and 20 CFR 404.421(a), rejects zero-amount events in every layer, rewrites the R2 statutory-order step, rewords the reservation case as deferred coverage, and records fifteen new mutations and the verification ledger. Subfleet job 20261025-105211-trackb-fix-g2-2b (gpt-6.1-sol) wrote this work and left it uncommitted; salvage ref 0d96d2e1 preserved its tree. Co-Authored-By: Claude Opus 5.5 --- docs/design/track_b_g2_r2b_mutations.json | 1614 ++++++++--- docs/design/track_b_g2_r2b_verification.json | 2582 ++++++++++++++++- docs/design/track_b_g_gross_benefits.md | 74 +- docs/design/track_b_r2_ret_ledger.md | 2 +- .../track_b/gross_benefits.py | 63 +- tests/README-tiers.md | 4 +- .../data/track_b/gross_benefit_examples.yaml | 2 + ...k_b_gross_benefits_deduction_age_inputs.py | 183 ++ .../test_track_b_gross_benefits_deductions.py | 1 + ...track_b_gross_benefits_fix_round_10_api.py | 1 + tests/test_track_b_gross_benefits_registry.py | 3 + tests/test_track_b_ret_ledger_fix_round_2.py | 28 +- tests/tier_counts.json | 2 +- 13 files changed, 4104 insertions(+), 455 deletions(-) create mode 100644 tests/test_track_b_gross_benefits_deduction_age_inputs.py diff --git a/docs/design/track_b_g2_r2b_mutations.json b/docs/design/track_b_g2_r2b_mutations.json index 12db8e659..0b3803831 100644 --- a/docs/design/track_b_g2_r2b_mutations.json +++ b/docs/design/track_b_g2_r2b_mutations.json @@ -2,10 +2,10 @@ "schema_version": 1, "verification_class": "statutory_conformance", "admitted_scope": "Mutation sensitivity of statutory rules on invented and captured worked cases only; no population, behavioral or forecast claim.", - "confirmed_mutation_count": 24, + "confirmed_mutation_count": 28, "counts_by_layer": { "shared_provenance": 1, - "g_deductions": 8, + "g_deductions": 12, "r2": 7, "g_savings": 8 }, @@ -581,37 +581,82 @@ "runner_reference": "scratch/savings_mutations/run_mutations.py" }, { - "id": "round2_no_care_discard_age_exclusion", + "id": "audit2_deductions_no_care_reduced_spouse", "layer": "g_deductions", "source": "src/populace_dynamics/track_b/gross_benefits.py", "change": { - "before": " if member.reduction_months:\n", - "after": " if False:\n" - }, - "environment": { - "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/deduction-mutation-tree/src:/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2", - "PYTHONDONTWRITEBYTECODE": "1", - "OMP_NUM_THREADS": "1", - "OMP_WAIT_POLICY": "PASSIVE", - "POLARS_MAX_THREADS": "1", - "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", - "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", - "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/hypothesis-deductions" + "before": "if member.reduction_months:\n raise InvalidFamilyInput(\n \"No-child-in-care", + "after": "if False:\n raise InvalidFamilyInput(\n \"No-child-in-care" + }, + "mutated": { + "label": "audit2_deductions_no_care_reduced_spouse", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-c", + "from populace_dynamics.track_b import gross_benefits as g; assert g.__file__.startswith('/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/mutated/src'), g.__file__; import pytest,sys; sys.exit(pytest.main(sys.argv[1:]))", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", + "-k", + "under_fra_attestation_cannot_admit_an_age_reduced_spouse", + "--tb=short" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/mutated/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/hypothesis", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/nonexistent" + }, + "exit_code": 1, + "wall_seconds": 16.302953499980504, + "log": "scratch/review/deduction-audit/audit2_deductions_no_care_reduced_spouse.log", + "log_sha256": "d6ade3ec32a8983be93941aae94bd64d9ffb433010e5a3c06c99f61e9d275f96", + "summary": "2 failed, 22 deselected in 7.08s", + "failed_tests": [ + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_under_fra_attestation_cannot_admit_an_age_reduced_spouse[False]", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_under_fra_attestation_cannot_admit_an_age_reduced_spouse[True]" + ] + }, + "restored": { + "label": "audit2_deductions_no_care_reduced_spouse-restored", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-c", + "from populace_dynamics.track_b import gross_benefits as g; assert g.__file__.startswith('/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/mutated/src'), g.__file__; import pytest,sys; sys.exit(pytest.main(sys.argv[1:]))", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", + "-k", + "under_fra_attestation_cannot_admit_an_age_reduced_spouse", + "--tb=short" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/mutated/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/hypothesis", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/nonexistent" + }, + "exit_code": 0, + "wall_seconds": 7.973216291982681, + "log": "scratch/review/deduction-audit/audit2_deductions_no_care_reduced_spouse-restored.log", + "log_sha256": "35da1de97711d8724bae7d08ebe79373c097a3e2593e7cf6586a381a4a23aec6", + "summary": "2 passed, 22 deselected in 3.20s", + "failed_tests": [] }, - "command": [ - "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", - "-c", - "import sys; from populace_dynamics.track_b import gross_benefits as g; assert \"deduction-mutation-tree/src\" in g.__file__, g.__file__; import pytest; sys.exit(pytest.main(sys.argv[1:]))", - "-p", - "no:xdist", - "-p", - "no:cacheprovider", - "-q", - "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", - "-k", - "test_under_fra_attestation_cannot_admit_an_age_reduced_spouse", - "--tb=short" - ], "mutated_exit_code": 1, "failed_tests": [ "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_under_fra_attestation_cannot_admit_an_age_reduced_spouse[False]", @@ -619,351 +664,986 @@ ], "restoration": { "reverted": true, - "restored_test_exit_code": 0, - "isolated_source_sha256": "83a73585b57ae29a036e7c013f64662dea019aa60605a0a1cd9f917d20273dd0", - "restored_test_summary": "2 passed, 22 deselected in 36.89s", - "restored_log": "scratch/review/round2_no_care_discard_age_exclusion-restored.log", - "restored_log_sha256": "ff762baf0580e3ce57472a9d12d3c212d9752d0655465eb3ce3c30735a76447e" + "isolated_source_restored": true, + "isolated_source_sha256": "4c1f5803b6b0dfd06e7c8f075248a5a49bbc932a4b8161499880f116b951b80f", + "restored_test_exit_code": 0 }, - "log": { - "path": "scratch/review/round2_no_care_discard_age_exclusion-mutated.log", - "sha256": "0c4c1b4e90f441d62e21453dbe495182459cef0f78a2133287f24c88fccd4ebf", - "failure_summary": "2 failed, 22 deselected in 39.92s" - } + "evidence_run": "Fresh completed continuation replay; isolated sources, exact byte restoration and restored tests." }, { - "id": "round2_no_care_discard_under_fra_requirement", + "id": "audit2_deductions_zero_own_event", "layer": "g_deductions", "source": "src/populace_dynamics/track_b/gross_benefits.py", "change": { - "before": " if event.under_full_retirement_age is not True:\n", - "after": " if False:\n" - }, - "environment": { - "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/deduction-mutation-tree/src:/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2", - "PYTHONDONTWRITEBYTECODE": "1", - "OMP_NUM_THREADS": "1", - "OMP_WAIT_POLICY": "PASSIVE", - "POLARS_MAX_THREADS": "1", - "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", - "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", - "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/hypothesis-deductions" + "before": "and event.payable == gross", + "after": "and False" + }, + "mutated": { + "label": "audit2_deductions_zero_own_event", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-c", + "from populace_dynamics.track_b import gross_benefits as g; assert g.__file__.startswith('/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/mutated/src'), g.__file__; import pytest,sys; sys.exit(pytest.main(sys.argv[1:]))", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", + "-k", + "reviewed_zero_deduction_cases", + "--tb=short" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/mutated/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/hypothesis", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/nonexistent" + }, + "exit_code": 1, + "wall_seconds": 19.16740883301827, + "log": "scratch/review/deduction-audit/audit2_deductions_zero_own_event.log", + "log_sha256": "787165f6b8611031245425f8c0413e689973121a9477e79180d25f2136b7bfa8", + "summary": "6 failed, 18 deselected in 11.47s", + "failed_tests": [ + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_reviewed_zero_deduction_cases_are_input_errors[small-False]", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_reviewed_zero_deduction_cases_are_input_errors[small-True]", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_reviewed_zero_deduction_cases_are_input_errors[large-False]", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_reviewed_zero_deduction_cases_are_input_errors[large-True]", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_reviewed_zero_deduction_cases_are_input_errors[survivor-False]", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_reviewed_zero_deduction_cases_are_input_errors[survivor-True]" + ] + }, + "restored": { + "label": "audit2_deductions_zero_own_event-restored", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-c", + "from populace_dynamics.track_b import gross_benefits as g; assert g.__file__.startswith('/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/mutated/src'), g.__file__; import pytest,sys; sys.exit(pytest.main(sys.argv[1:]))", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", + "-k", + "reviewed_zero_deduction_cases", + "--tb=short" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/mutated/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/hypothesis", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/nonexistent" + }, + "exit_code": 0, + "wall_seconds": 23.18791770900134, + "log": "scratch/review/deduction-audit/audit2_deductions_zero_own_event-restored.log", + "log_sha256": "c5932b4b17983ce06396877945ca354d18402fa2c649e48e384926c6708086ab", + "summary": "6 passed, 18 deselected in 8.01s", + "failed_tests": [] }, - "command": [ - "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", - "-c", - "import sys; from populace_dynamics.track_b import gross_benefits as g; assert \"deduction-mutation-tree/src\" in g.__file__, g.__file__; import pytest; sys.exit(pytest.main(sys.argv[1:]))", - "-p", - "no:xdist", - "-p", - "no:cacheprovider", - "-q", - "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", - "-k", - "test_no_care_spouse_requires_unreduced_under_fra_attestation", - "--tb=short" - ], "mutated_exit_code": 1, "failed_tests": [ - "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_no_care_spouse_requires_unreduced_under_fra_attestation[None-False]", - "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_no_care_spouse_requires_unreduced_under_fra_attestation[None-True]", - "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_no_care_spouse_requires_unreduced_under_fra_attestation[False-False]", - "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_no_care_spouse_requires_unreduced_under_fra_attestation[False-True]" + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_reviewed_zero_deduction_cases_are_input_errors[small-False]", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_reviewed_zero_deduction_cases_are_input_errors[small-True]", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_reviewed_zero_deduction_cases_are_input_errors[large-False]", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_reviewed_zero_deduction_cases_are_input_errors[large-True]", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_reviewed_zero_deduction_cases_are_input_errors[survivor-False]", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_reviewed_zero_deduction_cases_are_input_errors[survivor-True]" ], "restoration": { "reverted": true, - "restored_test_exit_code": 0, - "isolated_source_sha256": "83a73585b57ae29a036e7c013f64662dea019aa60605a0a1cd9f917d20273dd0", - "restored_test_summary": "6 passed, 18 deselected in 39.65s", - "restored_log": "scratch/review/round2_no_care_discard_under_fra_requirement-restored.log", - "restored_log_sha256": "8b635cf4d038f8abfb943060dae521d03dbf05e4060f95c61aed147d5a6f4838" + "isolated_source_restored": true, + "isolated_source_sha256": "4c1f5803b6b0dfd06e7c8f075248a5a49bbc932a4b8161499880f116b951b80f", + "restored_test_exit_code": 0 }, - "log": { - "path": "scratch/review/round2_no_care_discard_under_fra_requirement-mutated.log", - "sha256": "defd78c73d3771a3d58eaea369e05c80ba764e0545cb251d22f272d149c14eff", - "failure_summary": "4 failed, 2 passed, 18 deselected in 31.05s" - } + "evidence_run": "Fresh completed continuation replay; isolated sources, exact byte restoration and restored tests." }, { - "id": "round2_admit_zero_earnings_event", + "id": "audit2_deductions_household_coverage_before_zero_validation", "layer": "g_deductions", "source": "src/populace_dynamics/track_b/gross_benefits.py", "change": { - "before": " and event.payable == gross\n", - "after": " and event.payable > gross\n" - }, - "environment": { - "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/deduction-mutation-tree/src:/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2", - "PYTHONDONTWRITEBYTECODE": "1", - "OMP_NUM_THREADS": "1", - "OMP_WAIT_POLICY": "PASSIVE", - "POLARS_MAX_THREADS": "1", - "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", - "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", - "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/hypothesis-deductions" + "before": " family_refusals = []", + "after": " _refuse_household(held); family_refusals = []" + }, + "mutated": { + "label": "audit2_deductions_household_coverage_before_zero_validation", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-c", + "from populace_dynamics.track_b import gross_benefits as g; assert g.__file__.startswith('/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/mutated/src'), g.__file__; import pytest,sys; sys.exit(pytest.main(sys.argv[1:]))", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", + "-k", + "zero_event_validation_precedes", + "--tb=short" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/mutated/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/hypothesis", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/nonexistent" + }, + "exit_code": 1, + "wall_seconds": 14.848391458013793, + "log": "scratch/review/deduction-audit/audit2_deductions_household_coverage_before_zero_validation.log", + "log_sha256": "3ef1b589aa46c5a48ec9ad9a6a9d8c97c5ac0ad8e940b933cc5e3515a27de245", + "summary": "1 failed, 1 passed, 22 deselected in 4.56s", + "failed_tests": [ + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_zero_event_validation_precedes_an_unsupported_deduction[True]" + ] + }, + "restored": { + "label": "audit2_deductions_household_coverage_before_zero_validation-restored", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-c", + "from populace_dynamics.track_b import gross_benefits as g; assert g.__file__.startswith('/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/mutated/src'), g.__file__; import pytest,sys; sys.exit(pytest.main(sys.argv[1:]))", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", + "-k", + "zero_event_validation_precedes", + "--tb=short" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/mutated/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/hypothesis", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/nonexistent" + }, + "exit_code": 0, + "wall_seconds": 17.92546991701238, + "log": "scratch/review/deduction-audit/audit2_deductions_household_coverage_before_zero_validation-restored.log", + "log_sha256": "9202b6c9e0ffa13e7d872cdc798bbf34aa60036a3d1e36e9dee350571a3a8a0f", + "summary": "2 passed, 22 deselected in 7.39s", + "failed_tests": [] }, - "command": [ - "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", - "-c", - "import sys; from populace_dynamics.track_b import gross_benefits as g; assert \"deduction-mutation-tree/src\" in g.__file__, g.__file__; import pytest; sys.exit(pytest.main(sys.argv[1:]))", - "-p", - "no:xdist", - "-p", - "no:cacheprovider", - "-q", - "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", - "-k", - "test_reviewed_zero_deduction_cases_are_input_errors", - "--tb=short" - ], "mutated_exit_code": 1, "failed_tests": [ - "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_reviewed_zero_deduction_cases_are_input_errors[small-False]", - "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_reviewed_zero_deduction_cases_are_input_errors[small-True]", - "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_reviewed_zero_deduction_cases_are_input_errors[large-False]", - "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_reviewed_zero_deduction_cases_are_input_errors[large-True]", - "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_reviewed_zero_deduction_cases_are_input_errors[survivor-False]", - "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_reviewed_zero_deduction_cases_are_input_errors[survivor-True]" + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py::test_zero_event_validation_precedes_an_unsupported_deduction[True]" ], "restoration": { "reverted": true, - "restored_test_exit_code": 0, - "isolated_source_sha256": "83a73585b57ae29a036e7c013f64662dea019aa60605a0a1cd9f917d20273dd0", - "restored_test_summary": "6 passed, 18 deselected in 67.60s (0:01:07)", - "restored_log": "scratch/review/round2_admit_zero_earnings_event-restored.log", - "restored_log_sha256": "b9e70fbf6cd777507c544b0a778e5eb1d3b8d5a1f2e7d96cf7c3420f6f12741c" + "isolated_source_restored": true, + "isolated_source_sha256": "4c1f5803b6b0dfd06e7c8f075248a5a49bbc932a4b8161499880f116b951b80f", + "restored_test_exit_code": 0 }, - "log": { - "path": "scratch/review/round2_admit_zero_earnings_event-mutated.log", - "sha256": "49271283243cf25456e27795171a47a1c72166a7472f1dfdb3e268e82bbd96f2", - "failure_summary": "6 failed, 18 deselected in 45.39s" - } + "evidence_run": "Fresh completed continuation replay; isolated sources, exact byte restoration and restored tests." }, { - "id": "round2_r2_contextual_two_record_detection_removed", - "layer": "r2", - "source": "src/populace_dynamics/track_b/ret_ledger.py", + "id": "audit2_deductions_duplicate_person_validation", + "layer": "g_deductions", + "source": "src/populace_dynamics/track_b/gross_benefits.py", "change": { - "before": "if (b.two_record_entitlement or key in contextual_two_records) and (", - "after": "if b.two_record_entitlement and (" + "before": " for member in beneficiaries:\n event = deductions.get(member.beneficiary_id)", + "after": " for member in members.values():\n event = deductions.get(member.beneficiary_id)" + }, + "mutated": { + "label": "audit2_deductions_duplicate_person_validation", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-c", + "from populace_dynamics.track_b import gross_benefits as g; assert g.__file__.startswith('/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/mutated/src'), g.__file__; import pytest,sys; sys.exit(pytest.main(sys.argv[1:]))", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py", + "-k", + "each_household", + "--tb=short" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/mutated/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/hypothesis", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/nonexistent" + }, + "exit_code": 1, + "wall_seconds": 14.262563415977638, + "log": "scratch/review/deduction-audit/audit2_deductions_duplicate_person_validation.log", + "log_sha256": "81b3e00f5b8f60a96606443d27664f3f9c865596b8bac10b2fbe444666fd32ce", + "summary": "1 failed, 1 passed, 23 deselected in 6.98s", + "failed_tests": [ + "tests/test_track_b_gross_benefits_deduction_age_inputs.py::test_each_household_entitlement_checks_no_care_age_before_refusal[False]" + ] }, - "command": [ - "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", - "-c", - "import sys; from populace_dynamics.track_b import ret_ledger as r; assert r.__file__.startswith('/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/r2-mutation-tree'),r.__file__; import pytest; sys.exit(pytest.main(sys.argv[1:]))", - "-p", - "no:xdist", - "-p", - "no:cacheprovider", - "-q", - "tests/test_track_b_ret_ledger_fix_round_2.py", - "-k", - "contextual_own_rib_requires_two_record_refusal and None" - ], - "environment": { - "OMP_NUM_THREADS": "1", - "OMP_WAIT_POLICY": "PASSIVE", - "PYTHONDONTWRITEBYTECODE": "1", - "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/hypothesis-r2", - "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/r2-mutation-tree/src:/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2", - "POLARS_MAX_THREADS": "1", - "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", - "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent" + "restored": { + "label": "audit2_deductions_duplicate_person_validation-restored", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-c", + "from populace_dynamics.track_b import gross_benefits as g; assert g.__file__.startswith('/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/mutated/src'), g.__file__; import pytest,sys; sys.exit(pytest.main(sys.argv[1:]))", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py", + "-k", + "each_household", + "--tb=short" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/mutated/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/hypothesis", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/nonexistent" + }, + "exit_code": 0, + "wall_seconds": 7.320883625012357, + "log": "scratch/review/deduction-audit/audit2_deductions_duplicate_person_validation-restored.log", + "log_sha256": "62a07cb70b24f5198371d876294e472ae1d97f08fb034eeb95046d2dfe4b884b", + "summary": "2 passed, 23 deselected in 0.92s", + "failed_tests": [] }, "mutated_exit_code": 1, "failed_tests": [ - "FAILED tests/test_track_b_ret_ledger_fix_round_2.py::test_contextual_own_rib_requires_two_record_refusal[None-False-10-1]", - "FAILED tests/test_track_b_ret_ledger_fix_round_2.py::test_contextual_own_rib_requires_two_record_refusal[None-False-1000-100]", - "FAILED tests/test_track_b_ret_ledger_fix_round_2.py::test_contextual_own_rib_requires_two_record_refusal[None-True-10-1]", - "FAILED tests/test_track_b_ret_ledger_fix_round_2.py::test_contextual_own_rib_requires_two_record_refusal[None-True-1000-100]" + "tests/test_track_b_gross_benefits_deduction_age_inputs.py::test_each_household_entitlement_checks_no_care_age_before_refusal[False]" ], - "log": { - "failure_summary": "4 failed, 16 deselected in 50.80s" + "restoration": { + "reverted": true, + "isolated_source_restored": true, + "isolated_source_sha256": "4c1f5803b6b0dfd06e7c8f075248a5a49bbc932a4b8161499880f116b951b80f", + "restored_test_exit_code": 0 + }, + "evidence_run": "Fresh completed continuation replay; isolated sources, exact byte restoration and restored tests." + }, + { + "id": "audit2_deductions_derive_young_cohort", + "layer": "g_deductions", + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": " if month < earliest_fra:\n under_fra = True", + "after": " if month < earliest_fra:\n under_fra = None" + }, + "mutated": { + "label": "audit2_deductions_derive_young_cohort", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-c", + "from populace_dynamics.track_b import gross_benefits as g; assert g.__file__.startswith('/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/mutated/src'), g.__file__; import pytest,sys; sys.exit(pytest.main(sys.argv[1:]))", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py", + "-k", + "cohort_fra_interval", + "--tb=short" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/mutated/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/hypothesis", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/nonexistent" + }, + "exit_code": 1, + "wall_seconds": 3.119055707997177, + "log": "scratch/review/deduction-audit/audit2_deductions_derive_young_cohort.log", + "log_sha256": "0af9b8ce8038c3922011455b2b27c35600f526321343a5f4d1c9ff914cb09469", + "summary": "1 failed, 11 passed, 13 deselected in 1.79s", + "failed_tests": [ + "tests/test_track_b_gross_benefits_deduction_age_inputs.py::test_cohort_fra_interval_uses_attestation_only_when_needed[None--1-True]" + ] }, + "restored": { + "label": "audit2_deductions_derive_young_cohort-restored", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-c", + "from populace_dynamics.track_b import gross_benefits as g; assert g.__file__.startswith('/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/mutated/src'), g.__file__; import pytest,sys; sys.exit(pytest.main(sys.argv[1:]))", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py", + "-k", + "cohort_fra_interval", + "--tb=short" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/mutated/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/hypothesis", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/nonexistent" + }, + "exit_code": 0, + "wall_seconds": 2.7192072499892674, + "log": "scratch/review/deduction-audit/audit2_deductions_derive_young_cohort-restored.log", + "log_sha256": "34605d3b155ad38c389aa14029cff941518b88eac7578ea6469d8b07c9ce3856", + "summary": "12 passed, 13 deselected in 1.34s", + "failed_tests": [] + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_gross_benefits_deduction_age_inputs.py::test_cohort_fra_interval_uses_attestation_only_when_needed[None--1-True]" + ], "restoration": { "reverted": true, "isolated_source_restored": true, - "restored_test_exit_code": 0, - "restored_test_summary": "4 passed, 16 deselected in 45.32s", - "isolated_source_sha256": "0e3f19edfbe36571718fac2559972132db3ac8efbd282262ffbfc28dc366c64d" + "isolated_source_sha256": "4c1f5803b6b0dfd06e7c8f075248a5a49bbc932a4b8161499880f116b951b80f", + "restored_test_exit_code": 0 }, - "metadata_reference": "scratch/review/r2-mutations.json" + "evidence_run": "Fresh completed continuation replay; isolated sources, exact byte restoration and restored tests." }, { - "id": "round2_r2_contextual_two_record_consistency_removed", - "layer": "r2", - "source": "src/populace_dynamics/track_b/ret_ledger.py", + "id": "audit2_deductions_latest_fra_boundary", + "layer": "g_deductions", + "source": "src/populace_dynamics/track_b/gross_benefits.py", "change": { - "before": "key in contextual_people\n", - "after": "False\n" + "before": "latest_fra = earliest_fra + 11", + "after": "latest_fra = earliest_fra + 12" + }, + "mutated": { + "label": "audit2_deductions_latest_fra_boundary", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-c", + "from populace_dynamics.track_b import gross_benefits as g; assert g.__file__.startswith('/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/mutated/src'), g.__file__; import pytest,sys; sys.exit(pytest.main(sys.argv[1:]))", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py", + "-k", + "cohort_fra_interval", + "--tb=short" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/mutated/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/hypothesis", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/nonexistent" + }, + "exit_code": 1, + "wall_seconds": 4.111399207991781, + "log": "scratch/review/deduction-audit/audit2_deductions_latest_fra_boundary.log", + "log_sha256": "1e35600984e21bc33acb716774c7660f0fbabd8f001f96a69155308676d6cb57", + "summary": "1 failed, 11 passed, 13 deselected in 2.15s", + "failed_tests": [ + "tests/test_track_b_gross_benefits_deduction_age_inputs.py::test_cohort_fra_interval_uses_attestation_only_when_needed[True-11-False]" + ] }, - "command": [ - "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", - "-c", - "import sys; from populace_dynamics.track_b import ret_ledger as r; assert r.__file__.startswith('/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/r2-mutation-tree'),r.__file__; import pytest; sys.exit(pytest.main(sys.argv[1:]))", - "-p", - "no:xdist", - "-p", - "no:cacheprovider", - "-q", - "tests/test_track_b_ret_ledger_fix_round_2.py", - "-k", - "declared_two_record_contradiction_is_input_error" + "restored": { + "label": "audit2_deductions_latest_fra_boundary-restored", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-c", + "from populace_dynamics.track_b import gross_benefits as g; assert g.__file__.startswith('/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/mutated/src'), g.__file__; import pytest,sys; sys.exit(pytest.main(sys.argv[1:]))", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py", + "-k", + "cohort_fra_interval", + "--tb=short" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/mutated/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/hypothesis", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/nonexistent" + }, + "exit_code": 0, + "wall_seconds": 3.330219666007906, + "log": "scratch/review/deduction-audit/audit2_deductions_latest_fra_boundary-restored.log", + "log_sha256": "7cb530a4428905c4615959d7145a382d639dd39795e852f86499f61e86c87d3d", + "summary": "12 passed, 13 deselected in 1.50s", + "failed_tests": [] + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_gross_benefits_deduction_age_inputs.py::test_cohort_fra_interval_uses_attestation_only_when_needed[True-11-False]" ], - "environment": { - "OMP_NUM_THREADS": "1", - "OMP_WAIT_POLICY": "PASSIVE", - "PYTHONDONTWRITEBYTECODE": "1", - "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/hypothesis-r2", - "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/r2-mutation-tree/src:/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2", - "POLARS_MAX_THREADS": "1", - "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", - "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent" + "restoration": { + "reverted": true, + "isolated_source_restored": true, + "isolated_source_sha256": "4c1f5803b6b0dfd06e7c8f075248a5a49bbc932a4b8161499880f116b951b80f", + "restored_test_exit_code": 0 + }, + "evidence_run": "Fresh completed continuation replay; isolated sources, exact byte restoration and restored tests." + }, + { + "id": "audit2_deductions_delayed_credits_settle_age", + "layer": "g_deductions", + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": "if own is not None and own.delayed_credit_months:\n # Credits", + "after": "if False:\n # Credits" + }, + "mutated": { + "label": "audit2_deductions_delayed_credits_settle_age", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-c", + "from populace_dynamics.track_b import gross_benefits as g; assert g.__file__.startswith('/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/mutated/src'), g.__file__; import pytest,sys; sys.exit(pytest.main(sys.argv[1:]))", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py", + "-k", + "supplied_delayed_credits", + "--tb=short" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/mutated/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/hypothesis", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/nonexistent" + }, + "exit_code": 1, + "wall_seconds": 3.331539208011236, + "log": "scratch/review/deduction-audit/audit2_deductions_delayed_credits_settle_age.log", + "log_sha256": "b48746615778137984e7ce6dc094a44b36919c83413b8cb616c12a4911c414a2", + "summary": "1 failed, 24 deselected in 1.31s", + "failed_tests": [ + "tests/test_track_b_gross_benefits_deduction_age_inputs.py::test_supplied_delayed_credits_exclude_no_care_even_inside_cohort_interval" + ] + }, + "restored": { + "label": "audit2_deductions_delayed_credits_settle_age-restored", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-c", + "from populace_dynamics.track_b import gross_benefits as g; assert g.__file__.startswith('/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/mutated/src'), g.__file__; import pytest,sys; sys.exit(pytest.main(sys.argv[1:]))", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py", + "-k", + "supplied_delayed_credits", + "--tb=short" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/mutated/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/hypothesis", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/deduction-audit/nonexistent" + }, + "exit_code": 0, + "wall_seconds": 3.6897381669841707, + "log": "scratch/review/deduction-audit/audit2_deductions_delayed_credits_settle_age-restored.log", + "log_sha256": "14424bfbaa781b76e315a18f5b89307e3ab4a7e09d2d46b068cb94a3772cc3bc", + "summary": "1 passed, 24 deselected in 1.27s", + "failed_tests": [] }, "mutated_exit_code": 1, "failed_tests": [ - "FAILED tests/test_track_b_ret_ledger_fix_round_2.py::test_declared_two_record_contradiction_is_input_error[False-True-False]", - "FAILED tests/test_track_b_ret_ledger_fix_round_2.py::test_declared_two_record_contradiction_is_input_error[False-False-True]", - "FAILED tests/test_track_b_ret_ledger_fix_round_2.py::test_declared_two_record_contradiction_is_input_error[True-True-False]", - "FAILED tests/test_track_b_ret_ledger_fix_round_2.py::test_declared_two_record_contradiction_is_input_error[True-False-True]" + "tests/test_track_b_gross_benefits_deduction_age_inputs.py::test_supplied_delayed_credits_exclude_no_care_even_inside_cohort_interval" ], - "log": { - "failure_summary": "4 failed, 16 deselected in 29.01s" + "restoration": { + "reverted": true, + "isolated_source_restored": true, + "isolated_source_sha256": "4c1f5803b6b0dfd06e7c8f075248a5a49bbc932a4b8161499880f116b951b80f", + "restored_test_exit_code": 0 + }, + "evidence_run": "Fresh completed continuation replay; isolated sources, exact byte restoration and restored tests." + }, + { + "id": "fresh_r2_contextual_two_record_derivation_removed", + "layer": "r2", + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "mutation": { + "before": "if (b.two_record_entitlement or key in contextual_two_records) and (", + "after": "if b.two_record_entitlement and (" + }, + "failed": { + "label": "fresh_r2_contextual_two_record_derivation_removed", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_ret_ledger_fix_round_2.py", + "-k", + "test_contextual_own_rib_requires_two_record_refusal and None" + ], + "cwd": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/r2-audit/current", + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-no-data", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-no-data", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/r2-audit/hypothesis", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/r2-audit/current/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/r2-audit/current" + }, + "exit_code": 1, + "summary": "4 failed, 16 deselected in 21.76s", + "log": "scratch/review/r2-audit/fresh_r2_contextual_two_record_derivation_removed.log", + "failing_tests": [ + "tests/test_track_b_ret_ledger_fix_round_2.py::test_contextual_own_rib_requires_two_record_refusal[None-False-10-1]", + "tests/test_track_b_ret_ledger_fix_round_2.py::test_contextual_own_rib_requires_two_record_refusal[None-False-1000-100]", + "tests/test_track_b_ret_ledger_fix_round_2.py::test_contextual_own_rib_requires_two_record_refusal[None-True-10-1]", + "tests/test_track_b_ret_ledger_fix_round_2.py::test_contextual_own_rib_requires_two_record_refusal[None-True-1000-100]" + ] }, + "restored": { + "label": "fresh_r2_contextual_two_record_derivation_removed-restored", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_ret_ledger_fix_round_2.py", + "-k", + "test_contextual_own_rib_requires_two_record_refusal and None" + ], + "cwd": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/r2-audit/current", + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-no-data", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-no-data", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/r2-audit/hypothesis", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/r2-audit/current/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/r2-audit/current" + }, + "exit_code": 0, + "summary": "4 passed, 16 deselected in 10.81s", + "log": "scratch/review/r2-audit/fresh_r2_contextual_two_record_derivation_removed-restored.log", + "failing_tests": [] + }, + "source_restored_exactly": true, + "restored_sha256": "0e3f19edfbe36571718fac2559972132db3ac8efbd282262ffbfc28dc366c64d", + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_2.py::test_contextual_own_rib_requires_two_record_refusal[None-False-10-1]", + "tests/test_track_b_ret_ledger_fix_round_2.py::test_contextual_own_rib_requires_two_record_refusal[None-False-1000-100]", + "tests/test_track_b_ret_ledger_fix_round_2.py::test_contextual_own_rib_requires_two_record_refusal[None-True-10-1]", + "tests/test_track_b_ret_ledger_fix_round_2.py::test_contextual_own_rib_requires_two_record_refusal[None-True-1000-100]" + ], + "mutated_exit_code": 1, "restoration": { "reverted": true, "isolated_source_restored": true, "restored_test_exit_code": 0, - "restored_test_summary": "4 passed, 16 deselected in 38.60s", "isolated_source_sha256": "0e3f19edfbe36571718fac2559972132db3ac8efbd282262ffbfc28dc366c64d" }, - "metadata_reference": "scratch/review/r2-mutations.json" + "evidence_run": "Fresh completed continuation replay; isolated sources, exact byte restoration and restored tests." }, { - "id": "round2_r2_missing_parameter_hidden_by_held_g_refusal", + "id": "fresh_r2_contextual_two_record_contradiction_ignored", "layer": "r2", "source": "src/populace_dynamics/track_b/ret_ledger.py", - "change": { - "before": "if record.year >= 2000:\n", - "after": "if record.year >= 2000 and not held_family_refusals:\n" + "mutation": { + "before": "and beneficiary.two_record_entitlement is not None", + "after": "and False" }, - "command": [ - "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", - "-c", - "import sys; from populace_dynamics.track_b import ret_ledger as r; assert r.__file__.startswith('/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/r2-mutation-tree'),r.__file__; import pytest; sys.exit(pytest.main(sys.argv[1:]))", - "-p", - "no:xdist", - "-p", - "no:cacheprovider", - "-q", - "tests/test_track_b_ret_ledger_fix_round_2.py", - "-k", - "missing_r1_parameter_precedes_held_g_refusal" - ], - "environment": { - "OMP_NUM_THREADS": "1", - "OMP_WAIT_POLICY": "PASSIVE", - "PYTHONDONTWRITEBYTECODE": "1", - "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/hypothesis-r2", - "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/r2-mutation-tree/src:/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2", - "POLARS_MAX_THREADS": "1", - "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", - "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent" + "failed": { + "label": "fresh_r2_contextual_two_record_contradiction_ignored", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_ret_ledger_fix_round_2.py", + "-k", + "test_declared_two_record_contradiction_is_input_error" + ], + "cwd": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/r2-audit/current", + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-no-data", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-no-data", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/r2-audit/hypothesis", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/r2-audit/current/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/r2-audit/current" + }, + "exit_code": 1, + "summary": "4 failed, 16 deselected in 17.98s", + "log": "scratch/review/r2-audit/fresh_r2_contextual_two_record_contradiction_ignored.log", + "failing_tests": [ + "tests/test_track_b_ret_ledger_fix_round_2.py::test_declared_two_record_contradiction_is_input_error[False-True-False]", + "tests/test_track_b_ret_ledger_fix_round_2.py::test_declared_two_record_contradiction_is_input_error[False-False-True]", + "tests/test_track_b_ret_ledger_fix_round_2.py::test_declared_two_record_contradiction_is_input_error[True-True-False]", + "tests/test_track_b_ret_ledger_fix_round_2.py::test_declared_two_record_contradiction_is_input_error[True-False-True]" + ] }, - "mutated_exit_code": 1, + "restored": { + "label": "fresh_r2_contextual_two_record_contradiction_ignored-restored", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_ret_ledger_fix_round_2.py", + "-k", + "test_declared_two_record_contradiction_is_input_error" + ], + "cwd": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/r2-audit/current", + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-no-data", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-no-data", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/r2-audit/hypothesis", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/r2-audit/current/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/r2-audit/current" + }, + "exit_code": 0, + "summary": "4 passed, 16 deselected in 10.48s", + "log": "scratch/review/r2-audit/fresh_r2_contextual_two_record_contradiction_ignored-restored.log", + "failing_tests": [] + }, + "source_restored_exactly": true, + "restored_sha256": "0e3f19edfbe36571718fac2559972132db3ac8efbd282262ffbfc28dc366c64d", "failed_tests": [ - "FAILED tests/test_track_b_ret_ledger_fix_round_2.py::test_missing_r1_parameter_precedes_held_g_refusal[False]", - "FAILED tests/test_track_b_ret_ledger_fix_round_2.py::test_missing_r1_parameter_precedes_held_g_refusal[True]" + "tests/test_track_b_ret_ledger_fix_round_2.py::test_declared_two_record_contradiction_is_input_error[False-True-False]", + "tests/test_track_b_ret_ledger_fix_round_2.py::test_declared_two_record_contradiction_is_input_error[False-False-True]", + "tests/test_track_b_ret_ledger_fix_round_2.py::test_declared_two_record_contradiction_is_input_error[True-True-False]", + "tests/test_track_b_ret_ledger_fix_round_2.py::test_declared_two_record_contradiction_is_input_error[True-False-True]" ], - "log": { - "failure_summary": "2 failed, 18 deselected in 36.59s" - }, + "mutated_exit_code": 1, "restoration": { "reverted": true, "isolated_source_restored": true, "restored_test_exit_code": 0, - "restored_test_summary": "2 passed, 18 deselected in 30.77s", "isolated_source_sha256": "0e3f19edfbe36571718fac2559972132db3ac8efbd282262ffbfc28dc366c64d" }, - "metadata_reference": "scratch/review/r2-mutations.json" + "evidence_run": "Fresh completed continuation replay; isolated sources, exact byte restoration and restored tests." }, { - "id": "round2_r2_zero_excess_emits_a_g_deduction_event", + "id": "fresh_r2_missing_parameter_lookup_skipped_for_held_g_refusal", "layer": "r2", "source": "src/populace_dynamics/track_b/ret_ledger.py", - "change": { - "before": "if k != record.nh_id and own_deductions[k, m] > 0\n", - "after": "if k != record.nh_id and own_deductions[k, m] >= 0\n" + "mutation": { + "before": "if record.year >= 2000:", + "after": "if record.year >= 2000 and not held_family_refusals:" + }, + "failed": { + "label": "fresh_r2_missing_parameter_lookup_skipped_for_held_g_refusal", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_ret_ledger_fix_round_2.py", + "-k", + "test_missing_r1_parameter_precedes_held_g_refusal" + ], + "cwd": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/r2-audit/current", + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-no-data", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-no-data", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/r2-audit/hypothesis", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/r2-audit/current/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/r2-audit/current" + }, + "exit_code": 1, + "summary": "2 failed, 18 deselected in 12.03s", + "log": "scratch/review/r2-audit/fresh_r2_missing_parameter_lookup_skipped_for_held_g_refusal.log", + "failing_tests": [ + "tests/test_track_b_ret_ledger_fix_round_2.py::test_missing_r1_parameter_precedes_held_g_refusal[False]", + "tests/test_track_b_ret_ledger_fix_round_2.py::test_missing_r1_parameter_precedes_held_g_refusal[True]" + ] }, - "command": [ - "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", - "-c", - "import sys; from populace_dynamics.track_b import ret_ledger as r; assert r.__file__.startswith('/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/r2-mutation-tree'),r.__file__; import pytest; sys.exit(pytest.main(sys.argv[1:]))", - "-p", - "no:xdist", - "-p", - "no:cacheprovider", - "-q", - "tests/test_track_b_ret_ledger_fix_round_2.py", - "-k", - "r2_emits_only_positive_actual_deduction_events" + "restored": { + "label": "fresh_r2_missing_parameter_lookup_skipped_for_held_g_refusal-restored", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_ret_ledger_fix_round_2.py", + "-k", + "test_missing_r1_parameter_precedes_held_g_refusal" + ], + "cwd": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/r2-audit/current", + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-no-data", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-no-data", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/r2-audit/hypothesis", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/r2-audit/current/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/r2-audit/current" + }, + "exit_code": 0, + "summary": "2 passed, 18 deselected in 6.68s", + "log": "scratch/review/r2-audit/fresh_r2_missing_parameter_lookup_skipped_for_held_g_refusal-restored.log", + "failing_tests": [] + }, + "source_restored_exactly": true, + "restored_sha256": "0e3f19edfbe36571718fac2559972132db3ac8efbd282262ffbfc28dc366c64d", + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_2.py::test_missing_r1_parameter_precedes_held_g_refusal[False]", + "tests/test_track_b_ret_ledger_fix_round_2.py::test_missing_r1_parameter_precedes_held_g_refusal[True]" ], - "environment": { - "OMP_NUM_THREADS": "1", - "OMP_WAIT_POLICY": "PASSIVE", - "PYTHONDONTWRITEBYTECODE": "1", - "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/hypothesis-r2", - "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/r2-mutation-tree/src:/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2", - "POLARS_MAX_THREADS": "1", - "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", - "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent" - }, "mutated_exit_code": 1, + "restoration": { + "reverted": true, + "isolated_source_restored": true, + "restored_test_exit_code": 0, + "isolated_source_sha256": "0e3f19edfbe36571718fac2559972132db3ac8efbd282262ffbfc28dc366c64d" + }, + "evidence_run": "Fresh completed continuation replay; isolated sources, exact byte restoration and restored tests." + }, + { + "id": "fresh_r2_zero_deduction_events_emitted", + "layer": "r2", + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "mutation": { + "before": "if k != record.nh_id and own_deductions[k, m] > 0", + "after": "if k != record.nh_id and own_deductions[k, m] >= 0" + }, + "failed": { + "label": "fresh_r2_zero_deduction_events_emitted", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_ret_ledger_fix_round_2.py", + "-k", + "test_r2_emits_only_positive_actual_deduction_events" + ], + "cwd": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/r2-audit/current", + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-no-data", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-no-data", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/r2-audit/hypothesis", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/r2-audit/current/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/r2-audit/current" + }, + "exit_code": 1, + "summary": "1 failed, 19 deselected in 7.11s", + "log": "scratch/review/r2-audit/fresh_r2_zero_deduction_events_emitted.log", + "failing_tests": [ + "tests/test_track_b_ret_ledger_fix_round_2.py::test_r2_emits_only_positive_actual_deduction_events" + ] + }, + "restored": { + "label": "fresh_r2_zero_deduction_events_emitted-restored", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_ret_ledger_fix_round_2.py", + "-k", + "test_r2_emits_only_positive_actual_deduction_events" + ], + "cwd": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/r2-audit/current", + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-no-data", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-no-data", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/r2-audit/hypothesis", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/r2-audit/current/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/r2-audit/current" + }, + "exit_code": 0, + "summary": "1 passed, 19 deselected in 11.14s", + "log": "scratch/review/r2-audit/fresh_r2_zero_deduction_events_emitted-restored.log", + "failing_tests": [] + }, + "source_restored_exactly": true, + "restored_sha256": "0e3f19edfbe36571718fac2559972132db3ac8efbd282262ffbfc28dc366c64d", "failed_tests": [ - "FAILED tests/test_track_b_ret_ledger_fix_round_2.py::test_r2_emits_only_positive_actual_deduction_events" + "tests/test_track_b_ret_ledger_fix_round_2.py::test_r2_emits_only_positive_actual_deduction_events" ], - "log": { - "failure_summary": "1 failed, 19 deselected in 13.46s" - }, + "mutated_exit_code": 1, "restoration": { "reverted": true, "isolated_source_restored": true, "restored_test_exit_code": 0, - "restored_test_summary": "1 passed, 19 deselected in 31.97s", "isolated_source_sha256": "0e3f19edfbe36571718fac2559972132db3ac8efbd282262ffbfc28dc366c64d" }, - "metadata_reference": "scratch/review/r2-mutations.json" + "evidence_run": "Fresh completed continuation replay; isolated sources, exact byte restoration and restored tests." }, { - "id": "round2_savings_skip_first_membership_trigger", + "id": "audit2_savings_allow_first_trigger_membership", "layer": "g_savings", "source": "src/populace_dynamics/track_b/gross_benefits.py", "change": { - "before": " and result.pia > prior.pia\n", - "after": " and result.pia > prior.pia and membership == _savings_membership(prior.result)\n" + "before": " if membership != _savings_membership(prior.result):\n", + "after": " if False and membership != _savings_membership(prior.result):\n" + }, + "mutated": { + "label": "audit2_savings_allow_first_trigger_membership", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-c", + "from populace_dynamics.track_b import gross_benefits as g; assert g.__file__.startswith('/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/mutated/src'), g.__file__; import pytest, sys; sys.exit(pytest.main(sys.argv[1:]))", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py", + "-k", + "first_trigger_membership_change_refuses_and_retains_denominator", + "--tb=short" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/mutated/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/nonexistent", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/hypothesis" + }, + "exit_code": 1, + "wall_seconds": 24.129617083002813, + "summary": "4 failed, 14 deselected in 14.84s", + "log": "scratch/review/savings-audit/audit2_savings_allow_first_trigger_membership.log", + "log_sha256": "01c288eedce11d2cf91ae363df9176bd666d02a52622768e55b362c495e986c4", + "failed_tests": [ + "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_first_trigger_membership_change_refuses_and_retains_denominator[pia0-new_pia0-maximum0-names0-ordinary_total0]", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_first_trigger_membership_change_refuses_and_retains_denominator[pia1-new_pia1-maximum1-names1-ordinary_total1]", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_first_trigger_membership_change_refuses_and_retains_denominator[pia2-new_pia2-maximum2-names2-ordinary_total2]", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_first_trigger_membership_change_refuses_and_retains_denominator[pia3-new_pia3-maximum3-names3-ordinary_total3]" + ] }, - "command": [ - "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", - "-c", - "from populace_dynamics.track_b import gross_benefits as g; assert 'savings-mutation-tree/src' in g.__file__, g.__file__; import pytest,sys; sys.exit(pytest.main(sys.argv[1:]))", - "-p", - "no:xdist", - "-p", - "no:cacheprovider", - "-q", - "tests/test_track_b_gross_benefits_savings_fix_round_2.py", - "-k", - "first_trigger_membership_change" - ], - "environment": { - "PYTHONDONTWRITEBYTECODE": "1", - "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/savings-mutation-tree/src:/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2", - "OMP_NUM_THREADS": "1", - "OMP_WAIT_POLICY": "PASSIVE", - "POLARS_MAX_THREADS": "1", - "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", - "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", - "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/hypothesis-savings-mutation" + "restored": { + "label": "audit2_savings_allow_first_trigger_membership-restored", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-c", + "from populace_dynamics.track_b import gross_benefits as g; assert g.__file__.startswith('/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/mutated/src'), g.__file__; import pytest, sys; sys.exit(pytest.main(sys.argv[1:]))", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py", + "-k", + "first_trigger_membership_change_refuses_and_retains_denominator", + "--tb=short" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/mutated/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/nonexistent", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/hypothesis" + }, + "exit_code": 0, + "wall_seconds": 17.765461041009985, + "summary": "4 passed, 14 deselected in 5.21s", + "log": "scratch/review/savings-audit/audit2_savings_allow_first_trigger_membership-restored.log", + "log_sha256": "73c1e38f9e6e4196ddb42afceffb9e3a93ab3080c0dd63f2987cb32b6e2b34f7", + "failed_tests": [] }, "mutated_exit_code": 1, "failed_tests": [ @@ -972,51 +1652,92 @@ "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_first_trigger_membership_change_refuses_and_retains_denominator[pia2-new_pia2-maximum2-names2-ordinary_total2]", "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_first_trigger_membership_change_refuses_and_retains_denominator[pia3-new_pia3-maximum3-names3-ordinary_total3]" ], - "log": { - "path": "scratch/review/round2_savings_skip_first_membership_trigger.log", - "sha256": "d381b9f01739b7c37580e37d5f95a0fb49bafa1c8427fae4fff562e5e5b23f4f", - "failure_summary": "4 failed, 14 deselected in 32.75s" - }, "restoration": { "reverted": true, "isolated_source_restored": true, - "restored_test_exit_code": 0, - "isolated_source_sha256": "c5885aa63592f76e50867daa454bb9aee3f16a30abacbf3f3c487a27443aad6d", - "restored_log": "scratch/review/round2_savings_skip_first_membership_trigger-restored.log", - "restored_log_sha256": "3a701ed247406c521ef142c3e2c435dde7715e8db30275e1556f20cfb5c329f7", - "restored_test_summary": "4 passed, 14 deselected in 9.74s" - } + "isolated_source_sha256": "4c1f5803b6b0dfd06e7c8f075248a5a49bbc932a4b8161499880f116b951b80f", + "restored_test_exit_code": 0 + }, + "evidence_run": "Fresh completed continuation replay; isolated sources, exact byte restoration and restored tests." }, { - "id": "round2_savings_ignore_prior_own_benefit", + "id": "audit2_savings_ignore_prior_own_benefit", "layer": "g_savings", "source": "src/populace_dynamics/track_b/gross_benefits.py", "change": { - "before": " or _savings_has_own_benefits(prior.result)\n", - "after": " or False\n" + "before": "\n or _savings_has_own_benefits(prior.result)\n", + "after": "\n or False\n" + }, + "mutated": { + "label": "audit2_savings_ignore_prior_own_benefit", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-c", + "from populace_dynamics.track_b import gross_benefits as g; assert g.__file__.startswith('/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/mutated/src'), g.__file__; import pytest, sys; sys.exit(pytest.main(sys.argv[1:]))", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py", + "-k", + "prior_own_benefit_cessation_refuses_before_setting_protection", + "--tb=short" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/mutated/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/nonexistent", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/hypothesis" + }, + "exit_code": 1, + "wall_seconds": 20.010347708011977, + "summary": "4 failed, 14 deselected in 7.41s", + "log": "scratch/review/savings-audit/audit2_savings_ignore_prior_own_benefit.log", + "log_sha256": "96324364832a51585ac9ff50f669413e83a65ee969436175f658c5fde124a76a", + "failed_tests": [ + "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_prior_own_benefit_cessation_refuses_before_setting_protection[pia0-new_pia0-maximum0-own0-before_total0-prior_diagnostic0-after_total0-Role.SPOUSE]", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_prior_own_benefit_cessation_refuses_before_setting_protection[pia0-new_pia0-maximum0-own0-before_total0-prior_diagnostic0-after_total0-Role.CHILD]", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_prior_own_benefit_cessation_refuses_before_setting_protection[pia1-new_pia1-maximum1-own1-before_total1-prior_diagnostic1-after_total1-Role.SPOUSE]", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_prior_own_benefit_cessation_refuses_before_setting_protection[pia1-new_pia1-maximum1-own1-before_total1-prior_diagnostic1-after_total1-Role.CHILD]" + ] }, - "command": [ - "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", - "-c", - "from populace_dynamics.track_b import gross_benefits as g; assert 'savings-mutation-tree/src' in g.__file__, g.__file__; import pytest,sys; sys.exit(pytest.main(sys.argv[1:]))", - "-p", - "no:xdist", - "-p", - "no:cacheprovider", - "-q", - "tests/test_track_b_gross_benefits_savings_fix_round_2.py", - "-k", - "prior_own_benefit_cessation_refuses_before" - ], - "environment": { - "PYTHONDONTWRITEBYTECODE": "1", - "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/savings-mutation-tree/src:/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2", - "OMP_NUM_THREADS": "1", - "OMP_WAIT_POLICY": "PASSIVE", - "POLARS_MAX_THREADS": "1", - "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", - "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", - "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/hypothesis-savings-mutation" + "restored": { + "label": "audit2_savings_ignore_prior_own_benefit-restored", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-c", + "from populace_dynamics.track_b import gross_benefits as g; assert g.__file__.startswith('/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/mutated/src'), g.__file__; import pytest, sys; sys.exit(pytest.main(sys.argv[1:]))", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py", + "-k", + "prior_own_benefit_cessation_refuses_before_setting_protection", + "--tb=short" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/mutated/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/nonexistent", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/hypothesis" + }, + "exit_code": 0, + "wall_seconds": 26.98456649997388, + "summary": "4 passed, 14 deselected in 10.73s", + "log": "scratch/review/savings-audit/audit2_savings_ignore_prior_own_benefit-restored.log", + "log_sha256": "574e62be4226d83a391c3d8830a6bc5fb4b291f4150741e875e810d0f39723c3", + "failed_tests": [] }, "mutated_exit_code": 1, "failed_tests": [ @@ -1025,51 +1746,92 @@ "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_prior_own_benefit_cessation_refuses_before_setting_protection[pia1-new_pia1-maximum1-own1-before_total1-prior_diagnostic1-after_total1-Role.SPOUSE]", "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_prior_own_benefit_cessation_refuses_before_setting_protection[pia1-new_pia1-maximum1-own1-before_total1-prior_diagnostic1-after_total1-Role.CHILD]" ], - "log": { - "path": "scratch/review/round2_savings_ignore_prior_own_benefit.log", - "sha256": "efd32d1f9fdfec0f08e63bdab91a1ac74779f6ea7c111f5b385df5503965acfa", - "failure_summary": "4 failed, 14 deselected in 15.70s" - }, "restoration": { "reverted": true, "isolated_source_restored": true, - "restored_test_exit_code": 0, - "isolated_source_sha256": "c5885aa63592f76e50867daa454bb9aee3f16a30abacbf3f3c487a27443aad6d", - "restored_log": "scratch/review/round2_savings_ignore_prior_own_benefit-restored.log", - "restored_log_sha256": "fe284da226dee5ded0ee8c4c435163c913cac30f2dacb20f08ce98f36ea3ba76", - "restored_test_summary": "4 passed, 14 deselected in 4.58s" - } + "isolated_source_sha256": "4c1f5803b6b0dfd06e7c8f075248a5a49bbc932a4b8161499880f116b951b80f", + "restored_test_exit_code": 0 + }, + "evidence_run": "Fresh completed continuation replay; isolated sources, exact byte restoration and restored tests." }, { - "id": "round2_savings_ignore_current_own_benefit_on_carried_floor", + "id": "audit2_savings_ignore_current_own_carried_floor", "layer": "g_savings", "source": "src/populace_dynamics/track_b/gross_benefits.py", "change": { - "before": " or _savings_has_own_benefits(result)\n", - "after": " or False\n" + "before": "\n or _savings_has_own_benefits(result)\n", + "after": "\n or False\n" + }, + "mutated": { + "label": "audit2_savings_ignore_current_own_carried_floor", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-c", + "from populace_dynamics.track_b import gross_benefits as g; assert g.__file__.startswith('/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/mutated/src'), g.__file__; import pytest, sys; sys.exit(pytest.main(sys.argv[1:]))", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py", + "-k", + "current_own_benefit_refuses_carried_and_dormant_protection", + "--tb=short" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/mutated/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/nonexistent", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/hypothesis" + }, + "exit_code": 1, + "wall_seconds": 16.69854083401151, + "summary": "4 failed, 14 deselected in 8.36s", + "log": "scratch/review/savings-audit/audit2_savings_ignore_current_own_carried_floor.log", + "log_sha256": "27e92cc63c71f4137963de23e18ecaa060ced506c40668b5e6220bde7dbc3095", + "failed_tests": [ + "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_current_own_benefit_refuses_carried_and_dormant_protection[False-Role.SPOUSE]", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_current_own_benefit_refuses_carried_and_dormant_protection[False-Role.CHILD]", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_current_own_benefit_refuses_carried_and_dormant_protection[True-Role.SPOUSE]", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_current_own_benefit_refuses_carried_and_dormant_protection[True-Role.CHILD]" + ] }, - "command": [ - "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", - "-c", - "from populace_dynamics.track_b import gross_benefits as g; assert 'savings-mutation-tree/src' in g.__file__, g.__file__; import pytest,sys; sys.exit(pytest.main(sys.argv[1:]))", - "-p", - "no:xdist", - "-p", - "no:cacheprovider", - "-q", - "tests/test_track_b_gross_benefits_savings_fix_round_2.py", - "-k", - "current_own_benefit_refuses_carried_and_dormant" - ], - "environment": { - "PYTHONDONTWRITEBYTECODE": "1", - "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/savings-mutation-tree/src:/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2", - "OMP_NUM_THREADS": "1", - "OMP_WAIT_POLICY": "PASSIVE", - "POLARS_MAX_THREADS": "1", - "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", - "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", - "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/hypothesis-savings-mutation" + "restored": { + "label": "audit2_savings_ignore_current_own_carried_floor-restored", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-c", + "from populace_dynamics.track_b import gross_benefits as g; assert g.__file__.startswith('/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/mutated/src'), g.__file__; import pytest, sys; sys.exit(pytest.main(sys.argv[1:]))", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py", + "-k", + "current_own_benefit_refuses_carried_and_dormant_protection", + "--tb=short" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/mutated/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/nonexistent", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/hypothesis" + }, + "exit_code": 0, + "wall_seconds": 12.525136000011116, + "summary": "4 passed, 14 deselected in 4.13s", + "log": "scratch/review/savings-audit/audit2_savings_ignore_current_own_carried_floor-restored.log", + "log_sha256": "f682769320222a1aa19cbc021b742c35b8721fc008921906f232f8a15adecb57", + "failed_tests": [] }, "mutated_exit_code": 1, "failed_tests": [ @@ -1078,71 +1840,103 @@ "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_current_own_benefit_refuses_carried_and_dormant_protection[True-Role.SPOUSE]", "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_current_own_benefit_refuses_carried_and_dormant_protection[True-Role.CHILD]" ], - "log": { - "path": "scratch/review/round2_savings_ignore_current_own_benefit_on_carried_floor.log", - "sha256": "35c9170f75474a850df211acc14fa9eae34c53c1bff1d311be330ade5a555ee0", - "failure_summary": "4 failed, 14 deselected in 13.50s" - }, "restoration": { "reverted": true, "isolated_source_restored": true, - "restored_test_exit_code": 0, - "isolated_source_sha256": "c5885aa63592f76e50867daa454bb9aee3f16a30abacbf3f3c487a27443aad6d", - "restored_log": "scratch/review/round2_savings_ignore_current_own_benefit_on_carried_floor-restored.log", - "restored_log_sha256": "6e082ef7797e0df3a9d26ec51f623546720d30a1b9cba581735579b3881b215b", - "restored_test_summary": "4 passed, 14 deselected in 22.11s" - } + "isolated_source_sha256": "4c1f5803b6b0dfd06e7c8f075248a5a49bbc932a4b8161499880f116b951b80f", + "restored_test_exit_code": 0 + }, + "evidence_run": "Fresh completed continuation replay; isolated sources, exact byte restoration and restored tests." }, { - "id": "round2_savings_ignore_current_own_benefit_at_trigger", + "id": "audit2_savings_ignore_current_own_at_trigger", "layer": "g_savings", "source": "src/populace_dynamics/track_b/gross_benefits.py", "change": { - "before": " or _savings_has_own_benefits(result)\n", - "after": " or False\n" + "before": "\n or _savings_has_own_benefits(result)\n", + "after": "\n or False\n" + }, + "mutated": { + "label": "audit2_savings_ignore_current_own_at_trigger", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-c", + "from populace_dynamics.track_b import gross_benefits as g; assert g.__file__.startswith('/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/mutated/src'), g.__file__; import pytest, sys; sys.exit(pytest.main(sys.argv[1:]))", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py", + "-k", + "current_own_benefit_refuses_before_setting_protection", + "--tb=short" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/mutated/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/nonexistent", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/hypothesis" + }, + "exit_code": 1, + "wall_seconds": 6.040834375016857, + "summary": "2 failed, 16 deselected in 1.82s", + "log": "scratch/review/savings-audit/audit2_savings_ignore_current_own_at_trigger.log", + "log_sha256": "899fe18dc57099379f54c0967c72a0b3566da680505e93d23e6f191aeba5feda", + "failed_tests": [ + "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_current_own_benefit_refuses_before_setting_protection[Role.SPOUSE]", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_current_own_benefit_refuses_before_setting_protection[Role.CHILD]" + ] }, - "command": [ - "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", - "-c", - "from populace_dynamics.track_b import gross_benefits as g; assert 'savings-mutation-tree/src' in g.__file__, g.__file__; import pytest,sys; sys.exit(pytest.main(sys.argv[1:]))", - "-p", - "no:xdist", - "-p", - "no:cacheprovider", - "-q", - "tests/test_track_b_gross_benefits_savings_fix_round_2.py", - "-k", - "current_own_benefit_refuses_before_setting" - ], - "environment": { - "PYTHONDONTWRITEBYTECODE": "1", - "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/savings-mutation-tree/src:/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2", - "OMP_NUM_THREADS": "1", - "OMP_WAIT_POLICY": "PASSIVE", - "POLARS_MAX_THREADS": "1", - "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", - "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/nonexistent", - "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-031318-trackb-fix-g2-2/scratch/review/hypothesis-savings-mutation" + "restored": { + "label": "audit2_savings_ignore_current_own_at_trigger-restored", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-c", + "from populace_dynamics.track_b import gross_benefits as g; assert g.__file__.startswith('/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/mutated/src'), g.__file__; import pytest, sys; sys.exit(pytest.main(sys.argv[1:]))", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py", + "-k", + "current_own_benefit_refuses_before_setting_protection", + "--tb=short" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/mutated/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/nonexistent", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/savings-audit/hypothesis" + }, + "exit_code": 0, + "wall_seconds": 6.140525541995885, + "summary": "2 passed, 16 deselected in 2.91s", + "log": "scratch/review/savings-audit/audit2_savings_ignore_current_own_at_trigger-restored.log", + "log_sha256": "b1f244a95ae1c741f5a21d47f76123438083bb78139d815eeb8e5f617f3654a7", + "failed_tests": [] }, "mutated_exit_code": 1, "failed_tests": [ "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_current_own_benefit_refuses_before_setting_protection[Role.SPOUSE]", "tests/test_track_b_gross_benefits_savings_fix_round_2.py::test_current_own_benefit_refuses_before_setting_protection[Role.CHILD]" ], - "log": { - "path": "scratch/review/round2_savings_ignore_current_own_benefit_at_trigger.log", - "sha256": "bb7b92f25f39815bbaf21e0edd073a73d73777195ccfc43e951e6dcd2a0ac1d0", - "failure_summary": "2 failed, 16 deselected in 18.00s" - }, "restoration": { "reverted": true, "isolated_source_restored": true, - "restored_test_exit_code": 0, - "isolated_source_sha256": "c5885aa63592f76e50867daa454bb9aee3f16a30abacbf3f3c487a27443aad6d", - "restored_log": "scratch/review/round2_savings_ignore_current_own_benefit_at_trigger-restored.log", - "restored_log_sha256": "77e10f90c4b2ae97c372f4f6b02ae7fffdd2ba526591f813fb4f53ff98c9f310", - "restored_test_summary": "2 passed, 16 deselected in 20.72s" - } + "isolated_source_sha256": "4c1f5803b6b0dfd06e7c8f075248a5a49bbc932a4b8161499880f116b951b80f", + "restored_test_exit_code": 0 + }, + "evidence_run": "Fresh completed continuation replay; isolated sources, exact byte restoration and restored tests." } ], "restoration_verification_snapshot": { @@ -1161,9 +1955,17 @@ }, "restoration_snapshot_note": "These hashes identify the source state checked when mutations were consolidated. Subsequent reviewed fixes are separately hashed in the final verification artifact; mutation rules remain restored.", "round_2_head": "0ccf66ff63874167ffff0eca34b15c5eca57b3ad", - "round_2_note": "Eleven new isolated one-line mutations caught and restored; no production mutation was retained. Exact commands, environments, failing names and restored counts are in each new record.", + "round_2_note": "Fifteen fresh isolated one-line mutations caught and restored; prior 13 records are explicitly historical. Exact commands, environments, failing names and restored counts accompany each fresh record. Production sources were never mutated.", "round_2_restoration_snapshot": { - "src/populace_dynamics/track_b/gross_benefits.py": "43ac51f6dc0a38c08f858521d8e2074d2466a87efaac3e0462db5d81404e7a86", + "src/populace_dynamics/track_b/gross_benefits.py": "4c1f5803b6b0dfd06e7c8f075248a5a49bbc932a4b8161499880f116b951b80f", "src/populace_dynamics/track_b/ret_ledger.py": "0e3f19edfbe36571718fac2559972132db3ac8efbd282262ffbfc28dc366c64d" + }, + "continuation_audit": { + "baseline_head": "0ccf66ff63874167ffff0eca34b15c5eca57b3ad", + "head": "3e4d20d21f1634218595ee4570b08a7acd2bbdbd", + "fresh_caught_and_restored": 15, + "inherited_pre_round_2": 13, + "replaced_attempt_1_records": 11, + "note": "All round-2 claims were independently rerun in deduction-audit, r2-audit and savings-audit. Earlier historical records remain distinct. No production mutation was retained." } } diff --git a/docs/design/track_b_g2_r2b_verification.json b/docs/design/track_b_g2_r2b_verification.json index 0aeecd4f4..10934edac 100644 --- a/docs/design/track_b_g2_r2b_verification.json +++ b/docs/design/track_b_g2_r2b_verification.json @@ -1346,5 +1346,2585 @@ "The broad G remainder run passed 6612 tests and failed two explicit audit inventories imported before their updates. Both entire affected inventory files passed after the updates. Counts in separate runs overlap and must not be summed as unique coverage.", "Four concurrent final tier collection attempts were interrupted to reduce contention and rerun sequentially. No full-suite execution was performed.", "The requested absolute non-deductee monotonicity invariant conflicts with the captured single-full-deduction exception. The executed minimized counterexample and qualified invariant are recorded in the design and report; the existing property has no collection-count change." - ] + ], + "historical_verification_note": "Original verification fields are historical. This continuation independently reran all required checks; current evidence is in round_2_continuation.", + "round_2_continuation": { + "verification_class": "statutory_conformance", + "scope": "Invented cases and captured examples only; no population, behavioral or forecast claim.", + "head": "3e4d20d21f1634218595ee4570b08a7acd2bbdbd", + "baseline": "0ccf66ff63874167ffff0eca34b15c5eca57b3ad", + "report": "scratch/review/fix-round-2-report.md", + "source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "4c1f5803b6b0dfd06e7c8f075248a5a49bbc932a4b8161499880f116b951b80f", + "src/populace_dynamics/track_b/ret_ledger.py": "0e3f19edfbe36571718fac2559972132db3ac8efbd282262ffbfc28dc366c64d" + }, + "required_tests": { + "completed_broad_run": { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits.py", + "tests/test_track_b_gross_benefits_conformance_report.py", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py", + "tests/test_track_b_gross_benefits_deductions.py", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", + "tests/test_track_b_gross_benefits_dwb.py", + "tests/test_track_b_gross_benefits_fix_round_1.py", + "tests/test_track_b_gross_benefits_fix_round_10_api.py", + "tests/test_track_b_gross_benefits_fix_round_10_helpers.py", + "tests/test_track_b_gross_benefits_fix_round_10_objects.py", + "tests/test_track_b_gross_benefits_fix_round_10_parameters.py", + "tests/test_track_b_gross_benefits_fix_round_11_roles.py", + "tests/test_track_b_gross_benefits_fix_round_11_seals.py", + "tests/test_track_b_gross_benefits_fix_round_12_contract.py", + "tests/test_track_b_gross_benefits_fix_round_13_audit.py", + "tests/test_track_b_gross_benefits_fix_round_13_boundary.py", + "tests/test_track_b_gross_benefits_fix_round_13_guard.py", + "tests/test_track_b_gross_benefits_fix_round_15_arguments.py", + "tests/test_track_b_gross_benefits_fix_round_15_collections.py", + "tests/test_track_b_gross_benefits_fix_round_15_receivers.py", + "tests/test_track_b_gross_benefits_fix_round_2_care.py", + "tests/test_track_b_gross_benefits_fix_round_2_history.py", + "tests/test_track_b_gross_benefits_fix_round_2_periods.py", + "tests/test_track_b_gross_benefits_fix_round_3_rates.py", + "tests/test_track_b_gross_benefits_fix_round_4_care_floor.py", + "tests/test_track_b_gross_benefits_fix_round_4_divorced_care.py", + "tests/test_track_b_gross_benefits_fix_round_5_care_history.py", + "tests/test_track_b_gross_benefits_fix_round_5_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_6_care_note.py", + "tests/test_track_b_gross_benefits_fix_round_6_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_boundary.py", + "tests/test_track_b_gross_benefits_fix_round_7_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_history.py", + "tests/test_track_b_gross_benefits_fix_round_8_entries.py", + "tests/test_track_b_gross_benefits_fix_round_8_history.py", + "tests/test_track_b_gross_benefits_fix_round_9_citations.py", + "tests/test_track_b_gross_benefits_fix_round_9_outcomes.py", + "tests/test_track_b_gross_benefits_fix_round_9_validation.py", + "tests/test_track_b_gross_benefits_oracle.py", + "tests/test_track_b_gross_benefits_own_input_order.py", + "tests/test_track_b_gross_benefits_parents_ieds.py", + "tests/test_track_b_gross_benefits_parisi.py", + "tests/test_track_b_gross_benefits_payment_review.py", + "tests/test_track_b_gross_benefits_properties.py", + "tests/test_track_b_gross_benefits_registry.py", + "tests/test_track_b_gross_benefits_review.py", + "tests/test_track_b_gross_benefits_savings.py", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py", + "tests/test_track_b_gross_benefits_sources_20261011.py", + "tests/test_track_b_gross_benefits_ssfa.py", + "tests/test_track_b_refusal_notes.py", + "tests/test_track_b_input_schema.py", + "tests/test_track_b_ret_differential.py", + "tests/test_track_b_ret_grace.py", + "tests/test_track_b_ret_grace_differential.py", + "tests/test_track_b_ret_grace_provenance.py", + "tests/test_track_b_ret_ledger.py", + "tests/test_track_b_ret_ledger_deductions.py", + "tests/test_track_b_ret_ledger_fix_round_2.py", + "tests/test_track_b_ret_ledger_properties.py", + "tests/test_track_b_ret_ledger_readings.py", + "tests/test_track_b_ret_ledger_sources.py", + "tests/test_track_b_ret_params.py", + "tests/test_track_b_arf.py", + "tests/test_track_b_arf_properties.py", + "tests/test_track_b_recompute.py", + "tests/test_track_b_recompute_properties.py", + "tests/test_track_b_r3_fix_round_13.py", + "tests/test_track_b_r3_provenance.py", + "tests/test_track_b_r3_sources.py", + "tests/test_track_b_r3_validation_once.py" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/hypothesis", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/nonexistent", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/nonexistent" + }, + "returncode": 1, + "wall_seconds": 965.3794684589957, + "cpu_seconds": 476.83042700000004, + "log": "scratch/review/root-audit/required.log" + }, + "corrected_file_run": { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_registry.py" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/hypothesis", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/nonexistent", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/nonexistent" + }, + "returncode": 0, + "wall_seconds": 11.665603417000966, + "cpu_seconds": 3.0712900000000003, + "log": "scratch/review/root-audit/registry-final.log" + }, + "initial_failed_nodes": [ + "FAILED tests/test_track_b_gross_benefits_registry.py::test_registered_statutory_example_reproduces_every_figure[rs-02501-130-no-child-in-care]", + "FAILED tests/test_track_b_gross_benefits_registry.py::test_registered_maximum_tags_match_computed_scenarios[rs-02501-130-no-child-in-care]", + "FAILED tests/test_track_b_gross_benefits_registry.py::test_registry_is_deterministic_and_scenario_order_independent" + ], + "outcome": "Every required file covered; three initial registry failures repaired and the complete file rerun passes. Later property edits pass their full focused files. Duplicate broad rerun interrupted and uncounted." + }, + "focused": { + "registry-final": { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_registry.py" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/hypothesis", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/nonexistent", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/nonexistent" + }, + "returncode": 0, + "wall_seconds": 11.665603417000966, + "cpu_seconds": 3.0712900000000003, + "log": "scratch/review/root-audit/registry-final.log" + }, + "deduction-final": { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_deductions.py", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/hypothesis", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/nonexistent", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/nonexistent" + }, + "returncode": 0, + "wall_seconds": 12.532072292000521, + "cpu_seconds": 3.336023, + "log": "scratch/review/root-audit/deduction-final.log" + }, + "birth-evidence": { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/estimates/test_birth_evidence_artifact.py", + "-k", + "not test_artifact_rebuild_reproduces" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/hypothesis", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/nonexistent", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/nonexistent" + }, + "returncode": 0, + "wall_seconds": 159.7513649169996, + "cpu_seconds": 4.5973489999999995, + "log": "scratch/review/root-audit/birth-evidence.log" + }, + "importers": { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/bridge/test_pe_us_depletion_cut_g_compatibility.py", + "tests/ss/test_delayed_credit_statute.py" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/hypothesis", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/nonexistent", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/nonexistent" + }, + "returncode": 0, + "wall_seconds": 159.91085775001557, + "cpu_seconds": 14.416427, + "log": "scratch/review/root-audit/importers.log" + } + }, + "tiers": { + "counts": { + "unit": 19068, + "artifact": 4271, + "integration_psid": 1471, + "reproduction_legacy": 520, + "oracle_policyengine": 308 + }, + "runs": { + "tier-integration_psid": { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "--collect-only", + "-q", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-m", + "integration_psid" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/hypothesis", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/nonexistent", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/nonexistent" + }, + "returncode": 0, + "wall_seconds": 828.326343208988, + "cpu_seconds": 47.437863, + "log": "scratch/review/root-audit/tier-integration_psid.log" + }, + "tier-unit": { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "--collect-only", + "-q", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-m", + "unit" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/hypothesis", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/nonexistent", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/nonexistent" + }, + "returncode": 0, + "wall_seconds": 213.27609541700804, + "cpu_seconds": 43.706652999999996, + "log": "scratch/review/root-audit/tier-unit.log" + }, + "tier-reproduction_legacy": { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "--collect-only", + "-q", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-m", + "reproduction_legacy" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/hypothesis", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/nonexistent", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/nonexistent" + }, + "returncode": 0, + "wall_seconds": 759.0652046659961, + "cpu_seconds": 46.988037, + "log": "scratch/review/root-audit/tier-reproduction_legacy.log" + }, + "tier-oracle_policyengine": { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "--collect-only", + "-q", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-m", + "oracle_policyengine" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/hypothesis", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/nonexistent", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/nonexistent" + }, + "returncode": 0, + "wall_seconds": 515.3335319999896, + "cpu_seconds": 37.198918, + "log": "scratch/review/root-audit/tier-oracle_policyengine.log" + }, + "tier-policy": { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "tests", + "-k", + "test__given_collected_suite__then_tiers_match_policy_manifest" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/hypothesis", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/nonexistent", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/nonexistent" + }, + "returncode": 0, + "wall_seconds": 544.5926139169896, + "cpu_seconds": 34.347882, + "log": "scratch/review/root-audit/tier-policy.log" + }, + "tier-artifact": { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "--collect-only", + "-q", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-m", + "artifact" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "PYTHONDONTWRITEBYTECODE": "1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/hypothesis", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/nonexistent", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/root-audit/nonexistent" + }, + "returncode": 0, + "wall_seconds": 227.08068395900773, + "cpu_seconds": 45.656716, + "log": "scratch/review/root-audit/tier-artifact.log" + } + } + }, + "fresh_mutations": 15, + "historical_mutations": 13, + "verification": { + "verification_class": "statutory conformance", + "scope": "Invented cases and captured public statutory examples only; no population, behavioral or forecast claim.", + "baseline_ref": "0ccf66ff63874167ffff0eca34b15c5eca57b3ad", + "master_ref": "1ec57a5dbccea4c9910ed8169aeb0d5daeb05e5d", + "method": "Each baseline ran immediately before its current counterpart. CPU is child-process user plus system time from resource.getrusage(RUSAGE_CHILDREN), excluding archive preparation. The six R2 files share identical seed 5632026. One observation per head; host load and thermal state are uncontrolled, so these observations are costs, not speed claims.", + "measurements": { + "cpu-g-baseline": { + "label": "cpu-g-baseline", + "cwd": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/verification/baseline-0ccf66ff", + "command": "env PYTHONDONTWRITEBYTECODE=1 HYPOTHESIS_STORAGE_DIRECTORY=/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/verification/hypothesis PYTHONPATH=/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/verification/baseline-0ccf66ff/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/verification/baseline-0ccf66ff OMP_NUM_THREADS=1 POLARS_MAX_THREADS=1 OMP_WAIT_POLICY=PASSIVE POPULACE_DYNAMICS_PSID_DIR=/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/verification/nonexistent POPULACE_DYNAMICS_EPUF_DIR=/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/verification/nonexistent /Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python scripts/track_b_g_conformance_report.py --output /Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/verification/cpu-g-baseline-conformance.json", + "exit_code": 0, + "wall_seconds": 453.59619008298614, + "cpu_user_seconds": 156.357641, + "cpu_system_seconds": 4.1211839999999995, + "cpu_seconds": 160.478825, + "artifact_sha256": "ee8ef3247a700b4cec92dfc27bbb98b071deaba5566b092cb9c3df4f762be972", + "committed_sha256": "ee8ef3247a700b4cec92dfc27bbb98b071deaba5566b092cb9c3df4f762be972", + "byte_identical_to_tree": true + }, + "cpu-g-current": { + "label": "cpu-g-current", + "cwd": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "command": "env PYTHONDONTWRITEBYTECODE=1 HYPOTHESIS_STORAGE_DIRECTORY=/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/verification/hypothesis PYTHONPATH=/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b OMP_NUM_THREADS=1 POLARS_MAX_THREADS=1 OMP_WAIT_POLICY=PASSIVE POPULACE_DYNAMICS_PSID_DIR=/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/verification/nonexistent POPULACE_DYNAMICS_EPUF_DIR=/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/verification/nonexistent /Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python scripts/track_b_g_conformance_report.py --output /Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/verification/cpu-g-current-conformance.json", + "exit_code": 0, + "wall_seconds": 227.39955737499986, + "cpu_user_seconds": 136.64242299999998, + "cpu_system_seconds": 4.843366, + "cpu_seconds": 141.48578899999998, + "artifact_sha256": "ee8ef3247a700b4cec92dfc27bbb98b071deaba5566b092cb9c3df4f762be972", + "committed_sha256": "ee8ef3247a700b4cec92dfc27bbb98b071deaba5566b092cb9c3df4f762be972", + "byte_identical_to_tree": true + }, + "cpu-r2-baseline": { + "label": "cpu-r2-baseline", + "cwd": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/verification/baseline-0ccf66ff", + "command": "env PYTHONDONTWRITEBYTECODE=1 HYPOTHESIS_STORAGE_DIRECTORY=/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/verification/hypothesis PYTHONPATH=/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/verification/baseline-0ccf66ff/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/verification/baseline-0ccf66ff OMP_NUM_THREADS=1 POLARS_MAX_THREADS=1 OMP_WAIT_POLICY=PASSIVE POPULACE_DYNAMICS_PSID_DIR=/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/verification/nonexistent POPULACE_DYNAMICS_EPUF_DIR=/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/verification/nonexistent /Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python -m pytest -p no:xdist -p no:cacheprovider -q --hypothesis-seed=5632026 tests/test_track_b_ret_ledger.py tests/test_track_b_ret_ledger_sources.py tests/test_track_b_ret_ledger_properties.py tests/test_track_b_ret_ledger_readings.py tests/test_track_b_ret_ledger_deductions.py tests/test_track_b_ret_differential.py", + "exit_code": 0, + "wall_seconds": 284.3519893749908, + "cpu_user_seconds": 82.559193, + "cpu_system_seconds": 2.177826, + "cpu_seconds": 84.73701899999999 + }, + "cpu-r2-current": { + "label": "cpu-r2-current", + "cwd": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "command": "env PYTHONDONTWRITEBYTECODE=1 HYPOTHESIS_STORAGE_DIRECTORY=/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/verification/hypothesis PYTHONPATH=/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b OMP_NUM_THREADS=1 POLARS_MAX_THREADS=1 OMP_WAIT_POLICY=PASSIVE POPULACE_DYNAMICS_PSID_DIR=/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/verification/nonexistent POPULACE_DYNAMICS_EPUF_DIR=/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/verification/nonexistent /Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python -m pytest -p no:xdist -p no:cacheprovider -q --hypothesis-seed=5632026 tests/test_track_b_ret_ledger.py tests/test_track_b_ret_ledger_sources.py tests/test_track_b_ret_ledger_properties.py tests/test_track_b_ret_ledger_readings.py tests/test_track_b_ret_ledger_deductions.py tests/test_track_b_ret_differential.py", + "exit_code": 0, + "wall_seconds": 295.4095112089999, + "cpu_user_seconds": 89.43285800000001, + "cpu_system_seconds": 2.7008240000000003, + "cpu_seconds": 92.13368200000001 + }, + "cross-head": { + "label": "cross-head", + "cwd": "/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b", + "command": "env PYTHONDONTWRITEBYTECODE=1 HYPOTHESIS_STORAGE_DIRECTORY=/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/verification/hypothesis PYTHONPATH=/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/src:/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b OMP_NUM_THREADS=1 POLARS_MAX_THREADS=1 OMP_WAIT_POLICY=PASSIVE POPULACE_DYNAMICS_PSID_DIR=/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/verification/nonexistent POPULACE_DYNAMICS_EPUF_DIR=/Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/verification/nonexistent /Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python scripts/track_b_r2_cross_head.py --baseline-root /Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/verification/master-1ec57a5d --output /Users/maxghenis/.subfleet/worktrees/20261025-105211-trackb-fix-g2-2b/scratch/review/verification/cross-head-report.json", + "exit_code": 0, + "wall_seconds": 18.64534058299614, + "cpu_user_seconds": 7.444468, + "cpu_system_seconds": 0.31338099999999997, + "cpu_seconds": 7.757848999999999 + } + }, + "g_conformance": { + "all_regenerated_and_committed_bytes_identical": true, + "sha256": "ee8ef3247a700b4cec92dfc27bbb98b071deaba5566b092cb9c3df4f762be972", + "changed_rows": 0, + "lattice_denominator": { + "invalid": 286794, + "refused": 60775, + "rows": 356400, + "supported": 8831 + }, + "deduction_denominator": { + "invalid": 0, + "refused": 0, + "rows": 16, + "supported": 16 + }, + "supplemental_denominator": { + "invalid": 0, + "refused": 37, + "rows": 37, + "supported": 0 + } + }, + "cross_head": { + "verification_class": "statutory conformance", + "scope": "invented cases only; no population, behavioral or forecast claim", + "seed": 53014, + "r2_stable_rows": 240, + "r3_stable_rows": 240, + "identical_declared_output_bytes": true, + "stable_sha256": "799fc9e23a902ac1ca0c2563579ceb094d0dbcd631a912305c40062cf21a5f55", + "transitions": { + "baseline": { + "rows": 6, + "supported": 0, + "refused_by_reason": { + "deduction_before_reduction_part_b": 6 + } + }, + "head": { + "rows": 6, + "supported": 6, + "refused_by_reason": {} + } + }, + "transition_rows": [ + { + "id": "binding_survivor_own_excess_1", + "own_excess": 1, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_60", + "own_excess": 60, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_99", + "own_excess": 99, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_100", + "own_excess": 100, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_555", + "own_excess": 555, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_1188", + "own_excess": 1188, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + } + ] + }, + "g_cpu_difference_seconds": -18.993036000000018, + "g_cpu_difference_percent": -11.835228728774661, + "r2_cpu_difference_seconds": 7.396663000000018, + "r2_cpu_difference_percent": 8.728962957736353 + }, + "mechanics": { + "started_at_utc": "2026-10-25T19:45:50.256595+00:00", + "committed_paths_command": "git diff --name-only origin/master...HEAD (captured by root in scratch/review/root-audit/committed-paths.txt)", + "working_paths_command": "git -c core.fsmonitor=false diff --name-only", + "untracked_paths_command": "git -c core.fsmonitor=false ls-files --others --exclude-standard", + "committed_paths": [ + "docs/design/track_b_g2_r2b_mutations.json", + "docs/design/track_b_g2_r2b_verification.json", + "docs/design/track_b_g_conformance_report.json", + "docs/design/track_b_g_gross_benefits.md", + "docs/design/track_b_r2_ret_ledger.md", + "scripts/track_b_g_conformance_report.py", + "scripts/track_b_r2_cross_head.py", + "src/populace_dynamics/track_b/_provenance.py", + "src/populace_dynamics/track_b/gross_benefits.py", + "src/populace_dynamics/track_b/ret_ledger.py", + "tests/README-tiers.md", + "tests/data/track_b/gross_benefit_examples.yaml", + "tests/data/track_b/gross_benefit_sources/README.md", + "tests/data/track_b/gross_benefit_sources/manifest.json", + "tests/test_track_b_gross_benefits.py", + "tests/test_track_b_gross_benefits_conformance_report.py", + "tests/test_track_b_gross_benefits_deductions.py", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", + "tests/test_track_b_gross_benefits_fix_round_10_api.py", + "tests/test_track_b_gross_benefits_fix_round_10_helpers.py", + "tests/test_track_b_gross_benefits_fix_round_10_objects.py", + "tests/test_track_b_gross_benefits_fix_round_10_parameters.py", + "tests/test_track_b_gross_benefits_fix_round_11_seals.py", + "tests/test_track_b_gross_benefits_fix_round_12_contract.py", + "tests/test_track_b_gross_benefits_fix_round_13_audit.py", + "tests/test_track_b_gross_benefits_fix_round_13_guard.py", + "tests/test_track_b_gross_benefits_fix_round_15_receivers.py", + "tests/test_track_b_gross_benefits_fix_round_3_rates.py", + "tests/test_track_b_gross_benefits_fix_round_5_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_6_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_history.py", + "tests/test_track_b_gross_benefits_fix_round_8_entries.py", + "tests/test_track_b_gross_benefits_fix_round_8_history.py", + "tests/test_track_b_gross_benefits_fix_round_9_outcomes.py", + "tests/test_track_b_gross_benefits_fix_round_9_validation.py", + "tests/test_track_b_gross_benefits_properties.py", + "tests/test_track_b_gross_benefits_registry.py", + "tests/test_track_b_gross_benefits_review.py", + "tests/test_track_b_gross_benefits_savings.py", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py", + "tests/test_track_b_gross_benefits_sources_20261011.py", + "tests/test_track_b_input_schema.py", + "tests/test_track_b_r3_fix_round_13.py", + "tests/test_track_b_refusal_notes.py", + "tests/test_track_b_ret_ledger.py", + "tests/test_track_b_ret_ledger_deductions.py", + "tests/test_track_b_ret_ledger_fix_round_2.py", + "tests/test_track_b_ret_ledger_sources.py", + "tests/tier_counts.json", + "tests/track_b_gross_benefit_support.py" + ], + "working_paths": [ + "docs/design/track_b_g2_r2b_mutations.json", + "docs/design/track_b_g_gross_benefits.md", + "docs/design/track_b_r2_ret_ledger.md", + "src/populace_dynamics/track_b/gross_benefits.py", + "tests/data/track_b/gross_benefit_examples.yaml", + "tests/test_track_b_gross_benefits_deductions.py", + "tests/test_track_b_gross_benefits_fix_round_10_api.py", + "tests/test_track_b_gross_benefits_registry.py", + "tests/test_track_b_ret_ledger_fix_round_2.py" + ], + "untracked_paths": [ + "tests/test_track_b_gross_benefits_deduction_age_inputs.py" + ], + "changed_python_count": 42, + "changed_python_files": [ + "scripts/track_b_g_conformance_report.py", + "scripts/track_b_r2_cross_head.py", + "src/populace_dynamics/track_b/_provenance.py", + "src/populace_dynamics/track_b/gross_benefits.py", + "src/populace_dynamics/track_b/ret_ledger.py", + "tests/test_track_b_gross_benefits.py", + "tests/test_track_b_gross_benefits_conformance_report.py", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py", + "tests/test_track_b_gross_benefits_deductions.py", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", + "tests/test_track_b_gross_benefits_fix_round_10_api.py", + "tests/test_track_b_gross_benefits_fix_round_10_helpers.py", + "tests/test_track_b_gross_benefits_fix_round_10_objects.py", + "tests/test_track_b_gross_benefits_fix_round_10_parameters.py", + "tests/test_track_b_gross_benefits_fix_round_11_seals.py", + "tests/test_track_b_gross_benefits_fix_round_12_contract.py", + "tests/test_track_b_gross_benefits_fix_round_13_audit.py", + "tests/test_track_b_gross_benefits_fix_round_13_guard.py", + "tests/test_track_b_gross_benefits_fix_round_15_receivers.py", + "tests/test_track_b_gross_benefits_fix_round_3_rates.py", + "tests/test_track_b_gross_benefits_fix_round_5_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_6_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_history.py", + "tests/test_track_b_gross_benefits_fix_round_8_entries.py", + "tests/test_track_b_gross_benefits_fix_round_8_history.py", + "tests/test_track_b_gross_benefits_fix_round_9_outcomes.py", + "tests/test_track_b_gross_benefits_fix_round_9_validation.py", + "tests/test_track_b_gross_benefits_properties.py", + "tests/test_track_b_gross_benefits_registry.py", + "tests/test_track_b_gross_benefits_review.py", + "tests/test_track_b_gross_benefits_savings.py", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py", + "tests/test_track_b_gross_benefits_sources_20261011.py", + "tests/test_track_b_input_schema.py", + "tests/test_track_b_r3_fix_round_13.py", + "tests/test_track_b_refusal_notes.py", + "tests/test_track_b_ret_ledger.py", + "tests/test_track_b_ret_ledger_deductions.py", + "tests/test_track_b_ret_ledger_fix_round_2.py", + "tests/test_track_b_ret_ledger_sources.py", + "tests/track_b_gross_benefit_support.py" + ], + "commands": [ + { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "black", + "-l", + "79", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py" + ], + "exit_code": 0, + "output": "All done! \u2728 \ud83c\udf70 \u2728\n1 file left unchanged.\n" + }, + { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "black", + "-l", + "79", + "--check", + "scripts/track_b_g_conformance_report.py", + "scripts/track_b_r2_cross_head.py", + "src/populace_dynamics/track_b/_provenance.py", + "src/populace_dynamics/track_b/gross_benefits.py", + "src/populace_dynamics/track_b/ret_ledger.py", + "tests/test_track_b_gross_benefits.py", + "tests/test_track_b_gross_benefits_conformance_report.py", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py", + "tests/test_track_b_gross_benefits_deductions.py", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", + "tests/test_track_b_gross_benefits_fix_round_10_api.py", + "tests/test_track_b_gross_benefits_fix_round_10_helpers.py", + "tests/test_track_b_gross_benefits_fix_round_10_objects.py", + "tests/test_track_b_gross_benefits_fix_round_10_parameters.py", + "tests/test_track_b_gross_benefits_fix_round_11_seals.py", + "tests/test_track_b_gross_benefits_fix_round_12_contract.py", + "tests/test_track_b_gross_benefits_fix_round_13_audit.py", + "tests/test_track_b_gross_benefits_fix_round_13_guard.py", + "tests/test_track_b_gross_benefits_fix_round_15_receivers.py", + "tests/test_track_b_gross_benefits_fix_round_3_rates.py", + "tests/test_track_b_gross_benefits_fix_round_5_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_6_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_history.py", + "tests/test_track_b_gross_benefits_fix_round_8_entries.py", + "tests/test_track_b_gross_benefits_fix_round_8_history.py", + "tests/test_track_b_gross_benefits_fix_round_9_outcomes.py", + "tests/test_track_b_gross_benefits_fix_round_9_validation.py", + "tests/test_track_b_gross_benefits_properties.py", + "tests/test_track_b_gross_benefits_registry.py", + "tests/test_track_b_gross_benefits_review.py", + "tests/test_track_b_gross_benefits_savings.py", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py", + "tests/test_track_b_gross_benefits_sources_20261011.py", + "tests/test_track_b_input_schema.py", + "tests/test_track_b_r3_fix_round_13.py", + "tests/test_track_b_refusal_notes.py", + "tests/test_track_b_ret_ledger.py", + "tests/test_track_b_ret_ledger_deductions.py", + "tests/test_track_b_ret_ledger_fix_round_2.py", + "tests/test_track_b_ret_ledger_sources.py", + "tests/track_b_gross_benefit_support.py" + ], + "exit_code": 0, + "output": "All done! \u2728 \ud83c\udf70 \u2728\n42 files would be left unchanged.\n" + }, + { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "ruff", + "check", + "--no-cache", + "scripts/track_b_g_conformance_report.py", + "scripts/track_b_r2_cross_head.py", + "src/populace_dynamics/track_b/_provenance.py", + "src/populace_dynamics/track_b/gross_benefits.py", + "src/populace_dynamics/track_b/ret_ledger.py", + "tests/test_track_b_gross_benefits.py", + "tests/test_track_b_gross_benefits_conformance_report.py", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py", + "tests/test_track_b_gross_benefits_deductions.py", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", + "tests/test_track_b_gross_benefits_fix_round_10_api.py", + "tests/test_track_b_gross_benefits_fix_round_10_helpers.py", + "tests/test_track_b_gross_benefits_fix_round_10_objects.py", + "tests/test_track_b_gross_benefits_fix_round_10_parameters.py", + "tests/test_track_b_gross_benefits_fix_round_11_seals.py", + "tests/test_track_b_gross_benefits_fix_round_12_contract.py", + "tests/test_track_b_gross_benefits_fix_round_13_audit.py", + "tests/test_track_b_gross_benefits_fix_round_13_guard.py", + "tests/test_track_b_gross_benefits_fix_round_15_receivers.py", + "tests/test_track_b_gross_benefits_fix_round_3_rates.py", + "tests/test_track_b_gross_benefits_fix_round_5_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_6_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_history.py", + "tests/test_track_b_gross_benefits_fix_round_8_entries.py", + "tests/test_track_b_gross_benefits_fix_round_8_history.py", + "tests/test_track_b_gross_benefits_fix_round_9_outcomes.py", + "tests/test_track_b_gross_benefits_fix_round_9_validation.py", + "tests/test_track_b_gross_benefits_properties.py", + "tests/test_track_b_gross_benefits_registry.py", + "tests/test_track_b_gross_benefits_review.py", + "tests/test_track_b_gross_benefits_savings.py", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py", + "tests/test_track_b_gross_benefits_sources_20261011.py", + "tests/test_track_b_input_schema.py", + "tests/test_track_b_r3_fix_round_13.py", + "tests/test_track_b_refusal_notes.py", + "tests/test_track_b_ret_ledger.py", + "tests/test_track_b_ret_ledger_deductions.py", + "tests/test_track_b_ret_ledger_fix_round_2.py", + "tests/test_track_b_ret_ledger_sources.py", + "tests/track_b_gross_benefit_support.py" + ], + "exit_code": 0, + "output": "All checks passed!\n" + }, + { + "command": [ + "git", + "-c", + "core.fsmonitor=false", + "status", + "--short", + "--untracked-files=all" + ], + "exit_code": 0, + "output": " M docs/design/track_b_g2_r2b_mutations.json\n M docs/design/track_b_g_gross_benefits.md\n M docs/design/track_b_r2_ret_ledger.md\n M src/populace_dynamics/track_b/gross_benefits.py\n M tests/data/track_b/gross_benefit_examples.yaml\n M tests/test_track_b_gross_benefits_deductions.py\n M tests/test_track_b_gross_benefits_fix_round_10_api.py\n M tests/test_track_b_gross_benefits_registry.py\n M tests/test_track_b_ret_ledger_fix_round_2.py\n?? tests/test_track_b_gross_benefits_deduction_age_inputs.py\n" + }, + { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "black", + "--workers", + "1", + "-l", + "79", + "--check", + "scripts/track_b_g_conformance_report.py", + "scripts/track_b_r2_cross_head.py", + "src/populace_dynamics/track_b/_provenance.py", + "src/populace_dynamics/track_b/gross_benefits.py", + "src/populace_dynamics/track_b/ret_ledger.py", + "tests/test_track_b_gross_benefits.py", + "tests/test_track_b_gross_benefits_conformance_report.py", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py", + "tests/test_track_b_gross_benefits_deductions.py", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", + "tests/test_track_b_gross_benefits_fix_round_10_api.py", + "tests/test_track_b_gross_benefits_fix_round_10_helpers.py", + "tests/test_track_b_gross_benefits_fix_round_10_objects.py", + "tests/test_track_b_gross_benefits_fix_round_10_parameters.py", + "tests/test_track_b_gross_benefits_fix_round_11_seals.py", + "tests/test_track_b_gross_benefits_fix_round_12_contract.py", + "tests/test_track_b_gross_benefits_fix_round_13_audit.py", + "tests/test_track_b_gross_benefits_fix_round_13_guard.py", + "tests/test_track_b_gross_benefits_fix_round_15_receivers.py", + "tests/test_track_b_gross_benefits_fix_round_3_rates.py", + "tests/test_track_b_gross_benefits_fix_round_5_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_6_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_history.py", + "tests/test_track_b_gross_benefits_fix_round_8_entries.py", + "tests/test_track_b_gross_benefits_fix_round_8_history.py", + "tests/test_track_b_gross_benefits_fix_round_9_outcomes.py", + "tests/test_track_b_gross_benefits_fix_round_9_validation.py", + "tests/test_track_b_gross_benefits_properties.py", + "tests/test_track_b_gross_benefits_registry.py", + "tests/test_track_b_gross_benefits_review.py", + "tests/test_track_b_gross_benefits_savings.py", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py", + "tests/test_track_b_gross_benefits_sources_20261011.py", + "tests/test_track_b_input_schema.py", + "tests/test_track_b_r3_fix_round_13.py", + "tests/test_track_b_refusal_notes.py", + "tests/test_track_b_ret_ledger.py", + "tests/test_track_b_ret_ledger_deductions.py", + "tests/test_track_b_ret_ledger_fix_round_2.py", + "tests/test_track_b_ret_ledger_sources.py", + "tests/track_b_gross_benefit_support.py" + ], + "exit_code": 0, + "output": "All done! \u2728 \ud83c\udf70 \u2728\n42 files would be left unchanged.\n", + "environment": { + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "RAYON_NUM_THREADS": "1" + } + }, + { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "ruff", + "check", + "--no-cache", + "scripts/track_b_g_conformance_report.py", + "scripts/track_b_r2_cross_head.py", + "src/populace_dynamics/track_b/_provenance.py", + "src/populace_dynamics/track_b/gross_benefits.py", + "src/populace_dynamics/track_b/ret_ledger.py", + "tests/test_track_b_gross_benefits.py", + "tests/test_track_b_gross_benefits_conformance_report.py", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py", + "tests/test_track_b_gross_benefits_deductions.py", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", + "tests/test_track_b_gross_benefits_fix_round_10_api.py", + "tests/test_track_b_gross_benefits_fix_round_10_helpers.py", + "tests/test_track_b_gross_benefits_fix_round_10_objects.py", + "tests/test_track_b_gross_benefits_fix_round_10_parameters.py", + "tests/test_track_b_gross_benefits_fix_round_11_seals.py", + "tests/test_track_b_gross_benefits_fix_round_12_contract.py", + "tests/test_track_b_gross_benefits_fix_round_13_audit.py", + "tests/test_track_b_gross_benefits_fix_round_13_guard.py", + "tests/test_track_b_gross_benefits_fix_round_15_receivers.py", + "tests/test_track_b_gross_benefits_fix_round_3_rates.py", + "tests/test_track_b_gross_benefits_fix_round_5_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_6_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_history.py", + "tests/test_track_b_gross_benefits_fix_round_8_entries.py", + "tests/test_track_b_gross_benefits_fix_round_8_history.py", + "tests/test_track_b_gross_benefits_fix_round_9_outcomes.py", + "tests/test_track_b_gross_benefits_fix_round_9_validation.py", + "tests/test_track_b_gross_benefits_properties.py", + "tests/test_track_b_gross_benefits_registry.py", + "tests/test_track_b_gross_benefits_review.py", + "tests/test_track_b_gross_benefits_savings.py", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py", + "tests/test_track_b_gross_benefits_sources_20261011.py", + "tests/test_track_b_input_schema.py", + "tests/test_track_b_r3_fix_round_13.py", + "tests/test_track_b_refusal_notes.py", + "tests/test_track_b_ret_ledger.py", + "tests/test_track_b_ret_ledger_deductions.py", + "tests/test_track_b_ret_ledger_fix_round_2.py", + "tests/test_track_b_ret_ledger_sources.py", + "tests/track_b_gross_benefit_support.py" + ], + "exit_code": 0, + "output": "All checks passed!\n", + "environment": { + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "RAYON_NUM_THREADS": "1" + } + } + ], + "source_manifests": [ + { + "manifest": "tests/data/track_b/gross_benefit_sources/manifest.json", + "capture_count": 64, + "all_bytes_match": true, + "all_sha256_match": true, + "capture_records": [ + { + "id": "poms_rs_00605_900", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00605_900.html", + "bytes": 39703, + "expected_bytes": 39703, + "sha256": "6c6e22435bc4fbb18addd78dcaa602c3042ea7456fd996317ea62cf2181531b8", + "expected_sha256": "6c6e22435bc4fbb18addd78dcaa602c3042ea7456fd996317ea62cf2181531b8", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00605_910", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00605_910.html", + "bytes": 71104, + "expected_bytes": 71104, + "sha256": "d93cf03ad949dc2de601846dc74b8951c5ec8e39e44bc65e54c7c952a3113e84", + "expected_sha256": "d93cf03ad949dc2de601846dc74b8951c5ec8e39e44bc65e54c7c952a3113e84", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_005", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_005.html", + "bytes": 35278, + "expected_bytes": 35278, + "sha256": "c6a3aed427c9bd6bbd4a24daf7ed28a9fcf2f90566feeb9125ef3b12a77ac023", + "expected_sha256": "c6a3aed427c9bd6bbd4a24daf7ed28a9fcf2f90566feeb9125ef3b12a77ac023", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_020", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_020.html", + "bytes": 43216, + "expected_bytes": 43216, + "sha256": "90b200b670b49b5e7ea7f0ddc186c78cc289186ec87017cf3e1f88839cf11b19", + "expected_sha256": "90b200b670b49b5e7ea7f0ddc186c78cc289186ec87017cf3e1f88839cf11b19", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_101", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_101.html", + "bytes": 56312, + "expected_bytes": 56312, + "sha256": "36099e73939d13a2115dba175a177d832a58f2d49644500a6185eae328b98655", + "expected_sha256": "36099e73939d13a2115dba175a177d832a58f2d49644500a6185eae328b98655", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_201", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_201.html", + "bytes": 64158, + "expected_bytes": 64158, + "sha256": "d2a38cb3b36bc3f1637106805a6c39037b7e421f2b434364dbcf207eeaa5bc92", + "expected_sha256": "d2a38cb3b36bc3f1637106805a6c39037b7e421f2b434364dbcf207eeaa5bc92", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_210", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_210.html", + "bytes": 18130, + "expected_bytes": 18130, + "sha256": "f5e8b4c2d69f3bb452726d6228e69db985a5bacd86ba10bf0d7b24cf2bda3ce2", + "expected_sha256": "f5e8b4c2d69f3bb452726d6228e69db985a5bacd86ba10bf0d7b24cf2bda3ce2", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_240", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_240.html", + "bytes": 21092, + "expected_bytes": 21092, + "sha256": "d9c7b5fe938d66afd6cfd98a469112fb38c041f0b361dcd9c0bb25b7d6a5ee4b", + "expected_sha256": "d9c7b5fe938d66afd6cfd98a469112fb38c041f0b361dcd9c0bb25b7d6a5ee4b", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_250", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_250.html", + "bytes": 26171, + "expected_bytes": 26171, + "sha256": "0dcde241013f26e1172b9a0f359ff5b4a57c9fdcdec65d7ca7244a5a4d5c5891", + "expected_sha256": "0dcde241013f26e1172b9a0f359ff5b4a57c9fdcdec65d7ca7244a5a4d5c5891", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_260", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_260.html", + "bytes": 26310, + "expected_bytes": 26310, + "sha256": "d938b1f5f4a13903fd7004326a3c8cf305d9a72af958551d900e5a132951f72c", + "expected_sha256": "d938b1f5f4a13903fd7004326a3c8cf305d9a72af958551d900e5a132951f72c", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_301", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_301.html", + "bytes": 49791, + "expected_bytes": 49791, + "sha256": "60dada526931a9d714619c6496f9b1e6ed6a45ac37221f4594e9be6249c7cf4f", + "expected_sha256": "60dada526931a9d714619c6496f9b1e6ed6a45ac37221f4594e9be6249c7cf4f", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_320", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_320.html", + "bytes": 33496, + "expected_bytes": 33496, + "sha256": "864fec1510445a230bc310314d7c9445e7fa500bd3b0a2a795a11f8a66ce22cd", + "expected_sha256": "864fec1510445a230bc310314d7c9445e7fa500bd3b0a2a795a11f8a66ce22cd", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_680", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_680.html", + "bytes": 20106, + "expected_bytes": 20106, + "sha256": "786de87bbd02fb63e254ddf10cd6c02e93f485f368f297acee2beb8218db8587", + "expected_sha256": "786de87bbd02fb63e254ddf10cd6c02e93f485f368f297acee2beb8218db8587", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_682", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_682.html", + "bytes": 17689, + "expected_bytes": 17689, + "sha256": "949fee38b82eaacac31ccb0da85d8c7b92d83cee86b90217dd081d49d1c238eb", + "expected_sha256": "949fee38b82eaacac31ccb0da85d8c7b92d83cee86b90217dd081d49d1c238eb", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_684", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_684.html", + "bytes": 18330, + "expected_bytes": 18330, + "sha256": "43425e2eca3908b0a72986bced5ad21e7feb1aa2c7d245c7f116d13483b3a969", + "expected_sha256": "43425e2eca3908b0a72986bced5ad21e7feb1aa2c7d245c7f116d13483b3a969", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_692", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_692.html", + "bytes": 92227, + "expected_bytes": 92227, + "sha256": "80121425f03c001a0036dc772a740721fbcbe72e56bcd80d1b22295d62628864", + "expected_sha256": "80121425f03c001a0036dc772a740721fbcbe72e56bcd80d1b22295d62628864", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_694", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_694.html", + "bytes": 20944, + "expected_bytes": 20944, + "sha256": "0aecbf70eda3d5688ae381608a869c4de5843b9df601a2e2066f12b6ea0eaa66", + "expected_sha256": "0aecbf70eda3d5688ae381608a869c4de5843b9df601a2e2066f12b6ea0eaa66", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_695", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_695.html", + "bytes": 16816, + "expected_bytes": 16816, + "sha256": "fd9ae5fb8b7ba2f9607628c9d93a7c22ca8489cfe06a0f7db5c1444e396d2fcb", + "expected_sha256": "fd9ae5fb8b7ba2f9607628c9d93a7c22ca8489cfe06a0f7db5c1444e396d2fcb", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_710", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_710.html", + "bytes": 25021, + "expected_bytes": 25021, + "sha256": "65cdeb99016861a252d4985e5b888aa7572736714705f2d2b32e661486da864b", + "expected_sha256": "65cdeb99016861a252d4985e5b888aa7572736714705f2d2b32e661486da864b", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_730", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_730.html", + "bytes": 22271, + "expected_bytes": 22271, + "sha256": "6eab8bb9478162a7fe33f262a5db7da96c5b47c3ff4b500ef698622a82cff253", + "expected_sha256": "6eab8bb9478162a7fe33f262a5db7da96c5b47c3ff4b500ef698622a82cff253", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_736", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_736.html", + "bytes": 34421, + "expected_bytes": 34421, + "sha256": "918f805a196bc7791a6d2c79ecc83c58293dee33a3816a46a30c353ff5f38dd8", + "expected_sha256": "918f805a196bc7791a6d2c79ecc83c58293dee33a3816a46a30c353ff5f38dd8", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_740", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_740.html", + "bytes": 20450, + "expected_bytes": 20450, + "sha256": "f213beed725ad6b927b74371db2fd213fcb36951f7d124aab54fb4c378da3960", + "expected_sha256": "f213beed725ad6b927b74371db2fd213fcb36951f7d124aab54fb4c378da3960", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_742", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_742.html", + "bytes": 21119, + "expected_bytes": 21119, + "sha256": "08912c9cce862b4a11ca05c702e8883f7c08904ab06fe3f4f10f95cd01595583", + "expected_sha256": "08912c9cce862b4a11ca05c702e8883f7c08904ab06fe3f4f10f95cd01595583", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_752", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_752.html", + "bytes": 17498, + "expected_bytes": 17498, + "sha256": "4b357c2dcc32fb999296dee922bc2fd57464eba812d527e307aea76a851c3fbe", + "expected_sha256": "4b357c2dcc32fb999296dee922bc2fd57464eba812d527e307aea76a851c3fbe", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_754", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_754.html", + "bytes": 25024, + "expected_bytes": 25024, + "sha256": "b216b17c378aa2856b6d59f2307d10d25b02c2ecf920d4d256ca5ca0b2e03f50", + "expected_sha256": "b216b17c378aa2856b6d59f2307d10d25b02c2ecf920d4d256ca5ca0b2e03f50", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_756", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_756.html", + "bytes": 29411, + "expected_bytes": 29411, + "sha256": "709e99201b0635cf96e6f9b76232830b0d35110a0a68b06c51d40c6fbc8ee8b2", + "expected_sha256": "709e99201b0635cf96e6f9b76232830b0d35110a0a68b06c51d40c6fbc8ee8b2", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_766", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_766.html", + "bytes": 16889, + "expected_bytes": 16889, + "sha256": "93623a81ddb85f8c06ff04dbb9ad8074a96afd1852eb9d1081cfcabf76cfed44", + "expected_sha256": "93623a81ddb85f8c06ff04dbb9ad8074a96afd1852eb9d1081cfcabf76cfed44", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_768", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_768.html", + "bytes": 33955, + "expected_bytes": 33955, + "sha256": "be173b85838dba4680195b7636305a42870a761ae580a1380ee435972db276ce", + "expected_sha256": "be173b85838dba4680195b7636305a42870a761ae580a1380ee435972db276ce", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_801", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_801.html", + "bytes": 20532, + "expected_bytes": 20532, + "sha256": "e85df2eebd68b97337e2d720dba6279191089d1fc20e9b9b7603465e73f89a41", + "expected_sha256": "e85df2eebd68b97337e2d720dba6279191089d1fc20e9b9b7603465e73f89a41", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00630_400", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00630_400.html", + "bytes": 74809, + "expected_bytes": 74809, + "sha256": "e6242ec12c64aafba782e5c37a8cfea09f65820ef05b30b8a3bf2a50ecc03d61", + "expected_sha256": "e6242ec12c64aafba782e5c37a8cfea09f65820ef05b30b8a3bf2a50ecc03d61", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "ssa_oact_familymax", + "file": "tests/data/track_b/gross_benefit_sources/ssa_oact_familymax.txt", + "bytes": 2116, + "expected_bytes": 2116, + "sha256": "4a9d58226a03a4b2e1a9c532ab9b270de1bcd451798f6017f651515ba372b62c", + "expected_sha256": "4a9d58226a03a4b2e1a9c532ab9b270de1bcd451798f6017f651515ba372b62c", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "ssa_oact_dibfamilymax", + "file": "tests/data/track_b/gross_benefit_sources/ssa_oact_dibfamilymax.txt", + "bytes": 451, + "expected_bytes": 451, + "sha256": "45344f713fe48314c3fc3d8375d8cbb53d5e90d57b327dd6ad44985aac5ce066", + "expected_sha256": "45344f713fe48314c3fc3d8375d8cbb53d5e90d57b327dd6ad44985aac5ce066", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "ssa_ssb_v75n3_family_maximum", + "file": "tests/data/track_b/gross_benefit_sources/ssa_ssb_v75n3_family_maximum_excerpts.txt", + "bytes": 6738, + "expected_bytes": 6738, + "sha256": "e161084a266c1acc9f58cd9157ce7bc0c694e6d8847b8085272a024e338ee630", + "expected_sha256": "e161084a266c1acc9f58cd9157ce7bc0c694e6d8847b8085272a024e338ee630", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "ssa_act_202_215", + "file": "tests/data/track_b/gross_benefit_sources/ssa_act_202_215_excerpts.txt", + "bytes": 11723, + "expected_bytes": 11723, + "sha256": "f546b3df836ace22acba6ca0af5d3e89186251efae27f0b21b798cf44a87957c", + "expected_sha256": "f546b3df836ace22acba6ca0af5d3e89186251efae27f0b21b798cf44a87957c", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "lii_usc_402_415", + "file": "tests/data/track_b/gross_benefit_sources/lii_usc_402_415_excerpts.txt", + "bytes": 7358, + "expected_bytes": 7358, + "sha256": "31daedaea817bf97d7d63685a897343ea5a47dcf98a91f9294406edfe89d0979", + "expected_sha256": "31daedaea817bf97d7d63685a897343ea5a47dcf98a91f9294406edfe89d0979", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "ssa_act_203", + "file": "tests/data/track_b/gross_benefit_sources/../ret_sources/ssa_act_203.html", + "bytes": 99348, + "expected_bytes": 99348, + "sha256": "ea000092e140d2ff8ce058138a9f919fac4eeac0004bb71364d6e2bade53cf54", + "expected_sha256": "ea000092e140d2ff8ce058138a9f919fac4eeac0004bb71364d6e2bade53cf54", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_gn_02603_045", + "file": "tests/data/track_b/gross_benefit_sources/poms_gn_02603_045.html", + "bytes": 23259, + "expected_bytes": 23259, + "sha256": "99d515b4e1e635e91c489bb65f4d59f15c2d8e2a6935275f83b4b3030681549e", + "expected_sha256": "99d515b4e1e635e91c489bb65f4d59f15c2d8e2a6935275f83b4b3030681549e", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_gn_02603_050", + "file": "tests/data/track_b/gross_benefit_sources/poms_gn_02603_050.html", + "bytes": 40826, + "expected_bytes": 40826, + "sha256": "4b151ca0a071fb5cb42393b541d1e0bb0459e5734923988e132efa43f6c322d0", + "expected_sha256": "4b151ca0a071fb5cb42393b541d1e0bb0459e5734923988e132efa43f6c322d0", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_gn_02603_060", + "file": "tests/data/track_b/gross_benefit_sources/poms_gn_02603_060.html", + "bytes": 146989, + "expected_bytes": 146989, + "sha256": "662ca1764e01689dbf6daf0569a568961d9c8c5610f5f4db21a337bfdbbb9151", + "expected_sha256": "662ca1764e01689dbf6daf0569a568961d9c8c5610f5f4db21a337bfdbbb9151", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_003", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_003.html", + "bytes": 33488, + "expected_bytes": 33488, + "sha256": "935b391658a9f94117fde850fa4eb88293eb9ac5f19e05a5b9f946c4e15e6c2d", + "expected_sha256": "935b391658a9f94117fde850fa4eb88293eb9ac5f19e05a5b9f946c4e15e6c2d", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_010", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_010.html", + "bytes": 36552, + "expected_bytes": 36552, + "sha256": "cf6bf2ca186a3186735986d945508afbdb5bf55f32252782111e52be7212abd6", + "expected_sha256": "cf6bf2ca186a3186735986d945508afbdb5bf55f32252782111e52be7212abd6", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_310", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_310.html", + "bytes": 21636, + "expected_bytes": 21636, + "sha256": "cc33e051279b2781404a0d0cd26cd57b777243bdf1bf97a476c4badb006b386f", + "expected_sha256": "cc33e051279b2781404a0d0cd26cd57b777243bdf1bf97a476c4badb006b386f", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_315", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_315.html", + "bytes": 22053, + "expected_bytes": 22053, + "sha256": "7e388d45a2a786809ea3dfd342d4538f3865abf4f39175848bb543946cf46b08", + "expected_sha256": "7e388d45a2a786809ea3dfd342d4538f3865abf4f39175848bb543946cf46b08", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_590", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_590.html", + "bytes": 23730, + "expected_bytes": 23730, + "sha256": "2d0e05e38849fc9da5b58de7f2c5af594d84aefbc99cd7bbe088ee9441fb7004", + "expected_sha256": "2d0e05e38849fc9da5b58de7f2c5af594d84aefbc99cd7bbe088ee9441fb7004", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_712", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_712.html", + "bytes": 21788, + "expected_bytes": 21788, + "sha256": "cdf9d579f9260d358ee774ec14f00534d6632d4892361e880cfe8b3c7dd49508", + "expected_sha256": "cdf9d579f9260d358ee774ec14f00534d6632d4892361e880cfe8b3c7dd49508", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_758", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_758.html", + "bytes": 24283, + "expected_bytes": 24283, + "sha256": "06b6620dd4fd85fb24800abc5ba6c053c9c5c702b9c4357bcda971cc086bc75e", + "expected_sha256": "06b6620dd4fd85fb24800abc5ba6c053c9c5c702b9c4357bcda971cc086bc75e", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_770", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_770.html", + "bytes": 586558, + "expected_bytes": 586558, + "sha256": "93f737d9c1ba7368278762a505672abbea2539de323e284c974c81674abd864e", + "expected_sha256": "93f737d9c1ba7368278762a505672abbea2539de323e284c974c81674abd864e", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_772", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_772.html", + "bytes": 58243, + "expected_bytes": 58243, + "sha256": "5b08d4948ef9f5e2ee1ed0e810ec03a387137e61d1c1e251e5e35c5411f1cf22", + "expected_sha256": "5b08d4948ef9f5e2ee1ed0e810ec03a387137e61d1c1e251e5e35c5411f1cf22", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_774", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_774.html", + "bytes": 20354, + "expected_bytes": 20354, + "sha256": "93f7279db58e5447e519ff5eb29c5edcd491948f9b783f476fde0b65984d6b32", + "expected_sha256": "93f7279db58e5447e519ff5eb29c5edcd491948f9b783f476fde0b65984d6b32", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_776", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_776.html", + "bytes": 19073, + "expected_bytes": 19073, + "sha256": "61b7d24d09849a3ea66e26a61c2559510515da1ea67f2c315a7c89aa99e79a2a", + "expected_sha256": "61b7d24d09849a3ea66e26a61c2559510515da1ea67f2c315a7c89aa99e79a2a", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_778", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_778.html", + "bytes": 17047, + "expected_bytes": 17047, + "sha256": "c19a9fd500c8f45db9003bce3d672d7a2d914e9a9c05827e3facf1526de82e92", + "expected_sha256": "c19a9fd500c8f45db9003bce3d672d7a2d914e9a9c05827e3facf1526de82e92", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00202_005", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00202_005.html", + "bytes": 28361, + "expected_bytes": 28361, + "sha256": "3dd37652e8382deb896f4598bdc393f2878d14df8bdaf8eb8e508fc45635dbf5", + "expected_sha256": "3dd37652e8382deb896f4598bdc393f2878d14df8bdaf8eb8e508fc45635dbf5", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00202_100", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00202_100.html", + "bytes": 42512, + "expected_bytes": 42512, + "sha256": "10a741b98b0b975b245ed68daf4e10dd774803294495f1505d606433889f82a9", + "expected_sha256": "10a741b98b0b975b245ed68daf4e10dd774803294495f1505d606433889f82a9", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00209_001", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00209_001.html", + "bytes": 25788, + "expected_bytes": 25788, + "sha256": "1655746c729459a578d09e2653ce2b5b58069119fa5efd9fdbf2e6437d024bb7", + "expected_sha256": "1655746c729459a578d09e2653ce2b5b58069119fa5efd9fdbf2e6437d024bb7", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00209_015", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00209_015.html", + "bytes": 26907, + "expected_bytes": 26907, + "sha256": "f2892dcc142f79e773d701b5c10b0583cf05990cbd391e12a0e57c1c06855c07", + "expected_sha256": "f2892dcc142f79e773d701b5c10b0583cf05990cbd391e12a0e57c1c06855c07", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_gn_02608_100", + "file": "tests/data/track_b/gross_benefit_sources/poms_gn_02608_100.html", + "bytes": 33518, + "expected_bytes": 33518, + "sha256": "0cb301a522195b1446147d69739ee8a8f08acde931c2fe71ffad621ee19c170f", + "expected_sha256": "0cb301a522195b1446147d69739ee8a8f08acde931c2fe71ffad621ee19c170f", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00605_360", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00605_360.html", + "bytes": 42829, + "expected_bytes": 42829, + "sha256": "99ce6e28bc9cb044bfcf6cd1c24f6471d6635efcc8f130c449d078a1bab9c54b", + "expected_sha256": "99ce6e28bc9cb044bfcf6cd1c24f6471d6635efcc8f130c449d078a1bab9c54b", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_340", + "file": "tests/data/track_b/gross_benefit_sources/poms_rs_00615_340.html", + "bytes": 20846, + "expected_bytes": 20846, + "sha256": "2015c4840633e813391f43cb82324e5c46855a78c9459d78ad8003ed6340ffcd", + "expected_sha256": "2015c4840633e813391f43cb82324e5c46855a78c9459d78ad8003ed6340ffcd", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_02501_130", + "file": "tests/data/track_b/gross_benefit_sources/../ret_ledger_sources/poms_rs_02501_130.html", + "bytes": 23095, + "expected_bytes": 23095, + "sha256": "084beacc236c33fc88217486dccfeff7c23e564bf66717ebf8ab8d91818fbf82", + "expected_sha256": "084beacc236c33fc88217486dccfeff7c23e564bf66717ebf8ab8d91818fbf82", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_02501_155", + "file": "tests/data/track_b/gross_benefit_sources/../ret_ledger_sources/poms_rs_02501_155.html", + "bytes": 25236, + "expected_bytes": 25236, + "sha256": "4bd6fc3e1485d5d9c8e89c50c08071abb23af8031893671339f4e0e44b6fb554", + "expected_sha256": "4bd6fc3e1485d5d9c8e89c50c08071abb23af8031893671339f4e0e44b6fb554", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_02501_160", + "file": "tests/data/track_b/gross_benefit_sources/../ret_ledger_sources/poms_rs_02501_160.html", + "bytes": 24146, + "expected_bytes": 24146, + "sha256": "cd65f137741b83ba729b693f0c6f3fda118847b455c1c4d8ba33bbb1e404bca2", + "expected_sha256": "cd65f137741b83ba729b693f0c6f3fda118847b455c1c4d8ba33bbb1e404bca2", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_gn_02603_020", + "file": "tests/data/track_b/gross_benefit_sources/../ret_ledger_sources/poms_gn_02603_020.html", + "bytes": 21454, + "expected_bytes": 21454, + "sha256": "e397fd07d847f24c160e138de901dd89aca17e3fa7e06727de9a572f1c9eb508", + "expected_sha256": "e397fd07d847f24c160e138de901dd89aca17e3fa7e06727de9a572f1c9eb508", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_gn_02603_040", + "file": "tests/data/track_b/gross_benefit_sources/../ret_ledger_sources/poms_gn_02603_040.html", + "bytes": 24924, + "expected_bytes": 24924, + "sha256": "fec22e461e8cb1bb7829c717c5fbbc474b72ad7225e782a46b0f97c50b4bb16d", + "expected_sha256": "fec22e461e8cb1bb7829c717c5fbbc474b72ad7225e782a46b0f97c50b4bb16d", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_gn_02603_090", + "file": "tests/data/track_b/gross_benefit_sources/../ret_ledger_sources/poms_gn_02603_090.html", + "bytes": 30943, + "expected_bytes": 30943, + "sha256": "fc544d57f3e2ec998a54b54ca4e7267dcd95b536463cabd94f00494c64f3269c", + "expected_sha256": "fc544d57f3e2ec998a54b54ca4e7267dcd95b536463cabd94f00494c64f3269c", + "bytes_match": true, + "sha256_match": true + } + ], + "served_body_pins": [ + { + "source_id": "ssa_oact_familymax", + "sha256": "141a0c991b5f60648f6fb2771e19fc92b02982ebe8e5318e4aedfb7dbf0c730e", + "local_capture": null, + "verification": "remote provenance pin has no local file; no independent rehash claimed" + }, + { + "source_id": "ssa_oact_dibfamilymax", + "sha256": "4f5e4910754feae3bd533f02a294ea60d8f4476a1da2351495f7c191d9e8858f", + "local_capture": null, + "verification": "remote provenance pin has no local file; no independent rehash claimed" + }, + { + "source_id": "ssa_ssb_v75n3_family_maximum", + "sha256": "1338bd6f201e5aee9ce5b614397c8bac1c0cea8612b53e148517f2d21c5adc8c", + "local_capture": null, + "verification": "remote provenance pin has no local file; no independent rehash claimed" + }, + { + "source_id": "ssa_act_202_215", + "sha256": "9983b24c054b0e2cf3fa0f6c5184ac7a8aa1609e2fb45acced2e630db31e2946", + "local_capture": null, + "verification": "remote provenance pin has no local file; no independent rehash claimed" + }, + { + "source_id": "ssa_act_202_215", + "sha256": "fd8082cd30e327713e989d7dede902d3e19e67b673e2bf7b6955571e309f191a", + "local_capture": null, + "verification": "remote provenance pin has no local file; no independent rehash claimed" + }, + { + "source_id": "lii_usc_402_415", + "sha256": "e5bb977c3ab381c2c3bd4f6bb320b86f25e2f0ad2b629e01333be56727d3823b", + "local_capture": null, + "verification": "remote provenance pin has no local file; no independent rehash claimed" + }, + { + "source_id": "lii_usc_402_415", + "sha256": "c3262e82e8e674caf43709c522ce60760eafb0b133e1f99221ca7aa97d54ea3a", + "local_capture": null, + "verification": "remote provenance pin has no local file; no independent rehash claimed" + } + ], + "new_capture_logs": [] + }, + { + "manifest": "tests/data/track_b/ret_sources/manifest.json", + "capture_count": 5, + "all_bytes_match": true, + "all_sha256_match": true, + "capture_records": [ + { + "id": "ssa_ret_history", + "file": "tests/data/track_b/ret_sources/ssa_ret_history.html", + "bytes": 37056, + "expected_bytes": 37056, + "sha256": "b03f940a2cfe7b12f7c0c5edaf1b5c46dc79786ffd22a023a154e4fec76b2b5d", + "expected_sha256": "b03f940a2cfe7b12f7c0c5edaf1b5c46dc79786ffd22a023a154e4fec76b2b5d", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "ssa_ret_determination", + "file": "tests/data/track_b/ret_sources/ssa_ret_determination.html", + "bytes": 35643, + "expected_bytes": 35643, + "sha256": "bede06d5ab0aff9b620b143afb2e45cb1e0ab39de1aaeb5abdff08499c40c226", + "expected_sha256": "bede06d5ab0aff9b620b143afb2e45cb1e0ab39de1aaeb5abdff08499c40c226", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "ssa_nawi_history", + "file": "tests/data/track_b/ret_sources/ssa_nawi_history.html", + "bytes": 42308, + "expected_bytes": 42308, + "sha256": "ec58015bb689fbd8a1342eeda54f03b50656c60da1f9ddc8a660e5290fd23c18", + "expected_sha256": "ec58015bb689fbd8a1342eeda54f03b50656c60da1f9ddc8a660e5290fd23c18", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "ssa_cola_history", + "file": "tests/data/track_b/ret_sources/ssa_cola_history.html", + "bytes": 38197, + "expected_bytes": 38197, + "sha256": "41bb09736bb40be233625d2c1c724dee643f16666ab59a01d5e68a1d6d70d14f", + "expected_sha256": "41bb09736bb40be233625d2c1c724dee643f16666ab59a01d5e68a1d6d70d14f", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "ssa_act_203", + "file": "tests/data/track_b/ret_sources/ssa_act_203.html", + "bytes": 99348, + "expected_bytes": 99348, + "sha256": "ea000092e140d2ff8ce058138a9f919fac4eeac0004bb71364d6e2bade53cf54", + "expected_sha256": "ea000092e140d2ff8ce058138a9f919fac4eeac0004bb71364d6e2bade53cf54", + "bytes_match": true, + "sha256_match": true + } + ], + "served_body_pins": [], + "new_capture_logs": [] + }, + { + "manifest": "tests/data/track_b/ret_ledger_sources/manifest.json", + "capture_count": 41, + "all_bytes_match": true, + "all_sha256_match": true, + "capture_records": [ + { + "id": "poms_rs_02501_001", + "file": "tests/data/track_b/ret_ledger_sources/poms_rs_02501_001.html", + "bytes": 49627, + "expected_bytes": 49627, + "sha256": "8abd959ce646be7fb071db7a8008c14a81ed1ad4dd6712650fea61e67447c7bc", + "expected_sha256": "8abd959ce646be7fb071db7a8008c14a81ed1ad4dd6712650fea61e67447c7bc", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_02501_021", + "file": "tests/data/track_b/ret_ledger_sources/poms_rs_02501_021.html", + "bytes": 40121, + "expected_bytes": 40121, + "sha256": "cbec517461f09c253336433d6c6d11d0025071fcfc40ca1e645b00ca8877cb9f", + "expected_sha256": "cbec517461f09c253336433d6c6d11d0025071fcfc40ca1e645b00ca8877cb9f", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_02501_025", + "file": "tests/data/track_b/ret_ledger_sources/poms_rs_02501_025.html", + "bytes": 99322, + "expected_bytes": 99322, + "sha256": "c4619e3479ef8aba6f1b4fb937aa25a923ad60ffc23ec4f4da225d5711595ff2", + "expected_sha256": "c4619e3479ef8aba6f1b4fb937aa25a923ad60ffc23ec4f4da225d5711595ff2", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_02501_030", + "file": "tests/data/track_b/ret_ledger_sources/poms_rs_02501_030.html", + "bytes": 40109, + "expected_bytes": 40109, + "sha256": "92fe687bc11c8ff8d66f5779a5f0c88298f1f1d6684baf85d10b0c8c1c5760ec", + "expected_sha256": "92fe687bc11c8ff8d66f5779a5f0c88298f1f1d6684baf85d10b0c8c1c5760ec", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_02501_070", + "file": "tests/data/track_b/ret_ledger_sources/poms_rs_02501_070.html", + "bytes": 22583, + "expected_bytes": 22583, + "sha256": "a0367022b3384a46a9464b65d224ba2f11caaca7db51d7e91c230da524314da5", + "expected_sha256": "a0367022b3384a46a9464b65d224ba2f11caaca7db51d7e91c230da524314da5", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_02501_075", + "file": "tests/data/track_b/ret_ledger_sources/poms_rs_02501_075.html", + "bytes": 20333, + "expected_bytes": 20333, + "sha256": "1631e2703263dc250ef80ba973cb7f20b312c4b2df2f105c81cad45731365dc3", + "expected_sha256": "1631e2703263dc250ef80ba973cb7f20b312c4b2df2f105c81cad45731365dc3", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_02501_080", + "file": "tests/data/track_b/ret_ledger_sources/poms_rs_02501_080.html", + "bytes": 30907, + "expected_bytes": 30907, + "sha256": "cedc11dfbf44d23bea4f4f0974ee35caef4fef602d38dfcb3e2c479ec87ab962", + "expected_sha256": "cedc11dfbf44d23bea4f4f0974ee35caef4fef602d38dfcb3e2c479ec87ab962", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_02501_095", + "file": "tests/data/track_b/ret_ledger_sources/poms_rs_02501_095.html", + "bytes": 30130, + "expected_bytes": 30130, + "sha256": "befdc6d32c1f8206b962dacb66cf91a73b644f49d42a38f68570641a81816fc9", + "expected_sha256": "befdc6d32c1f8206b962dacb66cf91a73b644f49d42a38f68570641a81816fc9", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_02501_100", + "file": "tests/data/track_b/ret_ledger_sources/poms_rs_02501_100.html", + "bytes": 29069, + "expected_bytes": 29069, + "sha256": "aea7455b10f7f95550808dc1d3c89c849ed3724b149afa951130319d45982789", + "expected_sha256": "aea7455b10f7f95550808dc1d3c89c849ed3724b149afa951130319d45982789", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_02501_105", + "file": "tests/data/track_b/ret_ledger_sources/poms_rs_02501_105.html", + "bytes": 22023, + "expected_bytes": 22023, + "sha256": "c44b3cfe1b76d0205469113bde71d7052d45e1b11a64155f05c632f7655c53d5", + "expected_sha256": "c44b3cfe1b76d0205469113bde71d7052d45e1b11a64155f05c632f7655c53d5", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_02501_110", + "file": "tests/data/track_b/ret_ledger_sources/poms_rs_02501_110.html", + "bytes": 30869, + "expected_bytes": 30869, + "sha256": "e2ad22e7fe90686ad40709ba28a748733921bdacd72689b624707fccecefc4e0", + "expected_sha256": "e2ad22e7fe90686ad40709ba28a748733921bdacd72689b624707fccecefc4e0", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_02501_120", + "file": "tests/data/track_b/ret_ledger_sources/poms_rs_02501_120.html", + "bytes": 32525, + "expected_bytes": 32525, + "sha256": "98668567f6d3fc50b3748ceb9beae6b87ff91ed37c81b4e585b0013dfae4885b", + "expected_sha256": "98668567f6d3fc50b3748ceb9beae6b87ff91ed37c81b4e585b0013dfae4885b", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_02501_125", + "file": "tests/data/track_b/ret_ledger_sources/poms_rs_02501_125.html", + "bytes": 20180, + "expected_bytes": 20180, + "sha256": "4ea8fbbabf256f4ced3671935d3f9e971cc69363b2786eac17cdb617480f6819", + "expected_sha256": "4ea8fbbabf256f4ced3671935d3f9e971cc69363b2786eac17cdb617480f6819", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_02501_130", + "file": "tests/data/track_b/ret_ledger_sources/poms_rs_02501_130.html", + "bytes": 23095, + "expected_bytes": 23095, + "sha256": "084beacc236c33fc88217486dccfeff7c23e564bf66717ebf8ab8d91818fbf82", + "expected_sha256": "084beacc236c33fc88217486dccfeff7c23e564bf66717ebf8ab8d91818fbf82", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_02501_140", + "file": "tests/data/track_b/ret_ledger_sources/poms_rs_02501_140.html", + "bytes": 17568, + "expected_bytes": 17568, + "sha256": "57435f8afe81ca71757bc8d29e2885c73d83ed554dbcd095579f1e2e1c3c7e80", + "expected_sha256": "57435f8afe81ca71757bc8d29e2885c73d83ed554dbcd095579f1e2e1c3c7e80", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_02501_145", + "file": "tests/data/track_b/ret_ledger_sources/poms_rs_02501_145.html", + "bytes": 25743, + "expected_bytes": 25743, + "sha256": "76978e0237d421aa23b75b029ec1a1d33c78cf7e57e78c9d3ee3bf25ab6cef13", + "expected_sha256": "76978e0237d421aa23b75b029ec1a1d33c78cf7e57e78c9d3ee3bf25ab6cef13", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_02501_150", + "file": "tests/data/track_b/ret_ledger_sources/poms_rs_02501_150.html", + "bytes": 34312, + "expected_bytes": 34312, + "sha256": "ae5bfaa364a181510490e3fbf6ff2ef944a0a2bf82f17690ae34b4a19e84593d", + "expected_sha256": "ae5bfaa364a181510490e3fbf6ff2ef944a0a2bf82f17690ae34b4a19e84593d", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_02501_155", + "file": "tests/data/track_b/ret_ledger_sources/poms_rs_02501_155.html", + "bytes": 25236, + "expected_bytes": 25236, + "sha256": "4bd6fc3e1485d5d9c8e89c50c08071abb23af8031893671339f4e0e44b6fb554", + "expected_sha256": "4bd6fc3e1485d5d9c8e89c50c08071abb23af8031893671339f4e0e44b6fb554", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_02501_160", + "file": "tests/data/track_b/ret_ledger_sources/poms_rs_02501_160.html", + "bytes": 24146, + "expected_bytes": 24146, + "sha256": "cd65f137741b83ba729b693f0c6f3fda118847b455c1c4d8ba33bbb1e404bca2", + "expected_sha256": "cd65f137741b83ba729b693f0c6f3fda118847b455c1c4d8ba33bbb1e404bca2", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_gn_02603_010", + "file": "tests/data/track_b/ret_ledger_sources/poms_gn_02603_010.html", + "bytes": 22030, + "expected_bytes": 22030, + "sha256": "f92640034643a8a1eb4fe5a378bc144e21265bcbc0387968f9af3d04fbc6a6a3", + "expected_sha256": "f92640034643a8a1eb4fe5a378bc144e21265bcbc0387968f9af3d04fbc6a6a3", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_gn_02603_020", + "file": "tests/data/track_b/ret_ledger_sources/poms_gn_02603_020.html", + "bytes": 21454, + "expected_bytes": 21454, + "sha256": "e397fd07d847f24c160e138de901dd89aca17e3fa7e06727de9a572f1c9eb508", + "expected_sha256": "e397fd07d847f24c160e138de901dd89aca17e3fa7e06727de9a572f1c9eb508", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_gn_02603_040", + "file": "tests/data/track_b/ret_ledger_sources/poms_gn_02603_040.html", + "bytes": 24924, + "expected_bytes": 24924, + "sha256": "fec22e461e8cb1bb7829c717c5fbbc474b72ad7225e782a46b0f97c50b4bb16d", + "expected_sha256": "fec22e461e8cb1bb7829c717c5fbbc474b72ad7225e782a46b0f97c50b4bb16d", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_gn_02603_045", + "file": "tests/data/track_b/ret_ledger_sources/poms_gn_02603_045.html", + "bytes": 23259, + "expected_bytes": 23259, + "sha256": "99d515b4e1e635e91c489bb65f4d59f15c2d8e2a6935275f83b4b3030681549e", + "expected_sha256": "99d515b4e1e635e91c489bb65f4d59f15c2d8e2a6935275f83b4b3030681549e", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_gn_02603_050", + "file": "tests/data/track_b/ret_ledger_sources/poms_gn_02603_050.html", + "bytes": 40826, + "expected_bytes": 40826, + "sha256": "4b151ca0a071fb5cb42393b541d1e0bb0459e5734923988e132efa43f6c322d0", + "expected_sha256": "4b151ca0a071fb5cb42393b541d1e0bb0459e5734923988e132efa43f6c322d0", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_gn_02603_055", + "file": "tests/data/track_b/ret_ledger_sources/poms_gn_02603_055.html", + "bytes": 20866, + "expected_bytes": 20866, + "sha256": "1046c1eef2b704b7ffb7ddb7a274b72c8bf52246d3137f1204d736818a1e39e2", + "expected_sha256": "1046c1eef2b704b7ffb7ddb7a274b72c8bf52246d3137f1204d736818a1e39e2", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_gn_02603_060", + "file": "tests/data/track_b/ret_ledger_sources/poms_gn_02603_060.html", + "bytes": 146989, + "expected_bytes": 146989, + "sha256": "662ca1764e01689dbf6daf0569a568961d9c8c5610f5f4db21a337bfdbbb9151", + "expected_sha256": "662ca1764e01689dbf6daf0569a568961d9c8c5610f5f4db21a337bfdbbb9151", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_gn_02603_075", + "file": "tests/data/track_b/ret_ledger_sources/poms_gn_02603_075.html", + "bytes": 21932, + "expected_bytes": 21932, + "sha256": "2d7f21fa191149ebf7e63392920606667f4fb41e65b1c4df0ea7ddcbfc6a899c", + "expected_sha256": "2d7f21fa191149ebf7e63392920606667f4fb41e65b1c4df0ea7ddcbfc6a899c", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_gn_02603_090", + "file": "tests/data/track_b/ret_ledger_sources/poms_gn_02603_090.html", + "bytes": 30943, + "expected_bytes": 30943, + "sha256": "fc544d57f3e2ec998a54b54ca4e7267dcd95b536463cabd94f00494c64f3269c", + "expected_sha256": "fc544d57f3e2ec998a54b54ca4e7267dcd95b536463cabd94f00494c64f3269c", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_gn_02603_100", + "file": "tests/data/track_b/ret_ledger_sources/poms_gn_02603_100.html", + "bytes": 55778, + "expected_bytes": 55778, + "sha256": "6e12efa1541b0c949ae1b80caa889d2f21f223446b0be148325990f5f8e9de04", + "expected_sha256": "6e12efa1541b0c949ae1b80caa889d2f21f223446b0be148325990f5f8e9de04", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_02510_001", + "file": "tests/data/track_b/ret_ledger_sources/poms_rs_02510_001.html", + "bytes": 25028, + "expected_bytes": 25028, + "sha256": "d0490fd55091654444f5b3dd3f7d8fef3f22819ab23655fbc93a0026f6385b87", + "expected_sha256": "d0490fd55091654444f5b3dd3f7d8fef3f22819ab23655fbc93a0026f6385b87", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_02510_005", + "file": "tests/data/track_b/ret_ledger_sources/poms_rs_02510_005.html", + "bytes": 53114, + "expected_bytes": 53114, + "sha256": "d6e82fb7b07f863c2d91609818d225fd13624c3e4937c7e866342c25fffd8ef2", + "expected_sha256": "d6e82fb7b07f863c2d91609818d225fd13624c3e4937c7e866342c25fffd8ef2", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_02510_015", + "file": "tests/data/track_b/ret_ledger_sources/poms_rs_02510_015.html", + "bytes": 56635, + "expected_bytes": 56635, + "sha256": "b0293c1e967b280eb37e0fea238b65e260822f496e817fc0349a303d955ef489", + "expected_sha256": "b0293c1e967b280eb37e0fea238b65e260822f496e817fc0349a303d955ef489", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_02510_026", + "file": "tests/data/track_b/ret_ledger_sources/poms_rs_02510_026.html", + "bytes": 117125, + "expected_bytes": 117125, + "sha256": "44ecb84985ae4111b723b06dc6b1f65aa4c791c0dfab0a03a39ec05a94be3d29", + "expected_sha256": "44ecb84985ae4111b723b06dc6b1f65aa4c791c0dfab0a03a39ec05a94be3d29", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_02505_005", + "file": "tests/data/track_b/ret_ledger_sources/poms_rs_02505_005.html", + "bytes": 22505, + "expected_bytes": 22505, + "sha256": "5b089b579e549c2bc2217949078b507a9c32a788e2c8fd1317a98842a2e1464d", + "expected_sha256": "5b089b579e549c2bc2217949078b507a9c32a788e2c8fd1317a98842a2e1464d", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_02505_065", + "file": "tests/data/track_b/ret_ledger_sources/poms_rs_02505_065.html", + "bytes": 26134, + "expected_bytes": 26134, + "sha256": "f94b28b8a7ab75663a9ee0f2b17027bbb99c60b12880a4ba24493ec255dbda14", + "expected_sha256": "f94b28b8a7ab75663a9ee0f2b17027bbb99c60b12880a4ba24493ec255dbda14", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "ecfr_20cfr404_subpart_e", + "file": "tests/data/track_b/ret_ledger_sources/ecfr_20cfr404_subpart_e.xml", + "bytes": 261712, + "expected_bytes": 261712, + "sha256": "fa67514821b77e8a88cdeacacb420341e6481d0cfa0c662233b5359f0d67f39b", + "expected_sha256": "fa67514821b77e8a88cdeacacb420341e6481d0cfa0c662233b5359f0d67f39b", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "ssa_pub_05_10069", + "file": "tests/data/track_b/ret_ledger_sources/ssa_pub_05_10069.pdf", + "bytes": 261038, + "expected_bytes": 261038, + "sha256": "2ecbfd9234ba445e73259f284d861277ca186d2a8582744a541f2ac1077bbf4f", + "expected_sha256": "2ecbfd9234ba445e73259f284d861277ca186d2a8582744a541f2ac1077bbf4f", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "ssa_while_working", + "file": "tests/data/track_b/ret_ledger_sources/ssa_while_working.html", + "bytes": 36908, + "expected_bytes": 36908, + "sha256": "0ee2772439e9bf09876c4cf219cd050063b4f4c17a0c8bb46492b9080c740c5a", + "expected_sha256": "0ee2772439e9bf09876c4cf219cd050063b4f4c17a0c8bb46492b9080c740c5a", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "ssa_special_rule", + "file": "tests/data/track_b/ret_ledger_sources/ssa_special_rule.html", + "bytes": 31916, + "expected_bytes": 31916, + "sha256": "9c034dd26ea27a3657a5ba9dace1b229c009fa5020ef16dd0a46aeec2fa9bd73", + "expected_sha256": "9c034dd26ea27a3657a5ba9dace1b229c009fa5020ef16dd0a46aeec2fa9bd73", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "ssa_act_203", + "file": "tests/data/track_b/ret_ledger_sources/../ret_sources/ssa_act_203.html", + "bytes": 99348, + "expected_bytes": 99348, + "sha256": "ea000092e140d2ff8ce058138a9f919fac4eeac0004bb71364d6e2bade53cf54", + "expected_sha256": "ea000092e140d2ff8ce058138a9f919fac4eeac0004bb71364d6e2bade53cf54", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "ssa_pub_05_10069_text", + "file": "tests/data/track_b/ret_ledger_sources/ssa_pub_05_10069_excerpt.txt", + "bytes": 4790, + "expected_bytes": 4790, + "sha256": "30d320fe10b184dfb5766cca99b46f35ee2c34f5f609c510ddbb12ebbf882b6a", + "expected_sha256": "30d320fe10b184dfb5766cca99b46f35ee2c34f5f609c510ddbb12ebbf882b6a", + "bytes_match": true, + "sha256_match": true + } + ], + "served_body_pins": [ + { + "source_id": "ssa_pub_05_10069_text", + "sha256": "2ecbfd9234ba445e73259f284d861277ca186d2a8582744a541f2ac1077bbf4f", + "local_capture": "ssa_pub_05_10069.pdf", + "verification": "covered by listed local capture" + } + ], + "new_capture_logs": [] + }, + { + "manifest": "tests/data/track_b/arf_recompute_sources/manifest.json", + "capture_count": 38, + "all_bytes_match": true, + "all_sha256_match": true, + "capture_records": [ + { + "id": "poms_rs_00615_003", + "file": "tests/data/track_b/arf_recompute_sources/poms_rs_00615_003.html", + "bytes": 33488, + "expected_bytes": 33488, + "sha256": "935b391658a9f94117fde850fa4eb88293eb9ac5f19e05a5b9f946c4e15e6c2d", + "expected_sha256": "935b391658a9f94117fde850fa4eb88293eb9ac5f19e05a5b9f946c4e15e6c2d", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_004", + "file": "tests/data/track_b/arf_recompute_sources/poms_rs_00615_004.html", + "bytes": 227765, + "expected_bytes": 227765, + "sha256": "207a83b86365a276e97a882220b3413b1ae60677d5661415a88db4faf913b398", + "expected_sha256": "207a83b86365a276e97a882220b3413b1ae60677d5661415a88db4faf913b398", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_010", + "file": "tests/data/track_b/arf_recompute_sources/poms_rs_00615_010.html", + "bytes": 36552, + "expected_bytes": 36552, + "sha256": "cf6bf2ca186a3186735986d945508afbdb5bf55f32252782111e52be7212abd6", + "expected_sha256": "cf6bf2ca186a3186735986d945508afbdb5bf55f32252782111e52be7212abd6", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_015", + "file": "tests/data/track_b/arf_recompute_sources/poms_rs_00615_015.html", + "bytes": 52789, + "expected_bytes": 52789, + "sha256": "04fccc30851e1ecea2aaf3417b23305fc5af7754a22134cedc2f8cdca8dc29e5", + "expected_sha256": "04fccc30851e1ecea2aaf3417b23305fc5af7754a22134cedc2f8cdca8dc29e5", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_480", + "file": "tests/data/track_b/arf_recompute_sources/poms_rs_00615_480.html", + "bytes": 19441, + "expected_bytes": 19441, + "sha256": "c75dba7710902e1833371d8ef47c3272766260de05684bef5155a4399ac44c78", + "expected_sha256": "c75dba7710902e1833371d8ef47c3272766260de05684bef5155a4399ac44c78", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_482", + "file": "tests/data/track_b/arf_recompute_sources/poms_rs_00615_482.html", + "bytes": 33687, + "expected_bytes": 33687, + "sha256": "8b579019f4e8d0111175b9756ddaa688317026c7db68faefbdf7b322571cdad0", + "expected_sha256": "8b579019f4e8d0111175b9756ddaa688317026c7db68faefbdf7b322571cdad0", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_490", + "file": "tests/data/track_b/arf_recompute_sources/poms_rs_00615_490.html", + "bytes": 22950, + "expected_bytes": 22950, + "sha256": "62acdbcc3790601074414fd23fdee15081f56c8d75543216752f96fc64b40f1e", + "expected_sha256": "62acdbcc3790601074414fd23fdee15081f56c8d75543216752f96fc64b40f1e", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_491", + "file": "tests/data/track_b/arf_recompute_sources/poms_rs_00615_491.html", + "bytes": 18787, + "expected_bytes": 18787, + "sha256": "6bccc5680188c727cf68914ecc907b6c41d58b97aab62e2f26d1798ea735de5b", + "expected_sha256": "6bccc5680188c727cf68914ecc907b6c41d58b97aab62e2f26d1798ea735de5b", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_500", + "file": "tests/data/track_b/arf_recompute_sources/poms_rs_00615_500.html", + "bytes": 19385, + "expected_bytes": 19385, + "sha256": "14b0717fad5f6d392e8945f1f90525fbd08b67f042e39d16ecd3131aed0a272f", + "expected_sha256": "14b0717fad5f6d392e8945f1f90525fbd08b67f042e39d16ecd3131aed0a272f", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_580", + "file": "tests/data/track_b/arf_recompute_sources/poms_rs_00615_580.html", + "bytes": 22043, + "expected_bytes": 22043, + "sha256": "403981fe78797059314fb255173efadd0f49ac06f658e4f30c549ba037147319", + "expected_sha256": "403981fe78797059314fb255173efadd0f49ac06f658e4f30c549ba037147319", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_582", + "file": "tests/data/track_b/arf_recompute_sources/poms_rs_00615_582.html", + "bytes": 19920, + "expected_bytes": 19920, + "sha256": "61f0dc95c7318af53cbf9f5a26d3f21f97936802fc1f477a87be45be7c4b3fc1", + "expected_sha256": "61f0dc95c7318af53cbf9f5a26d3f21f97936802fc1f477a87be45be7c4b3fc1", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_585", + "file": "tests/data/track_b/arf_recompute_sources/poms_rs_00615_585.html", + "bytes": 19591, + "expected_bytes": 19591, + "sha256": "2e574c13ee21827cade7e35cbe3f39242a8d52174ab2b96c87c054106954da87", + "expected_sha256": "2e574c13ee21827cade7e35cbe3f39242a8d52174ab2b96c87c054106954da87", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_590", + "file": "tests/data/track_b/arf_recompute_sources/poms_rs_00615_590.html", + "bytes": 23730, + "expected_bytes": 23730, + "sha256": "2d0e05e38849fc9da5b58de7f2c5af594d84aefbc99cd7bbe088ee9441fb7004", + "expected_sha256": "2d0e05e38849fc9da5b58de7f2c5af594d84aefbc99cd7bbe088ee9441fb7004", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_595", + "file": "tests/data/track_b/arf_recompute_sources/poms_rs_00615_595.html", + "bytes": 18703, + "expected_bytes": 18703, + "sha256": "7c8725bb840e2b2707069947a000c5195a83b9dcec6f241675484bb2f54a89cf", + "expected_sha256": "7c8725bb840e2b2707069947a000c5195a83b9dcec6f241675484bb2f54a89cf", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00615_598", + "file": "tests/data/track_b/arf_recompute_sources/poms_rs_00615_598.html", + "bytes": 17499, + "expected_bytes": 17499, + "sha256": "159726c85182842c5c376b1a51335ae4f8dbe44c3cc9a8b23f04b793719f3595", + "expected_sha256": "159726c85182842c5c376b1a51335ae4f8dbe44c3cc9a8b23f04b793719f3595", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00605_005", + "file": "tests/data/track_b/arf_recompute_sources/poms_rs_00605_005.html", + "bytes": 32296, + "expected_bytes": 32296, + "sha256": "1f018b0996fc946c46603293d756332ec0847103a7cdfb795861e02a63a83815", + "expected_sha256": "1f018b0996fc946c46603293d756332ec0847103a7cdfb795861e02a63a83815", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00605_401", + "file": "tests/data/track_b/arf_recompute_sources/poms_rs_00605_401.html", + "bytes": 25076, + "expected_bytes": 25076, + "sha256": "2234e0909fb874b32c501892aec8db1b6d8bf94a98011b38cc1ac9c5b3720e01", + "expected_sha256": "2234e0909fb874b32c501892aec8db1b6d8bf94a98011b38cc1ac9c5b3720e01", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00605_405", + "file": "tests/data/track_b/arf_recompute_sources/poms_rs_00605_405.html", + "bytes": 17822, + "expected_bytes": 17822, + "sha256": "75c6d37811591f3d44f723e67512abcaae73526b9cb4b6d26e8c1a9dd99e6cc8", + "expected_sha256": "75c6d37811591f3d44f723e67512abcaae73526b9cb4b6d26e8c1a9dd99e6cc8", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00605_407", + "file": "tests/data/track_b/arf_recompute_sources/poms_rs_00605_407.html", + "bytes": 29539, + "expected_bytes": 29539, + "sha256": "0e9813c138269ad303f3dc26c796cc45ed5913d8cb652e8ab92104043e3f6878", + "expected_sha256": "0e9813c138269ad303f3dc26c796cc45ed5913d8cb652e8ab92104043e3f6878", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00605_501", + "file": "tests/data/track_b/arf_recompute_sources/poms_rs_00605_501.html", + "bytes": 25157, + "expected_bytes": 25157, + "sha256": "82d050e85f960956fb69e62ce5e10690a6088fa549711285ac194f0b37742096", + "expected_sha256": "82d050e85f960956fb69e62ce5e10690a6088fa549711285ac194f0b37742096", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00605_560", + "file": "tests/data/track_b/arf_recompute_sources/poms_rs_00605_560.html", + "bytes": 17435, + "expected_bytes": 17435, + "sha256": "a8b9162210f7a783ea5e2ce09cc2b012c7899b75b603e703f2f3aca4f2b3e365", + "expected_sha256": "a8b9162210f7a783ea5e2ce09cc2b012c7899b75b603e703f2f3aca4f2b3e365", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00605_570", + "file": "tests/data/track_b/arf_recompute_sources/poms_rs_00605_570.html", + "bytes": 19484, + "expected_bytes": 19484, + "sha256": "8cf357c54a8f316ea3afba2d2a171996768894d7c4fa9eee5b417e5546d25c79", + "expected_sha256": "8cf357c54a8f316ea3afba2d2a171996768894d7c4fa9eee5b417e5546d25c79", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "poms_rs_00605_580", + "file": "tests/data/track_b/arf_recompute_sources/poms_rs_00605_580.html", + "bytes": 21129, + "expected_bytes": 21129, + "sha256": "cd64e8e63d773dd94c50b0fa4a6cdf750816b38fecf921ec34236de923a0f5ec", + "expected_sha256": "cd64e8e63d773dd94c50b0fa4a6cdf750816b38fecf921ec34236de923a0f5ec", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "ecfr_20cfr_404_280", + "file": "tests/data/track_b/arf_recompute_sources/ecfr_20cfr_404_280.xml", + "bytes": 1389, + "expected_bytes": 1389, + "sha256": "7785688410ccc531336cf8bb6edcab062a3e7d4b891495de6bb3dd596edd2320", + "expected_sha256": "7785688410ccc531336cf8bb6edcab062a3e7d4b891495de6bb3dd596edd2320", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "ecfr_20cfr_404_281", + "file": "tests/data/track_b/arf_recompute_sources/ecfr_20cfr_404_281.xml", + "bytes": 2998, + "expected_bytes": 2998, + "sha256": "6220d7718179030f8ffae5a3c33523711bbcbf16d7abf12fb893320b616dee91", + "expected_sha256": "6220d7718179030f8ffae5a3c33523711bbcbf16d7abf12fb893320b616dee91", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "ecfr_20cfr_404_282", + "file": "tests/data/track_b/arf_recompute_sources/ecfr_20cfr_404_282.xml", + "bytes": 1251, + "expected_bytes": 1251, + "sha256": "601775c323a13319f5b1e348e1a020ebc7a1decee335d06cedae21324c56ff5e", + "expected_sha256": "601775c323a13319f5b1e348e1a020ebc7a1decee335d06cedae21324c56ff5e", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "ecfr_20cfr_404_283", + "file": "tests/data/track_b/arf_recompute_sources/ecfr_20cfr_404_283.xml", + "bytes": 630, + "expected_bytes": 630, + "sha256": "501e458e646c20f92a496f9f09f576e63bd7febc06c5b6647ccba43884e28532", + "expected_sha256": "501e458e646c20f92a496f9f09f576e63bd7febc06c5b6647ccba43884e28532", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "ecfr_20cfr_404_284", + "file": "tests/data/track_b/arf_recompute_sources/ecfr_20cfr_404_284.xml", + "bytes": 5474, + "expected_bytes": 5474, + "sha256": "5cbca424f931555ae8576b4e89d652a8be857041da39bf6836bb7f6aae0df1ea", + "expected_sha256": "5cbca424f931555ae8576b4e89d652a8be857041da39bf6836bb7f6aae0df1ea", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "ecfr_20cfr_404_285", + "file": "tests/data/track_b/arf_recompute_sources/ecfr_20cfr_404_285.xml", + "bytes": 1131, + "expected_bytes": 1131, + "sha256": "9d68132c1ecb47f95599894af72bd562a97c5eaa63da6d06c984e53fa689695d", + "expected_sha256": "9d68132c1ecb47f95599894af72bd562a97c5eaa63da6d06c984e53fa689695d", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "ecfr_20cfr_404_286", + "file": "tests/data/track_b/arf_recompute_sources/ecfr_20cfr_404_286.xml", + "bytes": 946, + "expected_bytes": 946, + "sha256": "b1c980f4204bf6fe073872ed66b25cc0639e0c62fb172e52233bc929229bd434", + "expected_sha256": "b1c980f4204bf6fe073872ed66b25cc0639e0c62fb172e52233bc929229bd434", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "ecfr_20cfr_404_287", + "file": "tests/data/track_b/arf_recompute_sources/ecfr_20cfr_404_287.xml", + "bytes": 742, + "expected_bytes": 742, + "sha256": "8cdbb57984bd5e64574c8302bdd4553191d40091e62a76e274635aa1b14fb6ca", + "expected_sha256": "8cdbb57984bd5e64574c8302bdd4553191d40091e62a76e274635aa1b14fb6ca", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "ecfr_20cfr_404_288", + "file": "tests/data/track_b/arf_recompute_sources/ecfr_20cfr_404_288.xml", + "bytes": 1923, + "expected_bytes": 1923, + "sha256": "1d07ea68fb8ce0b5c7b977f6c8a5e8911092d4a4d1b73dc1bcef87dd777d887c", + "expected_sha256": "1d07ea68fb8ce0b5c7b977f6c8a5e8911092d4a4d1b73dc1bcef87dd777d887c", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "ecfr_20cfr_404_410", + "file": "tests/data/track_b/arf_recompute_sources/ecfr_20cfr_404_410.xml", + "bytes": 7247, + "expected_bytes": 7247, + "sha256": "2b4c11db537329505d0f9534707cac9c969baebdeb1919c52ac103dd3a1797ba", + "expected_sha256": "2b4c11db537329505d0f9534707cac9c969baebdeb1919c52ac103dd3a1797ba", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "ecfr_20cfr_404_411", + "file": "tests/data/track_b/arf_recompute_sources/ecfr_20cfr_404_411.xml", + "bytes": 7186, + "expected_bytes": 7186, + "sha256": "afeee4eaf40387f1759ddf04b6c62d1fe9d6fa5ca1fb7170fe8872f9e651c5e8", + "expected_sha256": "afeee4eaf40387f1759ddf04b6c62d1fe9d6fa5ca1fb7170fe8872f9e651c5e8", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "ecfr_20cfr_404_412", + "file": "tests/data/track_b/arf_recompute_sources/ecfr_20cfr_404_412.xml", + "bytes": 2445, + "expected_bytes": 2445, + "sha256": "e560ab4ca39a5281573578ad89fcc64ef59edb6c3876bc2c75dd828bdac1aa89", + "expected_sha256": "e560ab4ca39a5281573578ad89fcc64ef59edb6c3876bc2c75dd828bdac1aa89", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "ecfr_20cfr_404_409", + "file": "tests/data/track_b/arf_recompute_sources/ecfr_20cfr_404_409.xml", + "bytes": 5298, + "expected_bytes": 5298, + "sha256": "f5545ff658026f9926715cbc75d032ab1d502833d828c552e303bef494e9dce9", + "expected_sha256": "f5545ff658026f9926715cbc75d032ab1d502833d828c552e303bef494e9dce9", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "lii_usc_402q_415f_excerpts", + "file": "tests/data/track_b/arf_recompute_sources/lii_usc_402q_415f_excerpts.txt", + "bytes": 21424, + "expected_bytes": 21424, + "sha256": "6e35d38fcf7a31e13338acd8a0ae3bc5a1acd82a980e424d61344b6634b01966", + "expected_sha256": "6e35d38fcf7a31e13338acd8a0ae3bc5a1acd82a980e424d61344b6634b01966", + "bytes_match": true, + "sha256_match": true + }, + { + "id": "ssa_pub_05_10069_arf_recompute_excerpts", + "file": "tests/data/track_b/arf_recompute_sources/ssa_pub_05_10069_arf_recompute_excerpts.txt", + "bytes": 1466, + "expected_bytes": 1466, + "sha256": "f2877909a960f6bcd5497641374d2e53b0feb46f59e2f7085eb6eab02de0e06b", + "expected_sha256": "f2877909a960f6bcd5497641374d2e53b0feb46f59e2f7085eb6eab02de0e06b", + "bytes_match": true, + "sha256_match": true + } + ], + "served_body_pins": [ + { + "source_id": "lii_usc_402q_415f_excerpts", + "sha256": "e5bb977c3ab381c2c3bd4f6bb320b86f25e2f0ad2b629e01333be56727d3823b", + "local_capture": null, + "verification": "remote provenance pin has no local file; no independent rehash claimed" + }, + { + "source_id": "lii_usc_402q_415f_excerpts", + "sha256": "c3262e82e8e674caf43709c522ce60760eafb0b133e1f99221ca7aa97d54ea3a", + "local_capture": null, + "verification": "remote provenance pin has no local file; no independent rehash claimed" + }, + { + "source_id": "ssa_pub_05_10069_arf_recompute_excerpts", + "sha256": "2ecbfd9234ba445e73259f284d861277ca186d2a8582744a541f2ac1077bbf4f", + "local_capture": null, + "verification": "remote provenance pin has no local file; no independent rehash claimed" + } + ], + "new_capture_logs": [] + } + ], + "total_local_captures_verified": 148, + "protected_path_violations": [], + "git_status_short": " M docs/design/track_b_g2_r2b_mutations.json\n M docs/design/track_b_g_gross_benefits.md\n M docs/design/track_b_r2_ret_ledger.md\n M src/populace_dynamics/track_b/gross_benefits.py\n M tests/data/track_b/gross_benefit_examples.yaml\n M tests/test_track_b_gross_benefits_deductions.py\n M tests/test_track_b_gross_benefits_fix_round_10_api.py\n M tests/test_track_b_gross_benefits_registry.py\n M tests/test_track_b_ret_ledger_fix_round_2.py\n?? tests/test_track_b_gross_benefits_deduction_age_inputs.py\n", + "finished_at_utc": "2026-10-25T19:58:04.511021+00:00", + "format_clean": true, + "final_status_paths": [ + "docs/design/track_b_g2_r2b_mutations.json", + "docs/design/track_b_g_gross_benefits.md", + "docs/design/track_b_r2_ret_ledger.md", + "src/populace_dynamics/track_b/gross_benefits.py", + "tests/data/track_b/gross_benefit_examples.yaml", + "tests/test_track_b_gross_benefits_deductions.py", + "tests/test_track_b_gross_benefits_fix_round_10_api.py", + "tests/test_track_b_gross_benefits_registry.py", + "tests/test_track_b_ret_ledger_fix_round_2.py", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py" + ], + "protected_path_violations_from_status": [], + "final_check_note": "Final Black check explicitly used --workers1; Ruff final rerun set RAYON_NUM_THREADS1. No pytest was launched by this mechanics audit." + } + } } diff --git a/docs/design/track_b_g_gross_benefits.md b/docs/design/track_b_g_gross_benefits.md index 81a846665..8b76784be 100644 --- a/docs/design/track_b_g_gross_benefits.md +++ b/docs/design/track_b_g_gross_benefits.md @@ -675,7 +675,7 @@ G never falls back to a single-worker computation. | `independently_entitled_divorced_spouse` | IEDS before January 1985 or a WEP-affected worker record before January 2024 (RS 00202.100) | | `non_aime_formula_pia` | Old-start, special-minimum and frozen-minimum PIAs (RS 00615.740B.1) | | `savings_clause_403a5` | Under explicit `LITERAL_REFUSAL`, a governed month whose total fell below a 403(a)(5) protected total, and every later governed month | -| `savings_clause_membership_change` | Membership or record kind changes during a carried operational protection; the capture supplies no successor protection rule | +| `savings_clause_membership_change` | Membership changes at the first qualifying fall, or membership/record kind changes during carried operational protection; the capture supplies no successor protection rule | | `savings_clause_rate_procedure` | An operational raise needs an uncaptured survivor/dual/deduction/reduced-auxiliary allocation, a simultaneous age-factor change or declining FMAX prevents causal attribution, or the protected rate exceeds OB; the captured procedure does not settle these payments | | `savings_clause_history_unknown` | A month for which a protected total G cannot see may exist (a path not started at entitlement, or a month G did not compute) | | `widow_drc_savings_clause` | A May 1978 beneficiary protected from widow(er) deceased-worker DRC reductions (RS 00615.712) | @@ -787,7 +787,8 @@ pins an accurate diagnostic, the 1929 control pins the exact payments, and 8. **Results are deterministic and independent of beneficiary order.** Every amount is a dime multiple, and each whole-dollar payment is the floor of its amount. -9. **403(a)(5).** Along any month path that starts at entitlement: +9. **403(a)(5), explicit `LITERAL_REFUSAL` reading.** Along any month + path that starts at entitlement: - an admitted month with anyone under the maximum is never below an earlier protected total, and never follows such a fall; - a refused month has someone under the maximum and a fall behind it; @@ -2624,30 +2625,55 @@ dictionaries retain associations. Types, enum identities and every raw container entry follow the existing public schema. `worker_deductions` optionally reserves the number holder's charges against auxiliaries; those charges do not release room (GN 02603.040B; RS 02501.155B.3.c). -For a spouse's `NO_CHILD_IN_CARE` event, `under_full_retirement_age=True` -is required and the supplied spouse benefit must be unreduced for age. -Act 203(c)(2) limits this deduction to a spouse "under retirement age" -whose benefit "was not reduced under the provisions of section 202(q)"; -20 CFR 404.421(a) likewise excludes the reduced-benefit election month. -Missing or false age attestation, age-reduced spouse benefits and declared -current care are `InvalidFamilyInput` before a family or household refusal. -The attestation must also agree with a supplied birth cohort. SSA cohorts -run from January 2 through January 1 of the following year, with age -attained the day before the birthday (RS 00615.003/.010). If the payment -month is at or after even that cohort's latest possible FRA month, an -under-FRA attestation is impossible and invalid; an unknown birthday inside -the cohort's FRA interval remains a caller-attested fact. A 1950-cohort -spouse in January 2024 therefore cannot lose its $2 ordinary benefit under -a falsely attested no-care event on PIA $4/MAX $6. +For a spouse's `NO_CHILD_IN_CARE` event the supplied spouse benefit must +be unreduced for age. The captured Act 203(c)(2) says "if a wife or husband +under retirement age" and "and such wife's or husband's insurance benefit +for such month was not reduced under the provisions of section 202(q)". +The captured 20 CFR 404.421(a) says "if he or she is under full retirement +age" and excludes a month when "there is in effect a certificate of election +for him or her to receive actuarially reduced wife's or husband's benefits +for such month". The quotation test checks each phrase verbatim against the +existing hashed Act and CFR captures. + +G first uses supplied facts. Positive spouse reduction months exclude this +deduction, irrespective of the age attestation. A beneficiary cohort, an +own-benefit cohort, or a cohort resolved across household records establishes +an FRA-attainment interval. SSA cohorts run January 2 through the following +January 1; age is attained the day before the birthday (RS 00615.003/.010). +The earliest FRA month is January of the cohort year plus FRA months, and +the latest is eleven months later. Before that interval, under-FRA status +is established and no attestation is required. At or after its latest month, +the deduction is invalid. Supplied own delayed-credit months also exclude +under-FRA status (Act 202(w)); own-RIB reduction months persist after FRA +and do not by themselves establish current age. Zero spouse reduction +months establish an unreduced benefit, but do not establish age. + +Only if no supplied fact settles age (including a payment month inside the +cohort's FRA interval) must `under_full_retirement_age=True` be supplied. +An explicit false attestation is incompatible with a no-care spouse event. +Contradictory age, age-reduced benefits and declared current care raise +`InvalidFamilyInput` before any family or household refusal and produce no +denominator row. Each entitlement on every household record is checked, +including repeated person IDs. A 1950-cohort spouse in January 2024 cannot +lose its $2 ordinary benefit through a falsely attested no-care event on +PIA $4/MAX $6. A 1960-cohort spouse needs no separate age attestation in +that month. The optional attestation completes missing age information; it +does not override facts G already admits. Mother/father deductions under 203(c)(3)-(4) have no spouse age condition. +The RS 02501.130 registry example explicitly describes "Their spouse +(age 55)". Both November and December inputs attest under-FRA status on +that supplied premise; the registry loader passes the optional field through. +The capture-quotation test checks the age phrase and retains all published +$83.50 child rates and $83 whole-dollar payments. + | Configuration | Result | |---|---| | No deductions | Exactly the existing family or household result | | Auxiliary or survivor own earnings deduction, full or partial | Supported | | Permanent deduction | GN 02603.050C redistribution | | Estimated own earnings deduction | Same-household increase; other households retain their previous rate | -| No child in care, full deduction | Supported for an unreduced spouse with an explicit under-FRA attestation, or a mother/father | +| No child in care, full deduction | Supported for an unreduced spouse whose under-FRA status is derived or, if unknown, attested; or a mother/father | | Dual entitlement | Existing Parisi computation, including zero technical rates | | Workers' compensation offset | `workers_compensation_offset` | | Prisoner suspension | `prisoner_suspension` | @@ -3016,6 +3042,18 @@ Every new invariant has a Hypothesis property beside the examples: the spouse age exclusion and required eligibility fact in both public forms. `test_age_reduced_no_care_is_input_error_before_refusal` keeps invalid declarations out of the denominator even with a held refusal. + `test_supplied_younger_cohort_needs_no_age_attestation` checks exact + equality with the explicitly attested result using either cohort field. + `test_supplied_older_cohort_is_input_error_before_household_refusal` + checks input priority and zero denominator rows. + `test_cohort_fra_interval_uses_attestation_only_when_needed` pins both + interval endpoints across generated cohorts 1938–1960 against an + independent Act 216(l) FRA schedule, retaining explicit cohort 1958 + examples. `test_each_household_entitlement_checks_no_care_age_before_refusal` + generates positive reductions and pins repeated-person order independence. + `test_supplied_delayed_credits_exclude_no_care_even_inside_cohort_interval` + generates positive credits and checks that attestation cannot override + a supplied post-FRA fact. - `test_zero_event_cannot_change_existing_full_deduction_output` rejects permanent and temporary no-op events without any result or denominator change, preserving exact and whole-dollar controls, determinism and the diff --git a/docs/design/track_b_r2_ret_ledger.md b/docs/design/track_b_r2_ret_ledger.md index 397237d57..05c2affad 100644 --- a/docs/design/track_b_r2_ret_ledger.md +++ b/docs/design/track_b_r2_ret_ledger.md @@ -902,7 +902,7 @@ In the table, unqualified property test names are in | R1 annual amounts and exact rates match every supported bundled year, with zero tolerance | `test_r1_differential_matches_every_supported_year_exactly`; `test_r1_differential_statutory_default_is_exactly_one_twelfth` | | The default statutory monthly limit is exactly annual/12, with zero tolerance; wages above it cannot protect a grace month | `test_r1_differential_statutory_default_is_exactly_one_twelfth`; readings `test_property_default_monthly_limit_is_exact_twelfth_and_controls_grace_wages`; unit `test_act_203_f_8_d_vi_exact_limit_is_not_chart_ceiling`; source `test_act_203_f_8_d_v_vi_monthly_amounts_are_quoted_and_equal_annual_twelfths` | | Missing R1 years raise rather than substitute | `test_r1_differential_missing_year_raises_without_substitution`; unit `test_missing_parameter_year_is_not_carried_forward` | -| G monthly own-benefit facts establish annual two-record exposure, independently of beneficiary and household order; an omitted flag cannot admit actual or estimated excess | review `test_contextual_own_rib_requires_two_record_refusal`; property `test_two_record_derivation_is_order_independent` | +| G monthly own-benefit facts establish annual two-record exposure, including own-benefit onset or cessation between supplied months, independently of month, beneficiary and household order; an omitted flag cannot admit actual or estimated excess | review `test_contextual_own_rib_requires_two_record_refusal`; property `test_two_record_derivation_is_order_independent` | | A declared two-record flag contradicting supplied G facts is an input error and creates no outcome or denominator row | review `test_declared_two_record_contradiction_is_input_error` | | Missing supported R1 years precede held G coverage refusals and create no outcome or denominator row | review `test_missing_r1_parameter_precedes_held_g_refusal`; property `test_unavailable_supported_r1_year_is_never_a_coverage_row` | | R2 emits G own-work events only for positive actual deductions; a person with zero excess never becomes a deductee in either actual or estimated runs | review property `test_r2_emits_only_positive_actual_deduction_events` | diff --git a/src/populace_dynamics/track_b/gross_benefits.py b/src/populace_dynamics/track_b/gross_benefits.py index f2083d5ef..b824e19e1 100644 --- a/src/populace_dynamics/track_b/gross_benefits.py +++ b/src/populace_dynamics/track_b/gross_benefits.py @@ -6,8 +6,9 @@ timing, no annual earnings or charge determination (R2), and no ARF or recomputation (R3). The deduction entry points apply caller-declared monthly deductions before redistributing the maximum (203(a)(4)). -No-care spouse deductions require an unreduced benefit and an explicit -under-full-retirement-age attestation (203(c)(2); 20 CFR 404.421(a)). +No-care spouse deductions require an unreduced benefit and under-FRA +status, derived from supplied facts or otherwise attested (203(c)(2); +20 CFR 404.421(a)). Own-work events must withhold a positive amount; a zero deduction is an input error and never changes the family-maximum computation. Max's ruling d515 (2026-09-28) adopted §10 question 9's default: a Python @@ -2265,8 +2266,9 @@ class BenefitDeduction: own-work deductions have ``permanent=False``; all other supported events are permanent. Dual entitlement is already declared by ``OwnBenefit``; an explicit marker must agree with the ordinary G payable. - ``under_full_retirement_age`` must be True for a spouse no-care - deduction (203(c)(2); 20 CFR 404.421(a)); None does not establish age. + ``under_full_retirement_age`` attests a spouse no-care deduction only + when the supplied cohort does not settle age (203(c)(2); 20 CFR + 404.421(a)). Supplied facts take priority over the attestation. Own-work payables must be strictly below the ordinary rate after NH reservations. R2 emits only strictly positive own-work deductions. """ @@ -3827,8 +3829,10 @@ def _check_deduction_inputs( raise InvalidFamilyInput( "Temporary deductions require every beneficiary's household" ) - for key, event in deductions.items(): - member = members[key] + for member in beneficiaries: + event = deductions.get(member.beneficiary_id) + if event is None: + continue if ( event.reason is DeductionReason.DUAL_ENTITLEMENT and member.own_benefit is None @@ -3851,26 +3855,39 @@ def _check_deduction_inputs( raise InvalidFamilyInput( "No-child-in-care deduction excludes age-reduced spouses" ) - if event.under_full_retirement_age is not True: - raise InvalidFamilyInput( - "No-child-in-care spouse deduction requires under-FRA status" - ) + under_fra = None if member.birth_year is not None: # SSA cohorts run Jan 2 through Jan 1 of the next - # year; the latest possible Jan 1 birth attains FRA - # in the preceding month (RS 00615.003/.010). - latest_fra = ( - (member.birth_year + 1) * 12 - + _fra_months(member.birth_year, params) - - 1 + # year, with age attained the day before the birthday + # (RS 00615.003/.010). A cohort gives an interval, + # not an exact birthday or FRA-attainment month. + earliest_fra = member.birth_year * 12 + _fra_months( + member.birth_year, params + ) + latest_fra = earliest_fra + 11 + month = payment_month.year * 12 + payment_month.month - 1 + if month < earliest_fra: + under_fra = True + elif month >= latest_fra: + under_fra = False + own = member.own_benefit + if own is not None and own.delayed_credit_months: + # Credits accrue only after FRA (Act 202(w)). Prior + # own-RIB reduction months instead persist after FRA + # and cannot establish the person's current age. + under_fra = False + if under_fra is False: + raise InvalidFamilyInput( + "No-child-in-care deduction contradicts the birth cohort " + "or supplied post-FRA credits" + ) + if event.under_full_retirement_age is False or ( + under_fra is None + and event.under_full_retirement_age is not True + ): + raise InvalidFamilyInput( + "No-child-in-care spouse deduction requires under-FRA status" ) - if ( - payment_month.year * 12 + payment_month.month - 1 - >= latest_fra - ): - raise InvalidFamilyInput( - "Under-FRA attestation contradicts the birth cohort" - ) if isinstance(member.child_in_care, str): raise InvalidFamilyInput( "No-child-in-care deduction conflicts with current care" diff --git a/tests/README-tiers.md b/tests/README-tiers.md index f28749a07..17e6a47cb 100644 --- a/tests/README-tiers.md +++ b/tests/README-tiers.md @@ -39,9 +39,9 @@ pytest --collect-only -q -m oracle_policyengine | tail -1 | Tier | Tests at HEAD | |---|---:| -| `unit` | 19,040 | +| `unit` | 19,068 | | `artifact` | 4,271 | | `integration_psid` | 1,471 | | `reproduction_legacy` | 520 | | `oracle_policyengine` | 308 | -| **Total** | **25,610** | +| **Total** | **25,638** | diff --git a/tests/data/track_b/gross_benefit_examples.yaml b/tests/data/track_b/gross_benefit_examples.yaml index 75b23aecb..008c22e88 100644 --- a/tests/data/track_b/gross_benefit_examples.yaml +++ b/tests/data/track_b/gross_benefit_examples.yaml @@ -2490,6 +2490,7 @@ examples: reason: no_child_in_care payable: '0' permanent: true + under_full_retirement_age: true households: B: home C2: home @@ -2515,6 +2516,7 @@ examples: reason: no_child_in_care payable: '0' permanent: true + under_full_retirement_age: true households: B: home C2: home diff --git a/tests/test_track_b_gross_benefits_deduction_age_inputs.py b/tests/test_track_b_gross_benefits_deduction_age_inputs.py new file mode 100644 index 000000000..524480372 --- /dev/null +++ b/tests/test_track_b_gross_benefits_deduction_age_inputs.py @@ -0,0 +1,183 @@ +"""Statutory conformance: derive spouse no-care age from supplied facts. + +Act 203(c)(2), 20 CFR 404.421(a), RS 00615.003/.010; invented inputs only. +No population, behavioral or forecast claim. +""" + +from dataclasses import replace + +import pytest +from hypothesis import example, given, settings +from hypothesis import strategies as st + +from populace_dynamics.track_b import gross_benefits as g +from tests.test_track_b_gross_benefits_deductions_fix_round_2 import ( + MONTH, + PARAMS, + compute, + retirement, +) + + +@pytest.mark.parametrize("household", (False, True)) +@pytest.mark.parametrize("own_cohort", (False, True)) +@given(cohort=st.integers(1960, 1980)) +@settings(max_examples=8, deadline=None) +def test_supplied_younger_cohort_needs_no_age_attestation( + household, own_cohort, cohort +): + state, members = retirement(children=0, reduction=0) + member = replace(members[0], birth_year=cohort) + if own_cohort: + member = replace( + member, + birth_year=None, + own_benefit_first=True, + own_benefit=g.OwnBenefit( + g.OwnBenefitKind.DISABILITY, 1, birth_year=cohort + ), + ) + event = g.BenefitDeduction(g.DeductionReason.NO_CHILD_IN_CARE) + result = compute(state, (member,), {"B": event}, household) + family = result.records["record"] if household else result + assert family.by_id()["B"].auxiliary_payable == 0 + explicit = replace(event, under_full_retirement_age=True) + assert compute(state, (member,), {"B": explicit}, household) == result + + +@pytest.mark.parametrize("household", (False, True)) +@pytest.mark.parametrize("attestation", (None, False, True)) +@given(cohort=st.integers(1930, 1950)) +@settings(max_examples=8, deadline=None) +def test_supplied_older_cohort_is_input_error_before_household_refusal( + household, attestation, cohort +): + state, members = retirement(children=0, reduction=0) + member = replace(members[0], birth_year=cohort) + event = g.BenefitDeduction( + g.DeductionReason.NO_CHILD_IN_CARE, + under_full_retirement_age=attestation, + ) + state = replace( + state, conditions={g.RecordCondition.ADMINISTRATIVE_FINALITY} + ) + outcomes = [] + with pytest.raises(g.InvalidFamilyInput): + outcomes.append( + g.evaluate_family( + "age", + 3, + lambda: compute(state, (member,), {"B": event}, household), + ) + ) + assert g.count_family_outcomes(outcomes).rows == 0 + + +@pytest.mark.parametrize( + "offset,expected_under", + ((-1, True), (0, None), (10, None), (11, False)), +) +@pytest.mark.parametrize("attestation", (None, False, True)) +@given(cohort=st.integers(1938, 1960)) +@example(cohort=1958) +@settings(max_examples=8, deadline=None) +def test_cohort_fra_interval_uses_attestation_only_when_needed( + offset, expected_under, attestation, cohort +): + # Cohort 1958 has FRA 66y8m: earliest September 2024, latest August 2025. + state, members = retirement(children=0, reduction=0) + member = replace(members[0], birth_year=cohort) + # Independent statutory FRA schedule, in months (Act 216(l)). + fra = ( + 780 + 2 * (cohort - 1937) + if cohort <= 1942 + else 792 if cohort <= 1954 else 792 + 2 * (cohort - 1954) + ) + year, month = divmod(cohort * 12 + fra + offset, 12) + payment = g.YearMonth(year, month + 1) + event = g.BenefitDeduction( + g.DeductionReason.NO_CHILD_IN_CARE, + under_full_retirement_age=attestation, + ) + kwargs = dict( + payment_month=payment, + params=PARAMS, + deductions={"B": event}, + households={}, + standalone=True, + ) + if ( + expected_under is False + or attestation is False + or (expected_under is None and attestation is None) + ): + with pytest.raises(g.InvalidFamilyInput): + g.family_benefits_after_deductions(state, (member,), **kwargs) + else: + result = g.family_benefits_after_deductions(state, (member,), **kwargs) + assert result.by_id()["B"].auxiliary_payable == 0 + + +@pytest.mark.parametrize("reverse", (False, True)) +@given(reduction=st.integers(1, 60)) +@example(reduction=60) +@settings(max_examples=8, deadline=None) +def test_each_household_entitlement_checks_no_care_age_before_refusal( + reverse, reduction +): + state, members = retirement(children=0, reduction=reduction) + reduced = members[0] + unreduced = replace(reduced, reduction_months=0) + entries = [ + ("a", g.HouseholdRecord("worker-a", state, (reduced,))), + ("b", g.HouseholdRecord("worker-b", state, (unreduced,))), + ] + records = dict(reversed(entries) if reverse else entries) + with pytest.raises(g.InvalidFamilyInput, match="age-reduced"): + g.household_benefits_after_deductions( + records, + payment_month=MONTH, + params=PARAMS, + deductions={ + "B": g.BenefitDeduction( + g.DeductionReason.NO_CHILD_IN_CARE, + under_full_retirement_age=True, + ) + }, + households={}, + ) + + +@given(credits=st.integers(1, 12)) +@example(credits=1) +@settings(max_examples=8, deadline=None) +def test_supplied_delayed_credits_exclude_no_care_even_inside_cohort_interval( + credits, +): + state, members = retirement(children=0, reduction=0) + member = replace( + members[0], + birth_year=1958, + own_benefit_first=True, + own_benefit=g.OwnBenefit( + g.OwnBenefitKind.OLD_AGE, + 1, + birth_year=1958, + delayed_credit_months=credits, + ), + ) + with pytest.raises(g.InvalidFamilyInput, match="post-FRA credits"): + g.family_benefits_after_deductions( + state, + (member,), + payment_month=g.YearMonth(2025, 2), + params=PARAMS, + standalone=True, + households={}, + deductions={ + "B": g.BenefitDeduction( + g.DeductionReason.NO_CHILD_IN_CARE, + under_full_retirement_age=True, + ) + }, + ) diff --git a/tests/test_track_b_gross_benefits_deductions.py b/tests/test_track_b_gross_benefits_deductions.py index 0cc0a02ee..0a177def8 100644 --- a/tests/test_track_b_gross_benefits_deductions.py +++ b/tests/test_track_b_gross_benefits_deductions.py @@ -167,6 +167,7 @@ def test_rs_02501_160_separate_households(payable, permanent, expected): def test_rs_02501_130_no_child_in_care(): + assert "Their spouse (age 55)" in source_text("poms_rs_02501_130") state = g.RecordState( g.FamilyKind.RETIREMENT, F("242.30"), diff --git a/tests/test_track_b_gross_benefits_fix_round_10_api.py b/tests/test_track_b_gross_benefits_fix_round_10_api.py index ce056ab62..2bf552021 100644 --- a/tests/test_track_b_gross_benefits_fix_round_10_api.py +++ b/tests/test_track_b_gross_benefits_fix_round_10_api.py @@ -88,6 +88,7 @@ "reason": (None, "own_earnings_test", g.FamilyKind.SURVIVOR), "payable": MONEY, "permanent": BOOL, + "under_full_retirement_age": (0, 1, "true"), }, "BeneficiaryBenefit": { "beneficiary_id": TEXT, diff --git a/tests/test_track_b_gross_benefits_registry.py b/tests/test_track_b_gross_benefits_registry.py index 2bbf1f64c..43ef5d0f5 100644 --- a/tests/test_track_b_gross_benefits_registry.py +++ b/tests/test_track_b_gross_benefits_registry.py @@ -186,6 +186,9 @@ def _scenario(raw): g.DeductionReason(value["reason"]), F(value.get("payable", "0")), value.get("permanent", True), + under_full_retirement_age=value.get( + "under_full_retirement_age" + ), ) for key, value in raw.get("deductions", {}).items() }, diff --git a/tests/test_track_b_ret_ledger_fix_round_2.py b/tests/test_track_b_ret_ledger_fix_round_2.py index fea4add0d..329b12fb4 100644 --- a/tests/test_track_b_ret_ledger_fix_round_2.py +++ b/tests/test_track_b_ret_ledger_fix_round_2.py @@ -198,9 +198,31 @@ def contradictory_record(): @settings(max_examples=12, deadline=None, derandomize=True) -@given(pia=st.integers(1, 100).map(lambda n: 10 * n), estimated=st.booleans()) -def test_two_record_derivation_is_order_independent(pia, estimated): - case = dual_record(pia, estimated=estimated) +@given( + pia=st.integers(1, 100).map(lambda n: 10 * n), + estimated=st.booleans(), + own_first=st.booleans(), +) +def test_two_record_derivation_is_order_independent(pia, estimated, own_first): + own = dual_record(pia, estimated=estimated) + no_own = dual_record(pia, estimated=estimated, own=False) + first, second = (own, no_own) if own_first else (no_own, own) + later_people = {b.beneficiary_id: b for b in second.beneficiaries} + case = replace( + first, + beneficiaries=tuple( + replace( + person, + gross_rates=(person.gross_rates[0],) + + later_people[person.beneficiary_id].gross_rates[1:], + ) + for person in first.beneficiaries + ), + family_months={ + 1: first.family_months[1], + 2: second.family_months[1], + }, + ) reordered = replace( case, beneficiaries=tuple(reversed(case.beneficiaries)), diff --git a/tests/tier_counts.json b/tests/tier_counts.json index fabd121a6..110492dd0 100644 --- a/tests/tier_counts.json +++ b/tests/tier_counts.json @@ -1,7 +1,7 @@ { "schema_version": 1, "counts": { - "unit": 19040, + "unit": 19068, "artifact": 4271, "integration_psid": 1471, "reproduction_legacy": 520, From 7fa124e305cca531a6006355851c9bf3e273a8c5 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 31 Oct 2026 09:26:45 -0400 Subject: [PATCH 06/17] Refresh the G conformance report's registry hash (#563) Round 2 added two under_full_retirement_age lines to the example registry after the fix lane's conformance check, so the report's registry hash went stale and CI's byte-for-byte test failed at bbcdf7f4. Regeneration changes that one line; all 356,400 configurations match. The verification ledger records the before and after hashes. Co-Authored-By: Claude Opus 5.5 --- docs/design/track_b_g_conformance_report.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/design/track_b_g_conformance_report.json b/docs/design/track_b_g_conformance_report.json index 6dc5b3927..9522d601a 100644 --- a/docs/design/track_b_g_conformance_report.json +++ b/docs/design/track_b_g_conformance_report.json @@ -508,7 +508,7 @@ ] } }, - "sha256": "a06a3f7158b6b5e4ce6901fd8de94bdf30e485ebbc3e967cdb9422ebd955abb6", + "sha256": "58bc989f71090b513f9ed86fd22935e37d8237501477fee38eaef82952bab036", "supported_classes": [ "cola_path", "credits:own_rib", From 872cebc73e4cfc41f21d82188cd11630266393d4 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 31 Oct 2026 09:27:04 -0400 Subject: [PATCH 07/17] Record the conformance hash refresh in the verification ledger (#563) The previous commit's message says the ledger records the before and after hashes, but that edit did not apply. This commit adds them. The ledger's earlier sha256 values stay as measurements from before the refresh. Co-Authored-By: Claude Opus 5.5 --- docs/design/track_b_g2_r2b_verification.json | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/design/track_b_g2_r2b_verification.json b/docs/design/track_b_g2_r2b_verification.json index 10934edac..0a9a7747b 100644 --- a/docs/design/track_b_g2_r2b_verification.json +++ b/docs/design/track_b_g2_r2b_verification.json @@ -3926,5 +3926,16 @@ "protected_path_violations_from_status": [], "final_check_note": "Final Black check explicitly used --workers1; Ruff final rerun set RAYON_NUM_THREADS1. No pytest was launched by this mechanics audit." } + }, + "conformance_registry_hash_refresh": { + "reason": "The fix lane added two under_full_retirement_age lines to tests/data/track_b/gross_benefit_examples.yaml after its conformance check, so the report's registry hash went stale. CI's byte-for-byte test caught it at bbcdf7f4.", + "changed_field": "registry.sha256", + "changed_lines": 1, + "configurations_regenerated": 356400, + "registry_sha256_before": "a06a3f7158b6b5e4ce6901fd8de94bdf30e485ebbc3e967cdb9422ebd955abb6", + "registry_sha256_after": "58bc989f71090b513f9ed86fd22935e37d8237501477fee38eaef82952bab036", + "report_sha256_before": "ee8ef3247a700b4cec92dfc27bbb98b071deaba5566b092cb9c3df4f762be972", + "report_sha256_after": "df2317b43437689f770e08977487cf732bf4a8cad509e4c077630cd71973ffe4", + "note": "Earlier sha256 values in this ledger are measurements taken before this refresh." } } From 1ce508e538cd7d2a9ed8e82bbbc32a29fb0a1669 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 31 Oct 2026 13:24:59 -0400 Subject: [PATCH 08/17] Check FRA facts, the OB bound and as-if-absent membership (#563 round 3) Sol's second review found three more defects. R2 accepted an FRA declaration that the family's G birth cohort contradicted, which let an own-earnings deduction run after FRA. RecordYear now checks the NH and every auxiliary against the twelve months each cohort allows, and own delayed credits against the snapshot month, before any coverage refusal. Act 203(f)(9) and RS 02501.021B.3 apply the old-age FRA to every role, so this needed no ruling. An OWN_EARNINGS_TEST event whose payable plus NH reservation equals the original benefit withholds nothing, so it's now an input error, even on a held record. An age-reduced divorced spouse outside the maximum could start operational protection. Act 203(a)(3)(C) determines the other benefits as if that spouse were absent, so operational membership, the age basis, the age trigger and the person count now skip anyone outside the maximum. That person's own rate stays ordinary, and the literal reading doesn't move. The tier files add this round's 176 unit tests to the previous sum; the coordinator's slot recount replaces them. Co-Authored-By: Claude Opus 5.5 --- docs/design/track_b_g2_r2b_mutations.json | 371 ++++++++++- docs/design/track_b_g2_r2b_verification.json | 620 +++++++++++++++++- docs/design/track_b_g_gross_benefits.md | 87 ++- docs/design/track_b_r2_ret_ledger.md | 85 +++ .../track_b/gross_benefits.py | 51 +- src/populace_dynamics/track_b/ret_ledger.py | 72 ++ tests/README-tiers.md | 4 +- ...st_track_b_gross_benefits_deduction_cap.py | 217 ++++++ ...t_track_b_gross_benefits_saving_absence.py | 371 +++++++++++ tests/test_track_b_ret_fra_facts.py | 537 +++++++++++++++ tests/tier_counts.json | 2 +- 11 files changed, 2396 insertions(+), 21 deletions(-) create mode 100644 tests/test_track_b_gross_benefits_deduction_cap.py create mode 100644 tests/test_track_b_gross_benefits_saving_absence.py create mode 100644 tests/test_track_b_ret_fra_facts.py diff --git a/docs/design/track_b_g2_r2b_mutations.json b/docs/design/track_b_g2_r2b_mutations.json index 0b3803831..893ed2b92 100644 --- a/docs/design/track_b_g2_r2b_mutations.json +++ b/docs/design/track_b_g2_r2b_mutations.json @@ -2,12 +2,12 @@ "schema_version": 1, "verification_class": "statutory_conformance", "admitted_scope": "Mutation sensitivity of statutory rules on invented and captured worked cases only; no population, behavioral or forecast claim.", - "confirmed_mutation_count": 28, + "confirmed_mutation_count": 39, "counts_by_layer": { "shared_provenance": 1, - "g_deductions": 12, - "r2": 7, - "g_savings": 8 + "g_deductions": 14, + "r2": 12, + "g_savings": 12 }, "environment_contract": { "OMP_NUM_THREADS": "1", @@ -1937,6 +1937,363 @@ "restored_test_exit_code": 0 }, "evidence_run": "Fresh completed continuation replay; isolated sources, exact byte restoration and restored tests." + }, + { + "id": "round3_own_cap_equality_accepted", + "layer": "g_deductions", + "round": 3, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": "and event.payable + nh == original", + "after": "and event.payable + nh > original" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_deduction_cap.py", + "-k", + "own_event_at_ob_cap", + "--tb=short" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_gross_benefits_deduction_cap.py::test_own_event_at_ob_cap_errors_before_coverage_and_has_no_row[False-reservation0-False-False]", + "tests/test_track_b_gross_benefits_deduction_cap.py::test_own_event_at_ob_cap_errors_before_coverage_and_has_no_row[False-reservation0-False-True]", + "tests/test_track_b_gross_benefits_deduction_cap.py::test_own_event_at_ob_cap_errors_before_coverage_and_has_no_row[False-reservation0-True-False]", + "tests/test_track_b_gross_benefits_deduction_cap.py::test_own_event_at_ob_cap_errors_before_coverage_and_has_no_row[False-reservation0-True-True]", + "tests/test_track_b_gross_benefits_deduction_cap.py::test_own_event_at_ob_cap_errors_before_coverage_and_has_no_row[False-reservation1-False-False]", + "tests/test_track_b_gross_benefits_deduction_cap.py::test_own_event_at_ob_cap_errors_before_coverage_and_has_no_row[False-reservation1-False-True]", + "tests/test_track_b_gross_benefits_deduction_cap.py::test_own_event_at_ob_cap_errors_before_coverage_and_has_no_row[False-reservation1-True-False]", + "tests/test_track_b_gross_benefits_deduction_cap.py::test_own_event_at_ob_cap_errors_before_coverage_and_has_no_row[False-reservation1-True-True]", + "tests/test_track_b_gross_benefits_deduction_cap.py::test_own_event_at_ob_cap_errors_before_coverage_and_has_no_row[True-reservation0-False-False]", + "tests/test_track_b_gross_benefits_deduction_cap.py::test_own_event_at_ob_cap_errors_before_coverage_and_has_no_row[True-reservation0-False-True]", + "tests/test_track_b_gross_benefits_deduction_cap.py::test_own_event_at_ob_cap_errors_before_coverage_and_has_no_row[True-reservation0-True-False]", + "tests/test_track_b_gross_benefits_deduction_cap.py::test_own_event_at_ob_cap_errors_before_coverage_and_has_no_row[True-reservation0-True-True]", + "tests/test_track_b_gross_benefits_deduction_cap.py::test_own_event_at_ob_cap_errors_before_coverage_and_has_no_row[True-reservation1-False-False]", + "tests/test_track_b_gross_benefits_deduction_cap.py::test_own_event_at_ob_cap_errors_before_coverage_and_has_no_row[True-reservation1-False-True]", + "tests/test_track_b_gross_benefits_deduction_cap.py::test_own_event_at_ob_cap_errors_before_coverage_and_has_no_row[True-reservation1-True-False]", + "tests/test_track_b_gross_benefits_deduction_cap.py::test_own_event_at_ob_cap_errors_before_coverage_and_has_no_row[True-reservation1-True-True]" + ], + "log": { + "path": "scratch/review/round3_own_cap_equality_accepted.log", + "sha256": "414b4d72de4989029d14ed391f6fc336b0a94d87afceeaaf456694cd1c11fae5", + "failure_summary": "16 failed, 17 deselected in 37.67s" + }, + "restoration": { + "reverted": true, + "isolated_source_restored": true, + "production_source_untouched": true + }, + "elapsed_seconds": 61.63 + }, + { + "id": "round3_cap_rejects_every_event_reason", + "layer": "g_deductions", + "round": 3, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": "and event.reason is DeductionReason.OWN_EARNINGS_TEST\n and event.payable + nh == original", + "after": "and event.reason is not None\n and event.payable + nh == original" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_deduction_cap.py", + "-k", + "other_event_equality or dual_marker_at_original", + "--tb=short" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_gross_benefits_deduction_cap.py::test_other_event_equality_keeps_existing_named_refusal[DeductionReason.DUAL_ENTITLEMENT-False]", + "tests/test_track_b_gross_benefits_deduction_cap.py::test_other_event_equality_keeps_existing_named_refusal[DeductionReason.DUAL_ENTITLEMENT-True]", + "tests/test_track_b_gross_benefits_deduction_cap.py::test_other_event_equality_keeps_existing_named_refusal[DeductionReason.PRISONER_SUSPENSION-False]", + "tests/test_track_b_gross_benefits_deduction_cap.py::test_other_event_equality_keeps_existing_named_refusal[DeductionReason.PRISONER_SUSPENSION-True]", + "tests/test_track_b_gross_benefits_deduction_cap.py::test_dual_marker_at_original_benefit_stays_supported[False]", + "tests/test_track_b_gross_benefits_deduction_cap.py::test_dual_marker_at_original_benefit_stays_supported[True]" + ], + "log": { + "path": "scratch/review/round3_cap_rejects_every_event_reason.log", + "sha256": "7aaaa1ddeaf2ed39444ccdb05c03291ddb697099703e1bbe1f2f36fd73bcd194", + "failure_summary": "6 failed, 27 deselected in 67.29s (0:01:07)" + }, + "restoration": { + "reverted": true, + "isolated_source_restored": true, + "production_source_untouched": true + }, + "elapsed_seconds": 103.4 + }, + { + "id": "round3_operational_age_filter_removed", + "layer": "g_savings", + "round": 3, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": "row.subject_to_family_maximum and row.age_reduction_factor < 1", + "after": "row.entitled and row.age_reduction_factor < 1" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-110425-trackb-fix-g2-3/scratch/review/saving/mutation-source/run_pytest.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_saving_absence.py", + "-k", + "review_outside_divorced_age_reduction or outside_surviving_divorced_age" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_gross_benefits_saving_absence.py::test_review_outside_divorced_age_reduction_cannot_start_protection[pia0-maximum0-child0-divorced0-total0-5-False]", + "tests/test_track_b_gross_benefits_saving_absence.py::test_review_outside_divorced_age_reduction_cannot_start_protection[pia0-maximum0-child0-divorced0-total0-5-True]", + "tests/test_track_b_gross_benefits_saving_absence.py::test_review_outside_divorced_age_reduction_cannot_start_protection[pia1-maximum1-child1-divorced1-total1-0-False]", + "tests/test_track_b_gross_benefits_saving_absence.py::test_review_outside_divorced_age_reduction_cannot_start_protection[pia1-maximum1-child1-divorced1-total1-0-True]", + "tests/test_track_b_gross_benefits_saving_absence.py::test_outside_surviving_divorced_age_cannot_trigger_survivor_protection[False]", + "tests/test_track_b_gross_benefits_saving_absence.py::test_outside_surviving_divorced_age_cannot_trigger_survivor_protection[True]" + ], + "failure_summary": "6 failed, 10 deselected in 46.69s", + "evidence": "scratch/review/saving/round3_mutations.json", + "restoration": { + "reverted": true, + "production_source_untouched": true + } + }, + { + "id": "round3_operational_membership_filter_removed", + "layer": "g_savings", + "round": 3, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": "if row.subject_to_family_maximum", + "after": "if row.entitled" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-110425-trackb-fix-g2-3/scratch/review/saving/mutation-source/run_pytest.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_saving_absence.py", + "-k", + "outside_membership_changes" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_gross_benefits_saving_absence.py::test_outside_membership_changes_preserve_active_and_dormant_protection[presence0-False]", + "tests/test_track_b_gross_benefits_saving_absence.py::test_outside_membership_changes_preserve_active_and_dormant_protection[presence0-True]", + "tests/test_track_b_gross_benefits_saving_absence.py::test_outside_membership_changes_preserve_active_and_dormant_protection[presence1-False]", + "tests/test_track_b_gross_benefits_saving_absence.py::test_outside_membership_changes_preserve_active_and_dormant_protection[presence1-True]" + ], + "failure_summary": "4 failed, 12 deselected in 30.36s", + "evidence": "scratch/review/saving/round3_mutations.json", + "restoration": { + "reverted": true, + "production_source_untouched": true + } + }, + { + "id": "round3_operational_age_basis_filter_removed", + "layer": "g_savings", + "round": 3, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": "if row.subject_to_family_maximum", + "after": "if row.entitled" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-110425-trackb-fix-g2-3/scratch/review/saving/mutation-source/run_pytest.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_saving_absence.py", + "-k", + "outside_age_basis_change" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_gross_benefits_saving_absence.py::test_outside_age_basis_change_does_not_hide_worker_protection[False]", + "tests/test_track_b_gross_benefits_saving_absence.py::test_outside_age_basis_change_does_not_hide_worker_protection[True]" + ], + "failure_summary": "2 failed, 14 deselected in 17.22s", + "evidence": "scratch/review/saving/round3_mutations.json", + "restoration": { + "reverted": true, + "production_source_untouched": true + } + }, + { + "id": "round3_operational_person_count_filter_removed", + "layer": "g_savings", + "round": 3, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": "row.subject_to_family_maximum for row in result.beneficiaries", + "after": "row.entitled for row in result.beneficiaries" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-110425-trackb-fix-g2-3/scratch/review/saving/mutation-source/run_pytest.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_saving_absence.py", + "-k", + "surviving_divorced_person_cannot_supply" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_gross_benefits_saving_absence.py::test_surviving_divorced_person_cannot_supply_operational_membership[False]", + "tests/test_track_b_gross_benefits_saving_absence.py::test_surviving_divorced_person_cannot_supply_operational_membership[True]" + ], + "failure_summary": "2 failed, 14 deselected in 14.30s", + "evidence": "scratch/review/saving/round3_mutations.json", + "restoration": { + "reverted": true, + "production_source_untouched": true + } + }, + { + "id": "round3-fra-bypass_fra", + "layer": "r2", + "round": 3, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": { + "before": " if own is not None and own.birth_year is not None:\n", + "after": " return\n if own is not None and own.birth_year is not None:\n" + }, + "command": "env PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=$PWD/scratch/review/fra_mutations/bypass_fra/src:$PWD/src:$PWD OMP_NUM_THREADS=1 POLARS_MAX_THREADS=1 OMP_WAIT_POLICY=PASSIVE POPULACE_DYNAMICS_PSID_DIR=$PWD/scratch/review/nonexistent POPULACE_DYNAMICS_EPUF_DIR=$PWD/scratch/review/nonexistent /Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python -m pytest -p no:xdist -p no:cacheprovider -q tests/test_track_b_ret_fra_facts.py -k sole_widow_contradictory", + "mutated_exit_code": 1, + "failed_tests": [ + "test_sole_widow_contradictory_fra_is_input_error_and_has_no_row" + ], + "log": { + "path": "scratch/review/fra_mutations/bypass_fra/result.log", + "sha256": "1423b5c4c3bdb9f5622e5e1f84e24301adc62d6b35796996b3581f74fd838e58", + "failure_summary": "1 failed, 123 deselected in 18.93s" + }, + "restoration": { + "reverted": true, + "production_source_untouched": true + } + }, + { + "id": "round3-fra-last_endpoint", + "layer": "r2", + "round": 3, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": { + "before": "latest = earliest + 11", + "after": "latest = earliest + 10" + }, + "command": "env PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=$PWD/scratch/review/fra_mutations/last_endpoint/src:$PWD/src:$PWD OMP_NUM_THREADS=1 POLARS_MAX_THREADS=1 OMP_WAIT_POLICY=PASSIVE POPULACE_DYNAMICS_PSID_DIR=$PWD/scratch/review/nonexistent POPULACE_DYNAMICS_EPUF_DIR=$PWD/scratch/review/nonexistent /Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python -m pytest -p no:xdist -p no:cacheprovider -q tests/test_track_b_ret_fra_facts.py -k every_cohort_interval -x", + "mutated_exit_code": 1, + "failed_tests": [ + "test_every_cohort_interval_endpoint_and_every_inside_declaration[False-1930-780]" + ], + "log": { + "path": "scratch/review/fra_mutations/last_endpoint/result.log", + "sha256": "3748f2a52616633219a9b174154a85a1dfe7b949fe04cd82520ac9d6837a0782", + "failure_summary": "1 failed, 90 deselected in 19.19s" + }, + "restoration": { + "reverted": true, + "production_source_untouched": true + } + }, + { + "id": "round3-fra-first_endpoint", + "layer": "r2", + "round": 3, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": { + "before": "earliest = birth_year * 12 + g._fra_months(birth_year, params)", + "after": "earliest = birth_year * 12 + g._fra_months(birth_year, params) + 1" + }, + "command": "env PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=$PWD/scratch/review/fra_mutations/first_endpoint/src:$PWD/src:$PWD OMP_NUM_THREADS=1 POLARS_MAX_THREADS=1 OMP_WAIT_POLICY=PASSIVE POPULACE_DYNAMICS_PSID_DIR=$PWD/scratch/review/nonexistent POPULACE_DYNAMICS_EPUF_DIR=$PWD/scratch/review/nonexistent /Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python -m pytest -p no:xdist -p no:cacheprovider -q tests/test_track_b_ret_fra_facts.py -k every_cohort_interval -x", + "mutated_exit_code": 1, + "failed_tests": [ + "test_every_cohort_interval_endpoint_and_every_inside_declaration[False-1930-780]" + ], + "log": { + "path": "scratch/review/fra_mutations/first_endpoint/result.log", + "sha256": "e81f46cfb1797a4c50ee48129d46a6fb45031329889e83dc000b70f890701981", + "failure_summary": "1 failed, 90 deselected in 39.39s" + }, + "restoration": { + "reverted": true, + "production_source_untouched": true + } + }, + { + "id": "round3-fra-ignore_own_drc", + "layer": "r2", + "round": 3, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": { + "before": " if own is not None and own.delayed_credit_months:\n", + "after": " if False:\n" + }, + "command": "env PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=$PWD/scratch/review/fra_mutations/ignore_own_drc/src:$PWD/src:$PWD OMP_NUM_THREADS=1 POLARS_MAX_THREADS=1 OMP_WAIT_POLICY=PASSIVE POPULACE_DYNAMICS_PSID_DIR=$PWD/scratch/review/nonexistent POPULACE_DYNAMICS_EPUF_DIR=$PWD/scratch/review/nonexistent /Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python -m pytest -p no:xdist -p no:cacheprovider -q tests/test_track_b_ret_fra_facts.py -k own_delayed -x", + "mutated_exit_code": 1, + "failed_tests": [ + "test_own_delayed_credits_prove_only_fra_by_context_month[None-False]" + ], + "log": { + "path": "scratch/review/fra_mutations/ignore_own_drc/result.log", + "sha256": "fffa2a38c60db4e7ff10889ae1f7748418821363e6887fd077af5739f70aa8c9", + "failure_summary": "1 failed, 96 deselected in 21.27s" + }, + "restoration": { + "reverted": true, + "production_source_untouched": true + } + }, + { + "id": "round3-fra-ignore_cohort_identity", + "layer": "r2", + "round": 3, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": { + "before": " if birth_year is not None and birth_year != own.birth_year:\n", + "after": " if False:\n" + }, + "command": "env PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=$PWD/scratch/review/fra_mutations/ignore_cohort_identity/src:$PWD/src:$PWD OMP_NUM_THREADS=1 POLARS_MAX_THREADS=1 OMP_WAIT_POLICY=PASSIVE POPULACE_DYNAMICS_PSID_DIR=$PWD/scratch/review/nonexistent POPULACE_DYNAMICS_EPUF_DIR=$PWD/scratch/review/nonexistent /Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python -m pytest -p no:xdist -p no:cacheprovider -q tests/test_track_b_ret_fra_facts.py -k paired_auxiliary_birth_cohorts", + "mutated_exit_code": 1, + "failed_tests": [ + "test_paired_auxiliary_birth_cohorts_error_at_declaration_before_refusal[False]", + "test_paired_auxiliary_birth_cohorts_error_at_declaration_before_refusal[True]" + ], + "log": { + "path": "scratch/review/fra_mutations/ignore_cohort_identity/result.log", + "sha256": "a950c798148ec4552ad01f1249972042c15058550ffdcad78971c6afbec9c4a2", + "failure_summary": "2 failed, 125 deselected in 14.51s" + }, + "restoration": { + "reverted": true, + "production_source_untouched": true + } } ], "restoration_verification_snapshot": { @@ -1967,5 +2324,11 @@ "inherited_pre_round_2": 13, "replaced_attempt_1_records": 11, "note": "All round-2 claims were independently rerun in deduction-audit, r2-audit and savings-audit. Earlier historical records remain distinct. No production mutation was retained." + }, + "round_3_head": "872cebc73e4cfc41f21d82188cd11630266393d4", + "round_3_note": "Eleven new one-line mutations were caught in isolated source copies and reverted; production source stayed fixed. Earlier mutation records and restoration snapshots are historical.", + "round_3_restoration_snapshot": { + "src/populace_dynamics/track_b/gross_benefits.py": "cd03ee0b2c828f1fb7e09980b48f4a23e9a8ca49295aaa7a1dd2799d1fff9ed8", + "src/populace_dynamics/track_b/ret_ledger.py": "7b5a1491453fbd61e76c670a1ce84deb3818138d3313c21327661d328d7fa0c8" } } diff --git a/docs/design/track_b_g2_r2b_verification.json b/docs/design/track_b_g2_r2b_verification.json index 0a9a7747b..6115c9c1c 100644 --- a/docs/design/track_b_g2_r2b_verification.json +++ b/docs/design/track_b_g2_r2b_verification.json @@ -3937,5 +3937,623 @@ "report_sha256_before": "ee8ef3247a700b4cec92dfc27bbb98b071deaba5566b092cb9c3df4f762be972", "report_sha256_after": "df2317b43437689f770e08977487cf732bf4a8cad509e4c077630cd71973ffe4", "note": "Earlier sha256 values in this ledger are measurements taken before this refresh." - } + }, + "round_3": { + "baseline_head": "872cebc73e4cfc41f21d82188cd11630266393d4", + "verification_class": "statutory conformance", + "admitted_scope": "Invented statutory cases and captured rules only; no population, behavioral or forecast claim.", + "environment": { + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "$PWD/.no-real-data", + "POPULACE_DYNAMICS_EPUF_DIR": "$PWD/.no-real-data", + "PYTHONPATH": "$PWD/src:$PWD" + }, + "restrictions": "All six required restriction-file hashes matched. Named modules only; no whole-suite collection, tier-policy, birth-evidence, real-data or network activity.", + "required_named_modules": [ + "tests/test_track_b_arf.py", + "tests/test_track_b_arf_properties.py", + "tests/test_track_b_gross_benefits.py", + "tests/test_track_b_gross_benefits_conformance_report.py", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py", + "tests/test_track_b_gross_benefits_deduction_cap.py", + "tests/test_track_b_gross_benefits_deductions.py", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", + "tests/test_track_b_gross_benefits_dwb.py", + "tests/test_track_b_gross_benefits_fix_round_1.py", + "tests/test_track_b_gross_benefits_fix_round_10_api.py", + "tests/test_track_b_gross_benefits_fix_round_10_helpers.py", + "tests/test_track_b_gross_benefits_fix_round_10_objects.py", + "tests/test_track_b_gross_benefits_fix_round_10_parameters.py", + "tests/test_track_b_gross_benefits_fix_round_11_roles.py", + "tests/test_track_b_gross_benefits_fix_round_11_seals.py", + "tests/test_track_b_gross_benefits_fix_round_12_contract.py", + "tests/test_track_b_gross_benefits_fix_round_13_audit.py", + "tests/test_track_b_gross_benefits_fix_round_13_boundary.py", + "tests/test_track_b_gross_benefits_fix_round_13_guard.py", + "tests/test_track_b_gross_benefits_fix_round_15_arguments.py", + "tests/test_track_b_gross_benefits_fix_round_15_collections.py", + "tests/test_track_b_gross_benefits_fix_round_15_receivers.py", + "tests/test_track_b_gross_benefits_fix_round_2_care.py", + "tests/test_track_b_gross_benefits_fix_round_2_history.py", + "tests/test_track_b_gross_benefits_fix_round_2_periods.py", + "tests/test_track_b_gross_benefits_fix_round_3_rates.py", + "tests/test_track_b_gross_benefits_fix_round_4_care_floor.py", + "tests/test_track_b_gross_benefits_fix_round_4_divorced_care.py", + "tests/test_track_b_gross_benefits_fix_round_5_care_history.py", + "tests/test_track_b_gross_benefits_fix_round_5_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_6_care_note.py", + "tests/test_track_b_gross_benefits_fix_round_6_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_boundary.py", + "tests/test_track_b_gross_benefits_fix_round_7_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_history.py", + "tests/test_track_b_gross_benefits_fix_round_8_entries.py", + "tests/test_track_b_gross_benefits_fix_round_8_history.py", + "tests/test_track_b_gross_benefits_fix_round_9_citations.py", + "tests/test_track_b_gross_benefits_fix_round_9_outcomes.py", + "tests/test_track_b_gross_benefits_fix_round_9_validation.py", + "tests/test_track_b_gross_benefits_oracle.py", + "tests/test_track_b_gross_benefits_own_input_order.py", + "tests/test_track_b_gross_benefits_parents_ieds.py", + "tests/test_track_b_gross_benefits_parisi.py", + "tests/test_track_b_gross_benefits_payment_review.py", + "tests/test_track_b_gross_benefits_properties.py", + "tests/test_track_b_gross_benefits_registry.py", + "tests/test_track_b_gross_benefits_review.py", + "tests/test_track_b_gross_benefits_saving_absence.py", + "tests/test_track_b_gross_benefits_savings.py", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py", + "tests/test_track_b_gross_benefits_sources_20261011.py", + "tests/test_track_b_gross_benefits_ssfa.py", + "tests/test_track_b_input_schema.py", + "tests/test_track_b_r3_fix_round_13.py", + "tests/test_track_b_r3_provenance.py", + "tests/test_track_b_r3_sources.py", + "tests/test_track_b_r3_validation_once.py", + "tests/test_track_b_recompute.py", + "tests/test_track_b_recompute_properties.py", + "tests/test_track_b_refusal_notes.py", + "tests/test_track_b_ret_differential.py", + "tests/test_track_b_ret_fra_facts.py", + "tests/test_track_b_ret_grace.py", + "tests/test_track_b_ret_grace_differential.py", + "tests/test_track_b_ret_grace_provenance.py", + "tests/test_track_b_ret_ledger.py", + "tests/test_track_b_ret_ledger_deductions.py", + "tests/test_track_b_ret_ledger_fix_round_2.py", + "tests/test_track_b_ret_ledger_properties.py", + "tests/test_track_b_ret_ledger_readings.py", + "tests/test_track_b_ret_ledger_sources.py", + "tests/test_track_b_ret_params.py" + ], + "validation_runs": [ + { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "scripts/track_b_r2_cross_head.py", + "--baseline-root", + "scratch/review/round3-baseline", + "--output", + "scratch/review/round3-cross-head.json" + ], + "exit_code": 0, + "path": "scratch/review/round3-cross-head.log", + "artifact": "scratch/review/round3-cross-head.json", + "artifact_sha256": "a945d2f0bb2f6b8918e052063aa41a730eb24e9331fb16a1164c45de3810fe3d", + "summary": "240 R2 and 240 R3 declared output bytes identical; six former refusals supported", + "result": { + "verification_class": "statutory conformance", + "scope": "invented cases only; no population, behavioral or forecast claim", + "seed": 53014, + "r2_stable_rows": 240, + "r3_stable_rows": 240, + "identical_declared_output_bytes": true, + "stable_sha256": "799fc9e23a902ac1ca0c2563579ceb094d0dbcd631a912305c40062cf21a5f55", + "transitions": { + "baseline": { + "rows": 6, + "supported": 0, + "refused_by_reason": { + "deduction_before_reduction_part_b": 6 + } + }, + "head": { + "rows": 6, + "supported": 6, + "refused_by_reason": {} + } + }, + "transition_rows": [ + { + "id": "binding_survivor_own_excess_1", + "own_excess": 1, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_60", + "own_excess": 60, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_99", + "own_excess": 99, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_100", + "own_excess": 100, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_555", + "own_excess": 555, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_1188", + "own_excess": 1188, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + } + ] + } + }, + { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "scratch/review/round3-run-conformance.py" + ], + "pytest_arguments": [ + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_conformance_report.py" + ], + "actual_launcher": "Unmodified named conformance pytest module via pytest.main; transparent wrapper saves canonical report.build_report return bytes and returns exact value to unchanged fixture.", + "path": "scratch/review/round3-conformance-pytest.log", + "status": "complete", + "exit_code": 0, + "summary": "53 passed in 4810.77s (1:20:10)", + "sha256": "62e848a8b23f323561a9df574de5dfb937b7d6c5559ed8ae59914e002b2e9c07", + "regenerated_artifact": "scratch/review/round3-g-conformance-report.json", + "regenerated_artifact_sha256": "df2317b43437689f770e08977487cf732bf4a8cad509e4c077630cd71973ffe4" + }, + { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_arf.py", + "tests/test_track_b_arf_properties.py", + "tests/test_track_b_gross_benefits.py", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py", + "tests/test_track_b_gross_benefits_deduction_cap.py", + "tests/test_track_b_gross_benefits_deductions.py", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", + "tests/test_track_b_gross_benefits_dwb.py", + "tests/test_track_b_gross_benefits_fix_round_1.py", + "tests/test_track_b_gross_benefits_fix_round_10_api.py", + "tests/test_track_b_gross_benefits_fix_round_10_helpers.py", + "tests/test_track_b_gross_benefits_fix_round_10_objects.py", + "tests/test_track_b_gross_benefits_fix_round_10_parameters.py", + "tests/test_track_b_gross_benefits_fix_round_11_roles.py", + "tests/test_track_b_gross_benefits_fix_round_11_seals.py", + "tests/test_track_b_gross_benefits_fix_round_12_contract.py", + "tests/test_track_b_gross_benefits_fix_round_13_audit.py", + "tests/test_track_b_gross_benefits_fix_round_13_boundary.py", + "tests/test_track_b_gross_benefits_fix_round_13_guard.py", + "tests/test_track_b_gross_benefits_fix_round_15_arguments.py", + "tests/test_track_b_gross_benefits_fix_round_15_collections.py", + "tests/test_track_b_gross_benefits_fix_round_15_receivers.py", + "tests/test_track_b_gross_benefits_fix_round_2_care.py", + "tests/test_track_b_gross_benefits_fix_round_2_history.py", + "tests/test_track_b_gross_benefits_fix_round_2_periods.py", + "tests/test_track_b_gross_benefits_fix_round_3_rates.py", + "tests/test_track_b_gross_benefits_fix_round_4_care_floor.py", + "tests/test_track_b_gross_benefits_fix_round_4_divorced_care.py", + "tests/test_track_b_gross_benefits_fix_round_5_care_history.py", + "tests/test_track_b_gross_benefits_fix_round_5_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_6_care_note.py", + "tests/test_track_b_gross_benefits_fix_round_6_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_boundary.py", + "tests/test_track_b_gross_benefits_fix_round_7_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_history.py", + "tests/test_track_b_gross_benefits_fix_round_8_entries.py", + "tests/test_track_b_gross_benefits_fix_round_8_history.py", + "tests/test_track_b_gross_benefits_fix_round_9_citations.py", + "tests/test_track_b_gross_benefits_fix_round_9_outcomes.py", + "tests/test_track_b_gross_benefits_fix_round_9_validation.py", + "tests/test_track_b_gross_benefits_oracle.py", + "tests/test_track_b_gross_benefits_own_input_order.py", + "tests/test_track_b_gross_benefits_parents_ieds.py", + "tests/test_track_b_gross_benefits_parisi.py", + "tests/test_track_b_gross_benefits_payment_review.py", + "tests/test_track_b_gross_benefits_properties.py", + "tests/test_track_b_gross_benefits_registry.py", + "tests/test_track_b_gross_benefits_review.py", + "tests/test_track_b_gross_benefits_saving_absence.py", + "tests/test_track_b_gross_benefits_savings.py", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py", + "tests/test_track_b_gross_benefits_sources_20261011.py", + "tests/test_track_b_gross_benefits_ssfa.py", + "tests/test_track_b_input_schema.py", + "tests/test_track_b_r3_fix_round_13.py", + "tests/test_track_b_r3_provenance.py", + "tests/test_track_b_r3_sources.py", + "tests/test_track_b_r3_validation_once.py", + "tests/test_track_b_recompute.py", + "tests/test_track_b_recompute_properties.py", + "tests/test_track_b_refusal_notes.py", + "tests/test_track_b_ret_differential.py", + "tests/test_track_b_ret_fra_facts.py", + "tests/test_track_b_ret_grace.py", + "tests/test_track_b_ret_grace_differential.py", + "tests/test_track_b_ret_grace_provenance.py", + "tests/test_track_b_ret_ledger.py", + "tests/test_track_b_ret_ledger_deductions.py", + "tests/test_track_b_ret_ledger_fix_round_2.py", + "tests/test_track_b_ret_ledger_properties.py", + "tests/test_track_b_ret_ledger_readings.py", + "tests/test_track_b_ret_ledger_sources.py", + "tests/test_track_b_ret_params.py" + ], + "actual_launcher": "sh scratch/review/round3-ordinary-command.sh; command file names all 73 ordinary test modules explicitly.", + "path": "scratch/review/round3-ordinary-pytest.log", + "status": "complete_with_all_failures_resolved_by_current_full_module_reruns", + "exit_code": 1, + "summary": "4 failed, 11272 passed in 6127.45s (1:42:07)", + "sha256": "d1403906ac76e1ca60834347942b1075f0fb312684274bc167b070496f5eee76", + "failed_nodes": [ + "tests/test_track_b_gross_benefits_fix_round_15_collections.py::test_membership_months_collapse_equivalent_month_encodings[tuple]", + "tests/test_track_b_gross_benefits_fix_round_15_collections.py::test_membership_months_collapse_equivalent_month_encodings[frozenset]", + "tests/test_track_b_ret_fra_facts.py::test_consistent_fra_keeps_named_coverage_refusal_in_denominator", + "tests/test_track_b_ret_fra_facts.py::test_reduction_months_and_deceased_worker_credits_do_not_prove_current_fra" + ], + "failure_classification": { + "tests/test_track_b_gross_benefits_fix_round_15_collections.py::test_membership_months_collapse_equivalent_month_encodings[tuple]": "Hypothesis timing-only FlakyFailure:378.73 ms first call versus 0.21 ms repeat; 200 ms deadline.", + "tests/test_track_b_gross_benefits_fix_round_15_collections.py::test_membership_months_collapse_equivalent_month_encodings[frozenset]": "Hypothesis timing-only FlakyFailure:348.24 ms first call versus 0.18 ms repeat; 200 ms deadline.", + "tests/test_track_b_ret_fra_facts.py::test_consistent_fra_keeps_named_coverage_refusal_in_denominator": "Stale collected new-test source used refused_weight; corrected current full FRA module passed 127 tests.", + "tests/test_track_b_ret_fra_facts.py::test_reduction_months_and_deceased_worker_credits_do_not_prove_current_fra": "Stale collected new-test source used survivor_base; corrected current full FRA module passed 127 tests." + } + }, + { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "black", + "--check", + "-l", + "79", + "--workers", + "1", + "src/populace_dynamics/track_b/gross_benefits.py", + "src/populace_dynamics/track_b/ret_ledger.py", + "tests/test_track_b_gross_benefits_deduction_cap.py", + "tests/test_track_b_gross_benefits_saving_absence.py", + "tests/test_track_b_ret_fra_facts.py" + ], + "exit_code": 0, + "path": "scratch/review/round3-black.log", + "sha256": "25369eabb8c122f861d58ddb255f81f4b9ee797f42f3882975bef953218258ed", + "summary": "5 files would be left unchanged" + }, + { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "ruff", + "check", + "src/populace_dynamics/track_b/gross_benefits.py", + "src/populace_dynamics/track_b/ret_ledger.py", + "tests/test_track_b_gross_benefits_deduction_cap.py", + "tests/test_track_b_gross_benefits_saving_absence.py", + "tests/test_track_b_ret_fra_facts.py" + ], + "exit_code": 0, + "path": "scratch/review/round3-ruff.log", + "sha256": "82b3e6a6c090a57601d22943bd23fca9218d1031dbe5a7b754092f9a156b4f18", + "summary": "All checks passed!" + }, + { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "black", + "--check", + "-l", + "79", + "--workers", + "1", + "tests/test_track_b_ret_fra_facts.py" + ], + "exit_code": 0, + "path": "scratch/review/round3-black-final-fra.log", + "sha256": "1a56c7cd8457fd05d978cfbd139d7bfd86e86acaa9b57668e718ef8bccc0cf48", + "summary": "1 file would be left unchanged", + "reason": "Recheck after correcting two new-test API field names; production unchanged." + }, + { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "ruff", + "check", + "tests/test_track_b_ret_fra_facts.py" + ], + "exit_code": 0, + "path": "scratch/review/round3-ruff-final-fra.log", + "sha256": "82b3e6a6c090a57601d22943bd23fca9218d1031dbe5a7b754092f9a156b4f18", + "summary": "All checks passed!", + "reason": "Recheck after correcting two new-test API field names; production unchanged." + }, + { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "black", + "--check", + "-l", + "79", + "--workers", + "1", + "src/populace_dynamics/track_b/gross_benefits.py", + "src/populace_dynamics/track_b/ret_ledger.py", + "tests/test_track_b_gross_benefits_deduction_cap.py", + "tests/test_track_b_gross_benefits_saving_absence.py", + "tests/test_track_b_ret_fra_facts.py" + ], + "exit_code": 0, + "path": "scratch/review/round3-black-final.log", + "sha256": "25369eabb8c122f861d58ddb255f81f4b9ee797f42f3882975bef953218258ed", + "summary": "5 files would be left unchanged", + "reason": "Final check after FRA expanded to127 tests; both production and all3new modules final." + }, + { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "ruff", + "check", + "src/populace_dynamics/track_b/gross_benefits.py", + "src/populace_dynamics/track_b/ret_ledger.py", + "tests/test_track_b_gross_benefits_deduction_cap.py", + "tests/test_track_b_gross_benefits_saving_absence.py", + "tests/test_track_b_ret_fra_facts.py" + ], + "exit_code": 0, + "path": "scratch/review/round3-ruff-final.log", + "sha256": "82b3e6a6c090a57601d22943bd23fca9218d1031dbe5a7b754092f9a156b4f18", + "summary": "All checks passed!", + "reason": "Final check after FRA expanded to127 tests; both production and all3new modules final." + }, + { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_fix_round_15_collections.py" + ], + "path": "scratch/review/round3-collections-final.log", + "status": "complete", + "reason": "Full unchanged existing module rerun after two timing-only failures in concurrent batch.", + "exit_code": 0, + "summary": "288 passed in 10.05s", + "sha256": "7d21889ebf1df7d35acb3e3c2d15a967a124f531cfce4b6baeb12d311e91f0d8" + } + ], + "final_gate_summary": { + "required_named_modules": 74, + "ordinary_batch": "4 failed, 11272 passed in 6127.45s (1:42:07)", + "ordinary_failures": "Two timing-only Hypothesis FlakyFailure cases and two stale new-test API field names; all current full affected modules pass.", + "existing_collections_current_module": "288 passed in 10.05s", + "expanded_fra_current_module": "127 passed in 122.75s (0:02:02)", + "conformance_current_module": "53 passed in 4810.77s (1:20:10)", + "cross_head": "240 R2 and 240 R3 byte-identical to master; six former refusals computed", + "black": "5 files would be left unchanged", + "ruff": "All checks passed!", + "current_parametrized_case_count": 11332, + "current_case_count_derivation": "11276 cases in ordinary batch -124 old FRA cases +127 final FRA cases +53 conformance cases", + "all_foreground_verification_sessions_awaited": true, + "deferred_to_ci": [ + "tier-policy", + "birth-evidence" + ], + "no_whole_suite_collection": true + }, + "ordinary_failure_resolution": { + "production_unchanged": true, + "source_assertions_unchanged": true, + "timing_nodes_focused_rerun": { + "path": "scratch/review/round3-existing-collection-failures.log", + "summary": "2 passed in 19.57s", + "owner": "root", + "sha256": "067aa2ea7e14a2819708e0321744ded7234db98a25430f886945875d567acde8" + }, + "corrected_current_fra_module": { + "path": "scratch/review/fra-final-expanded.log", + "summary": "127 passed in 122.75s (0:02:02)", + "command_record": "scratch/review/fra-mutation-records.json final_fra_module", + "sha256": "656712e3601f734448a5e4dcc8ec7bc70dd5e8321a584ea0229da5715823752e" + }, + "complete_collections_module_rerun": { + "path": "scratch/review/round3-collections-final.log", + "summary": "288 passed in 10.05s", + "sha256": "7d21889ebf1df7d35acb3e3c2d15a967a124f531cfce4b6baeb12d311e91f0d8", + "source_changes_required": false + } + }, + "all_required_current_modules_pass_across_recorded_runs": true, + "supplemental_root_validation_runs": [ + { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "--collect-only", + "-q", + "tests/test_track_b_arf.py", + "tests/test_track_b_arf_properties.py", + "tests/test_track_b_gross_benefits.py", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py", + "tests/test_track_b_gross_benefits_deduction_cap.py", + "tests/test_track_b_gross_benefits_deductions.py", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", + "tests/test_track_b_gross_benefits_dwb.py", + "tests/test_track_b_gross_benefits_fix_round_1.py", + "tests/test_track_b_gross_benefits_fix_round_10_api.py", + "tests/test_track_b_gross_benefits_fix_round_10_helpers.py", + "tests/test_track_b_gross_benefits_fix_round_10_objects.py", + "tests/test_track_b_gross_benefits_fix_round_10_parameters.py", + "tests/test_track_b_gross_benefits_fix_round_11_roles.py", + "tests/test_track_b_gross_benefits_fix_round_11_seals.py", + "tests/test_track_b_gross_benefits_fix_round_12_contract.py", + "tests/test_track_b_gross_benefits_fix_round_13_audit.py", + "tests/test_track_b_gross_benefits_fix_round_13_boundary.py", + "tests/test_track_b_gross_benefits_fix_round_13_guard.py", + "tests/test_track_b_gross_benefits_fix_round_15_arguments.py", + "tests/test_track_b_gross_benefits_fix_round_15_collections.py", + "tests/test_track_b_gross_benefits_fix_round_15_receivers.py", + "tests/test_track_b_gross_benefits_fix_round_2_care.py", + "tests/test_track_b_gross_benefits_fix_round_2_history.py", + "tests/test_track_b_gross_benefits_fix_round_2_periods.py", + "tests/test_track_b_gross_benefits_fix_round_3_rates.py", + "tests/test_track_b_gross_benefits_fix_round_4_care_floor.py", + "tests/test_track_b_gross_benefits_fix_round_4_divorced_care.py", + "tests/test_track_b_gross_benefits_fix_round_5_care_history.py", + "tests/test_track_b_gross_benefits_fix_round_5_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_6_care_note.py", + "tests/test_track_b_gross_benefits_fix_round_6_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_boundary.py", + "tests/test_track_b_gross_benefits_fix_round_7_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_history.py", + "tests/test_track_b_gross_benefits_fix_round_8_entries.py", + "tests/test_track_b_gross_benefits_fix_round_8_history.py", + "tests/test_track_b_gross_benefits_fix_round_9_citations.py", + "tests/test_track_b_gross_benefits_fix_round_9_outcomes.py", + "tests/test_track_b_gross_benefits_fix_round_9_validation.py" + ], + "exit_code": 0, + "summary": "8681 tests collected in 164.32s (0:02:44)", + "path": "scratch/review/round3-failure-prefix-collection.log", + "scope": "Explicit first 40 named modules only, to map two live failure ordinals; no whole-suite collection or tier recount." + }, + { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_fix_round_15_collections.py::test_membership_months_collapse_equivalent_month_encodings[tuple]", + "tests/test_track_b_gross_benefits_fix_round_15_collections.py::test_membership_months_collapse_equivalent_month_encodings[frozenset]", + "--tb=short" + ], + "exit_code": 0, + "summary": "2 passed in 19.57s", + "path": "scratch/review/round3-existing-collection-failures.log", + "sha256": "067aa2ea7e14a2819708e0321744ded7234db98a25430f886945875d567acde8", + "source_changes_required": false + } + ], + "corrected_fra_module": { + "command": "env PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=$PWD/src:$PWD OMP_NUM_THREADS=1 POLARS_MAX_THREADS=1 OMP_WAIT_POLICY=PASSIVE POPULACE_DYNAMICS_PSID_DIR=$PWD/scratch/review/nonexistent POPULACE_DYNAMICS_EPUF_DIR=$PWD/scratch/review/nonexistent /Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python -m pytest -p no:xdist -p no:cacheprovider -q tests/test_track_b_ret_fra_facts.py", + "result": "127 passed in 122.75s", + "log": "scratch/review/fra-final-expanded.log" + }, + "failing_first": { + "fra": "15 failed, 100 deselected at reviewed behavior; sole widow, actual/estimated old-cohort declarations and refusal priority", + "cap": { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_deduction_cap.py", + "-k", + "own_event_at_ob_cap", + "--tb=short" + ], + "returncode": 1, + "summary": "16 failed, 17 deselected in 32.37s", + "log": "scratch/review/round3-cap-reviewed-head.log", + "head": "872cebc73e4cfc41f21d82188cd11630266393d4" + }, + "savings": "Reviewer cases failed first; additional surviving-age pair: 2 failed, 14 deselected against exact 872cebc7 source" + }, + "cap_fixed_module": "33 passed in 16.28s", + "savings_fixed_module": "16 passed in 59.01s; combined original/new savings gate 49 passed in 197.38s", + "literal_comparison": { + "rows": 480, + "identical": true, + "evidence": "scratch/review/saving/round3-report-fragment.md" + }, + "conformance": { + "original_pins": { + "docs/design/track_b_g_conformance_report.json": "df2317b43437689f770e08977487cf732bf4a8cad509e4c077630cd71973ffe4", + "tests/data/track_b/gross_benefit_examples.yaml": "58bc989f71090b513f9ed86fd22935e37d8237501477fee38eaef82952bab036", + "scripts/track_b_g_conformance_report.py": "3cb5cf9b27b1019daf224040554ea707a0dc96c4962bae8dc2cbaaa8f48ca2e4" + }, + "unchanged_original_pins": { + "docs/design/track_b_g_conformance_report.json": true, + "tests/data/track_b/gross_benefit_examples.yaml": true, + "scripts/track_b_g_conformance_report.py": true + }, + "regenerated_artifact": "scratch/review/round3-g-conformance-report.json", + "regenerated_artifact_available": true, + "full_lattice_rows": 356400, + "method": "Unmodified report script build_report output saved transparently by conformance fixture launcher; unchanged tests compare canonical bytes to committed report.", + "regenerated_sha256": "df2317b43437689f770e08977487cf732bf4a8cad509e4c077630cd71973ffe4", + "bytes_equal_committed": true + }, + "new_mutations_caught_and_reverted": 11, + "confirmed_mutations_total": 39, + "production_stable_through_verification": true, + "final_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cd03ee0b2c828f1fb7e09980b48f4a23e9a8ca49295aaa7a1dd2799d1fff9ed8", + "src/populace_dynamics/track_b/ret_ledger.py": "7b5a1491453fbd61e76c670a1ce84deb3818138d3313c21327661d328d7fa0c8", + "tests/test_track_b_gross_benefits_deduction_cap.py": "2057e1fb3322aeb29f32339cf450118a241269dda0711c48c09da24a44f06e43", + "tests/test_track_b_gross_benefits_saving_absence.py": "e6078f978ee7bf1d0802dde67c2de94397fd3e9cd142b2c96d6d504ceb0a6862", + "tests/test_track_b_ret_fra_facts.py": "7bfb53be6660bbfad0831904d5b39a3e8d997216308b136959ece10bb04c72a8", + "docs/design/track_b_g_gross_benefits.md": "202250b8a0549b6a8baaa30de50bfed0e94387b5f83ee50dd3839f6479dbf610", + "docs/design/track_b_r2_ret_ledger.md": "5834fcee545111283a8a9422e8f7096ebc6bc1fcf364647dafc0f76ccfe861b2", + "docs/design/track_b_g2_r2b_mutations.json": "47e7c53344f379380c4048522036736356b7ec2a9bb155fbafa282b512f8e490" + }, + "protected_path_violations": [], + "tier_files_unchanged": true, + "existing_assertions_edited": false, + "readings_for_orchestrator": "No new ruling. Act203(f)(9), CFR404.430(b)/.434(c), RS02501.021B.3 settle RIB FRA for every role. No credit-effective-date chronology is inferred from own DRC count.", + "independent_adversarial_review": "23 FRA/DRC/cap controls plus unentitled-NH/inherited-credit checks passed; no introduced false rejection. Pre-existing held-parent difference remains an unadjudicated coverage boundary, not a demonstrated input error.", + "detailed_report": "scratch/review/fix-round-3-report.md", + "all_changes_uncommitted": true + }, + "round_3_current_evidence_note": "Earlier source hashes, counts and validation records remain historical. The round_3 section records this fix round separately and is the current evidence for its changed sources." } diff --git a/docs/design/track_b_g_gross_benefits.md b/docs/design/track_b_g_gross_benefits.md index 8b76784be..650ed5387 100644 --- a/docs/design/track_b_g_gross_benefits.md +++ b/docs/design/track_b_g_gross_benefits.md @@ -2836,8 +2836,15 @@ change—only total benefits payable are affected." ### Conditions and supported procedures Under `SSA_OPERATIONAL`, the prior month must have two or more entitled -persons, a binding maximum, and at least one age-reduced beneficiary. The -next month's PIA must rise and its family total must fall. These are the +persons governed by the maximum, a binding maximum, and at least one +governed age-reduced beneficiary. The NH counts as a governed person. +Divorced spouses and surviving divorced spouses outside the maximum are +absent from every operational predicate under Act 203(a)(3)(C): the person +count, membership, age trigger, age-factor comparison, deductions, +own-benefit checks and protected total. Their own ordinary rates remain +unchanged. `LITERAL_REFUSAL` retains its earlier predicates and behavior. +The next month's PIA must rise and its governed family total must fall. +These are the four requirements in RS 00630.400's "1972 Family Payment Saving Clause". Membership and exact worker/auxiliary age factors must be unchanged for the supported payment computation. The four source conditions are evaluated @@ -3125,3 +3132,79 @@ individuals = 225.30." Its displayed formula correctly gives $274.20 before the original-benefit cap of $225.30. The existing A.2 test pins the literal narrative, raw quotient and capped payment side by side. This is an omitted cap in the narrative, not an alternate arithmetic rule. + +## Round-3 input premises and excluded beneficiaries + +Verification class: statutory conformance on invented cases and captured +rules. This round adds no population, behavioral or forecast claim. + +The own-work input bound applies before either family or household +coverage refusal. `OWN_EARNINGS_TEST` requires payable plus NH reservation +strictly below the original-benefit upper bound: equality leaves no room +for a positive own deduction. GN 02603.050A says "In all cases, +beneficiaries are still limited to the original benefit amount." The +deduction entry points take `RecordState` and compute ordinary G before +any `SavingsClauseGuard`; a carried protected payment cannot enter this +check. A future combined protected-payment/deduction procedure would need +its own bound. Current above-OB protected-rate requests already refuse as +`savings_clause_rate_procedure` rather than entering this path. + +The bound uses a widow's supplied larger OB basis and a parent's +conservative one-parent OB (Act 202(e)/(f)(2), 202(h)(2)). On PIA $4, a +parent's OB is $3.30 and a payable $3 event legitimately withholds $.30; +using the two-parent $3 rate as an unconditional upper bound would reject +that valid case. A widow with OB basis $5 and payable $4 likewise withholds +$1. Equality remains permitted for dual-entitlement markers and other +event reasons according to their existing semantics. + +The new fact-pattern input errors in this PR's third fix round have these +premises. RET uses the same table in its design note. + +| Fact pattern classified as `InvalidFamilyInput` | Source proving impossibility | What would falsify the premise | +|---|---|---| +| RET NH or auxiliary FRA declaration lies outside every possible attainment month in the supplied G cohort | Act 203(f)(8)(E), (9); 20 CFR 404.430(b), 404.434(c); RS 02501.021B.3; cohort/attainment conventions in RS 00615.003/.010 | A birthday within the cohort whose RIB FRA satisfies the declaration; every such intersecting declaration remains admitted | +| An auxiliary and that same person's own benefit supply different SSA birth cohorts, even if their FRA declaration fits both separately | Act 202(q)(6); RS 00615.003/.010; G's existing single-person cohort-consistency contract | The fields describe different people or different declared cohort conventions; this interface permits neither | +| RET declaration places FRA after a supplied own DRC-increased G snapshot | Act 202(w)(2); RS 00615.692 | Credits belonging only to the deceased NH, or an own age reduction without own delayed credits; neither proves the survivor's age | +| Own-work payable plus NH reservation equals the applicable OB upper bound | GN 02603.050A's OB limit and a strictly positive own-work deduction | A supported entry route carrying gross above that OB; this API has none, and larger widow OBs and one-parent rates are explicitly preserved | + +### Reproduced cases and invariants + +With survivor PIA $4/MAX $6 and child OB $3, own-work payable $3, or NH +reservation $1 plus payable $2, is invalid even with administrative finality +or another-record entitlement. PIA/MAX/OB $0 with payable $0 is also +invalid. Both public forms produce no outcome or denominator row. The +test `test_own_event_at_ob_cap_errors_before_coverage_and_has_no_row` +pins actual and estimated events; Hypothesis +`test_upper_bound_equality_is_invalid_for_every_exact_reservation` varies +PIA, role, exact reservation, coverage condition and public form. +`test_other_event_equality_keeps_existing_named_refusal` and +`test_dual_marker_at_original_benefit_stays_supported` preserve the other +event semantics and counted coverage refusals. The parent and larger-widow +tests pin the valid routes described above. + +In the excluded-divorced-spouse regression, January 2026 retirement PIA +$4/MAX $6 rises to PIA $4.10 with MAX unchanged in February. The unreduced +worker and two children have no governed age reduction. Adding an +age-reduced divorced spouse D does not start protection: the children +receive $.90 each and D receives $1.30. Exact record payment is $7.20, +the sum of separate whole-dollar payments is $5, and protected total is +`None`. At PIA $.40 to $.50/MAX $.60 the children receive $0 each, +D $.10, exact record $.60 and whole-dollar record $0. Both beneficiary +orders are pinned in +`test_review_outside_divorced_age_reduction_cannot_start_protection`. +The surviving-divorced regression uses the independently retained +survivor COLA fall from governed $6.60 to $6.50; that person's age reduction +cannot start protection for the governed survivors. + +Hypothesis histories in +`test_property_operational_histories_treat_outside_people_as_absent` enforce +unchanged other-person rates, protected totals, history and refusal +decisions when either excluded spouse role is added or removed, in both +orders. Named examples also cover active and dormant protection, +excluded age-factor changes, and a sole governed survivor whose second +person is outside the maximum. Every excluded person's own row remains +ordinary. The old-guard comparison retains all 480 `LITERAL_REFUSAL` rows. + +No new statutory reading is required. The existing operational/literal +choice and all previously recorded readings remain unchanged. No source +capture, registry input or source manifest changes in this round. diff --git a/docs/design/track_b_r2_ret_ledger.md b/docs/design/track_b_r2_ret_ledger.md index 05c2affad..2200064b8 100644 --- a/docs/design/track_b_r2_ret_ledger.md +++ b/docs/design/track_b_r2_ret_ledger.md @@ -1842,6 +1842,91 @@ other tests deselected. Both staged microdata directory overrides pointed to nonexistent paths for every whole-suite collection and the selected policy test; that test's temporary directory was inside the workspace. +## Round-3 consistency of declared FRA and G facts + +Verification class remains statutory conformance on invented record-years +and captured rules. No population, behavioral or forecast claim is added. + +`RecordYear` checks each supplied G monthly context before any annual or +G coverage refusal. For the NH it uses `worker_birth_year` and the own +worker benefit; for auxiliaries it uses the beneficiary and own-benefit +cohorts. A contradiction raises `InvalidFamilyInput`, so an evaluator +cannot count that input as a coverage gap. Missing birth facts remain +supported. No earnings or annual parameter lookup is needed to classify +the supplied age facts, and validation runs once per public ledger call. + +The earnings test uses RIB FRA for every role. Act 203(f)(9) specifies the +retirement age "which is applicable in the case of old-age insurance +benefits, regardless of whether or not the particular benefits" are +old-age benefits. RS 02501.021B.3 says "Always use the FRA for retirement +insurance benefits (RIB) when applying the ET for RIB or widow(er)'s +insurance benefits (WIB)." The captured 20 CFR 404.430(b) and 404.434(c) +also point to 404.409(a). Thus the distinct widow age-reduction schedule +under 216(l) does not create a competing RET reading. No new refusal or +orchestrator ruling is needed. + +Under the cohort convention in RS 00615.003/.010, the possible FRA months +run from `birth_year * 12 + RIB_FRA_months` through eleven months later. +`fra_month=0` intersects dates before this calendar year; `None` intersects +dates after this year; values 1 through 12 specify the corresponding +month. A declaration is invalid only if its intersection with the whole +cohort interval is empty. Both endpoints and every interior declaration +remain accepted. The test enumerates every possible birthday independently +of the implementation's interval arithmetic and FRA lookup. + +Positive own delayed credits prove only that FRA occurred by the G +snapshot month. Act 202(w)(2) permits increment months from the FRA month +itself. This check does not reconstruct credit dates, an exact birthday or +a benefit-effective-date calendar; the staged captures do not supply the +additional effective-date chronology for such a reconstruction. Own age +reductions can persist after FRA and establish no current age. A larger +survivor basis can reflect the deceased worker's credits and establishes +no FRA date for the survivor. + +| Fact pattern classified as `InvalidFamilyInput` | Source proving impossibility | What would falsify the premise | +|---|---|---| +| NH or auxiliary FRA declaration has no overlap with the supplied G cohort interval | Act 203(f)(8)(E), (9); 20 CFR 404.430(b), 404.434(c); RS 02501.021B.3 and 00615.003/.010 | A birthday inside the cohort consistent with the declaration; all such intersections remain accepted | +| An auxiliary's cohort disagrees with that same person's own-benefit cohort, even when FRA 0 fits each cohort separately | Act 202(q)(6); RS 00615.003/.010 and G's existing single-person cohort-consistency contract | Different people or different declared cohort conventions; neither is admitted for these two fields | +| FRA is declared after a snapshot carrying that person's positive own delayed credits | Act 202(w)(2); RS 00615.692 | Only age-reduction months or inherited deceased-worker credits were supplied; these do not constrain the person's current FRA | + +### Examples and executed invariants + +The sole-widow regression has January 2024 PIA/MAX/OB $1 and cohort 1950. +With `fra_month=None` the input errors without a denominator row. With +`fra_month=0` it pays $1 with no own deduction, as required by Act +203(f)(8)(E). The nearby spouse/child case and actual/estimated cases for +cohorts 1930, 1950 and 1957 with declarations `None` and 12 also error. +Consistent facts preserve existing named refusals and their full weights. + +The new `tests/test_track_b_ret_fra_facts.py` executes these invariants: + +- `test_every_cohort_interval_endpoint_and_every_inside_declaration` + covers both NH and auxiliary facts across every FRA cohort band. +- Hypothesis + `test_fra_classification_matches_independent_birthday_enumeration` + checks acceptance exactly when at least one legal birthday agrees, + over all declaration values and both roles. +- `test_missing_cohort_preserves_every_fra_declaration` and + `test_own_delayed_credits_prove_only_fra_by_context_month` preserve + uncertainty and the limited own-credit implication. +- `test_every_auxiliary_role_uses_rib_fra_not_widow_reduction_age` + pins the role-specific source conclusion. +- `test_fra_contradiction_precedes_coverage_refusal` and + `test_consistent_fra_keeps_named_coverage_refusal_in_denominator` + check both directions of input/refusal classification. +- `test_paired_auxiliary_birth_cohorts_error_at_declaration_before_refusal` + and Hypothesis + `test_one_auxiliary_cannot_have_two_individually_post_fra_cohorts` + reject contradictory cohorts before a coverage refusal even when FRA 0 + fits each separately. The NH's corresponding identity check already + runs in G's `RecordState` constructor. +- `test_fra_facts_validate_once_per_public_ledger_call` checks the + public-call validation count. The source test independently recomputes + capture hashes and checks each quoted rule verbatim. + +No source capture, manifest, published worked-example figure, annual +earnings formula or existing assertion changes in this round. + ## Not in scope No real microdata, population pipeline, behavioral response or forecast diff --git a/src/populace_dynamics/track_b/gross_benefits.py b/src/populace_dynamics/track_b/gross_benefits.py index b824e19e1..90e1d203b 100644 --- a/src/populace_dynamics/track_b/gross_benefits.py +++ b/src/populace_dynamics/track_b/gross_benefits.py @@ -10,7 +10,9 @@ status, derived from supplied facts or otherwise attested (203(c)(2); 20 CFR 404.421(a)). Own-work events must withhold a positive amount; a zero deduction is an -input error and never changes the family-maximum computation. +input error and never changes the family-maximum computation. Payable plus +NH reservation must therefore be strictly below the original-benefit upper +bound, including before a held coverage refusal. Max's ruling d515 (2026-09-28) adopted §10 question 9's default: a Python reference now, with Axiom differential checks as diagnostics once a pinned rule exists. At this module's creation rulespec-us had no 42 U.S.C. 403 @@ -3902,9 +3904,13 @@ def _check_deduction_amount_bounds( ): """Reject impossible amounts before any statutory coverage refusal. - The original benefit is an unconditional upper bound on a post-work - payable. For a parent, the one-parent OB is the conservative upper - bound until a supported computation resolves entitlement/count. + These entry points compute ordinary G from RecordState, before any + saving-clause guard. They cannot receive a carried protected rate. + The original benefit is therefore an upper bound on gross here + (GN 02603.050A). For a parent, the one-parent OB is the conservative + upper bound until a supported computation resolves entitlement/count. + Own-work events need strictly positive withholding after NH reserves; + equality to this upper bound is impossible even on a refused record. """ for member in beneficiaries: bid = member.beneficiary_id @@ -3921,6 +3927,14 @@ def _check_deduction_amount_bounds( raise InvalidFamilyInput( "Deductee payable and NH reservation exceed the original benefit" ) + if ( + event is not None + and event.reason is DeductionReason.OWN_EARNINGS_TEST + and event.payable + nh == original + ): + raise InvalidFamilyInput( + "Own-earnings-test event must withhold a positive amount" + ) @_validated_entry @@ -4748,33 +4762,45 @@ class SavingsClauseReading(Enum): def _savings_membership(result: FamilyBenefits) -> tuple: - """Membership is unordered; a change of record kind changes it too.""" + """Operational membership excludes everyone outside 203(a)(3)(C).""" return ( result.kind, result.worker_benefit is not None, frozenset( (row.beneficiary_id, row.role) for row in result.beneficiaries - if row.entitled + if row.subject_to_family_maximum ), ) def _operational_age_reduced(result: FamilyBenefits) -> bool: + """An outside spouse cannot supply another person's age trigger.""" return result.worker_reduced_for_age or any( - row.entitled and row.age_reduction_factor < 1 + row.subject_to_family_maximum and row.age_reduction_factor < 1 for row in result.beneficiaries ) +def _operational_qualifies(result: FamilyBenefits) -> bool: + """Apply 203(a)(3)(C)'s as-if-absent rule to the entitled-person count. + + The literal reading deliberately retains its old count in _qualifies. + """ + persons = sum( + row.subject_to_family_maximum for row in result.beneficiaries + ) + (result.worker_benefit is not None) + return result.family_maximum_binding and persons >= 2 + + def _savings_age_basis(result: FamilyBenefits) -> tuple: - """Do not attribute a simultaneous change of age factors to the PIA.""" + """Only governed age-factor changes can confound the PIA's effect.""" return ( result.worker_age_reduction_factor, frozenset( (row.beneficiary_id, row.age_reduction_factor) for row in result.beneficiaries - if row.entitled + if row.subject_to_family_maximum ), ) @@ -4894,7 +4920,10 @@ class SavingsClauseGuard: ``reading`` is an exact canonical SavingsClauseReading enum; its default SSA_OPERATIONAL follows d1338 and POMS RS 00630.400. Protection starts only after an age-reduced, maximum-reduced month with at least two - entitled persons, followed by a PIA increase that lowers payment. The + entitled persons, followed by a PIA increase that lowers payment. + Persons outside the maximum do not enter operational membership, age + conditions, or the entitled-person count (203(a)(3)(C)); their own + rates remain unchanged. The two captured life-case procedures compute protected auxiliary payments. Formula FMAX and its counted shares stay unchanged. RS 00615.801B.2 carries the protected total, including a period when the formula payment @@ -5180,7 +5209,7 @@ def _operational_admit( if ( prior is not None and prior.result is not None - and _qualifies(prior.result) + and _operational_qualifies(prior.result) and _operational_age_reduced(prior.result) and result.pia > prior.pia and total < _savings_clause_total_validated(prior.result) diff --git a/src/populace_dynamics/track_b/ret_ledger.py b/src/populace_dynamics/track_b/ret_ledger.py index 98a4abef3..67f674b55 100644 --- a/src/populace_dynamics/track_b/ret_ledger.py +++ b/src/populace_dynamics/track_b/ret_ledger.py @@ -23,6 +23,12 @@ G's declared monthly own-benefit facts establish two-record entitlement; an optional annual declaration must agree with those facts. Actual or estimated excess on two records remains refused (RS 02501.145-.150). +Supplied G cohorts constrain the RET FRA declaration to the whole possible +attainment-month interval, for the NH and every auxiliary. The old-age FRA +governs all roles, including survivors (Act 203(f)(9); RS 02501.021B.3). +Applied own delayed credits establish FRA by the supplied context month; +age reductions and the deceased worker's credits do not establish a +survivor's current age. Contradictions error before coverage refusals. Every raw month-set element must be an integer month before deduplication; malformed input raises before a coverage refusal can become an outcome. @@ -412,6 +418,55 @@ def __post_init__(self): object.__setattr__(self, "households", dict(self.households)) +def _check_fra_facts( + beneficiary: RETBeneficiary, + year: int, + month: int, + birth_year: int | None, + own: g.OwnBenefit | None, + params: g.SSAParameters, +) -> None: + """Reject only FRA declarations impossible under supplied G facts. + + Act 203(f)(9), CFR .430(b)/.434(c), RS 02501.021B.3: every role uses + old-age FRA, not the widow's age-reduction schedule. SSA cohort years + run Jan 2 through the following Jan 1 (RS 00615.003); age attainment + precedes the birthday, so the possible FRA months span eleven months + after the earliest one. Missing dates leave the entire interval open. + Own DRCs establish only that FRA has occurred by this snapshot; do + not infer an exact FRA date or use another person's inherited DRCs. + """ + if own is not None and own.birth_year is not None: + if birth_year is not None and birth_year != own.birth_year: + raise InvalidFamilyInput( + "G own and beneficiary birth cohorts differ" + ) + birth_year = own.birth_year + earliest = latest = None + if birth_year is not None: + earliest = birth_year * 12 + g._fra_months(birth_year, params) + latest = earliest + 11 + if own is not None and own.delayed_credit_months: + known_by = year * 12 + month - 1 + latest = known_by if latest is None else min(latest, known_by) + fra = beneficiary.fra_month + if fra is None: + consistent = latest is None or latest >= (year + 1) * 12 + elif fra == 0: + consistent = earliest is None or earliest < year * 12 + else: + declared = year * 12 + fra - 1 + consistent = (earliest is None or earliest <= declared) and ( + latest is None or declared <= latest + ) + if earliest is not None and latest is not None and earliest > latest: + consistent = False + if not consistent: + raise InvalidFamilyInput( + "RET FRA declaration contradicts G birth cohort or own delayed credits" + ) + + @_declared_input @dataclass(frozen=True) class RecordYear: @@ -537,7 +592,24 @@ def __post_init__(self): g.Role.DISABLED_WIDOW: (BenefitType.DWB,), } ret_people = {b.beneficiary_id: b for b in beneficiaries} + if self.kind is not RecordKind.DECEASED: + _check_fra_facts( + ret_people[self.nh_id], + self.year, + month, + context.state.worker_birth_year, + context.state.worker, + context.params, + ) for auxiliary in context.beneficiaries: + _check_fra_facts( + ret_people[auxiliary.beneficiary_id], + self.year, + month, + auxiliary.birth_year, + auxiliary.own_benefit, + context.params, + ) contextual_people.add(auxiliary.beneficiary_id) if auxiliary.own_benefit is not None: contextual_two_records.add(auxiliary.beneficiary_id) diff --git a/tests/README-tiers.md b/tests/README-tiers.md index 3b16d2ec1..3b0a41cc5 100644 --- a/tests/README-tiers.md +++ b/tests/README-tiers.md @@ -39,9 +39,9 @@ pytest --collect-only -q -m oracle_policyengine | tail -1 | Tier | Tests at HEAD | |---|---:| -| `unit` | 19,682 | +| `unit` | 19,858 | | `artifact` | 4,271 | | `integration_psid` | 1,471 | | `reproduction_legacy` | 520 | | `oracle_policyengine` | 308 | -| **Total** | **26,252** | +| **Total** | **26,428** | diff --git a/tests/test_track_b_gross_benefits_deduction_cap.py b/tests/test_track_b_gross_benefits_deduction_cap.py new file mode 100644 index 000000000..a91342c0c --- /dev/null +++ b/tests/test_track_b_gross_benefits_deduction_cap.py @@ -0,0 +1,217 @@ +"""Statutory conformance: positive own-work events on invented records. + +GN 02603.050A caps deduction-before-reduction rates at OB. Invalid events +precede coverage refusals and never enter the shared denominator. No +population, behavioral or forecast claim. +""" + +from dataclasses import replace +from fractions import Fraction as F + +import pytest +from hypothesis import given, settings +from hypothesis import strategies as st + +from populace_dynamics.track_b import gross_benefits as g +from tests.track_b_gross_benefit_support import ssa_params +from tests.track_b_ret_ledger_support import source_text + +PARAMS = ssa_params() +MONTH = g.YearMonth(2024, 1) + + +def compute( + *, + household=False, + combined=False, + pia=F(4), + reservation=F(0), + payable=None, + role=g.Role.CHILD, + reason=g.DeductionReason.OWN_EARNINGS_TEST, + permanent=True, + member=None, + held=True, +): + state = g.RecordState( + g.FamilyKind.SURVIVOR, + pia, + pia * F(3, 2), + widow_drc_savings_clause=False, + conditions=( + {g.RecordCondition.ADMINISTRATIVE_FINALITY} + if held and not combined + else set() + ), + ) + member = member or g.Beneficiary("C", role) + if combined: + member = replace( + member, + conditions={g.BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD}, + ) + upper = g.original_benefit( + member.role, state.kind, pia, member.original_benefit_basis + ) + if payable is None: + payable = upper - reservation + kwargs = dict( + payment_month=MONTH, + params=PARAMS, + deductions={"C": g.BenefitDeduction(reason, payable, permanent)}, + households={"C": "home"}, + worker_deductions={"C": reservation}, + ) + if household: + return g.household_benefits_after_deductions( + {"r": g.HouseholdRecord("nh", state, (member,))}, **kwargs + ) + return g.family_benefits_after_deductions( + state, (member,), standalone=True, **kwargs + ) + + +@pytest.mark.parametrize("household", (False, True)) +@pytest.mark.parametrize("combined", (False, True)) +@pytest.mark.parametrize("reservation", (F(0), F(1))) +@pytest.mark.parametrize("permanent", (False, True)) +def test_own_event_at_ob_cap_errors_before_coverage_and_has_no_row( + household, combined, reservation, permanent +): + outcomes = [] + with pytest.raises(g.InvalidFamilyInput, match="positive"): + outcomes.append( + g.evaluate_family( + "zero cap", + 7, + lambda: compute( + household=household, + combined=combined, + reservation=reservation, + permanent=permanent, + ), + ) + ) + assert g.count_family_outcomes(outcomes).rows == 0 + + +@pytest.mark.parametrize("household", (False, True)) +@pytest.mark.parametrize("combined", (False, True)) +@settings(max_examples=20, deadline=None) +@given( + pia=st.integers(0, 100), + role=st.sampled_from((g.Role.CHILD, g.Role.PARENT, g.Role.WIDOW)), + reserved_fraction=st.fractions(min_value=0, max_value=1), +) +def test_upper_bound_equality_is_invalid_for_every_exact_reservation( + household, combined, pia, role, reserved_fraction +): + upper = g.original_benefit(role, g.FamilyKind.SURVIVOR, F(pia)) + outcomes = [] + with pytest.raises(g.InvalidFamilyInput, match="positive"): + outcomes.append( + g.evaluate_family( + "exact cap", + 7, + lambda: compute( + household=household, + combined=combined, + pia=F(pia), + role=role, + reservation=upper * reserved_fraction, + ), + ) + ) + assert g.count_family_outcomes(outcomes).rows == 0 + + +@pytest.mark.parametrize("household", (False, True)) +def test_zero_pia_maximum_and_ob_cannot_hide_own_event(household): + with pytest.raises(g.InvalidFamilyInput, match="positive"): + compute(household=household, pia=F(0)) + + +@pytest.mark.parametrize("household", (False, True)) +def test_parent_bound_preserves_legitimate_rate_above_two_parent_ob(household): + result = compute( + household=household, + role=g.Role.PARENT, + payable=F(3), + held=False, + ) + family = result.records["r"] if household else result + row = family.by_id()["C"] + assert row.original_benefit == F("3.30") + assert row.auxiliary_payable == F(3) + assert row.deduction == F(".30") + + +@pytest.mark.parametrize("household", (False, True)) +def test_widow_larger_original_basis_preserves_positive_event(household): + result = compute( + household=household, + member=g.Beneficiary("C", g.Role.WIDOW, original_benefit_basis=F(5)), + payable=F(4), + held=False, + ) + family = result.records["r"] if household else result + row = family.by_id()["C"] + assert row.original_benefit == F(5) + assert row.auxiliary_payable == F(4) + assert row.deduction == F(1) + + +@pytest.mark.parametrize("household", (False, True)) +@pytest.mark.parametrize( + "reason", + ( + g.DeductionReason.DUAL_ENTITLEMENT, + g.DeductionReason.PRISONER_SUSPENSION, + ), +) +def test_other_event_equality_keeps_existing_named_refusal(household, reason): + member = g.Beneficiary( + "C", + g.Role.CHILD, + own_benefit=( + g.OwnBenefit(g.OwnBenefitKind.DISABILITY, F(0)) + if reason is g.DeductionReason.DUAL_ENTITLEMENT + else None + ), + ) + outcome = g.evaluate_family( + "other event", + 7, + lambda: compute(household=household, reason=reason, member=member), + ) + assert ( + outcome.unsupported.reason + is g.UnsupportedReason.ADMINISTRATIVE_FINALITY + ) + counts = g.count_family_outcomes([outcome]) + assert counts.rows == counts.unsupported_rows == 1 + assert counts.unsupported_weight == F(7) + + +@pytest.mark.parametrize("household", (False, True)) +def test_dual_marker_at_original_benefit_stays_supported(household): + result = compute( + household=household, + reason=g.DeductionReason.DUAL_ENTITLEMENT, + member=g.Beneficiary( + "C", + g.Role.CHILD, + own_benefit=g.OwnBenefit(g.OwnBenefitKind.DISABILITY, F(0)), + ), + held=False, + ) + family = result.records["r"] if household else result + assert family.by_id()["C"].auxiliary_payable == F(3) + assert family.by_id()["C"].deduction == 0 + + +def test_original_benefit_cap_rule_is_quoted_from_capture(): + assert ( + "In all cases, beneficiaries are still limited to the original " + "benefit amount." + ) in source_text("poms_gn_02603_050") diff --git a/tests/test_track_b_gross_benefits_saving_absence.py b/tests/test_track_b_gross_benefits_saving_absence.py new file mode 100644 index 000000000..819ce0521 --- /dev/null +++ b/tests/test_track_b_gross_benefits_saving_absence.py @@ -0,0 +1,371 @@ +"""Statutory conformance: outside-maximum saving-clause independence. + +Invented families only; no population, behavioral or forecast claim. Act +203(a)(3)(C)'s as-if-absent rule governs every operational predicate, while +the separately selected literal refusal reading retains its old semantics. +""" + +from fractions import Fraction as F + +import pytest +from hypothesis import example, given, settings +from hypothesis import strategies as st + +from populace_dynamics.track_b import gross_benefits as g +from tests.track_b_gross_benefit_support import source_text, ssa_params + +PARAMS = ssa_params() +JAN = g.YearMonth(2026, 1) + + +def family( + month, + pia, + maximum, + *, + outside=False, + reduction=0, + outside_reduction=60, + kind=g.FamilyKind.RETIREMENT, + sole_widow=False, + reverse=False, +): + worker = ( + g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, pia, reduction_months=reduction) + if kind is g.FamilyKind.RETIREMENT + else None + ) + state = g.RecordState( + kind, + pia, + maximum, + worker=worker, + widow_drc_savings_clause=False, + ) + rows = ( + [ + g.Beneficiary( + "W", + g.Role.WIDOW, + original_benefit_basis=2 * pia, + reduction_months=reduction, + reduction_period_months=60, + child_in_care=False, + ) + ] + if sole_widow + else [g.Beneficiary(name, g.Role.CHILD) for name in ("C1", "C2")] + ) + if outside: + life = kind is g.FamilyKind.RETIREMENT + rows.append( + g.Beneficiary( + "D", + ( + g.Role.DIVORCED_SPOUSE + if life + else g.Role.SURVIVING_DIVORCED_SPOUSE + ), + reduction_months=outside_reduction, + reduction_period_months=None if life else 60, + child_in_care=False, + first_entitlement_child_in_care=False if life else None, + ) + ) + return g.family_benefits( + state, + rows[::-1] if reverse else rows, + payment_month=g.YearMonth(2026, month), + params=PARAMS, + standalone=True, + ) + + +def guard(): + return g.SavingsClauseGuard(JAN, earlier_months_unknown=False) + + +def test_outside_maximum_operational_rules_are_quoted_from_captures(): + assert ( + "shall be determined as if no such divorced spouse or surviving " + "divorced spouse were entitled to benefits for such month." + ) in source_text("ssa_act_203") + assert ( + "Benefits for that month are reduced for the MAX and at least one " + "beneficiary is reduced for age;" + ) in source_text("poms_rs_00630_400") + + +@pytest.mark.parametrize("reverse", (False, True)) +@pytest.mark.parametrize( + "pia,maximum,child,divorced,total,whole", + ( + (F(4), F(6), F(".90"), F("1.30"), F("7.20"), 5), + (F(".4"), F(".6"), F(0), F(".1"), F(".6"), 0), + ), +) +def test_review_outside_divorced_age_reduction_cannot_start_protection( + reverse, pia, maximum, child, divorced, total, whole +): + before = family(1, pia, maximum, outside=True, reverse=reverse) + after = family(2, pia + F(".1"), maximum, outside=True, reverse=reverse) + value = guard() + value.admit(before) + outcome = value.evaluate( + "outside age only", F(7), lambda after=after: after + ) + assert outcome.supported + paid = outcome.benefits + assert paid.by_id()["C1"].auxiliary_payable == child + assert paid.by_id()["C2"].auxiliary_payable == child + assert paid.by_id()["D"] == after.by_id()["D"] + assert paid.by_id()["D"].auxiliary_payable == divorced + assert not paid.by_id()["D"].subject_to_family_maximum + assert paid.record_total == total + assert paid.record_total_whole_dollars == whole + assert value.protected_total is None + counts = g.count_family_outcomes([outcome]) + assert counts.rows == counts.supported_rows == 1 + assert counts.weight == counts.supported_weight == F(7) + + +@pytest.mark.parametrize("reverse", (False, True)) +@pytest.mark.parametrize("presence", ((False, True), (True, False))) +def test_outside_membership_changes_preserve_active_and_dormant_protection( + reverse, presence +): + plain, decorated = guard(), guard() + for month, pia, maximum in ( + (1, F(1000), F(1500)), + (2, F(1010), F(1500)), + (3, F(1010), F(1600)), + (4, F(1010), F(1500)), + ): + options = dict(reduction=60, reverse=reverse) + baseline = plain.admit(family(month, pia, maximum, **options)) + ordinary = family( + month, + pia, + maximum, + outside=presence[(month - 1) % 2], + **options, + ) + out = decorated.evaluate( + "outside membership", F(7), lambda ordinary=ordinary: ordinary + ) + assert out.supported + assert decorated.protected_total == plain.protected_total + assert decorated.protected_since == plain.protected_since + for name, row in baseline.by_id().items(): + assert out.benefits.by_id()[name] == row + if "D" in ordinary.by_id(): + assert out.benefits.by_id()["D"] == ordinary.by_id()["D"] + assert plain.protected_total == F(1200) + + +@pytest.mark.parametrize("reverse", (False, True)) +def test_outside_age_basis_change_does_not_hide_worker_protection(reverse): + value = guard() + value.admit( + family( + 1, F(1000), F(1500), outside=True, reduction=60, reverse=reverse + ) + ) + after = family( + 2, + F(1010), + F(1500), + outside=True, + outside_reduction=0, + reduction=60, + reverse=reverse, + ) + out = value.evaluate("outside age changes", 1, lambda after=after: after) + assert out.supported + assert value.protected_total == F(1200) + assert out.benefits.by_id()["C1"].auxiliary_payable == F("246.50") + assert out.benefits.by_id()["C2"].auxiliary_payable == F("246.50") + assert out.benefits.by_id()["D"] == after.by_id()["D"] + + +@pytest.mark.parametrize("reverse", (False, True)) +def test_surviving_divorced_person_cannot_supply_operational_membership( + reverse, +): + # Only W is governed. Adding D must not turn W's independent age change + # into a two-person saving-clause event or a rate-procedure refusal. + for outside in (False, True): + value = guard() + value.admit( + family( + 1, + F(4), + F(6), + outside=outside, + reduction=12, + kind=g.FamilyKind.SURVIVOR, + sole_widow=True, + reverse=reverse, + ) + ) + after = family( + 2, + F("4.1"), + F(6), + outside=outside, + reduction=60, + kind=g.FamilyKind.SURVIVOR, + sole_widow=True, + reverse=reverse, + ) + out = value.evaluate( + "one governed widow", 1, lambda after=after: after + ) + assert out.supported + assert out.benefits == after + assert value.protected_total is None + + +@pytest.mark.parametrize("reverse", (False, True)) +def test_outside_surviving_divorced_age_cannot_trigger_survivor_protection( + reverse, +): + rows = [ + g.Beneficiary(name, g.Role.WIDOW, child_in_care=False) + for name in ("W1", "W2") + ] + [ + g.Beneficiary("M", g.Role.MOTHER_FATHER), + g.Beneficiary( + "D", + g.Role.SURVIVING_DIVORCED_SPOUSE, + reduction_months=60, + reduction_period_months=60, + child_in_care=False, + ), + ] + value = guard() + for month, pia, maximum, expected in ( + (1, F("4.4"), F("6.6"), F("6.6")), + (2, F("4.5"), F("6.7"), F("6.5")), + ): + state = g.RecordState( + g.FamilyKind.SURVIVOR, + pia, + maximum, + widow_drc_savings_clause=False, + ) + ordinary = g.family_benefits( + state, + rows[::-1] if reverse else rows, + payment_month=g.YearMonth(2026, month), + params=PARAMS, + standalone=True, + ) + assert g.savings_clause_total(ordinary) == expected + out = value.evaluate( + "surviving divorced age only", + 1, + lambda ordinary=ordinary: ordinary, + ) + assert out.supported + assert out.benefits == ordinary + assert value.protected_total is None + + +@settings(max_examples=60, deadline=None, derandomize=True) +@example( + base=1000, + retirement=True, + sole_widow=False, + history=[ + (0, 0, 60, False, 60), + (10, 0, 60, True, 0), + (10, 10, 60, False, 30), + (10, 0, 60, True, 60), + ], +) +@example( + base=20, + retirement=True, + sole_widow=False, + history=[(0, 0, 0, True, 60), (1, 0, 0, True, 60)], +) +@given( + base=st.integers(20, 2000), + retirement=st.booleans(), + sole_widow=st.booleans(), + history=st.lists( + st.tuples( + st.integers(0, 30), + st.integers(-10, 10), + st.integers(0, 60), + st.booleans(), + st.integers(0, 60), + ), + min_size=2, + max_size=6, + ), +) +def test_property_operational_histories_treat_outside_people_as_absent( + base, retirement, sole_widow, history +): + kind = g.FamilyKind.RETIREMENT if retirement else g.FamilyKind.SURVIVOR + snapshots = [] + for reverse in (False, True): + plain, decorated = guard(), guard() + results = [] + for month, ( + rise, + max_change, + reduction, + present, + outside_rf, + ) in enumerate(history, 1): + pia = F(base, 5) + F(rise, 10) + maximum = max(pia, F(3 * base, 10) + F(max_change, 10)) + options = dict( + reduction=reduction, + kind=kind, + sole_widow=sole_widow and not retirement, + reverse=reverse, + ) + baseline = family(month, pia, maximum, **options) + ordinary = family( + month, + pia, + maximum, + outside=present, + outside_reduction=outside_rf, + **options, + ) + plain_out = plain.evaluate( + "plain", F(7), lambda baseline=baseline: baseline + ) + out = decorated.evaluate( + "outside", F(7), lambda ordinary=ordinary: ordinary + ) + assert out.supported == plain_out.supported + assert decorated.protected_total == plain.protected_total + assert decorated.protected_since == plain.protected_since + assert decorated.unknown_since == plain.unknown_since + assert decorated.refused_since == plain.refused_since + if out.supported: + expected = plain_out.benefits.by_id() + assert { + name: row + for name, row in out.benefits.by_id().items() + if name != "D" + } == expected + assert g.savings_clause_total(out.benefits) == ( + g.savings_clause_total(plain_out.benefits) + ) + if present: + assert out.benefits.by_id()["D"] == ordinary.by_id()["D"] + results.append((expected, decorated.protected_total)) + else: + assert out.unsupported.reason is plain_out.unsupported.reason + results.append( + (out.unsupported.reason, decorated.protected_total) + ) + snapshots.append(results) + assert snapshots[0] == snapshots[1] diff --git a/tests/test_track_b_ret_fra_facts.py b/tests/test_track_b_ret_fra_facts.py new file mode 100644 index 000000000..763170102 --- /dev/null +++ b/tests/test_track_b_ret_fra_facts.py @@ -0,0 +1,537 @@ +"""RET FRA facts: statutory conformance on invented declarations only. + +No population, behavioral, or forecast claim. Act 203(f)(9) makes the RIB +FRA govern every section 202 benefit; a cohort identifies twelve possible +attainment months rather than a particular birthday. +""" + +from __future__ import annotations + +import hashlib +import html +import json +import re +from dataclasses import replace +from datetime import date, timedelta +from fractions import Fraction as F +from pathlib import Path + +import pytest +from hypothesis import given, settings +from hypothesis import strategies as st + +from populace_dynamics.track_b import gross_benefits as g +from populace_dynamics.track_b import ret_ledger as r +from populace_dynamics.track_b.ret_grace import BenefitType as T +from populace_dynamics.track_b.ret_params import load_ret_parameters +from tests.track_b_gross_benefit_support import ssa_params + +PARAMS = load_ret_parameters() +DECLARATIONS = (None, *range(13)) +# Independent statutory bands, not the implementation's parameter lookup. +COHORTS = ( + (1930, 780), + (1937, 780), + (1938, 782), + (1939, 784), + (1940, 786), + (1941, 788), + (1942, 790), + (1943, 792), + (1950, 792), + (1954, 792), + (1955, 794), + (1956, 796), + (1957, 798), + (1958, 800), + (1959, 802), + (1960, 804), + (1961, 804), +) + + +def _person(key, kind, rate, fra=None, *, estimated=False): + work = r.WorkEarnings((F(22322),) + (F(0),) * 11) + return r.RETBeneficiary( + key, + (kind,) * 12, + {1}, + (F(rate),) + (F(0),) * 11, + (F(rate),) * 12, + fra_month=fra, + **({"estimated_earnings": work} if estimated else {"earnings": work}), + ) + + +def _widow( + fra=None, *, cohort=1950, estimated=False, fiscal=False, held_g=False +): + state = g.RecordState( + g.FamilyKind.SURVIVOR, + F(1), + F(1), + conditions=( + {g.RecordCondition.ADMINISTRATIVE_FINALITY} if held_g else () + ), + eligibility_year=2024, + widow_drc_savings_clause=False, + ) + member = g.Beneficiary("w", g.Role.WIDOW, birth_year=cohort) + return r.RecordYear( + 2024, + "nh", + r.RecordKind.DECEASED, + (_person("w", T.WIDOW, 1, fra, estimated=estimated),), + fiscal_year=fiscal, + family_months={ + 1: r.RETFamilyMonth(state, (member,), ssa_params(), {"w": "h"}) + }, + ) + + +def _facts( + year, fra, cohort, *, nh=False, role=g.Role.WIDOW, month=1, own=None +): + """Declare facts without calculating money or needing a parameter year.""" + if nh: + state = g.RecordState( + g.FamilyKind.RETIREMENT, + own.pia if own else F(4), + F(6), + worker=own or g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, F(4)), + worker_birth_year=cohort, + ) + people = (_person("nh", T.RIB, 4, fra),) + members = () + kind = r.RecordKind.RETIREMENT + else: + living = role in { + g.Role.SPOUSE, + g.Role.SPOUSE_CHILD_IN_CARE, + g.Role.DIVORCED_SPOUSE, + } + state = g.RecordState( + g.FamilyKind.RETIREMENT if living else g.FamilyKind.SURVIVOR, + F(4), + F(6), + worker=( + g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, F(4)) + if living + else None + ), + widow_drc_savings_clause=False, + ) + benefit_type = { + g.Role.WIDOW: T.WIDOW, + g.Role.SURVIVING_DIVORCED_SPOUSE: T.WIDOW, + g.Role.DISABLED_WIDOW: T.DWB, + g.Role.MOTHER_FATHER: T.MOTHER_FATHER, + g.Role.CHILD: T.CHILD, + g.Role.SPOUSE: T.SPOUSE, + g.Role.SPOUSE_CHILD_IN_CARE: T.SPOUSE, + g.Role.DIVORCED_SPOUSE: T.DIVORCED_SPOUSE, + }[role] + people = (_person("w", benefit_type, 1, fra),) + if living: + people += (_person("nh", T.RIB, 4),) + members = ( + g.Beneficiary("w", role, birth_year=cohort, own_benefit=own), + ) + kind = r.RecordKind.RETIREMENT if living else r.RecordKind.DECEASED + people = tuple( + replace( + p, + entitled_months={month}, + gross_rates=tuple( + F(1) if m == month else F(0) for m in range(1, 13) + ), + ) + for p in people + ) + return r.RecordYear( + year, + "nh", + kind, + people, + family_months={ + month: r.RETFamilyMonth( + state, + members, + ssa_params(), + {b.beneficiary_id: "h" for b in members}, + ) + }, + ) + + +def _spouse_case(fra=None, *, cohort=1950, estimated=False): + state = g.RecordState( + g.FamilyKind.RETIREMENT, + F(4), + F(6), + worker=g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, F(4)), + eligibility_year=2024, + ) + members = ( + g.Beneficiary("s", g.Role.SPOUSE, birth_year=cohort), + g.Beneficiary("c", g.Role.CHILD), + ) + spouse = replace( + _person("s", T.SPOUSE, 1, fra, estimated=estimated), + original_rates=(F(2),) * 12, + ) + people = ( + replace(_person("nh", T.RIB, 4), earnings=r.WorkEarnings()), + spouse, + replace( + _person("c", T.CHILD, 1), + earnings=r.WorkEarnings(), + original_rates=(F(2),) * 12, + ), + ) + return r.RecordYear( + 2024, + "nh", + beneficiaries=people, + family_maximum_binding_months={1}, + family_months={ + 1: r.RETFamilyMonth( + state, members, ssa_params(), {"s": "h", "c": "h"} + ) + }, + ) + + +def test_sole_widow_contradictory_fra_is_input_error_and_has_no_row(): + outcomes = [] + with pytest.raises(g.InvalidFamilyInput, match="FRA"): + outcomes.append( + r.evaluate_ret( + "aged", 3, lambda: r.apply_ret_year(_widow(), PARAMS) + ) + ) + assert g.count_family_outcomes(outcomes).rows == 0 + + +def test_sole_widow_consistent_fra_has_no_own_deduction(): + result = r.apply_ret_year(_widow(0), PARAMS) + january = next(row for row in result.months if row.month == 1) + assert (january.net_due, january.payment, january.own_deduction) == ( + 1, + 1, + 0, + ) + + +def test_spouse_counterexample_is_input_error_and_has_no_row(): + outcomes = [] + with pytest.raises(g.InvalidFamilyInput, match="FRA"): + outcomes.append( + r.evaluate_ret( + "aged", 3, lambda: r.apply_ret_year(_spouse_case(), PARAMS) + ) + ) + assert g.count_family_outcomes(outcomes).rows == 0 + + +@pytest.mark.parametrize("cohort", [1930, 1950, 1957]) +@pytest.mark.parametrize("fra", [None, 12]) +@pytest.mark.parametrize("estimated", [False, True]) +def test_old_cohort_cannot_be_overridden_by_actual_or_estimated_declaration( + cohort, fra, estimated +): + with pytest.raises(g.InvalidFamilyInput, match="FRA"): + r.apply_ret_year( + _spouse_case(fra, cohort=cohort, estimated=estimated), PARAMS + ) + + +@pytest.mark.parametrize("estimated", [False, True]) +@pytest.mark.parametrize("held_g", [False, True]) +def test_fra_contradiction_precedes_coverage_refusal(estimated, held_g): + outcomes = [] + with pytest.raises(g.InvalidFamilyInput, match="FRA"): + outcomes.append( + r.evaluate_ret( + "aged", + 3, + lambda: r.apply_ret_year( + _widow(estimated=estimated, fiscal=True, held_g=held_g), + PARAMS, + ), + ) + ) + assert g.count_family_outcomes(outcomes).rows == 0 + + +def test_consistent_fra_keeps_named_coverage_refusal_in_denominator(): + outcome = r.evaluate_ret( + "aged", 3, lambda: r.apply_ret_year(_widow(0, held_g=True), PARAMS) + ) + assert ( + outcome.unsupported.reason + is g.UnsupportedReason.ADMINISTRATIVE_FINALITY + ) + denominator = g.count_family_outcomes([outcome]) + assert (denominator.rows, denominator.unsupported_weight) == (1, 3) + + +def _birthday_months(cohort, age_months): + """Enumerate actual SSA-cohort birthdays and age-attainment dates.""" + birthday = date(cohort, 1, 2) + result = set() + while birthday <= date(cohort + 1, 1, 1): + target = birthday.year * 12 + birthday.month - 1 + age_months + # Month-end dates do not affect the endpoints; use the first and + # second of every month to independently enumerate all months. + if birthday.day in (1, 2): + attained = date( + target // 12, target % 12 + 1, birthday.day + ) - timedelta(days=1) + result.add(attained.year * 12 + attained.month - 1) + birthday += timedelta(days=1) + return result + + +def _accepted_months(year, months): + return { + 0 if m < year * 12 else None if m >= (year + 1) * 12 else m % 12 + 1 + for m in months + } + + +@pytest.mark.parametrize("cohort,age", COHORTS) +@pytest.mark.parametrize("nh", [False, True]) +def test_every_cohort_interval_endpoint_and_every_inside_declaration( + cohort, age, nh +): + months = _birthday_months(cohort, age) + assert (min(months), max(months)) == ( + cohort * 12 + age, + cohort * 12 + age + 11, + ) + for year in range(min(months) // 12 - 1, max(months) // 12 + 2): + accepted = _accepted_months(year, months) + for fra in DECLARATIONS: + if fra in accepted: + assert ( + _facts(year, fra, cohort, nh=nh).beneficiaries[0].fra_month + == fra + ) + else: + with pytest.raises(g.InvalidFamilyInput, match="FRA"): + _facts(year, fra, cohort, nh=nh) + + +@settings(max_examples=65, deadline=None) +@given( + st.sampled_from(COHORTS), + st.integers(-1, 2), + st.sampled_from(DECLARATIONS), + st.booleans(), +) +def test_fra_classification_matches_independent_birthday_enumeration( + cohort_age, offset, fra, nh +): + cohort, age = cohort_age + months = _birthday_months(cohort, age) + year = min(months) // 12 + offset + if fra in _accepted_months(year, months): + assert ( + _facts(year, fra, cohort, nh=nh).beneficiaries[0].fra_month == fra + ) + else: + with pytest.raises(g.InvalidFamilyInput, match="FRA"): + _facts(year, fra, cohort, nh=nh) + + +@pytest.mark.parametrize( + "role", + [ + g.Role.WIDOW, + g.Role.SURVIVING_DIVORCED_SPOUSE, + g.Role.DISABLED_WIDOW, + g.Role.MOTHER_FATHER, + g.Role.CHILD, + g.Role.SPOUSE, + g.Role.SPOUSE_CHILD_IN_CARE, + g.Role.DIVORCED_SPOUSE, + ], +) +def test_every_auxiliary_role_uses_rib_fra_not_widow_reduction_age(role): + # 1957: RIB age 66y6m; WIB reduction FRA 66y2m. March 2023 is + # possible only under the WIB reduction schedule and must error. + with pytest.raises(g.InvalidFamilyInput, match="FRA"): + _facts(2023, 3, 1957, role=role) + assert _facts(2023, 7, 1957, role=role) + + +@pytest.mark.parametrize("nh", [False, True]) +@pytest.mark.parametrize("fra", DECLARATIONS) +def test_missing_cohort_preserves_every_fra_declaration(nh, fra): + assert _facts(2024, fra, None, nh=nh) + + +@pytest.mark.parametrize("nh", [False, True]) +@pytest.mark.parametrize("fra", DECLARATIONS) +def test_own_delayed_credits_prove_only_fra_by_context_month(nh, fra): + own = g.OwnBenefit( + g.OwnBenefitKind.OLD_AGE, + F(1), + delayed_credit_months=1, + birth_year=1957, + ) + # July is the first possible FRA month. Applied credits prove FRA has + # occurred by the September snapshot, without fixing a birthday. + if fra is not None and fra <= 9 and fra >= 7: + assert _facts(2023, fra, 1957, nh=nh, month=9, own=own) + else: + with pytest.raises(g.InvalidFamilyInput, match="FRA"): + _facts(2023, fra, 1957, nh=nh, month=9, own=own) + + +def test_auxiliary_own_cohort_alone_constrains_fra(): + own = g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, F(1), birth_year=1950) + with pytest.raises(g.InvalidFamilyInput, match="FRA"): + _facts(2024, None, None, own=own) + assert _facts(2024, 0, None, own=own) + + +def _paired_cohort_record(cohort, own_cohort, held_g): + # FRA0 is valid for either old cohort on its own. Only the assertion + # that one auxiliary has two different birth cohorts is impossible. + own = g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, F(1), birth_year=own_cohort) + assert _facts(2024, 0, None, own=own) + case = _facts(2024, 0, cohort) + context = case.family_months[1] + auxiliary = replace(context.beneficiaries[0], own_benefit=own) + state = replace( + context.state, + conditions=( + {g.RecordCondition.ADMINISTRATIVE_FINALITY} if held_g else () + ), + ) + return replace( + case, + fiscal_year=True, + family_months={ + 1: replace(context, state=state, beneficiaries=(auxiliary,)) + }, + ) + + +@pytest.mark.parametrize("held_g", [False, True]) +def test_paired_auxiliary_birth_cohorts_error_at_declaration_before_refusal( + held_g, +): + # This tests the public declaration boundary itself, before G money + # computation or either declared coverage condition is considered. + with pytest.raises( + g.InvalidFamilyInput, + match="G own and beneficiary birth cohorts differ", + ): + _paired_cohort_record(1930, 1950, held_g) + + +@settings(max_examples=25, deadline=None) +@given( + st.tuples(st.integers(1930, 1956), st.integers(1930, 1956)).filter( + lambda pair: pair[0] != pair[1] + ), + st.booleans(), +) +def test_one_auxiliary_cannot_have_two_individually_post_fra_cohorts( + pair, held_g +): + with pytest.raises( + g.InvalidFamilyInput, + match="G own and beneficiary birth cohorts differ", + ): + _paired_cohort_record(*pair, held_g) + + +def test_unentitled_nh_still_retains_cohort_facts(): + case = _facts(2024, 0, 1950, nh=True) + context = case.family_months[1] + state = replace( + context.state, + worker=None, + conditions={g.RecordCondition.WORKER_NOT_ENTITLED}, + ) + person = replace( + case.beneficiaries[0], + entitled_months=(), + gross_rates=(F(0),) * 12, + ) + assert replace( + case, + beneficiaries=(person,), + family_months={1: replace(context, state=state)}, + ) + with pytest.raises(g.InvalidFamilyInput, match="FRA"): + replace( + case, + beneficiaries=(replace(person, fra_month=None),), + family_months={1: replace(context, state=state)}, + ) + + +def test_fra_facts_validate_once_per_public_ledger_call(monkeypatch): + case = _widow(0) + calls = [] + check = r._check_fra_facts + + def counted(*args): + calls.append(args[0].beneficiary_id) + return check(*args) + + monkeypatch.setattr(r, "_check_fra_facts", counted) + r.apply_ret_year(case, PARAMS) + assert calls == ["w"] + + +def test_reduction_months_and_deceased_worker_credits_do_not_prove_current_fra(): + own = g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, F(1), reduction_months=1) + assert _facts(2024, None, None, nh=True, own=own) + assert _facts(2024, 0, None, nh=True, own=own) + # A survivor's deceased worker is a different person. + case = _facts(2024, None, None) + context = case.family_months[1] + inherited = replace(context.beneficiaries[0], original_benefit_basis=F(5)) + assert ( + replace( + case, + family_months={1: replace(context, beneficiaries=(inherited,))}, + ) + .beneficiaries[0] + .fra_month + is None + ) + + +def test_fra_sources_are_hashed_and_role_rules_are_quoted(): + root = Path(__file__).with_name("data") / "track_b" + quotes = { + "ret_sources": { + "ssa_act_203": "which is applicable in the case of old-age insurance benefits, regardless of whether or not the particular benefits" + }, + "ret_ledger_sources": { + "poms_rs_02501_021": "Always use the FRA for retirement insurance benefits (RIB) when applying the ET for RIB or widow(er)'s insurance benefits (WIB).", + "ecfr_20cfr404_subpart_e": "full retirement age (as defined in § 404.409(a))", + }, + "gross_benefit_sources": { + "poms_rs_00615_003": "FRA for retirement or spouse's benefits is age 65.", + "lii_usc_402_415": "after the month before the month in which such individual attained retirement age", + }, + } + for folder, rules in quotes.items(): + manifest = json.loads((root / folder / "manifest.json").read_text()) + for source_id, quote in rules.items(): + source = next( + s for s in manifest["sources"] if s["id"] == source_id + ) + raw = (root / folder / source["file"]).read_bytes() + assert hashlib.sha256(raw).hexdigest() == source["sha256"] + plain = re.sub(r"<[^>]+>", " ", raw.decode()) + plain = " ".join(html.unescape(plain).replace("’", "'").split()) + assert quote in plain diff --git a/tests/tier_counts.json b/tests/tier_counts.json index 25270b1c3..1c8aaa47b 100644 --- a/tests/tier_counts.json +++ b/tests/tier_counts.json @@ -1,7 +1,7 @@ { "schema_version": 1, "counts": { - "unit": 19682, + "unit": 19858, "artifact": 4271, "integration_psid": 1471, "reproduction_legacy": 520, From e3315bafb592e29031d72b5ef368ca428e4a0b55 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 31 Oct 2026 17:01:58 -0400 Subject: [PATCH 09/17] Keep outside events out of governed decisions and check declared facts first (#563 round 4) Sol's third review kept the round-3 fixes and found three mediums, plus an open question on two POMS exceptions. An outside divorced spouse's deduction counted as an "other deduction" under GN 02603.050A.1, so a governed child got $175, not $200. Act 203(a)(3)(C) and GN 02603.020B keep outside people out of the governed decision, so deduction decisions and the reservation total now read subject rows only. Outside events still apply to their own cash. The same audit showed an outside event was what activated a subject's NH reservation, so a reservation now reduces cash with or without an event. A held coverage refusal hid a contradiction in declared NH entitlement. apply_ret_year now compares every month's declared facts before any G computation, through a helper shared with G. The lane's audit of the loop adds raw own-PIA spouse eligibility, NH original rates and DIB gross rates. Checks that need G's money stay after it. RecordYear now rejects two known cohorts for one person across months and fields. A missing cohort adds no constraint. GN 02603.050A.1 and A.2 don't settle how a sole full permanent deduction composes with a zero-rate dual row. The rule adopts neither reading: a new named refusal fires only where their exact payments differ. The conformance report gains that reason and nothing else moves, and 240 R2 and 240 R3 cross-head results stay unchanged. Adds 637 unit tests and eleven caught mutations. Co-Authored-By: Claude Opus 5.5 --- docs/design/track_b_g2_r2b_mutations.json | 441 +++++- docs/design/track_b_g2_r2b_verification.json | 1193 ++++++++++++++++- docs/design/track_b_g_conformance_report.json | 12 +- docs/design/track_b_g_gross_benefits.md | 114 +- docs/design/track_b_r2_ret_ledger.md | 96 ++ scripts/track_b_g_conformance_report.py | 29 + .../track_b/gross_benefits.py | 139 +- src/populace_dynamics/track_b/ret_ledger.py | 83 +- tests/README-tiers.md | 4 +- tests/test_track_b_gross_benefits.py | 27 + ...ack_b_gross_benefits_conformance_report.py | 6 +- ..._gross_benefits_fix_round_4_composition.py | 736 ++++++++++ tests/test_track_b_refusal_notes.py | 22 + tests/test_track_b_ret_ledger_fix_round_4.py | 970 ++++++++++++++ tests/tier_counts.json | 2 +- 15 files changed, 3824 insertions(+), 50 deletions(-) create mode 100644 tests/test_track_b_gross_benefits_fix_round_4_composition.py create mode 100644 tests/test_track_b_ret_ledger_fix_round_4.py diff --git a/docs/design/track_b_g2_r2b_mutations.json b/docs/design/track_b_g2_r2b_mutations.json index 893ed2b92..c3fa52227 100644 --- a/docs/design/track_b_g2_r2b_mutations.json +++ b/docs/design/track_b_g2_r2b_mutations.json @@ -2,11 +2,11 @@ "schema_version": 1, "verification_class": "statutory_conformance", "admitted_scope": "Mutation sensitivity of statutory rules on invented and captured worked cases only; no population, behavioral or forecast claim.", - "confirmed_mutation_count": 39, + "confirmed_mutation_count": 50, "counts_by_layer": { "shared_provenance": 1, - "g_deductions": 14, - "r2": 12, + "g_deductions": 18, + "r2": 19, "g_savings": 12 }, "environment_contract": { @@ -2294,6 +2294,432 @@ "reverted": true, "production_source_untouched": true } + }, + { + "id": "round4-deduction-refuse_equal_composition_payments", + "round": 4, + "layer": "g_deductions", + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": " if any(\n row.auxiliary_payable\n != alternative_rows", + "after": " if True or any(\n row.auxiliary_payable\n != alternative_rows" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py", + "--tb=short", + "-k", + "composition_refusal_exactly_matches_competing_payment_readings" + ], + "environment": { + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONPATH": "$PWD/src:$PWD", + "POPULACE_DYNAMICS_PSID_DIR": "$PWD/.no-real-data", + "POPULACE_DYNAMICS_EPUF_DIR": "$PWD/.no-real-data" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_gross_benefits_fix_round_4_composition.py::test_composition_refusal_exactly_matches_competing_payment_readings[False]", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py::test_composition_refusal_exactly_matches_competing_payment_readings[True]" + ], + "log": { + "path": "scratch/review/deduction-round4-mutation-refuse_equal_composition_payments.log", + "sha256": "f3d517dc85bc08a4a855342d97fd58943e140b4ac09eee8cb0271d06791ebcfb", + "failure_summary": "2 failed, 69 deselected in 15.95s" + }, + "mutation_method": "Assigned-workspace source changed for one foreground check, then restored in finally; no alternate git metadata.", + "restoration": { + "reverted": true, + "final_source_sha256": "6ed10a1f4c637ab136511792d574dc49236acb726818532c4a3c865781af14d0" + } + }, + { + "id": "round4-deduction-miss_different_composition_payments", + "round": 4, + "layer": "g_deductions", + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": " if any(\n row.auxiliary_payable\n != alternative_rows", + "after": " if False and any(\n row.auxiliary_payable\n != alternative_rows" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py", + "--tb=short", + "-k", + "composition_refusal_exactly_matches_competing_payment_readings" + ], + "environment": { + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONPATH": "$PWD/src:$PWD", + "POPULACE_DYNAMICS_PSID_DIR": "$PWD/.no-real-data", + "POPULACE_DYNAMICS_EPUF_DIR": "$PWD/.no-real-data" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_gross_benefits_fix_round_4_composition.py::test_composition_refusal_exactly_matches_competing_payment_readings[False]", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py::test_composition_refusal_exactly_matches_competing_payment_readings[True]" + ], + "log": { + "path": "scratch/review/deduction-round4-mutation-miss_different_composition_payments.log", + "sha256": "ab4935a5597c6bf0277893c7267448ae4cf3d8c5c0e2f791a01979558850fb55", + "failure_summary": "2 failed, 75 deselected in 18.15s" + }, + "mutation_method": "Assigned-workspace source changed for one foreground check, then restored in finally; no alternate git metadata.", + "restoration": { + "reverted": true, + "final_source_sha256": "6ed10a1f4c637ab136511792d574dc49236acb726818532c4a3c865781af14d0" + } + }, + { + "id": "round4-deduction-restore_empty_event_shortcut", + "round": 4, + "layer": "g_deductions", + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": "if not events and not any(worker_deductions.values()):", + "after": "if not events:" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py", + "-k", + "outside_independence_with_nh_only_reservations", + "--tb=short" + ], + "environment": { + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONPATH": "$PWD/src:$PWD", + "POPULACE_DYNAMICS_PSID_DIR": "$PWD/.no-real-data", + "POPULACE_DYNAMICS_EPUF_DIR": "$PWD/.no-real-data" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_gross_benefits_fix_round_4_composition.py::test_outside_independence_with_nh_only_reservations[False]", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py::test_outside_independence_with_nh_only_reservations[True]" + ], + "log": { + "path": "scratch/review/deduction-round4-mutation-restore_empty_event_shortcut.log", + "sha256": "649c4dce74627ddb2fab2b31ea40373acd77835ecad547e0d9abcb8e28db915a", + "failure_summary": "2 failed, 75 deselected in 10.69s" + }, + "mutation_method": "Assigned-workspace source changed for one foreground check, then restored in finally; no alternate git metadata.", + "restoration": { + "reverted": true, + "final_source_sha256": "6ed10a1f4c637ab136511792d574dc49236acb726818532c4a3c865781af14d0" + } + }, + { + "id": "round4-deduction-restore_all_event_count", + "round": 4, + "layer": "g_deductions", + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": "if len(explicit) == 1\n and not dual", + "after": "if len(events) == 1\n and not dual" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py", + "--tb=short", + "-k", + "outside_independence_in_any_beneficiary_order" + ], + "environment": { + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONPATH": "$PWD/src:$PWD", + "POPULACE_DYNAMICS_PSID_DIR": "$PWD/.no-real-data", + "POPULACE_DYNAMICS_EPUF_DIR": "$PWD/.no-real-data" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_gross_benefits_fix_round_4_composition.py::test_outside_independence_in_any_beneficiary_order[False-FamilyKind.RETIREMENT]", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py::test_outside_independence_in_any_beneficiary_order[False-FamilyKind.DISABILITY]", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py::test_outside_independence_in_any_beneficiary_order[False-FamilyKind.SURVIVOR]", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py::test_outside_independence_in_any_beneficiary_order[True-FamilyKind.RETIREMENT]", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py::test_outside_independence_in_any_beneficiary_order[True-FamilyKind.DISABILITY]", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py::test_outside_independence_in_any_beneficiary_order[True-FamilyKind.SURVIVOR]" + ], + "log": { + "path": "scratch/review/deduction-round4-mutation-restore_all_event_count.log", + "sha256": "5d7206f2ea4df76c6f2d8318b9c6e6bb07e7e503e2b97b690f5dc74a7eaac3f3", + "failure_summary": "6 failed, 87 deselected in 36.22s" + }, + "mutation_method": "Assigned-workspace source changed for one foreground check, then restored in finally; no alternate git metadata.", + "restoration": { + "reverted": true, + "final_source_sha256": "6ed10a1f4c637ab136511792d574dc49236acb726818532c4a3c865781af14d0" + } + }, + { + "id": "round4-ret-drop_nh_direction", + "round": 4, + "layer": "r2", + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": { + "before": "if g._declared_worker_entitled(context.state) != (", + "after": "if g._declared_worker_entitled(context.state) < (" + }, + "command": "OMP_NUM_THREADS=1 OMP_WAIT_POLICY=PASSIVE POLARS_MAX_THREADS=1 PYTHONPATH=$PWD/src:$PWD POPULACE_DYNAMICS_PSID_DIR=/nonexistent/track-b-round4 POPULACE_DYNAMICS_EPUF_DIR=/nonexistent/track-b-round4 /Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python scratch/review/ret-round4-mutation-check.py drop_nh_direction", + "environment": { + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONPATH": "$PWD/src:$PWD", + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/track-b-round4", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/track-b-round4" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_4.py::test_no_held_coverage_condition_masks_nh_contradiction" + ], + "log": { + "path": "scratch/review/ret-round4-mutation-drop_nh_direction.log", + "sha256": "fa07b5c3181b691ac16806ba1d9f2e958f1e20d3e8cbff258160d2770cdbda87", + "failure_summary": "1 failed, 2 warnings in 12.62s" + }, + "mutation_method": "Assigned-workspace source changed for one foreground check, then restored in finally; no alternate git metadata.", + "restoration": { + "reverted": true, + "final_source_sha256": "e9b01a765a7951937a7035da3ab2ef29b13dc1efa663e35e224ae558d622515b" + } + }, + { + "id": "round4-ret-nh_after_held_refusal", + "round": 4, + "layer": "r2", + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": { + "before": " # Entitlement is a declared fact, including a zero-rate entitlement.\n # Check every context before computing any G money or holding a refusal.\n if record.kind is not RecordKind.DECEASED:\n nh = next(\n b for b in record.beneficiaries if b.beneficiary_id == record.nh_id\n )\n for month, context in record.family_months.items():\n if g._declared_worker_entitled(context.state) != (\n month in nh.entitled_months\n ):\n raise InvalidFamilyInput(\n \"G and RET NH entitlement facts differ\"\n )\n", + "after": " # Entitlement is a declared fact, including a zero-rate entitlement.\n # Check every context before computing any G money or holding a refusal.\n if record.kind is not RecordKind.DECEASED:\n nh = next(\n b for b in record.beneficiaries if b.beneficiary_id == record.nh_id\n )\n for month, context in record.family_months.items():\n if g._declared_worker_entitled(context.state) != (\n month in nh.entitled_months\n ):\n raise InvalidFamilyInput(\n \"G and RET NH entitlement facts differ\"\n )\n" + }, + "command": "OMP_NUM_THREADS=1 OMP_WAIT_POLICY=PASSIVE POLARS_MAX_THREADS=1 PYTHONPATH=$PWD/src:$PWD POPULACE_DYNAMICS_PSID_DIR=/nonexistent/track-b-round4 POPULACE_DYNAMICS_EPUF_DIR=/nonexistent/track-b-round4 /Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python scratch/review/ret-round4-mutation-check.py nh_after_held_refusal", + "environment": { + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONPATH": "$PWD/src:$PWD", + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/track-b-round4", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/track-b-round4" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_4.py::test_no_held_coverage_condition_masks_nh_contradiction" + ], + "log": { + "path": "scratch/review/ret-round4-mutation-nh_after_held_refusal.log", + "sha256": "612e9f6dee0e8431306b89519f0baa39ced3709573ab6a57d8752a7ad7db4291", + "failure_summary": "1 failed, 2 warnings in 8.56s" + }, + "mutation_method": "Assigned-workspace source changed for one foreground check, then restored in finally; no alternate git metadata.", + "restoration": { + "reverted": true, + "final_source_sha256": "e9b01a765a7951937a7035da3ab2ef29b13dc1efa663e35e224ae558d622515b" + }, + "operation": "Move the exact block; do not change its contents", + "before_location": "before the G monthly computation loop", + "after_location": "after if held_family_refusals: raise held_family_refusals[0]" + }, + { + "id": "round4-ret-drop_auxiliary_own_cohort", + "round": 4, + "layer": "r2", + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": { + "before": " auxiliary.own_benefit.birth_year,", + "after": " None," + }, + "command": "OMP_NUM_THREADS=1 OMP_WAIT_POLICY=PASSIVE POLARS_MAX_THREADS=1 PYTHONPATH=$PWD/src:$PWD POPULACE_DYNAMICS_PSID_DIR=/nonexistent/track-b-round4 POPULACE_DYNAMICS_EPUF_DIR=/nonexistent/track-b-round4 /Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python scratch/review/ret-round4-mutation-check.py drop_auxiliary_own_cohort", + "environment": { + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONPATH": "$PWD/src:$PWD", + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/track-b-round4", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/track-b-round4" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_4.py::test_one_cohort_across_every_month_and_field_pair" + ], + "log": { + "path": "scratch/review/ret-round4-mutation-drop_auxiliary_own_cohort.log", + "sha256": "3c2cf4744a5eb9dcf6170145a0b2d4fd446119aa5a074a99dca4ff4b42cde1cb", + "failure_summary": "1 failed, 2 warnings in 8.42s" + }, + "mutation_method": "Assigned-workspace source changed for one foreground check, then restored in finally; no alternate git metadata.", + "restoration": { + "reverted": true, + "final_source_sha256": "e9b01a765a7951937a7035da3ab2ef29b13dc1efa663e35e224ae558d622515b" + } + }, + { + "id": "round4-ret-drop_worker_record_cohort", + "round": 4, + "layer": "r2", + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": { + "before": " remember_cohort(self.nh_id, context.state.worker_birth_year)", + "after": " remember_cohort(self.nh_id, None)" + }, + "command": "OMP_NUM_THREADS=1 OMP_WAIT_POLICY=PASSIVE POLARS_MAX_THREADS=1 PYTHONPATH=$PWD/src:$PWD POPULACE_DYNAMICS_PSID_DIR=/nonexistent/track-b-round4 POPULACE_DYNAMICS_EPUF_DIR=/nonexistent/track-b-round4 /Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python scratch/review/ret-round4-mutation-check.py drop_worker_record_cohort", + "environment": { + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONPATH": "$PWD/src:$PWD", + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/track-b-round4", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/track-b-round4" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_4.py::test_one_cohort_across_every_month_and_field_pair" + ], + "log": { + "path": "scratch/review/ret-round4-mutation-drop_worker_record_cohort.log", + "sha256": "3d9f1bacb0122a691785816db0ea6dbb7342a1f3c681ae56418026d451cfb8fb", + "failure_summary": "1 failed, 2 warnings in 11.30s" + }, + "mutation_method": "Assigned-workspace source changed for one foreground check, then restored in finally; no alternate git metadata.", + "restoration": { + "reverted": true, + "final_source_sha256": "e9b01a765a7951937a7035da3ab2ef29b13dc1efa663e35e224ae558d622515b" + } + }, + { + "id": "round4-ret-disable_spouse_preflight", + "round": 4, + "layer": "r2", + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": { + "before": " if not entitled:", + "after": " if False:" + }, + "command": "OMP_NUM_THREADS=1 OMP_WAIT_POLICY=PASSIVE POLARS_MAX_THREADS=1 PYTHONPATH=$PWD/src:$PWD POPULACE_DYNAMICS_PSID_DIR=/nonexistent/track-b-round4 POPULACE_DYNAMICS_EPUF_DIR=/nonexistent/track-b-round4 /Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python scratch/review/ret-round4-mutation-check.py disable_spouse_preflight", + "environment": { + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONPATH": "$PWD/src:$PWD", + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/track-b-round4", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/track-b-round4" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_4.py::test_no_held_coverage_condition_masks_spouse_pia_contradiction" + ], + "log": { + "path": "scratch/review/ret-round4-mutation-disable_spouse_preflight.log", + "sha256": "379fe03d48f0a837ee6ec77d6bda4d0ac0ce872c5f169f916cf0073759921bc4", + "failure_summary": "1 failed, 2 warnings in 3.85s" + }, + "mutation_method": "Assigned-workspace source changed for one foreground check, then restored in finally; no alternate git metadata.", + "restoration": { + "reverted": true, + "final_source_sha256": "e9b01a765a7951937a7035da3ab2ef29b13dc1efa663e35e224ae558d622515b" + } + }, + { + "id": "round4-ret-drop_nh_original_preflight", + "round": 4, + "layer": "r2", + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": { + "before": " if nh.original_rates[month - 1] != context.state.pia:", + "after": " if False and nh.original_rates[month - 1] != context.state.pia:" + }, + "command": "OMP_NUM_THREADS=1 OMP_WAIT_POLICY=PASSIVE POLARS_MAX_THREADS=1 PYTHONPATH=$PWD/src:$PWD POPULACE_DYNAMICS_PSID_DIR=/nonexistent/track-b-round4 POPULACE_DYNAMICS_EPUF_DIR=/nonexistent/track-b-round4 /Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python scratch/review/ret-round4-mutation-check.py drop_nh_original_preflight", + "environment": { + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONPATH": "$PWD/src:$PWD", + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/track-b-round4", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/track-b-round4" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_4.py::test_no_held_coverage_condition_masks_direct_nh_rate_contradiction" + ], + "log": { + "path": "scratch/review/ret-round4-mutation-drop_nh_original_preflight.log", + "sha256": "b6c02d50b815da2c4b103c4523a7473646df8682b861e4fc5411cbe02051f3bc", + "failure_summary": "1 failed, 2 warnings in 5.00s" + }, + "mutation_method": "Assigned-workspace source changed for one foreground check, then restored in finally; no alternate git metadata.", + "restoration": { + "reverted": true, + "final_source_sha256": "e9b01a765a7951937a7035da3ab2ef29b13dc1efa663e35e224ae558d622515b" + } + }, + { + "id": "round4-ret-drop_dib_gross_preflight", + "round": 4, + "layer": "r2", + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": { + "before": " record.kind is RecordKind.DISABILITY", + "after": " False" + }, + "command": "OMP_NUM_THREADS=1 OMP_WAIT_POLICY=PASSIVE POLARS_MAX_THREADS=1 PYTHONPATH=$PWD/src:$PWD POPULACE_DYNAMICS_PSID_DIR=/nonexistent/track-b-round4 POPULACE_DYNAMICS_EPUF_DIR=/nonexistent/track-b-round4 /Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python scratch/review/ret-round4-mutation-check.py drop_dib_gross_preflight", + "environment": { + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONPATH": "$PWD/src:$PWD", + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/track-b-round4", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/track-b-round4" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_4.py::test_no_held_coverage_condition_masks_direct_nh_rate_contradiction" + ], + "log": { + "path": "scratch/review/ret-round4-mutation-drop_dib_gross_preflight.log", + "sha256": "0c078a28570835fb721ade004a50c3ff777f401209c39c637d49f70d2fb185ad", + "failure_summary": "1 failed, 2 warnings in 6.86s" + }, + "mutation_method": "Assigned-workspace source changed for one foreground check, then restored in finally; no alternate git metadata.", + "restoration": { + "reverted": true, + "final_source_sha256": "e9b01a765a7951937a7035da3ab2ef29b13dc1efa663e35e224ae558d622515b" + } } ], "restoration_verification_snapshot": { @@ -2330,5 +2756,12 @@ "round_3_restoration_snapshot": { "src/populace_dynamics/track_b/gross_benefits.py": "cd03ee0b2c828f1fb7e09980b48f4a23e9a8ca49295aaa7a1dd2799d1fff9ed8", "src/populace_dynamics/track_b/ret_ledger.py": "7b5a1491453fbd61e76c670a1ce84deb3818138d3313c21327661d328d7fa0c8" - } + }, + "round_4_head": "1ce508e538cd7d2a9ed8e82bbbc32a29fb0a1669", + "round_4_note": "Eleven fresh mutations caught by named Hypothesis properties and reverted: the eight original finding/shortcut checks, plus three declared-fact loop-audit checks. Valid corrected cohort fixtures and explicit survivor/NH minima were used for the final evidence. Earlier records remain historical.", + "round_4_restoration_snapshot": { + "src/populace_dynamics/track_b/gross_benefits.py": "6ed10a1f4c637ab136511792d574dc49236acb726818532c4a3c865781af14d0", + "src/populace_dynamics/track_b/ret_ledger.py": "e9b01a765a7951937a7035da3ab2ef29b13dc1efa663e35e224ae558d622515b" + }, + "round_4_environment_note": "The older isolated-source imports contract describes historical rounds. Round 4 records identify foreground, reversible workspace mutations and their environments. Final restoration hashes include the completed declared-fact audit extension." } diff --git a/docs/design/track_b_g2_r2b_verification.json b/docs/design/track_b_g2_r2b_verification.json index 6115c9c1c..a5daeb53c 100644 --- a/docs/design/track_b_g2_r2b_verification.json +++ b/docs/design/track_b_g2_r2b_verification.json @@ -4555,5 +4555,1196 @@ "detailed_report": "scratch/review/fix-round-3-report.md", "all_changes_uncommitted": true }, - "round_3_current_evidence_note": "Earlier source hashes, counts and validation records remain historical. The round_3 section records this fix round separately and is the current evidence for its changed sources." + "round_3_current_evidence_note": "Earlier source hashes, counts and validation records remain historical. The round_3 section records this fix round separately and is the current evidence for its changed sources.", + "round_4": { + "head": "1ce508e538cd7d2a9ed8e82bbbc32a29fb0a1669", + "verification_class": "statutory_conformance", + "admitted_scope": "Invented cases and captured published examples only; no population, behavioral or forecast claim.", + "workspace": "/Users/maxghenis/.subfleet/worktrees/20261031-152902-trackb-fix-g2-4", + "named_test_modules": [ + "tests/test_track_b_arf.py", + "tests/test_track_b_arf_properties.py", + "tests/test_track_b_gross_benefits.py", + "tests/test_track_b_gross_benefits_conformance_report.py", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py", + "tests/test_track_b_gross_benefits_deduction_cap.py", + "tests/test_track_b_gross_benefits_deductions.py", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", + "tests/test_track_b_gross_benefits_dwb.py", + "tests/test_track_b_gross_benefits_fix_round_1.py", + "tests/test_track_b_gross_benefits_fix_round_10_api.py", + "tests/test_track_b_gross_benefits_fix_round_10_helpers.py", + "tests/test_track_b_gross_benefits_fix_round_10_objects.py", + "tests/test_track_b_gross_benefits_fix_round_10_parameters.py", + "tests/test_track_b_gross_benefits_fix_round_11_roles.py", + "tests/test_track_b_gross_benefits_fix_round_11_seals.py", + "tests/test_track_b_gross_benefits_fix_round_12_contract.py", + "tests/test_track_b_gross_benefits_fix_round_13_audit.py", + "tests/test_track_b_gross_benefits_fix_round_13_boundary.py", + "tests/test_track_b_gross_benefits_fix_round_13_guard.py", + "tests/test_track_b_gross_benefits_fix_round_15_arguments.py", + "tests/test_track_b_gross_benefits_fix_round_15_collections.py", + "tests/test_track_b_gross_benefits_fix_round_15_receivers.py", + "tests/test_track_b_gross_benefits_fix_round_2_care.py", + "tests/test_track_b_gross_benefits_fix_round_2_history.py", + "tests/test_track_b_gross_benefits_fix_round_2_periods.py", + "tests/test_track_b_gross_benefits_fix_round_3_rates.py", + "tests/test_track_b_gross_benefits_fix_round_4_care_floor.py", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py", + "tests/test_track_b_gross_benefits_fix_round_4_divorced_care.py", + "tests/test_track_b_gross_benefits_fix_round_5_care_history.py", + "tests/test_track_b_gross_benefits_fix_round_5_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_6_care_note.py", + "tests/test_track_b_gross_benefits_fix_round_6_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_boundary.py", + "tests/test_track_b_gross_benefits_fix_round_7_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_history.py", + "tests/test_track_b_gross_benefits_fix_round_8_entries.py", + "tests/test_track_b_gross_benefits_fix_round_8_history.py", + "tests/test_track_b_gross_benefits_fix_round_9_citations.py", + "tests/test_track_b_gross_benefits_fix_round_9_outcomes.py", + "tests/test_track_b_gross_benefits_fix_round_9_validation.py", + "tests/test_track_b_gross_benefits_oracle.py", + "tests/test_track_b_gross_benefits_own_input_order.py", + "tests/test_track_b_gross_benefits_parents_ieds.py", + "tests/test_track_b_gross_benefits_parisi.py", + "tests/test_track_b_gross_benefits_payment_review.py", + "tests/test_track_b_gross_benefits_properties.py", + "tests/test_track_b_gross_benefits_registry.py", + "tests/test_track_b_gross_benefits_review.py", + "tests/test_track_b_gross_benefits_saving_absence.py", + "tests/test_track_b_gross_benefits_savings.py", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py", + "tests/test_track_b_gross_benefits_sources_20261011.py", + "tests/test_track_b_gross_benefits_ssfa.py", + "tests/test_track_b_input_schema.py", + "tests/test_track_b_r3_fix_round_13.py", + "tests/test_track_b_r3_provenance.py", + "tests/test_track_b_r3_sources.py", + "tests/test_track_b_r3_validation_once.py", + "tests/test_track_b_recompute.py", + "tests/test_track_b_recompute_properties.py", + "tests/test_track_b_refusal_notes.py", + "tests/test_track_b_ret_differential.py", + "tests/test_track_b_ret_fra_facts.py", + "tests/test_track_b_ret_grace.py", + "tests/test_track_b_ret_grace_differential.py", + "tests/test_track_b_ret_grace_provenance.py", + "tests/test_track_b_ret_ledger.py", + "tests/test_track_b_ret_ledger_deductions.py", + "tests/test_track_b_ret_ledger_fix_round_2.py", + "tests/test_track_b_ret_ledger_fix_round_4.py", + "tests/test_track_b_ret_ledger_properties.py", + "tests/test_track_b_ret_ledger_readings.py", + "tests/test_track_b_ret_ledger_sources.py", + "tests/test_track_b_ret_params.py" + ], + "named_test_module_count": 76, + "gate_runs": { + "g_boundary": { + "partition": "g_boundary", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-152902-trackb-fix-g2-4/scratch/review/run_round4_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=short", + "tests/test_track_b_gross_benefits_fix_round_1.py", + "tests/test_track_b_gross_benefits_fix_round_10_api.py", + "tests/test_track_b_gross_benefits_fix_round_10_helpers.py", + "tests/test_track_b_gross_benefits_fix_round_10_objects.py", + "tests/test_track_b_gross_benefits_fix_round_10_parameters.py", + "tests/test_track_b_gross_benefits_fix_round_11_roles.py", + "tests/test_track_b_gross_benefits_fix_round_11_seals.py", + "tests/test_track_b_gross_benefits_fix_round_12_contract.py", + "tests/test_track_b_gross_benefits_fix_round_13_audit.py", + "tests/test_track_b_gross_benefits_fix_round_13_boundary.py", + "tests/test_track_b_gross_benefits_fix_round_13_guard.py", + "tests/test_track_b_gross_benefits_fix_round_15_arguments.py", + "tests/test_track_b_gross_benefits_fix_round_15_collections.py", + "tests/test_track_b_gross_benefits_fix_round_15_receivers.py", + "tests/test_track_b_gross_benefits_fix_round_2_care.py", + "tests/test_track_b_gross_benefits_fix_round_2_history.py", + "tests/test_track_b_gross_benefits_fix_round_2_periods.py", + "tests/test_track_b_gross_benefits_fix_round_3_rates.py", + "tests/test_track_b_gross_benefits_fix_round_4_care_floor.py", + "tests/test_track_b_gross_benefits_fix_round_4_divorced_care.py", + "tests/test_track_b_gross_benefits_fix_round_5_care_history.py", + "tests/test_track_b_gross_benefits_fix_round_5_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_6_care_note.py", + "tests/test_track_b_gross_benefits_fix_round_6_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_boundary.py", + "tests/test_track_b_gross_benefits_fix_round_7_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_history.py", + "tests/test_track_b_gross_benefits_fix_round_8_entries.py", + "tests/test_track_b_gross_benefits_fix_round_8_history.py", + "tests/test_track_b_gross_benefits_fix_round_9_citations.py", + "tests/test_track_b_gross_benefits_fix_round_9_outcomes.py", + "tests/test_track_b_gross_benefits_fix_round_9_validation.py" + ], + "environment": { + "PYTHONDONTWRITEBYTECODE": "1", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-152902-trackb-fix-g2-4/src:/Users/maxghenis/.subfleet/worktrees/20261031-152902-trackb-fix-g2-4", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-152902-trackb-fix-g2-4/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-152902-trackb-fix-g2-4/scratch/review/nonexistent", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-152902-trackb-fix-g2-4/scratch/review/round4-hypothesis-g_boundary" + }, + "named_modules": [ + "tests/test_track_b_gross_benefits_fix_round_1.py", + "tests/test_track_b_gross_benefits_fix_round_10_api.py", + "tests/test_track_b_gross_benefits_fix_round_10_helpers.py", + "tests/test_track_b_gross_benefits_fix_round_10_objects.py", + "tests/test_track_b_gross_benefits_fix_round_10_parameters.py", + "tests/test_track_b_gross_benefits_fix_round_11_roles.py", + "tests/test_track_b_gross_benefits_fix_round_11_seals.py", + "tests/test_track_b_gross_benefits_fix_round_12_contract.py", + "tests/test_track_b_gross_benefits_fix_round_13_audit.py", + "tests/test_track_b_gross_benefits_fix_round_13_boundary.py", + "tests/test_track_b_gross_benefits_fix_round_13_guard.py", + "tests/test_track_b_gross_benefits_fix_round_15_arguments.py", + "tests/test_track_b_gross_benefits_fix_round_15_collections.py", + "tests/test_track_b_gross_benefits_fix_round_15_receivers.py", + "tests/test_track_b_gross_benefits_fix_round_2_care.py", + "tests/test_track_b_gross_benefits_fix_round_2_history.py", + "tests/test_track_b_gross_benefits_fix_round_2_periods.py", + "tests/test_track_b_gross_benefits_fix_round_3_rates.py", + "tests/test_track_b_gross_benefits_fix_round_4_care_floor.py", + "tests/test_track_b_gross_benefits_fix_round_4_divorced_care.py", + "tests/test_track_b_gross_benefits_fix_round_5_care_history.py", + "tests/test_track_b_gross_benefits_fix_round_5_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_6_care_note.py", + "tests/test_track_b_gross_benefits_fix_round_6_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_boundary.py", + "tests/test_track_b_gross_benefits_fix_round_7_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_history.py", + "tests/test_track_b_gross_benefits_fix_round_8_entries.py", + "tests/test_track_b_gross_benefits_fix_round_8_history.py", + "tests/test_track_b_gross_benefits_fix_round_9_citations.py", + "tests/test_track_b_gross_benefits_fix_round_9_outcomes.py", + "tests/test_track_b_gross_benefits_fix_round_9_validation.py" + ], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "6ed10a1f4c637ab136511792d574dc49236acb726818532c4a3c865781af14d0", + "src/populace_dynamics/track_b/ret_ledger.py": "e9b01a765a7951937a7035da3ab2ef29b13dc1efa663e35e224ae558d622515b", + "scripts/track_b_g_conformance_report.py": "884811d5968cab6f22e7c72385bf6b14274f2273bb133ff1b12cb3bea06e6fbb" + }, + "test_sha256_before": { + "tests/test_track_b_gross_benefits_fix_round_1.py": "9275a8a4963ce7ed086482644d044a927100efcbeb5a05315d9cc6394168ee8c", + "tests/test_track_b_gross_benefits_fix_round_10_api.py": "227fde023692f1c73a3eeb6de75213468c8e5e160ade3536bf5b7fb688c4ded6", + "tests/test_track_b_gross_benefits_fix_round_10_helpers.py": "e5014776670ca9b552de756c63976e606290fb4fad85a1501b017700a05c8fdb", + "tests/test_track_b_gross_benefits_fix_round_10_objects.py": "7576cc18923ad3ff38d0f44379637e822008a92cc9968d52f47b991e56fb9cfb", + "tests/test_track_b_gross_benefits_fix_round_10_parameters.py": "981eced43d10a6720ccab0292c4a8c281b9ac9bf7d83132f6666254d7a4b72ee", + "tests/test_track_b_gross_benefits_fix_round_11_roles.py": "d26fd86d7067eb7f4f97e1537110eab5223104ad817c3470a9eae022a90dfc73", + "tests/test_track_b_gross_benefits_fix_round_11_seals.py": "937b07b094816eade9bf072595ede18b1b109db527de9805c3a3cb3d333ba4b5", + "tests/test_track_b_gross_benefits_fix_round_12_contract.py": "9779ae3b22cf12daf6727cd21a6bcb12afbf3cfd34c84209bd406942a0c089e1", + "tests/test_track_b_gross_benefits_fix_round_13_audit.py": "fb04098e3982aca18b439f2df148bee6333ce20406fe773da0858731a6c94ff0", + "tests/test_track_b_gross_benefits_fix_round_13_boundary.py": "acac7951783a0e11140e717feab3924973e290e58857396dfab9c0b4319a5e8d", + "tests/test_track_b_gross_benefits_fix_round_13_guard.py": "e5fabfda3fcab2ba9e0347449278a21b9cfc1f89645e1ab148cb4a23da9e7c2e", + "tests/test_track_b_gross_benefits_fix_round_15_arguments.py": "16d5a875f4271839799738a89f2b904084bc0847eb25cd397168cea570be6d54", + "tests/test_track_b_gross_benefits_fix_round_15_collections.py": "2206b9734458774d581d3d20bfb50f1d517fd1b7d8191225cf5cacbca6561e58", + "tests/test_track_b_gross_benefits_fix_round_15_receivers.py": "3de91e8701ab82a3063be9eb859e6cd0058c7d3a35ac93dce9e110e0959061ff", + "tests/test_track_b_gross_benefits_fix_round_2_care.py": "7e983b28cdd1ba2c03935858610788754de66fb9489fef46672ebbf3d566225e", + "tests/test_track_b_gross_benefits_fix_round_2_history.py": "17fb81a1d18ad90ccf99cc841360aec524822cc2404e03d33cfbbab3a830b3a5", + "tests/test_track_b_gross_benefits_fix_round_2_periods.py": "21030c220e1b4690ac3d6754dcd9baddc23b33e824e07a842673c4128b7e6b09", + "tests/test_track_b_gross_benefits_fix_round_3_rates.py": "1c638ac3d5f0b0d25b49d1abf4924d9fff45bcf5ce25366616a60d3f060faa16", + "tests/test_track_b_gross_benefits_fix_round_4_care_floor.py": "d137d59fb7af48f21fda7b4e3aaf9a991d43b295930b5f341cc7cd595b875401", + "tests/test_track_b_gross_benefits_fix_round_4_divorced_care.py": "cd50249e8d84a2bbb61901f08b84310d48b8d390495beadfe5112144143b4fd7", + "tests/test_track_b_gross_benefits_fix_round_5_care_history.py": "a3e73482553c5fb804adaba8ed0d5e4d1520470f384bb58a0fe46cb41e58eb07", + "tests/test_track_b_gross_benefits_fix_round_5_cohorts.py": "f5be483a533e47edcb58dc05bc202390e959e6ece7eca3ff11728aa46b00409d", + "tests/test_track_b_gross_benefits_fix_round_6_care_note.py": "b2d158f37d35aaa63a6a1293345010bc4445c3b20c480c035932bf9725a91eca", + "tests/test_track_b_gross_benefits_fix_round_6_cohorts.py": "b06e95d0a8a93af3e60b96222381b46377673e407385958b5120817bc60c2e84", + "tests/test_track_b_gross_benefits_fix_round_7_boundary.py": "b2c875f010c402e4f373be5712a39affd87b6533805ed33bf63dbea60b1e6ae5", + "tests/test_track_b_gross_benefits_fix_round_7_cohorts.py": "0eb73d51e1f7a61f76917df670f89bdade0e5f45f4c044be30673dff2494ca31", + "tests/test_track_b_gross_benefits_fix_round_7_history.py": "fc6a7b5281e2f429a8e9f92c595b4491aa2de4229630fc5ca15eab333bacab26", + "tests/test_track_b_gross_benefits_fix_round_8_entries.py": "4589caceb3f7996a6175d6f15f8038805450d8c448c56a8d95e4ccc9a5f872e5", + "tests/test_track_b_gross_benefits_fix_round_8_history.py": "cf4d84edf72b150dd343d408d84e60ebd70500c8e219bc00b1552d6292af4e91", + "tests/test_track_b_gross_benefits_fix_round_9_citations.py": "2ce5f13cd58a929583f659ec5bea6b2fbfa7216edd00291400773882118b9b4e", + "tests/test_track_b_gross_benefits_fix_round_9_outcomes.py": "139a90841182ca8a1bbece8acd3b30df68f7d88cef833fd092c202b22017a3e6", + "tests/test_track_b_gross_benefits_fix_round_9_validation.py": "0d420e98106ffe4ce7d9f1f0ae121488c4aca9ce1e1a3d941bc5aff0083efd92" + }, + "pytest_pid": 31047, + "exit_code": 0, + "seconds": 1254.7110287079922, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "6ed10a1f4c637ab136511792d574dc49236acb726818532c4a3c865781af14d0", + "src/populace_dynamics/track_b/ret_ledger.py": "e9b01a765a7951937a7035da3ab2ef29b13dc1efa663e35e224ae558d622515b", + "scripts/track_b_g_conformance_report.py": "884811d5968cab6f22e7c72385bf6b14274f2273bb133ff1b12cb3bea06e6fbb" + }, + "test_sha256_after": { + "tests/test_track_b_gross_benefits_fix_round_1.py": "9275a8a4963ce7ed086482644d044a927100efcbeb5a05315d9cc6394168ee8c", + "tests/test_track_b_gross_benefits_fix_round_10_api.py": "227fde023692f1c73a3eeb6de75213468c8e5e160ade3536bf5b7fb688c4ded6", + "tests/test_track_b_gross_benefits_fix_round_10_helpers.py": "e5014776670ca9b552de756c63976e606290fb4fad85a1501b017700a05c8fdb", + "tests/test_track_b_gross_benefits_fix_round_10_objects.py": "7576cc18923ad3ff38d0f44379637e822008a92cc9968d52f47b991e56fb9cfb", + "tests/test_track_b_gross_benefits_fix_round_10_parameters.py": "981eced43d10a6720ccab0292c4a8c281b9ac9bf7d83132f6666254d7a4b72ee", + "tests/test_track_b_gross_benefits_fix_round_11_roles.py": "d26fd86d7067eb7f4f97e1537110eab5223104ad817c3470a9eae022a90dfc73", + "tests/test_track_b_gross_benefits_fix_round_11_seals.py": "937b07b094816eade9bf072595ede18b1b109db527de9805c3a3cb3d333ba4b5", + "tests/test_track_b_gross_benefits_fix_round_12_contract.py": "9779ae3b22cf12daf6727cd21a6bcb12afbf3cfd34c84209bd406942a0c089e1", + "tests/test_track_b_gross_benefits_fix_round_13_audit.py": "fb04098e3982aca18b439f2df148bee6333ce20406fe773da0858731a6c94ff0", + "tests/test_track_b_gross_benefits_fix_round_13_boundary.py": "acac7951783a0e11140e717feab3924973e290e58857396dfab9c0b4319a5e8d", + "tests/test_track_b_gross_benefits_fix_round_13_guard.py": "e5fabfda3fcab2ba9e0347449278a21b9cfc1f89645e1ab148cb4a23da9e7c2e", + "tests/test_track_b_gross_benefits_fix_round_15_arguments.py": "16d5a875f4271839799738a89f2b904084bc0847eb25cd397168cea570be6d54", + "tests/test_track_b_gross_benefits_fix_round_15_collections.py": "2206b9734458774d581d3d20bfb50f1d517fd1b7d8191225cf5cacbca6561e58", + "tests/test_track_b_gross_benefits_fix_round_15_receivers.py": "3de91e8701ab82a3063be9eb859e6cd0058c7d3a35ac93dce9e110e0959061ff", + "tests/test_track_b_gross_benefits_fix_round_2_care.py": "7e983b28cdd1ba2c03935858610788754de66fb9489fef46672ebbf3d566225e", + "tests/test_track_b_gross_benefits_fix_round_2_history.py": "17fb81a1d18ad90ccf99cc841360aec524822cc2404e03d33cfbbab3a830b3a5", + "tests/test_track_b_gross_benefits_fix_round_2_periods.py": "21030c220e1b4690ac3d6754dcd9baddc23b33e824e07a842673c4128b7e6b09", + "tests/test_track_b_gross_benefits_fix_round_3_rates.py": "1c638ac3d5f0b0d25b49d1abf4924d9fff45bcf5ce25366616a60d3f060faa16", + "tests/test_track_b_gross_benefits_fix_round_4_care_floor.py": "d137d59fb7af48f21fda7b4e3aaf9a991d43b295930b5f341cc7cd595b875401", + "tests/test_track_b_gross_benefits_fix_round_4_divorced_care.py": "cd50249e8d84a2bbb61901f08b84310d48b8d390495beadfe5112144143b4fd7", + "tests/test_track_b_gross_benefits_fix_round_5_care_history.py": "a3e73482553c5fb804adaba8ed0d5e4d1520470f384bb58a0fe46cb41e58eb07", + "tests/test_track_b_gross_benefits_fix_round_5_cohorts.py": "f5be483a533e47edcb58dc05bc202390e959e6ece7eca3ff11728aa46b00409d", + "tests/test_track_b_gross_benefits_fix_round_6_care_note.py": "b2d158f37d35aaa63a6a1293345010bc4445c3b20c480c035932bf9725a91eca", + "tests/test_track_b_gross_benefits_fix_round_6_cohorts.py": "b06e95d0a8a93af3e60b96222381b46377673e407385958b5120817bc60c2e84", + "tests/test_track_b_gross_benefits_fix_round_7_boundary.py": "b2c875f010c402e4f373be5712a39affd87b6533805ed33bf63dbea60b1e6ae5", + "tests/test_track_b_gross_benefits_fix_round_7_cohorts.py": "0eb73d51e1f7a61f76917df670f89bdade0e5f45f4c044be30673dff2494ca31", + "tests/test_track_b_gross_benefits_fix_round_7_history.py": "fc6a7b5281e2f429a8e9f92c595b4491aa2de4229630fc5ca15eab333bacab26", + "tests/test_track_b_gross_benefits_fix_round_8_entries.py": "4589caceb3f7996a6175d6f15f8038805450d8c448c56a8d95e4ccc9a5f872e5", + "tests/test_track_b_gross_benefits_fix_round_8_history.py": "cf4d84edf72b150dd343d408d84e60ebd70500c8e219bc00b1552d6292af4e91", + "tests/test_track_b_gross_benefits_fix_round_9_citations.py": "2ce5f13cd58a929583f659ec5bea6b2fbfa7216edd00291400773882118b9b4e", + "tests/test_track_b_gross_benefits_fix_round_9_outcomes.py": "139a90841182ca8a1bbece8acd3b30df68f7d88cef833fd092c202b22017a3e6", + "tests/test_track_b_gross_benefits_fix_round_9_validation.py": "0d420e98106ffe4ce7d9f1f0ae121488c4aca9ce1e1a3d941bc5aff0083efd92" + }, + "log": "scratch/review/round4-gate-g_boundary.log", + "tail": [ + "........................................................................ [ 91%]", + "........................................................................ [ 92%]", + "........................................................................ [ 93%]", + "........................................................................ [ 94%]", + "........................................................................ [ 95%]", + "........................................................................ [ 96%]", + "........................................................................ [ 97%]", + "........................................................................ [ 98%]", + "........................................................................ [ 99%]", + "......................................... [100%]", + "7241 passed in 1241.55s (0:20:41)", + "ROUND4_OPEN_AUDIT {\"restricted_opens\": 0, \"subprocess.Popen\": 0, \"os.system\": 0}" + ], + "log_sha256": "31c3c5f37f271acc438159f1fa6537c06aeee551a7f7712ff5fd0a207e176a51", + "source_stable": true, + "tests_stable": true, + "summary": "7241 passed in 1241.55s (0:20:41)", + "passed": 7241 + }, + "g_rules": { + "partition": "g_rules", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-152902-trackb-fix-g2-4/scratch/review/run_round4_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=short", + "tests/test_track_b_gross_benefits.py", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py", + "tests/test_track_b_gross_benefits_deduction_cap.py", + "tests/test_track_b_gross_benefits_deductions.py", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", + "tests/test_track_b_gross_benefits_dwb.py", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py", + "tests/test_track_b_gross_benefits_oracle.py", + "tests/test_track_b_gross_benefits_own_input_order.py", + "tests/test_track_b_gross_benefits_parents_ieds.py", + "tests/test_track_b_gross_benefits_parisi.py", + "tests/test_track_b_gross_benefits_payment_review.py", + "tests/test_track_b_gross_benefits_properties.py", + "tests/test_track_b_gross_benefits_registry.py", + "tests/test_track_b_gross_benefits_review.py", + "tests/test_track_b_gross_benefits_saving_absence.py", + "tests/test_track_b_gross_benefits_savings.py", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py", + "tests/test_track_b_gross_benefits_sources_20261011.py", + "tests/test_track_b_gross_benefits_ssfa.py", + "tests/test_track_b_input_schema.py", + "tests/test_track_b_refusal_notes.py" + ], + "environment": { + "PYTHONDONTWRITEBYTECODE": "1", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-152902-trackb-fix-g2-4/src:/Users/maxghenis/.subfleet/worktrees/20261031-152902-trackb-fix-g2-4", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-152902-trackb-fix-g2-4/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-152902-trackb-fix-g2-4/scratch/review/nonexistent", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-152902-trackb-fix-g2-4/scratch/review/round4-hypothesis-g_rules" + }, + "named_modules": [ + "tests/test_track_b_gross_benefits.py", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py", + "tests/test_track_b_gross_benefits_deduction_cap.py", + "tests/test_track_b_gross_benefits_deductions.py", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", + "tests/test_track_b_gross_benefits_dwb.py", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py", + "tests/test_track_b_gross_benefits_oracle.py", + "tests/test_track_b_gross_benefits_own_input_order.py", + "tests/test_track_b_gross_benefits_parents_ieds.py", + "tests/test_track_b_gross_benefits_parisi.py", + "tests/test_track_b_gross_benefits_payment_review.py", + "tests/test_track_b_gross_benefits_properties.py", + "tests/test_track_b_gross_benefits_registry.py", + "tests/test_track_b_gross_benefits_review.py", + "tests/test_track_b_gross_benefits_saving_absence.py", + "tests/test_track_b_gross_benefits_savings.py", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py", + "tests/test_track_b_gross_benefits_sources_20261011.py", + "tests/test_track_b_gross_benefits_ssfa.py", + "tests/test_track_b_input_schema.py", + "tests/test_track_b_refusal_notes.py" + ], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "6ed10a1f4c637ab136511792d574dc49236acb726818532c4a3c865781af14d0", + "src/populace_dynamics/track_b/ret_ledger.py": "e9b01a765a7951937a7035da3ab2ef29b13dc1efa663e35e224ae558d622515b", + "scripts/track_b_g_conformance_report.py": "884811d5968cab6f22e7c72385bf6b14274f2273bb133ff1b12cb3bea06e6fbb" + }, + "test_sha256_before": { + "tests/test_track_b_gross_benefits.py": "de0946a014d054bd47f30dadaf675105aebb1dd562209c4002dee05354628286", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py": "5d9fe8c5cb052d39c82249d6efcf4d88dace5ec68538340e7000f73af5e016df", + "tests/test_track_b_gross_benefits_deduction_cap.py": "2057e1fb3322aeb29f32339cf450118a241269dda0711c48c09da24a44f06e43", + "tests/test_track_b_gross_benefits_deductions.py": "b6f0493ecbb19434c09de42ff7e62a87b85818ea6dc8a5cde78963d780598e02", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py": "5cebe4f986fa7d01d7769c1d1db0581b54ae88e7c4710409285e12393244fdab", + "tests/test_track_b_gross_benefits_dwb.py": "61b6270fdd9a6d156d31194535797d1f59c092943ecdb3773787d1471e2bb80a", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py": "bc1b396f0cc729d56d06cafc0e8a5e196864268ec948f9833039a53cb034c1f4", + "tests/test_track_b_gross_benefits_oracle.py": "d4b88ec7a6945e76499e50266448894e99809737b1bc2a55de060bf03f591d24", + "tests/test_track_b_gross_benefits_own_input_order.py": "3bb4bd7fb3b7567109ed3f132f6b8a775e43e90a04aa4a2a0fa8542c78575291", + "tests/test_track_b_gross_benefits_parents_ieds.py": "98e5f81c99b3b80332db203c07db680b09a633c3d34bc58d15ee986f252bf73c", + "tests/test_track_b_gross_benefits_parisi.py": "4f446013cc7bd9f2ae8dc4dfe3ee59d952a9f5e7d2aaa2f104497dfe36425c1a", + "tests/test_track_b_gross_benefits_payment_review.py": "4c239c468e06a0c522151e182693a91024f61b7f38e49bbd7f03c66b01889dd7", + "tests/test_track_b_gross_benefits_properties.py": "483d502f88457f89cbc4f13b2904718eae59997a81a1189f51b0fbe635c54cfb", + "tests/test_track_b_gross_benefits_registry.py": "93dd3a5d3750cea367ddfe6ccc42f08084ae2f09e6278a1de728baf6a8ddc4df", + "tests/test_track_b_gross_benefits_review.py": "e602dfbf58ec57e25a1270d0e26bb3c5204045e43ab726266e0ef805abe2cd7c", + "tests/test_track_b_gross_benefits_saving_absence.py": "e6078f978ee7bf1d0802dde67c2de94397fd3e9cd142b2c96d6d504ceb0a6862", + "tests/test_track_b_gross_benefits_savings.py": "607bf6cb7415d03bd7b863673d7b9d403841d175a1684f211a562536f4f4755b", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py": "d84130cc73468a8b3f8223c5526f0e982597e552c40e714d691608d32da59233", + "tests/test_track_b_gross_benefits_sources_20261011.py": "e3291d0b6bf497a20835800c4d6ee833854e5edf5b25229932e7a142f8e51a13", + "tests/test_track_b_gross_benefits_ssfa.py": "07fee44e63376a58508296b6f66d1fc20adfa1c88c8cd110a1d5fc45dc4f1ebf", + "tests/test_track_b_input_schema.py": "d638f55a4de888d49cf236e5b58086ef773e63365e5f5ba5578aef3b9d7a8d32", + "tests/test_track_b_refusal_notes.py": "5c765432752317684e4059f2d45a2a95fd03ff327fb1225f853267588fc76abe" + }, + "pytest_pid": 73408, + "exit_code": 0, + "seconds": 1038.8454939589938, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "6ed10a1f4c637ab136511792d574dc49236acb726818532c4a3c865781af14d0", + "src/populace_dynamics/track_b/ret_ledger.py": "e9b01a765a7951937a7035da3ab2ef29b13dc1efa663e35e224ae558d622515b", + "scripts/track_b_g_conformance_report.py": "884811d5968cab6f22e7c72385bf6b14274f2273bb133ff1b12cb3bea06e6fbb" + }, + "test_sha256_after": { + "tests/test_track_b_gross_benefits.py": "de0946a014d054bd47f30dadaf675105aebb1dd562209c4002dee05354628286", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py": "5d9fe8c5cb052d39c82249d6efcf4d88dace5ec68538340e7000f73af5e016df", + "tests/test_track_b_gross_benefits_deduction_cap.py": "2057e1fb3322aeb29f32339cf450118a241269dda0711c48c09da24a44f06e43", + "tests/test_track_b_gross_benefits_deductions.py": "b6f0493ecbb19434c09de42ff7e62a87b85818ea6dc8a5cde78963d780598e02", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py": "5cebe4f986fa7d01d7769c1d1db0581b54ae88e7c4710409285e12393244fdab", + "tests/test_track_b_gross_benefits_dwb.py": "61b6270fdd9a6d156d31194535797d1f59c092943ecdb3773787d1471e2bb80a", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py": "bc1b396f0cc729d56d06cafc0e8a5e196864268ec948f9833039a53cb034c1f4", + "tests/test_track_b_gross_benefits_oracle.py": "d4b88ec7a6945e76499e50266448894e99809737b1bc2a55de060bf03f591d24", + "tests/test_track_b_gross_benefits_own_input_order.py": "3bb4bd7fb3b7567109ed3f132f6b8a775e43e90a04aa4a2a0fa8542c78575291", + "tests/test_track_b_gross_benefits_parents_ieds.py": "98e5f81c99b3b80332db203c07db680b09a633c3d34bc58d15ee986f252bf73c", + "tests/test_track_b_gross_benefits_parisi.py": "4f446013cc7bd9f2ae8dc4dfe3ee59d952a9f5e7d2aaa2f104497dfe36425c1a", + "tests/test_track_b_gross_benefits_payment_review.py": "4c239c468e06a0c522151e182693a91024f61b7f38e49bbd7f03c66b01889dd7", + "tests/test_track_b_gross_benefits_properties.py": "483d502f88457f89cbc4f13b2904718eae59997a81a1189f51b0fbe635c54cfb", + "tests/test_track_b_gross_benefits_registry.py": "93dd3a5d3750cea367ddfe6ccc42f08084ae2f09e6278a1de728baf6a8ddc4df", + "tests/test_track_b_gross_benefits_review.py": "e602dfbf58ec57e25a1270d0e26bb3c5204045e43ab726266e0ef805abe2cd7c", + "tests/test_track_b_gross_benefits_saving_absence.py": "e6078f978ee7bf1d0802dde67c2de94397fd3e9cd142b2c96d6d504ceb0a6862", + "tests/test_track_b_gross_benefits_savings.py": "607bf6cb7415d03bd7b863673d7b9d403841d175a1684f211a562536f4f4755b", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py": "d84130cc73468a8b3f8223c5526f0e982597e552c40e714d691608d32da59233", + "tests/test_track_b_gross_benefits_sources_20261011.py": "e3291d0b6bf497a20835800c4d6ee833854e5edf5b25229932e7a142f8e51a13", + "tests/test_track_b_gross_benefits_ssfa.py": "07fee44e63376a58508296b6f66d1fc20adfa1c88c8cd110a1d5fc45dc4f1ebf", + "tests/test_track_b_input_schema.py": "d638f55a4de888d49cf236e5b58086ef773e63365e5f5ba5578aef3b9d7a8d32", + "tests/test_track_b_refusal_notes.py": "5c765432752317684e4059f2d45a2a95fd03ff327fb1225f853267588fc76abe" + }, + "log": "scratch/review/round4-gate-g_rules.log", + "tail": [ + "........................................................................ [ 63%]", + "........................................................................ [ 67%]", + "........................................................................ [ 72%]", + "........................................................................ [ 76%]", + "........................................................................ [ 81%]", + "........................................................................ [ 85%]", + "........................................................................ [ 90%]", + "........................................................................ [ 94%]", + "........................................................................ [ 99%]", + "............ [100%]", + "1596 passed in 1026.46s (0:17:06)", + "ROUND4_OPEN_AUDIT {\"restricted_opens\": 0, \"subprocess.Popen\": 2, \"os.system\": 0}" + ], + "log_sha256": "de01d912d850afcc4ae63ca5f8072d1aaf4a374a34f6eacc8c548868b88307dc", + "source_stable": true, + "tests_stable": true, + "summary": "1596 passed in 1026.46s (0:17:06)", + "passed": 1596 + }, + "ret_r3": { + "partition": "ret_r3", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-152902-trackb-fix-g2-4/scratch/review/run_round4_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=short", + "tests/test_track_b_arf.py", + "tests/test_track_b_arf_properties.py", + "tests/test_track_b_r3_fix_round_13.py", + "tests/test_track_b_r3_provenance.py", + "tests/test_track_b_r3_sources.py", + "tests/test_track_b_r3_validation_once.py", + "tests/test_track_b_recompute.py", + "tests/test_track_b_recompute_properties.py", + "tests/test_track_b_ret_differential.py", + "tests/test_track_b_ret_fra_facts.py", + "tests/test_track_b_ret_grace.py", + "tests/test_track_b_ret_grace_differential.py", + "tests/test_track_b_ret_grace_provenance.py", + "tests/test_track_b_ret_ledger.py", + "tests/test_track_b_ret_ledger_deductions.py", + "tests/test_track_b_ret_ledger_fix_round_2.py", + "tests/test_track_b_ret_ledger_fix_round_4.py", + "tests/test_track_b_ret_ledger_properties.py", + "tests/test_track_b_ret_ledger_readings.py", + "tests/test_track_b_ret_ledger_sources.py", + "tests/test_track_b_ret_params.py" + ], + "environment": { + "PYTHONDONTWRITEBYTECODE": "1", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-152902-trackb-fix-g2-4/src:/Users/maxghenis/.subfleet/worktrees/20261031-152902-trackb-fix-g2-4", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-152902-trackb-fix-g2-4/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-152902-trackb-fix-g2-4/scratch/review/nonexistent", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-152902-trackb-fix-g2-4/scratch/review/round4-hypothesis-ret_r3" + }, + "named_modules": [ + "tests/test_track_b_arf.py", + "tests/test_track_b_arf_properties.py", + "tests/test_track_b_r3_fix_round_13.py", + "tests/test_track_b_r3_provenance.py", + "tests/test_track_b_r3_sources.py", + "tests/test_track_b_r3_validation_once.py", + "tests/test_track_b_recompute.py", + "tests/test_track_b_recompute_properties.py", + "tests/test_track_b_ret_differential.py", + "tests/test_track_b_ret_fra_facts.py", + "tests/test_track_b_ret_grace.py", + "tests/test_track_b_ret_grace_differential.py", + "tests/test_track_b_ret_grace_provenance.py", + "tests/test_track_b_ret_ledger.py", + "tests/test_track_b_ret_ledger_deductions.py", + "tests/test_track_b_ret_ledger_fix_round_2.py", + "tests/test_track_b_ret_ledger_fix_round_4.py", + "tests/test_track_b_ret_ledger_properties.py", + "tests/test_track_b_ret_ledger_readings.py", + "tests/test_track_b_ret_ledger_sources.py", + "tests/test_track_b_ret_params.py" + ], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "6ed10a1f4c637ab136511792d574dc49236acb726818532c4a3c865781af14d0", + "src/populace_dynamics/track_b/ret_ledger.py": "e9b01a765a7951937a7035da3ab2ef29b13dc1efa663e35e224ae558d622515b", + "scripts/track_b_g_conformance_report.py": "884811d5968cab6f22e7c72385bf6b14274f2273bb133ff1b12cb3bea06e6fbb" + }, + "test_sha256_before": { + "tests/test_track_b_arf.py": "292587c9ee1d160ad6c66da6e388e3a0b2bf4c9831f8ad3b18853c802f5bd68e", + "tests/test_track_b_arf_properties.py": "d1346b68bd07b469cea6357e1881d743e3a90c66e04080fc19fd66b44da7b68e", + "tests/test_track_b_r3_fix_round_13.py": "bfb81d8316574e9df0e2e7cb9f890e1b9f584cac2cd17e025825580e219cebc7", + "tests/test_track_b_r3_provenance.py": "58243309d56acb9dc38e9bf5a701e79ac961ac062e0d37690b12a561592245c9", + "tests/test_track_b_r3_sources.py": "6300b1a4075a0f2549cce4db0aab25d6908eba9071a5a2da3bbfc6d020dd04ba", + "tests/test_track_b_r3_validation_once.py": "ad28687b52c6386e7c5e28525eac12dc9a4ba62b75d18e066d5bdac1252624c0", + "tests/test_track_b_recompute.py": "06db2b43c6c13d679a71a6d2176dc3ee13fce8fc1645684fcbe7c582f9e54f9c", + "tests/test_track_b_recompute_properties.py": "ced431cb4fd0de82a7cde6ff63c6a38eaad1649939d364b1023dcc81aff30759", + "tests/test_track_b_ret_differential.py": "8e38e1040d61d9f0262bbe25c5c17e0f608c433cb29ab898b7f954358bcf1e12", + "tests/test_track_b_ret_fra_facts.py": "7bfb53be6660bbfad0831904d5b39a3e8d997216308b136959ece10bb04c72a8", + "tests/test_track_b_ret_grace.py": "772f6b94187593549cd21a2dbb19a75f998fb840f6b6eb3a97bbeca3f36636dc", + "tests/test_track_b_ret_grace_differential.py": "fbf01f2c6e76f2cc8a60bad5e9c9ac5c4da0c68013578b91de9488aa2623abf5", + "tests/test_track_b_ret_grace_provenance.py": "8cf4446fb0bb6da77a7b84815caafe595ec81b9b7a2cc1e56f686cd25f0e77a5", + "tests/test_track_b_ret_ledger.py": "6d6684e63aa3d56874fb0fd174867d1e2b41e54119ad8077c2e6b689ca723065", + "tests/test_track_b_ret_ledger_deductions.py": "a3fcc50166b867f9d3d719bcf611880cba169b3b99f6bf695ff397a36b2fcd2e", + "tests/test_track_b_ret_ledger_fix_round_2.py": "62a81110909ddebfa77f65078d685464f553c37de89cb88efd743ca406b1aa70", + "tests/test_track_b_ret_ledger_fix_round_4.py": "d19510d831aff24728c9c699608f5f00f932ca96d3e54ec61e76ae6790d59014", + "tests/test_track_b_ret_ledger_properties.py": "803433fd9d3aa7601b45e2f5346d716254409710e9f9d3ac61f1a42d87cc7d64", + "tests/test_track_b_ret_ledger_readings.py": "630bdd1d5f53d93c63674192f205e17edff601f8dcc8d941348db98cf094bdad", + "tests/test_track_b_ret_ledger_sources.py": "ab6b6d66d370c93e5b2cc82b88670f48eb5bceeb0d313c36550986c3ff1844b6", + "tests/test_track_b_ret_params.py": "57a1be52d32c3549d711aba4f88f42cdb0affd98bc3b3d5bf7e607fc0b2c3514" + }, + "pytest_pid": 30321, + "exit_code": 0, + "seconds": 1489.1617076670009, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "6ed10a1f4c637ab136511792d574dc49236acb726818532c4a3c865781af14d0", + "src/populace_dynamics/track_b/ret_ledger.py": "e9b01a765a7951937a7035da3ab2ef29b13dc1efa663e35e224ae558d622515b", + "scripts/track_b_g_conformance_report.py": "884811d5968cab6f22e7c72385bf6b14274f2273bb133ff1b12cb3bea06e6fbb" + }, + "test_sha256_after": { + "tests/test_track_b_arf.py": "292587c9ee1d160ad6c66da6e388e3a0b2bf4c9831f8ad3b18853c802f5bd68e", + "tests/test_track_b_arf_properties.py": "d1346b68bd07b469cea6357e1881d743e3a90c66e04080fc19fd66b44da7b68e", + "tests/test_track_b_r3_fix_round_13.py": "bfb81d8316574e9df0e2e7cb9f890e1b9f584cac2cd17e025825580e219cebc7", + "tests/test_track_b_r3_provenance.py": "58243309d56acb9dc38e9bf5a701e79ac961ac062e0d37690b12a561592245c9", + "tests/test_track_b_r3_sources.py": "6300b1a4075a0f2549cce4db0aab25d6908eba9071a5a2da3bbfc6d020dd04ba", + "tests/test_track_b_r3_validation_once.py": "ad28687b52c6386e7c5e28525eac12dc9a4ba62b75d18e066d5bdac1252624c0", + "tests/test_track_b_recompute.py": "06db2b43c6c13d679a71a6d2176dc3ee13fce8fc1645684fcbe7c582f9e54f9c", + "tests/test_track_b_recompute_properties.py": "ced431cb4fd0de82a7cde6ff63c6a38eaad1649939d364b1023dcc81aff30759", + "tests/test_track_b_ret_differential.py": "8e38e1040d61d9f0262bbe25c5c17e0f608c433cb29ab898b7f954358bcf1e12", + "tests/test_track_b_ret_fra_facts.py": "7bfb53be6660bbfad0831904d5b39a3e8d997216308b136959ece10bb04c72a8", + "tests/test_track_b_ret_grace.py": "772f6b94187593549cd21a2dbb19a75f998fb840f6b6eb3a97bbeca3f36636dc", + "tests/test_track_b_ret_grace_differential.py": "fbf01f2c6e76f2cc8a60bad5e9c9ac5c4da0c68013578b91de9488aa2623abf5", + "tests/test_track_b_ret_grace_provenance.py": "8cf4446fb0bb6da77a7b84815caafe595ec81b9b7a2cc1e56f686cd25f0e77a5", + "tests/test_track_b_ret_ledger.py": "6d6684e63aa3d56874fb0fd174867d1e2b41e54119ad8077c2e6b689ca723065", + "tests/test_track_b_ret_ledger_deductions.py": "a3fcc50166b867f9d3d719bcf611880cba169b3b99f6bf695ff397a36b2fcd2e", + "tests/test_track_b_ret_ledger_fix_round_2.py": "62a81110909ddebfa77f65078d685464f553c37de89cb88efd743ca406b1aa70", + "tests/test_track_b_ret_ledger_fix_round_4.py": "d19510d831aff24728c9c699608f5f00f932ca96d3e54ec61e76ae6790d59014", + "tests/test_track_b_ret_ledger_properties.py": "803433fd9d3aa7601b45e2f5346d716254409710e9f9d3ac61f1a42d87cc7d64", + "tests/test_track_b_ret_ledger_readings.py": "630bdd1d5f53d93c63674192f205e17edff601f8dcc8d941348db98cf094bdad", + "tests/test_track_b_ret_ledger_sources.py": "ab6b6d66d370c93e5b2cc82b88670f48eb5bceeb0d313c36550986c3ff1844b6", + "tests/test_track_b_ret_params.py": "57a1be52d32c3549d711aba4f88f42cdb0affd98bc3b3d5bf7e607fc0b2c3514" + }, + "log": "scratch/review/round4-gate-ret_r3.log", + "tail": [ + "........................................................................ [ 79%]", + "........................................................................ [ 81%]", + "........................................................................ [ 84%]", + "........................................................................ [ 86%]", + "........................................................................ [ 88%]", + "........................................................................ [ 91%]", + "........................................................................ [ 93%]", + "........................................................................ [ 95%]", + "........................................................................ [ 98%]", + "...................................................... [100%]", + "3078 passed in 1483.61s (0:24:43)", + "ROUND4_OPEN_AUDIT {\"restricted_opens\": 0, \"subprocess.Popen\": 1, \"os.system\": 0}" + ], + "log_sha256": "57a7aa5077726df5a4ef6c0a57dd03c11f3f5ec20ea518457b23843410a47aa7", + "source_stable": true, + "tests_stable": true, + "summary": "3078 passed in 1483.61s (0:24:43)", + "passed": 3078 + }, + "g_report": { + "partition": "g_report", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-152902-trackb-fix-g2-4/scratch/review/run_round4_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=short", + "tests/test_track_b_gross_benefits_conformance_report.py" + ], + "environment": { + "PYTHONDONTWRITEBYTECODE": "1", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-152902-trackb-fix-g2-4/src:/Users/maxghenis/.subfleet/worktrees/20261031-152902-trackb-fix-g2-4", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-152902-trackb-fix-g2-4/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-152902-trackb-fix-g2-4/scratch/review/nonexistent", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-152902-trackb-fix-g2-4/scratch/review/round4-hypothesis-g_report" + }, + "named_modules": [ + "tests/test_track_b_gross_benefits_conformance_report.py" + ], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "6ed10a1f4c637ab136511792d574dc49236acb726818532c4a3c865781af14d0", + "src/populace_dynamics/track_b/ret_ledger.py": "e9b01a765a7951937a7035da3ab2ef29b13dc1efa663e35e224ae558d622515b", + "scripts/track_b_g_conformance_report.py": "884811d5968cab6f22e7c72385bf6b14274f2273bb133ff1b12cb3bea06e6fbb" + }, + "test_sha256_before": { + "tests/test_track_b_gross_benefits_conformance_report.py": "7ec6f605783c15c88abbb0834ff894645fe14e2956239c83532cd88132e699c8" + }, + "pytest_pid": 74399, + "exit_code": 0, + "seconds": 909.467283375001, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "6ed10a1f4c637ab136511792d574dc49236acb726818532c4a3c865781af14d0", + "src/populace_dynamics/track_b/ret_ledger.py": "e9b01a765a7951937a7035da3ab2ef29b13dc1efa663e35e224ae558d622515b", + "scripts/track_b_g_conformance_report.py": "884811d5968cab6f22e7c72385bf6b14274f2273bb133ff1b12cb3bea06e6fbb" + }, + "test_sha256_after": { + "tests/test_track_b_gross_benefits_conformance_report.py": "7ec6f605783c15c88abbb0834ff894645fe14e2956239c83532cd88132e699c8" + }, + "log": "scratch/review/round4-gate-g_report.log", + "tail": [ + "...................................................... [100%]", + "54 passed in 906.13s (0:15:06)", + "ROUND4_OPEN_AUDIT {\"restricted_opens\": 0, \"subprocess.Popen\": 0, \"os.system\": 0}" + ], + "log_sha256": "c6943dcaf7db5382b462c58e5bf1dd37de6bfef29f8f1ef9cdeefb9b8ed907e0", + "source_stable": true, + "tests_stable": true, + "summary": "54 passed in 906.13s (0:15:06)", + "passed": 54 + } + }, + "total_named_gate_passes": 11969, + "fresh_mutations_caught_and_reverted": 11, + "confirmed_mutations_including_history": 50, + "final_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "6ed10a1f4c637ab136511792d574dc49236acb726818532c4a3c865781af14d0", + "src/populace_dynamics/track_b/ret_ledger.py": "e9b01a765a7951937a7035da3ab2ef29b13dc1efa663e35e224ae558d622515b", + "scripts/track_b_g_conformance_report.py": "884811d5968cab6f22e7c72385bf6b14274f2273bb133ff1b12cb3bea06e6fbb", + "tests/test_track_b_gross_benefits.py": "de0946a014d054bd47f30dadaf675105aebb1dd562209c4002dee05354628286", + "tests/test_track_b_gross_benefits_conformance_report.py": "7ec6f605783c15c88abbb0834ff894645fe14e2956239c83532cd88132e699c8", + "tests/test_track_b_refusal_notes.py": "5c765432752317684e4059f2d45a2a95fd03ff327fb1225f853267588fc76abe", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py": "bc1b396f0cc729d56d06cafc0e8a5e196864268ec948f9833039a53cb034c1f4", + "tests/test_track_b_ret_ledger_fix_round_4.py": "d19510d831aff24728c9c699608f5f00f932ca96d3e54ec61e76ae6790d59014", + "docs/design/track_b_g_conformance_report.json": "17d144575b38bb85080d8cbed28fad470ec93fd6eb6803b48729bb26a78b3d45", + "docs/design/track_b_g_gross_benefits.md": "2b7b0c8671a3bb1fae57f074989cecf5f3897fc89a32f1462d7e64d8840fc2aa", + "docs/design/track_b_r2_ret_ledger.md": "a535e8904f293550c25f73fbe2ebaca48288fa65c1cb855309ae51b1142c9990", + "docs/design/track_b_g2_r2b_mutations.json": "085bd1b3f1c727cbfec7abb3965f8b685307253eea2a9bd4697bbd36b94873ef", + "tests/data/track_b/gross_benefit_examples.yaml": "58bc989f71090b513f9ed86fd22935e37d8237501477fee38eaef82952bab036" + }, + "independent_verification": { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "scratch/review/run_round4_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "scratch/review/test_round4_adversarial.py" + ], + "environment": { + "OMP_NUM_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-152902-trackb-fix-g2-4/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-152902-trackb-fix-g2-4/scratch/review/nonexistent", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-152902-trackb-fix-g2-4/src:/Users/maxghenis/.subfleet/worktrees/20261031-152902-trackb-fix-g2-4" + }, + "exit_code": 0, + "passed": 50, + "seconds": 9.23, + "open_audit": { + "restricted_opens": 0, + "subprocess.Popen": 0, + "os.system": 0 + }, + "source_and_artifact_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "6ed10a1f4c637ab136511792d574dc49236acb726818532c4a3c865781af14d0", + "src/populace_dynamics/track_b/ret_ledger.py": "e9b01a765a7951937a7035da3ab2ef29b13dc1efa663e35e224ae558d622515b", + "scripts/track_b_r2_cross_head.py": "4f2a1bea264d906ea0fb4cec08a2b233b458bb3a0ca0d09dbe580d6cc78e8178", + "scratch/review/test_round4_adversarial.py": "8fde1ddcbcc7e2c24a7dfa4bc23efc8d402c099b461f30958e011c5597aae26f", + "scratch/review/run_round4_guarded.py": "c605ccf38ca9fd331c4f8c43253d651dfce8aa334ddd458d6608b322bb3c76bc", + "scratch/review/run_round4_guarded_child.py": "98420b7407b12805d665b2133f4b66954dc052940f43e3597005403d7677e779", + "scratch/review/run_round4_crosshead_guarded.py": "9e8f1fa7c6903f980d7141081b979b278021b4d724356aabd3c5ffb4fa8e997d", + "scratch/review/round4-adversarial.log": "0fbc57da4395d922f15b1f5246bf97c84a64618817a3ffbcc3011b625ddff807", + "scratch/review/round4-cross-head.attempt-1.log": "7e2fc0bd9886ff9717424bdb2716c08dfd1e31eb9d40aadc673c8d10958ed7bb" + }, + "crosshead": { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "scratch/review/run_round4_guarded.py", + "scratch/review/run_round4_crosshead_guarded.py", + "--baseline-root", + "scratch/review/master-baseline", + "--output", + "scratch/review/round4-cross-head.json" + ], + "original_script": "scripts/track_b_r2_cross_head.py", + "adapter": "Wrap only the original script\u2019s two --dump children with audit guards; retain their selected source-root imports.", + "exit_code": 0, + "report": { + "verification_class": "statutory conformance", + "scope": "invented cases only; no population, behavioral or forecast claim", + "seed": 53014, + "r2_stable_rows": 240, + "r3_stable_rows": 240, + "identical_declared_output_bytes": true, + "stable_sha256": "799fc9e23a902ac1ca0c2563579ceb094d0dbcd631a912305c40062cf21a5f55", + "transitions": { + "baseline": { + "rows": 6, + "supported": 0, + "refused_by_reason": { + "deduction_before_reduction_part_b": 6 + } + }, + "head": { + "rows": 6, + "supported": 6, + "refused_by_reason": {} + } + }, + "transition_rows": [ + { + "id": "binding_survivor_own_excess_1", + "own_excess": 1, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_60", + "own_excess": 60, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_99", + "own_excess": 99, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_100", + "own_excess": 100, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_555", + "own_excess": 555, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_1188", + "own_excess": 1188, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + } + ] + }, + "audit_records": [ + { + "restricted_opens": 0, + "subprocess.Popen": 0, + "os.system": 0 + }, + { + "restricted_opens": 0, + "subprocess.Popen": 0, + "os.system": 0 + }, + { + "restricted_opens": 0, + "subprocess.Popen": 2, + "os.system": 0 + } + ], + "restricted_opens_total": 0, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "6ed10a1f4c637ab136511792d574dc49236acb726818532c4a3c865781af14d0", + "src/populace_dynamics/track_b/ret_ledger.py": "e9b01a765a7951937a7035da3ab2ef29b13dc1efa663e35e224ae558d622515b", + "scripts/track_b_r2_cross_head.py": "4f2a1bea264d906ea0fb4cec08a2b233b458bb3a0ca0d09dbe580d6cc78e8178" + }, + "report_sha256": "a945d2f0bb2f6b8918e052063aa41a730eb24e9331fb16a1164c45de3810fe3d", + "log_sha256": "c435d8bc5ceb9213f8cdb98642cedfc670c750f8aa26cbc7582e266954f1944c", + "setup_retry": "Initial adapter used a relative child-guard path, which failed before baseline source import. Corrected only the scratch adapter to use an absolute path; initial log retained in round4-cross-head.attempt-1.log.", + "source_stable": true, + "final_source": true, + "historical_report_unchanged": true + }, + "final_source": true, + "historical_preflight_record": "scratch/review/round4-independent-verification.pre-auxiliary-preflight.json", + "formatting": { + "black_command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "black", + "-l", + "79", + "scratch/review/test_round4_adversarial.py" + ], + "black_result": "1 file reformatted before final execution", + "ruff_command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "ruff", + "check", + "scratch/review/test_round4_adversarial.py" + ], + "ruff_result": "All checks passed!" + }, + "g_rules_gate": { + "named_module_count": 22, + "passed": 1596, + "pytest_seconds": 1026.46, + "runner_seconds": 1038.8454939589938, + "exit_code": 0, + "source_stable": true, + "tests_stable": true, + "audit": { + "restricted_opens": 0, + "subprocess.Popen": 2, + "os.system": 0 + }, + "metadata": "scratch/review/round4-gate-g_rules.result.json", + "metadata_sha256": "cf4998a2d13fc3680ca9b5a4d801e6c39f0b963c72dadbf5dbe6bcc3ebd34480", + "log": "scratch/review/round4-gate-g_rules.log", + "log_sha256": "de01d912d850afcc4ae63ca5f8072d1aaf4a374a34f6eacc8c548868b88307dc" + } + }, + "failing_first_exact_head_modules": { + "snapshots": { + "head": "1ce508e538cd7d2a9ed8e82bbbc32a29fb0a1669", + "snapshots": { + "src/populace_dynamics/track_b/gross_benefits.py": { + "file": "scratch/review/gross_benefits_exact_head_round4.py", + "sha256": "cd03ee0b2c828f1fb7e09980b48f4a23e9a8ca49295aaa7a1dd2799d1fff9ed8", + "bytes": 233661 + }, + "src/populace_dynamics/track_b/ret_ledger.py": { + "file": "scratch/review/ret_ledger_exact_head_round4.py", + "sha256": "7b5a1491453fbd61e76c670a1ce84deb3818138d3313c21327661d328d7fa0c8", + "bytes": 62016 + } + } + }, + "reviewed_proof": { + "loaded_modules": { + "gross_benefits": "/Users/maxghenis/.subfleet/worktrees/20261031-152902-trackb-fix-g2-4/scratch/review/gross_benefits_exact_head_round4.py", + "ret_ledger": "/Users/maxghenis/.subfleet/worktrees/20261031-152902-trackb-fix-g2-4/scratch/review/ret_ledger_exact_head_round4.py" + }, + "pytest_arguments": [ + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_4.py::test_nh_entitlement_contradiction_never_becomes_held_refusal[RecordCondition.ADMINISTRATIVE_FINALITY-False-0-1]", + "tests/test_track_b_ret_ledger_fix_round_4.py::test_nh_entitlement_contradiction_never_becomes_held_refusal[RecordCondition.ADMINISTRATIVE_FINALITY-True-4-12]", + "tests/test_track_b_ret_ledger_fix_round_4.py::test_two_known_monthly_cohorts_are_input_error_before_any_refusal[False-none-1-False-fields2]", + "tests/test_track_b_ret_ledger_fix_round_4.py::test_two_known_monthly_cohorts_are_input_error_before_any_refusal[False-ret-0-False-fields3]", + "tests/test_track_b_ret_ledger_fix_round_4.py::test_two_known_monthly_cohorts_are_input_error_before_any_refusal[False-g-1-True-fields6]", + "tests/test_track_b_ret_ledger_fix_round_4.py::test_two_known_monthly_cohorts_are_input_error_before_any_refusal[True-none-0-True-fields7]", + "tests/test_track_b_ret_ledger_fix_round_4.py::test_review_widow_cross_month_probe_has_no_row" + ], + "exit_code": 1, + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "6ed10a1f4c637ab136511792d574dc49236acb726818532c4a3c865781af14d0", + "src/populace_dynamics/track_b/ret_ledger.py": "e9b01a765a7951937a7035da3ab2ef29b13dc1efa663e35e224ae558d622515b" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "6ed10a1f4c637ab136511792d574dc49236acb726818532c4a3c865781af14d0", + "src/populace_dynamics/track_b/ret_ledger.py": "e9b01a765a7951937a7035da3ab2ef29b13dc1efa663e35e224ae558d622515b" + }, + "source_stable": true + }, + "raw_fact_proof": { + "loaded_modules": { + "gross_benefits": "/Users/maxghenis/.subfleet/worktrees/20261031-152902-trackb-fix-g2-4/scratch/review/gross_benefits_exact_head_round4.py", + "ret_ledger": "/Users/maxghenis/.subfleet/worktrees/20261031-152902-trackb-fix-g2-4/scratch/review/ret_ledger_exact_head_round4.py" + }, + "pytest_arguments": [ + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "tests/test_track_b_ret_ledger_fix_round_4.py", + "-k", + "(declared_spouse_pia_disqualification_precedes_held_refusal or declared_nh_original_pia_mismatch_precedes_held_refusal or declared_dib_nh_gross_pia_mismatch_precedes_held_refusal) and ADMINISTRATIVE_FINALITY", + "--tb=short" + ], + "exit_code": 1, + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "6ed10a1f4c637ab136511792d574dc49236acb726818532c4a3c865781af14d0", + "src/populace_dynamics/track_b/ret_ledger.py": "e9b01a765a7951937a7035da3ab2ef29b13dc1efa663e35e224ae558d622515b" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "6ed10a1f4c637ab136511792d574dc49236acb726818532c4a3c865781af14d0", + "src/populace_dynamics/track_b/ret_ledger.py": "e9b01a765a7951937a7035da3ab2ef29b13dc1efa663e35e224ae558d622515b" + }, + "source_stable": true + }, + "failure_classification": { + "reviewed": { + "expected_failures": 12, + "all_failures": "DID NOT RAISE InvalidFamilyInput", + "unexpected_errors": 0, + "source_stable": true, + "audit": { + "restricted_opens": 0, + "subprocess.Popen": 0, + "os.system": 0 + }, + "nodes": [ + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_nh_entitlement_contradiction_never_becomes_held_refusal[RecordCondition.ADMINISTRATIVE_FINALITY-False-0-1]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_nh_entitlement_contradiction_never_becomes_held_refusal[RecordCondition.ADMINISTRATIVE_FINALITY-True-4-12]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_two_known_monthly_cohorts_are_input_error_before_any_refusal[False-none-1-False-fields2]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_two_known_monthly_cohorts_are_input_error_before_any_refusal[False-ret-0-False-fields3]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_two_known_monthly_cohorts_are_input_error_before_any_refusal[False-g-1-True-fields6]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_two_known_monthly_cohorts_are_input_error_before_any_refusal[True-none-0-True-fields7]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_review_widow_cross_month_probe_has_no_row[birth-False]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_review_widow_cross_month_probe_has_no_row[birth-True]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_review_widow_cross_month_probe_has_no_row[own-False]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_review_widow_cross_month_probe_has_no_row[own-True]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_review_widow_cross_month_probe_has_no_row[mixed-False]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_review_widow_cross_month_probe_has_no_row[mixed-True]" + ] + }, + "raw-audit": { + "expected_failures": 32, + "all_failures": "DID NOT RAISE InvalidFamilyInput", + "unexpected_errors": 0, + "source_stable": true, + "audit": { + "restricted_opens": 0, + "subprocess.Popen": 0, + "os.system": 0 + }, + "nodes": [ + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_declared_spouse_pia_disqualification_precedes_held_refusal[False-RecordCondition.ADMINISTRATIVE_FINALITY-0-OwnBenefitKind.OLD_AGE-Role.SPOUSE]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_declared_spouse_pia_disqualification_precedes_held_refusal[False-RecordCondition.ADMINISTRATIVE_FINALITY-0-OwnBenefitKind.OLD_AGE-Role.SPOUSE_CHILD_IN_CARE]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_declared_spouse_pia_disqualification_precedes_held_refusal[False-RecordCondition.ADMINISTRATIVE_FINALITY-0-OwnBenefitKind.OLD_AGE-Role.DIVORCED_SPOUSE]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_declared_spouse_pia_disqualification_precedes_held_refusal[False-RecordCondition.ADMINISTRATIVE_FINALITY-0-OwnBenefitKind.DISABILITY-Role.SPOUSE]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_declared_spouse_pia_disqualification_precedes_held_refusal[False-RecordCondition.ADMINISTRATIVE_FINALITY-0-OwnBenefitKind.DISABILITY-Role.SPOUSE_CHILD_IN_CARE]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_declared_spouse_pia_disqualification_precedes_held_refusal[False-RecordCondition.ADMINISTRATIVE_FINALITY-0-OwnBenefitKind.DISABILITY-Role.DIVORCED_SPOUSE]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_declared_spouse_pia_disqualification_precedes_held_refusal[False-RecordCondition.ADMINISTRATIVE_FINALITY-4-OwnBenefitKind.OLD_AGE-Role.SPOUSE]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_declared_spouse_pia_disqualification_precedes_held_refusal[False-RecordCondition.ADMINISTRATIVE_FINALITY-4-OwnBenefitKind.OLD_AGE-Role.SPOUSE_CHILD_IN_CARE]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_declared_spouse_pia_disqualification_precedes_held_refusal[False-RecordCondition.ADMINISTRATIVE_FINALITY-4-OwnBenefitKind.OLD_AGE-Role.DIVORCED_SPOUSE]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_declared_spouse_pia_disqualification_precedes_held_refusal[False-RecordCondition.ADMINISTRATIVE_FINALITY-4-OwnBenefitKind.DISABILITY-Role.SPOUSE]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_declared_spouse_pia_disqualification_precedes_held_refusal[False-RecordCondition.ADMINISTRATIVE_FINALITY-4-OwnBenefitKind.DISABILITY-Role.SPOUSE_CHILD_IN_CARE]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_declared_spouse_pia_disqualification_precedes_held_refusal[False-RecordCondition.ADMINISTRATIVE_FINALITY-4-OwnBenefitKind.DISABILITY-Role.DIVORCED_SPOUSE]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_declared_spouse_pia_disqualification_precedes_held_refusal[True-RecordCondition.ADMINISTRATIVE_FINALITY-0-OwnBenefitKind.OLD_AGE-Role.SPOUSE]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_declared_spouse_pia_disqualification_precedes_held_refusal[True-RecordCondition.ADMINISTRATIVE_FINALITY-0-OwnBenefitKind.OLD_AGE-Role.SPOUSE_CHILD_IN_CARE]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_declared_spouse_pia_disqualification_precedes_held_refusal[True-RecordCondition.ADMINISTRATIVE_FINALITY-0-OwnBenefitKind.OLD_AGE-Role.DIVORCED_SPOUSE]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_declared_spouse_pia_disqualification_precedes_held_refusal[True-RecordCondition.ADMINISTRATIVE_FINALITY-0-OwnBenefitKind.DISABILITY-Role.SPOUSE]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_declared_spouse_pia_disqualification_precedes_held_refusal[True-RecordCondition.ADMINISTRATIVE_FINALITY-0-OwnBenefitKind.DISABILITY-Role.SPOUSE_CHILD_IN_CARE]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_declared_spouse_pia_disqualification_precedes_held_refusal[True-RecordCondition.ADMINISTRATIVE_FINALITY-0-OwnBenefitKind.DISABILITY-Role.DIVORCED_SPOUSE]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_declared_spouse_pia_disqualification_precedes_held_refusal[True-RecordCondition.ADMINISTRATIVE_FINALITY-4-OwnBenefitKind.OLD_AGE-Role.SPOUSE]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_declared_spouse_pia_disqualification_precedes_held_refusal[True-RecordCondition.ADMINISTRATIVE_FINALITY-4-OwnBenefitKind.OLD_AGE-Role.SPOUSE_CHILD_IN_CARE]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_declared_spouse_pia_disqualification_precedes_held_refusal[True-RecordCondition.ADMINISTRATIVE_FINALITY-4-OwnBenefitKind.OLD_AGE-Role.DIVORCED_SPOUSE]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_declared_spouse_pia_disqualification_precedes_held_refusal[True-RecordCondition.ADMINISTRATIVE_FINALITY-4-OwnBenefitKind.DISABILITY-Role.SPOUSE]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_declared_spouse_pia_disqualification_precedes_held_refusal[True-RecordCondition.ADMINISTRATIVE_FINALITY-4-OwnBenefitKind.DISABILITY-Role.SPOUSE_CHILD_IN_CARE]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_declared_spouse_pia_disqualification_precedes_held_refusal[True-RecordCondition.ADMINISTRATIVE_FINALITY-4-OwnBenefitKind.DISABILITY-Role.DIVORCED_SPOUSE]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_declared_nh_original_pia_mismatch_precedes_held_refusal[RecordCondition.ADMINISTRATIVE_FINALITY-1-0]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_declared_nh_original_pia_mismatch_precedes_held_refusal[RecordCondition.ADMINISTRATIVE_FINALITY-1-4]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_declared_nh_original_pia_mismatch_precedes_held_refusal[RecordCondition.ADMINISTRATIVE_FINALITY-12-0]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_declared_nh_original_pia_mismatch_precedes_held_refusal[RecordCondition.ADMINISTRATIVE_FINALITY-12-4]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_declared_dib_nh_gross_pia_mismatch_precedes_held_refusal[RecordCondition.ADMINISTRATIVE_FINALITY-1-0]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_declared_dib_nh_gross_pia_mismatch_precedes_held_refusal[RecordCondition.ADMINISTRATIVE_FINALITY-1-3]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_declared_dib_nh_gross_pia_mismatch_precedes_held_refusal[RecordCondition.ADMINISTRATIVE_FINALITY-12-0]", + "FAILED tests/test_track_b_ret_ledger_fix_round_4.py::test_declared_dib_nh_gross_pia_mismatch_precedes_held_refusal[RecordCondition.ADMINISTRATIVE_FINALITY-12-3]" + ] + } + }, + "summary": "12 reviewed NH/cohort failures in 4.78s plus 32 declared-fact failures in 8.62s; every failure DID NOT RAISE InvalidFamilyInput; zero restricted opens; working source unchanged" + }, + "cross_head": { + "verification_class": "statutory conformance", + "scope": "invented cases only; no population, behavioral or forecast claim", + "seed": 53014, + "r2_stable_rows": 240, + "r3_stable_rows": 240, + "identical_declared_output_bytes": true, + "stable_sha256": "799fc9e23a902ac1ca0c2563579ceb094d0dbcd631a912305c40062cf21a5f55", + "transitions": { + "baseline": { + "rows": 6, + "supported": 0, + "refused_by_reason": { + "deduction_before_reduction_part_b": 6 + } + }, + "head": { + "rows": 6, + "supported": 6, + "refused_by_reason": {} + } + }, + "transition_rows": [ + { + "id": "binding_survivor_own_excess_1", + "own_excess": 1, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_60", + "own_excess": 60, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_99", + "own_excess": 99, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_100", + "own_excess": 100, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_555", + "own_excess": 555, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_1188", + "own_excess": 1188, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + } + ] + }, + "conformance": { + "command": "env PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=$PWD/src:$PWD OMP_NUM_THREADS=1 POLARS_MAX_THREADS=1 OMP_WAIT_POLICY=PASSIVE POPULACE_DYNAMICS_PSID_DIR=$PWD/scratch/review/nonexistent POPULACE_DYNAMICS_EPUF_DIR=$PWD/scratch/review/nonexistent /Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python scratch/review/run_round4_guarded.py scripts/track_b_g_conformance_report.py --output docs/design/track_b_g_conformance_report.json", + "log": "scratch/review/round4-conformance-regenerate.log", + "log_sha256": "47c5237e9ebaca72a2bebc40244b3b3a62f1d63130721fdbe3e460bc57d780ac", + "sha256": "17d144575b38bb85080d8cbed28fad470ec93fd6eb6803b48729bb26a78b3d45", + "lattice": { + "invalid": 286794, + "refused": 60775, + "rows": 356400, + "supported": 8831 + }, + "named_refusals": { + "invalid": 0, + "refused": 38, + "rows": 38, + "supported": 0 + }, + "registry_sha256": "58bc989f71090b513f9ed86fd22935e37d8237501477fee38eaef82952bab036", + "byte_reproduction_test_passed": true, + "generation_follows_final_g_inputs": true + }, + "formatting": { + "python_files": [ + "src/populace_dynamics/track_b/gross_benefits.py", + "src/populace_dynamics/track_b/ret_ledger.py", + "scripts/track_b_g_conformance_report.py", + "tests/test_track_b_gross_benefits.py", + "tests/test_track_b_gross_benefits_conformance_report.py", + "tests/test_track_b_refusal_notes.py", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py", + "tests/test_track_b_ret_ledger_fix_round_4.py" + ], + "black": "python -m black --workers 1 -l 79 --check; all 8 unchanged", + "ruff": "python -m ruff check; all checks passed" + }, + "git_checks": { + "head": { + "command": [ + "git", + "--no-optional-locks", + "-c", + "core.fsmonitor=false", + "rev-parse", + "HEAD" + ], + "exit_code": 0, + "stdout": "1ce508e538cd7d2a9ed8e82bbbc32a29fb0a1669\n", + "stderr": "" + }, + "log_since_origin_master": { + "command": [ + "git", + "--no-optional-locks", + "-c", + "core.fsmonitor=false", + "log", + "--oneline", + "origin/master..HEAD" + ], + "exit_code": 0, + "stdout": "1ce508e5 Check FRA facts, the OB bound and as-if-absent membership (#563 round 3)\n872cebc7 Record the conformance hash refresh in the verification ledger (#563)\n7fa124e3 Refresh the G conformance report's registry hash (#563)\nbbcdf7f4 Merge master a747bafa into the G part 2 / R2 part (b) branch\n1a9c8b7e Finish and verify #563 fix round 2 (part 2)\n4493e58b Merge master 1ec57a5d into the G part 2 / R2 part (b) branch\n2f88f07e Refuse uncovered G2 and R2 part (b) paths (#563 fix round 2, part 1)\n0ccf66ff Merge master 9967dfd6 into the G part 2 / R2 part (b) branch\nf3b9a719 Regenerate the G conformance report with the deduction denominator; record mutations and verification; recount tiers\n57756aa1 G part 2 and R2 part (b): deduction before reduction; SSA's operational saving clause\n0e7a7706 Let refusal exception notes be deleted again; register guard enums before first use\n", + "stderr": "" + }, + "committed_changed_paths": { + "command": [ + "git", + "--no-optional-locks", + "-c", + "core.fsmonitor=false", + "diff", + "--name-only", + "origin/master...HEAD" + ], + "exit_code": 0, + "stdout": "docs/design/track_b_g2_r2b_mutations.json\ndocs/design/track_b_g2_r2b_verification.json\ndocs/design/track_b_g_conformance_report.json\ndocs/design/track_b_g_gross_benefits.md\ndocs/design/track_b_r2_ret_ledger.md\nscripts/track_b_g_conformance_report.py\nscripts/track_b_r2_cross_head.py\nsrc/populace_dynamics/track_b/_provenance.py\nsrc/populace_dynamics/track_b/gross_benefits.py\nsrc/populace_dynamics/track_b/ret_ledger.py\ntests/README-tiers.md\ntests/data/track_b/gross_benefit_examples.yaml\ntests/data/track_b/gross_benefit_sources/README.md\ntests/data/track_b/gross_benefit_sources/manifest.json\ntests/test_track_b_gross_benefits.py\ntests/test_track_b_gross_benefits_conformance_report.py\ntests/test_track_b_gross_benefits_deduction_age_inputs.py\ntests/test_track_b_gross_benefits_deduction_cap.py\ntests/test_track_b_gross_benefits_deductions.py\ntests/test_track_b_gross_benefits_deductions_fix_round_2.py\ntests/test_track_b_gross_benefits_fix_round_10_api.py\ntests/test_track_b_gross_benefits_fix_round_10_helpers.py\ntests/test_track_b_gross_benefits_fix_round_10_objects.py\ntests/test_track_b_gross_benefits_fix_round_10_parameters.py\ntests/test_track_b_gross_benefits_fix_round_11_seals.py\ntests/test_track_b_gross_benefits_fix_round_12_contract.py\ntests/test_track_b_gross_benefits_fix_round_13_audit.py\ntests/test_track_b_gross_benefits_fix_round_13_guard.py\ntests/test_track_b_gross_benefits_fix_round_15_receivers.py\ntests/test_track_b_gross_benefits_fix_round_3_rates.py\ntests/test_track_b_gross_benefits_fix_round_5_cohorts.py\ntests/test_track_b_gross_benefits_fix_round_6_cohorts.py\ntests/test_track_b_gross_benefits_fix_round_7_cohorts.py\ntests/test_track_b_gross_benefits_fix_round_7_history.py\ntests/test_track_b_gross_benefits_fix_round_8_entries.py\ntests/test_track_b_gross_benefits_fix_round_8_history.py\ntests/test_track_b_gross_benefits_fix_round_9_outcomes.py\ntests/test_track_b_gross_benefits_fix_round_9_validation.py\ntests/test_track_b_gross_benefits_properties.py\ntests/test_track_b_gross_benefits_registry.py\ntests/test_track_b_gross_benefits_review.py\ntests/test_track_b_gross_benefits_saving_absence.py\ntests/test_track_b_gross_benefits_savings.py\ntests/test_track_b_gross_benefits_savings_fix_round_2.py\ntests/test_track_b_gross_benefits_sources_20261011.py\ntests/test_track_b_input_schema.py\ntests/test_track_b_r3_fix_round_13.py\ntests/test_track_b_refusal_notes.py\ntests/test_track_b_ret_fra_facts.py\ntests/test_track_b_ret_ledger.py\ntests/test_track_b_ret_ledger_deductions.py\ntests/test_track_b_ret_ledger_fix_round_2.py\ntests/test_track_b_ret_ledger_sources.py\ntests/tier_counts.json\ntests/track_b_gross_benefit_support.py\n", + "stderr": "" + }, + "working_changed_paths": { + "command": [ + "git", + "--no-optional-locks", + "-c", + "core.fsmonitor=false", + "diff", + "--name-only" + ], + "exit_code": 0, + "stdout": "docs/design/track_b_g2_r2b_mutations.json\ndocs/design/track_b_g2_r2b_verification.json\ndocs/design/track_b_g_conformance_report.json\ndocs/design/track_b_g_gross_benefits.md\ndocs/design/track_b_r2_ret_ledger.md\nscripts/track_b_g_conformance_report.py\nsrc/populace_dynamics/track_b/gross_benefits.py\nsrc/populace_dynamics/track_b/ret_ledger.py\ntests/test_track_b_gross_benefits.py\ntests/test_track_b_gross_benefits_conformance_report.py\ntests/test_track_b_refusal_notes.py\n", + "stderr": "" + }, + "status": { + "command": [ + "git", + "--no-optional-locks", + "-c", + "core.fsmonitor=false", + "status", + "--short" + ], + "exit_code": 0, + "stdout": " M docs/design/track_b_g2_r2b_mutations.json\n M docs/design/track_b_g2_r2b_verification.json\n M docs/design/track_b_g_conformance_report.json\n M docs/design/track_b_g_gross_benefits.md\n M docs/design/track_b_r2_ret_ledger.md\n M scripts/track_b_g_conformance_report.py\n M src/populace_dynamics/track_b/gross_benefits.py\n M src/populace_dynamics/track_b/ret_ledger.py\n M tests/test_track_b_gross_benefits.py\n M tests/test_track_b_gross_benefits_conformance_report.py\n M tests/test_track_b_refusal_notes.py\n?? tests/test_track_b_gross_benefits_fix_round_4_composition.py\n?? tests/test_track_b_ret_ledger_fix_round_4.py\n", + "stderr": "" + }, + "diff_check": { + "command": [ + "git", + "--no-optional-locks", + "-c", + "core.fsmonitor=false", + "diff", + "--check", + "--", + "docs/design/track_b_g2_r2b_mutations.json", + "docs/design/track_b_g2_r2b_verification.json", + "docs/design/track_b_g_conformance_report.json", + "docs/design/track_b_g_gross_benefits.md", + "docs/design/track_b_r2_ret_ledger.md", + "scripts/track_b_g_conformance_report.py", + "src/populace_dynamics/track_b/gross_benefits.py", + "src/populace_dynamics/track_b/ret_ledger.py", + "tests/test_track_b_gross_benefits.py", + "tests/test_track_b_gross_benefits_conformance_report.py", + "tests/test_track_b_refusal_notes.py" + ], + "exit_code": 0, + "stdout": "", + "stderr": "" + } + }, + "protected_paths_unchanged": true, + "six_restricted_record_hashes_matched_before_source_work": true, + "tier_files_unchanged_this_round": true, + "ci_only_checks": [ + "tier-policy", + "birth-evidence" + ], + "whole_suite_collection_run": false, + "all_changes_uncommitted": true, + "existing_assertions": "No prior monetary or input assertion weakened. Only complete named-refusal count assertions expand from 37 to 38 for the added reason.", + "readings_for_orchestrator": "GN 02603.050A.1/A.2 composition follows the delegated named-refusal ruling only when exact subject payments differ. Earlier readings stand.", + "detailed_report": "scratch/review/fix-round-4-report.md", + "lane_command_notes": [ + "scratch/review/deduction-round4-notes.md", + "scratch/review/ret-round4-notes.md", + "scratch/review/round4-adversarial-audit.md" + ] + }, + "round_4_current_evidence_note": "Earlier records remain historical. The round_4 section is the current evidence for the final rules, declarations, report inputs and artifact." } diff --git a/docs/design/track_b_g_conformance_report.json b/docs/design/track_b_g_conformance_report.json index 9522d601a..3b7a71751 100644 --- a/docs/design/track_b_g_conformance_report.json +++ b/docs/design/track_b_g_conformance_report.json @@ -347,6 +347,7 @@ "savings_clause_history_unknown": 0, "savings_clause_membership_change": 0, "savings_clause_rate_procedure": 0, + "sole_full_deduction_zero_dual_composition": 0, "widow_child_in_care_unknown": 168, "widow_drc_savings_clause": 4860, "widow_drc_savings_clause_history_unknown": 0, @@ -562,8 +563,8 @@ "supplemental_refusal_witnesses": { "denominator": { "invalid": 0, - "refused": 37, - "rows": 37, + "refused": 38, + "rows": 38, "supported": 0 }, "refused_by_reason": { @@ -600,6 +601,7 @@ "savings_clause_history_unknown": 1, "savings_clause_membership_change": 1, "savings_clause_rate_procedure": 1, + "sole_full_deduction_zero_dual_composition": 1, "widow_child_in_care_unknown": 1, "widow_drc_savings_clause": 1, "widow_drc_savings_clause_history_unknown": 1, @@ -805,6 +807,12 @@ "reason": "savings_clause_rate_procedure", "status": "refused" }, + { + "description": "GN 02603.050 A.1 and A.2 compose differently: child 175 versus 200", + "id": "sole_full_deduction_zero_dual_composition", + "reason": "sole_full_deduction_zero_dual_composition", + "status": "refused" + }, { "description": "A widow and an entitled child lack a current care attestation", "id": "widow_child_in_care_unknown", diff --git a/docs/design/track_b_g_gross_benefits.md b/docs/design/track_b_g_gross_benefits.md index 650ed5387..1cdcda46d 100644 --- a/docs/design/track_b_g_gross_benefits.md +++ b/docs/design/track_b_g_gross_benefits.md @@ -672,6 +672,7 @@ G never falls back to a single-worker computation. | `dual_entitlement_sequence` | A spouse's DIB after the spouse benefit (RS 00615.260), an aged widow(er) with DIB, an own-RIB widow(er) before G's cohort-1929 implementation boundary (the source's method-D boundary is January 2, 1928; RS 00615.010/.020B), or DWB with own RIB or DIB | | `parisi_redistribution_ambiguous` | Own delayed credits, an actually limiting RIB-LIM after maximum and age reduction, or dual zero reached only after auxiliary age reduction remain unsettled by GN 02603.050A/C | | `parisi_before_october_1999` | A binding maximum with dual entitlement before 10/99 | +| `sole_full_deduction_zero_dual_composition` | GN 02603.050 A.1's sole full permanent deduction and A.2's zero dual rate admit different subject payments depending on composition order; equal-payment cases compute | | `independently_entitled_divorced_spouse` | IEDS before January 1985 or a WEP-affected worker record before January 2024 (RS 00202.100) | | `non_aime_formula_pia` | Old-start, special-minimum and frozen-minimum PIAs (RS 00615.740B.1) | | `savings_clause_403a5` | Under explicit `LITERAL_REFUSAL`, a governed month whose total fell below a 403(a)(5) protected total, and every later governed month | @@ -2669,7 +2670,7 @@ $83.50 child rates and $83 whole-dollar payments. | Configuration | Result | |---|---| -| No deductions | Exactly the existing family or household result | +| No events or NH reservations | Exactly the existing family or household result | | Auxiliary or survivor own earnings deduction, full or partial | Supported | | Permanent deduction | GN 02603.050C redistribution | | Estimated own earnings deduction | Same-household increase; other households retain their previous rate | @@ -2682,7 +2683,8 @@ $83.50 child rates and $83 whole-dollar payments. | Penalty | `penalty_deduction` | | Maritime tax | `maritime_deduction` | | Missing election certificate | `election_certificate_suspension` | -| Concurrent number-holder reservations and age reductions | `deduction_age_work_interaction` | +| Concurrent subject number-holder reservations and subject age reductions | `deduction_age_work_interaction` | +| Sole full permanent subject deduction and zero dual rows whose A.1/A.2 compositions change payment | `sole_full_deduction_zero_dual_composition` | | Combined maxima; multiple auxiliary records | Existing named refusals remain | The computation first obtains the ordinary G maximum-adjusted rates and @@ -3157,8 +3159,8 @@ that valid case. A widow with OB basis $5 and payable $4 likewise withholds $1. Equality remains permitted for dual-entitlement markers and other event reasons according to their existing semantics. -The new fact-pattern input errors in this PR's third fix round have these -premises. RET uses the same table in its design note. +The fact-pattern input errors added in this PR's third and fourth fix +rounds have these premises. RET uses the same table in its design note. | Fact pattern classified as `InvalidFamilyInput` | Source proving impossibility | What would falsify the premise | |---|---|---| @@ -3166,6 +3168,10 @@ premises. RET uses the same table in its design note. | An auxiliary and that same person's own benefit supply different SSA birth cohorts, even if their FRA declaration fits both separately | Act 202(q)(6); RS 00615.003/.010; G's existing single-person cohort-consistency contract | The fields describe different people or different declared cohort conventions; this interface permits neither | | RET declaration places FRA after a supplied own DRC-increased G snapshot | Act 202(w)(2); RS 00615.692 | Credits belonging only to the deceased NH, or an own age reduction without own delayed credits; neither proves the survivor's age | | Own-work payable plus NH reservation equals the applicable OB upper bound | GN 02603.050A's OB limit and a strictly positive own-work deduction | A supported entry route carrying gross above that OB; this API has none, and larger widow OBs and one-parent rates are explicitly preserved | +| G and RET declare opposite NH entitlement for the same person and month | Act 202(a), 203(b); `WORKER_NOT_ENTITLED` explicitly declares no RIB/DIB entitlement, while RET `entitled_months` declares entitlement; G's record kind also determines whether an NH benefit exists | Different people or months, or a declaration about cash rather than entitlement; this interface distinguishes zero cash from absence of entitlement | +| A person's known SSA cohort differs between monthly contexts, including between an explicit cohort and an own-benefit cohort | Act 202(q)(6); RS 00615.003/.010 define one birth cohort for one person; G already requires the same identity across household records | Different people or cohort conventions; neither is allowed for one identifier. Missing cohort facts do not imply a conflicting cohort | +| RET declares an entitled spouse whose declared own RIB/DIB PIA equals or exceeds half the insured person's PIA | Act 202(b)(1)(D), (c)(1)(D); RS 00202.005; G's canonical spouse entitlement predicate compares the declared PIAs directly | No own entitlement in that month, a different person's own PIA, or a different PIA basis; the supplied G own benefit describes this person's current entitlement | +| An entitled NH's RET original rate differs from G's declared PIA, or a DIB NH's gross rate differs from that PIA | RS 02501.110 states the NH original benefit is 100% of PIA; Social Security Bulletin 75(3), Table 2 shows DIB worker benefit at 100% of PIA; the G/RET interface copies these declared rates directly | An unentitled month, a different person/month, or a different rate definition; unentitled original-rate declarations remain unconstrained by this comparison | ### Reproduced cases and invariants @@ -3208,3 +3214,103 @@ ordinary. The old-guard comparison retains all 480 `LITERAL_REFUSAL` rows. No new statutory reading is required. The existing operational/literal choice and all previously recorded readings remain unchanged. No source capture, registry input or source manifest changes in this round. + +## PR 563 round 4: outside deductions and competing exceptions + +Verification class: statutory conformance on invented cases and captured +rules only. This round admits no population, behavioral or forecast claim. + +### Subject events and the deduction pipeline + +Act 203(a)(3)(C) computes the governed family as if the divorced or +surviving divorced spouse were absent. GN 02603.020B states: + +> When any auxiliary or survivor is entitled to benefits that are not subject to the family maximum; i.e., a divorced spouse or surviving divorced spouse, consider only the auxiliaries or survivors who are subject to the maximum in calculating a benefit readjustment. + +The GN 02603.050A.1 sole-deductee predicate therefore counts subject events. +An outside event still reduces that person's own cash. With January 2024 +retirement PIA $400 and MAX $600, spouse B has cohort 1960 and 36 reduction +months, C is a child, and outside spouse D has cohort 1962 and 60 reduction +months with no current or first-entitlement child in care. Full permanent +own-work deductions on B and D leave NH $400, B $0, C $200 and D $0: +record payment $600. The former $175 child rate and $575 total incorrectly +counted D's event. At PIA $.80/MAX $1.20, C receives $.40 instead of $.30. +Both public forms and beneficiary orders execute these cases. + +The survivor counterpart has PIA $400/MAX $600, widow B with cohort 1960, +36 reduction months and an 80-month reduction period, and three children. +Adding a surviving divorced spouse with cohort 1962, 60 reduction months, +an 84-month period and a full own-work deduction preserves each child's +$200 payment. The former event count reduced each child to $192.10. + +The audit covered every deduction-pipeline event use: removal of explicit +dual markers, the empty-event shortcut, deferred age/NH allocation +coverage, the subject explicit/permanent sets, the sole-full predicate, +per-row cash updates, and subject reservations in the readjustment loop. +Subject sets govern readjustment and its age/NH coverage check. Validation +and unsupported event reasons still apply to every declared beneficiary; +a malformed outside declaration or an outside person's own uncovered +procedure can invalidate or refuse the complete public call. + +The empty-event shortcut also required correction: NH reservations must +be applied even when there is no own-work event. With PIA $400/MAX $600, +two children ordinarily receive $100 each. A $10 NH reservation on one +child leaves that child $90, whether D and D's own event are present or +absent. The earlier shortcut paid $100 until D's event activated the +allocation loop. Outside ages and outside NH reservations likewise cannot +supply a subject age/NH coverage trigger (GN 02603.020B; RS 02501.155B.3.c). + +### Readings for the orchestrator: A.1 and A.2 composition + +The conflict is named +`us:oasdi-sole-full-deduction-zero-dual-composition`. GN 02603.050A.1 says: + +> If a beneficiary is subject to a full permanent deduction for any reason and no other deduction is involved for any beneficiary, disregard that beneficiary when distributing the family maximum. + +GN 02603.040A lists "Deduction because of entitlement to a benefit on +another record" first in its deduction priority. This supports counting +zero-rate dual entitlement as another deduction that blocks A.1. +GN 02603.050A.2 instead says: + +> If dual entitlement reduces a beneficiary's rate to $0.00 (technically entitled) regardless of other deductions that may apply for any other beneficiary on record disregard the dually entitled beneficiary when distributing the family maximum. + +Disregarding that row first can leave the full permanent deductee alone. +The captures do not settle the composition. The orchestrator's round-4 +ruling adopts neither payment when they differ. G raises +`sole_full_deduction_zero_dual_composition`, retaining the refusal and its +weight in every denominator. The check compares subject payments under +both compositions using the same statutory allocation procedure. It runs +when one subject full permanent deduction would qualify after disregarding +zero dual rows, at least one such row exists, and no positive dual rate or +NH reservation independently blocks A.1. Equal-payment cases compute, +including an unbound maximum or no age amount to reserve. Partial, +temporary and multiple subject events retain their existing procedure. + +For PIA $400/MAX $600, spouse B with 36 reduction months, child C and +technically entitled child Z with own DIB $400, B's full permanent +deduction produces C $175/record $575 under strict A.1, versus +C $200/record $600 when A.2 is applied first. The $.80/$1.20 case differs +by $.10. These are invented calculations derived from captured rules; +no new published monetary example or capture is introduced. + +The check precedes any result admitted to a saving-clause guard. +Round 3's `_savings_membership` continues to omit outside beneficiaries. +Zero dual rows remain declared subject members; comparing the deduction +compositions does not rewrite membership or the order of NH and own-work +charges. The ordinary deduction priority and the earlier saving-clause +readings remain in effect. + +### Executed invariants + +| Invariant | Executing test | +| --- | --- | +| Adding a supported outside spouse, with or without an event, preserves every subject payment in any order | `test_review_outside_deduction_cannot_lower_governed_child`; `test_surviving_divorced_deduction_cannot_lower_governed_children`; Hypothesis `test_outside_independence_in_any_beneficiary_order` | +| NH reservations apply independently of an outside event or age | `test_outside_only_event_cannot_activate_subject_nh_deduction`; `test_outside_age_and_nh_reservation_do_not_trigger_subject_coverage`; Hypothesis `test_outside_independence_with_nh_only_reservations` | +| The composition refusal occurs exactly when the two readings give different subject payments | `test_review_zero_dual_composition_refuses_with_preserved_denominator`; Hypothesis `test_composition_refusal_exactly_matches_competing_payment_readings` | +| Equal-payment compositions and independent blockers retain computation | `test_composition_valid_controls_keep_computing` | +| A difference only in counted maximum room cannot trigger a payment-conflict refusal | `test_composition_agrees_when_only_counted_reservation_changes` | +| New reason metadata, exception notes and the complete refusal denominator retain their integrity | `test_zero_dual_composition_refusal_notes_preserve_reason_and_weight`; `test_every_unsupported_reason_has_a_refusal_case`; `test_every_retained_refusal_has_an_executed_named_witness` | + +Only named Track B test modules are run locally. Tier-policy and +birth-evidence checks remain with CI. The conformance report is regenerated +after the final rule, witness and report-input edits. diff --git a/docs/design/track_b_r2_ret_ledger.md b/docs/design/track_b_r2_ret_ledger.md index 2200064b8..2d455ccc8 100644 --- a/docs/design/track_b_r2_ret_ledger.md +++ b/docs/design/track_b_r2_ret_ledger.md @@ -1888,6 +1888,10 @@ no FRA date for the survivor. | NH or auxiliary FRA declaration has no overlap with the supplied G cohort interval | Act 203(f)(8)(E), (9); 20 CFR 404.430(b), 404.434(c); RS 02501.021B.3 and 00615.003/.010 | A birthday inside the cohort consistent with the declaration; all such intersections remain accepted | | An auxiliary's cohort disagrees with that same person's own-benefit cohort, even when FRA 0 fits each cohort separately | Act 202(q)(6); RS 00615.003/.010 and G's existing single-person cohort-consistency contract | Different people or different declared cohort conventions; neither is admitted for these two fields | | FRA is declared after a snapshot carrying that person's positive own delayed credits | Act 202(w)(2); RS 00615.692 | Only age-reduction months or inherited deceased-worker credits were supplied; these do not constrain the person's current FRA | +| G and RET declare opposite NH entitlement for the same person and month | Act 202(a), 203(b); G's record kind and `WORKER_NOT_ENTITLED` state entitlement independently of cash, while RET `entitled_months` states the same month's entitlement | Different people or months, or confusion between zero payment and no entitlement; neither applies to these fields | +| One person's known SSA cohort differs across monthly contexts or across explicit and own-benefit cohort fields | Act 202(q)(6); RS 00615.003/.010; G's existing single-person cohort-consistency contract | Different people or cohort conventions; neither is admitted for one identifier. A missing cohort remains unknown | +| RET declares an entitled spouse whose own RIB/DIB PIA is at least half the NH's PIA | Act 202(b)(1)(D), (c)(1)(D); RS 00202.005; G's spouse entitlement test uses the declared PIAs without an own-MBA calculation | No own entitlement that month, a different person's benefit, or a different PIA basis; none matches these fields | +| An entitled NH's original RET rate, or a DIB NH's gross RET rate, differs from G's declared PIA | RS 02501.110's 100%-of-PIA NH original share; Social Security Bulletin 75(3), Table 2's DIB worker benefit at 100% of PIA; G's direct PIA assignments | An unentitled month or a different person/month/rate concept; original rates for unentitled months remain valid without this constraint | ### Examples and executed invariants @@ -1946,3 +1950,95 @@ check differences and actual deduction months so later milestones can implement their own cited rules. Axiom differentials remain diagnostics after a pinned rule exists; this build's verification remains statutory conformance within the stated supported scope. + +## PR 563 round 4: consistent entitlement and monthly identity + +Verification class remains statutory conformance on invented record-years +and captured rules. No population, behavioral or forecast claim is added. + +G and RET declare the same NH's entitlement in each supplied month. The +shared G helper `_declared_worker_entitled` resolves this from the record +kind and `WORKER_NOT_ENTITLED`: a retirement record ordinarily has RIB, a +disability record has DIB even without a retirement `OwnBenefit`, and a +survivor record has no living NH payment. Zero money does not mean absence +of entitlement. Before any G computation, `apply_ret_year` compares that +declaration with RET `entitled_months` for every context in both directions +(Act 202(a), 203(b)). Administrative finality and other coverage conditions +cannot turn a contradiction into a counted refusal. + +`RecordYear` also gathers known cohorts by person over every monthly +context. It reads the NH's `worker_birth_year` and worker own-benefit cohort, +and each auxiliary's `birth_year` and `own_benefit.birth_year`. Distinct +known cohorts for one identity error before coverage. Missing fields and +cohorts declared only in some months remain valid. The implementation +uses the same known-cohort identity rule as G's household check +(Act 202(q)(6); RS 00615.003/.010). The existing per-month RIB-FRA and +own-credit checks remain in place. + +### Audit of the held-refusal loop + +The former NH entitlement check depended only on declarations and now +runs in a separate pass before any G computation. The audit also found a +spouse subcase of the auxiliary entitlement check: own PIA at least half +the NH PIA rules out spouse entitlement without computing own MBA. That +subcase uses G's canonical `_is_entitled` predicate before any held +refusal. At PIA/MAX $0/$0 with own PIA $0, and at $4/$6 with own PIA $2, +administrative finality previously changed this contradiction from an +input error into one refused row of weight 7; it now produces zero rows. +This also covers spouse-with-child-in-care and divorced-spouse roles and +both own RIB and DIB. A spouse with no own entitlement is not subject to +that threshold, so matching zero-cash entitlement remains valid. + +The NH original-rate comparison also reads a declaration directly: +G supplies `state.pia` as the original rate. The DIB NH gross rate is the +same direct PIA assignment. Both validate before a held refusal, only in +entitled months. RS 02501.110 states that the NH original benefit is 100% +of PIA; the captured Bulletin Table 2 shows the DIB worker benefit at +100% of PIA before and after the maximum. An original rate $.10 against +PIA $0, or $4.10 against PIA $4, is therefore an input error even with +administrative finality. A DIB gross rate $3 against PIA $4 is likewise +an input error. Unentitled-month original rates retain their existing +freedom because the original post-G comparison did not constrain them. + +Maximum binding requires statutory original and payable rates. Other +auxiliary entitlement branches need computed own MBA and, for parents, +the original-benefit threshold. Retirement NH gross and auxiliary gross +and original rates need G's monetary computation. Those checks stay after successful G +computation. Record-kind, monthly roster, +role/type, cohort, FRA and explicit dual-entitlement consistency checks +already run in `RecordYear` before coverage. R1 year availability remains +an input requirement checked before re-raising a held G refusal. + +### Examples and executed invariants + +An NH declared not entitled by G but entitled in RET month 1 is invalid at +PIA/MAX $0/$0 and $4/$6. The reverse declaration is invalid as well. +Adding administrative finality previously produced one refused row of +weight 7; both forms now raise `InvalidFamilyInput` and produce zero rows. +The tests extend both directions through every month and retain unheld +controls and matching zero-cash entitlements. + +A cohort 1950 in January and 1951 in February is contradictory whether +the facts occur on the NH, an auxiliary, or move between explicit and +own-benefit fields. Held and unheld, zero and positive cases all error +with zero rows. The review's mixed auxiliary case previously paid $2; +it now errors. Same-cohort and missing-cohort controls still compute or +retain their independently declared coverage refusal and weight. + +| Invariant | Executing test | +| --- | --- | +| No held coverage condition masks an NH entitlement contradiction; no outcome row is constructed | `test_nh_entitlement_contradiction_never_becomes_held_refusal`; Hypothesis `test_no_held_coverage_condition_masks_nh_contradiction` | +| No held coverage condition masks a spouse's disqualifying declared own PIA | `test_declared_spouse_pia_disqualification_precedes_held_refusal`; Hypothesis `test_no_held_coverage_condition_masks_spouse_pia_contradiction` | +| A spouse's own PIA strictly below half the NH PIA retains eligibility, and absence of own entitlement retains valid zero cash | `test_strictly_lower_spouse_own_pia_preserves_eligible_entitlement`; `test_spouse_without_own_entitlement_keeps_zero_and_positive_payments`; Hypothesis `test_own_pia_strictly_below_half_never_triggers_spouse_preflight` | +| Entitled NH original rates and DIB gross rates agree with their directly declared PIA before any held refusal | `test_declared_nh_original_pia_mismatch_precedes_held_refusal`; `test_declared_dib_nh_gross_pia_mismatch_precedes_held_refusal`; Hypothesis `test_no_held_coverage_condition_masks_direct_nh_rate_contradiction` | +| Matching direct NH rates and unentitled-month original-rate declarations retain their existing outcomes | `test_matching_direct_nh_rates_keep_zero_and_positive_payments`; `test_unentitled_nh_original_share_is_not_a_payable_rate_declaration`; Hypothesis `test_direct_nh_rate_preflight_preserves_every_matching_declaration` | +| All monthly NH declarations validate before the first G computation | `test_later_nh_contradiction_precedes_every_g_computation` | +| Record kind determines DIB entitlement even without an own RIB declaration | `test_disability_nh_entitlement_comes_from_record_kind` | +| One person has one known cohort over every month and field pair, independent of context order | `test_two_known_monthly_cohorts_are_input_error_before_any_refusal`; Hypothesis `test_one_cohort_across_every_month_and_field_pair` | +| Unentitled NHs retain their declared cohort identity | `test_unclaimed_nh_keeps_cross_month_worker_cohort_identity` | +| One known cohort with gaps and consistent cohorts remain valid | `test_same_and_missing_monthly_cohorts_remain_valid`; Hypothesis `test_one_known_cohort_with_gaps_never_errors` | + +The premise table above records each new fact-pattern input error and its +falsifier. This round introduces no additional RET statutory reading. +The A.1/A.2 G composition refusal and its two source quotations are +recorded in the G design note. Earlier statutory readings stand. diff --git a/scripts/track_b_g_conformance_report.py b/scripts/track_b_g_conformance_report.py index 55cc6ffba..b52b1853d 100644 --- a/scripts/track_b_g_conformance_report.py +++ b/scripts/track_b_g_conformance_report.py @@ -282,6 +282,31 @@ def _deduction_witness(reason, *, age_worker=False): ) +def _zero_dual_composition_witness(): + """GN 02603.050 A.1/A.2 disagree on C's $175 versus $200 rate.""" + return g.family_benefits_after_deductions( + _retired(pia=400, maximum=600), + ( + g.Beneficiary( + "b", g.Role.SPOUSE, birth_year=1960, reduction_months=36 + ), + g.Beneficiary("c", g.Role.CHILD), + g.Beneficiary( + "z", + g.Role.CHILD, + own_benefit=g.OwnBenefit(g.OwnBenefitKind.DISABILITY, F(400)), + ), + ), + payment_month=NOW, + params=PARAMS, + deductions={ + "b": g.BenefitDeduction(g.DeductionReason.OWN_EARNINGS_TEST) + }, + households={}, + standalone=True, + ) + + def _operational_savings_witness(*, membership): month = g.YearMonth(2026, 1) guard = g.SavingsClauseGuard(month, earlier_months_unknown=False) @@ -593,6 +618,10 @@ def multiple_records(child): g.DeductionReason.OWN_EARNINGS_TEST, age_worker=True ), ), + reasons.SOLE_FULL_DEDUCTION_ZERO_DUAL_COMPOSITION: ( + "GN 02603.050 A.1 and A.2 compose differently: child 175 versus 200", + _zero_dual_composition_witness, + ), reasons.WIDOW_DRC_SAVINGS_CLAUSE: ( "May 1978 survivor protected from widow deceased-worker DRCs", lambda: _family(_survivor(widow_drc_savings_clause=True)), diff --git a/src/populace_dynamics/track_b/gross_benefits.py b/src/populace_dynamics/track_b/gross_benefits.py index 90e1d203b..3695c20f5 100644 --- a/src/populace_dynamics/track_b/gross_benefits.py +++ b/src/populace_dynamics/track_b/gross_benefits.py @@ -13,6 +13,10 @@ input error and never changes the family-maximum computation. Payable plus NH reservation must therefore be strictly below the original-benefit upper bound, including before a held coverage refusal. +Outside-maximum beneficiaries and their events do not enter governed +readjustment decisions (203(a)(3)(C); GN 02603.020B). Their own deductions +still apply. GN 02603.050A.1 and A.2's sole-full and zero-dual exceptions +have a named composition refusal only when their readings change cash. Max's ruling d515 (2026-09-28) adopted §10 question 9's default: a Python reference now, with Axiom differential checks as diagnostics once a pinned rule exists. At this module's creation rulespec-us had no 42 U.S.C. 403 @@ -468,6 +472,9 @@ class UnsupportedReason(Enum): #: Deferred coverage: no NH-reservation/age-reduction allocation #: procedure has been derived; no competing authoritative algorithms. DEDUCTION_AGE_WORK_INTERACTION = "deduction_age_work_interaction" + SOLE_FULL_DEDUCTION_ZERO_DUAL_COMPOSITION = ( + "sole_full_deduction_zero_dual_composition" + ) @_sealed_refusal(UnsupportedReason) @@ -3515,6 +3522,19 @@ def _refuse_widow_drc_savings_clause( ) +def _declared_worker_entitled(state: RecordState) -> bool: + """Resolve NH entitlement from the record kind and declared condition. + + A survivor record has no living NH benefit. A disability record has + DIB; a retirement record has RIB unless WORKER_NOT_ENTITLED is declared. + This identity is knowable before any statutory coverage refusal. + """ + return state.kind is FamilyKind.DISABILITY or ( + state.kind is FamilyKind.RETIREMENT + and RecordCondition.WORKER_NOT_ENTITLED not in state.conditions + ) + + def _family_benefits( state: RecordState, beneficiaries: Sequence[Beneficiary], @@ -3560,12 +3580,13 @@ def _family_benefits( parent_count = _entitled_parent_count(state, beneficiaries, params) life_case = state.kind is not FamilyKind.SURVIVOR and not ieds worker_benefit = None - if state.kind is FamilyKind.RETIREMENT and not ieds: - worker_benefit = _own_monthly_benefit_validated(state.worker, params)[ - 1 - ] - elif state.kind is FamilyKind.DISABILITY: - worker_benefit = state.pia + if _declared_worker_entitled(state): + if state.kind is FamilyKind.RETIREMENT: + worker_benefit = _own_monthly_benefit_validated( + state.worker, params + )[1] + else: + worker_benefit = state.pia rows: list[_Row] = [] for beneficiary in beneficiaries: @@ -3953,8 +3974,8 @@ def family_benefits_after_deductions( Mappings preserve associations; beneficiaries is an ordered tuple/list. Households are monthly membership IDs, required for all beneficiaries - whenever an own-work event is estimated. Empty deductions returns G's - ordinary result. ``worker_deductions`` reserves NH work deductions; + whenever an own-work event is estimated. No events or NH reservations + returns G's ordinary result. ``worker_deductions`` reserves NH deductions; these never release room (GN 02603.040B; RS 02501.155B.3.c). Concurrent NH reservations and auxiliary age reductions have deferred allocation coverage and refuse as ``deduction_age_work_interaction``; @@ -4045,16 +4066,8 @@ def _after_deductions( for bid, event in deductions.items() if event.reason is not DeductionReason.DUAL_ENTITLEMENT } - if not events: + if not events and not any(worker_deductions.values()): return baseline - if any(worker_deductions.values()) and any( - row.age_reduction_factor != 1 for row in baseline.beneficiaries - ): - raise _computed( - FamilyConfigurationUnsupported, - UnsupportedReason.DEDUCTION_AGE_WORK_INTERACTION, - "Concurrent NH reservations and age reductions have deferred allocation coverage", - ) subject = [ row for row in baseline.beneficiaries if row.subject_to_family_maximum ] @@ -4066,8 +4079,6 @@ def _after_deductions( dual = { row.beneficiary_id for row in subject if row.own_benefit is not None } - permanent = dual | {bid for bid in explicit if events[bid].permanent} - members = {b.beneficiary_id: b for b in beneficiaries} reserve = sum( ( worker_deductions.get(row.beneficiary_id, Fraction(0)) @@ -4075,17 +4086,103 @@ def _after_deductions( ), Fraction(0), ) + if reserve and any(row.age_reduction_factor != 1 for row in subject): + raise _computed( + FamilyConfigurationUnsupported, + UnsupportedReason.DEDUCTION_AGE_WORK_INTERACTION, + "Concurrent NH reservations and age reductions have deferred allocation coverage", + ) # GN 02603.050A.1 expressly overrides the C formula for one full, - # permanent deduction and no other deduction event: disregard the row. + # permanent subject deduction and no other subject deduction event. + # Act 203(a)(3)(C), GN 02603.020B: outside events affect only their cash. disregard_full = { bid for bid in explicit - if len(events) == 1 + if len(explicit) == 1 and not dual and not reserve and events[bid].permanent and events[bid].payable == 0 } + arguments = ( + state, + beneficiaries, + payment_month, + params, + baseline, + events, + households, + worker_deductions, + ) + result = _readjust_deduction_rows(*arguments, disregard_full) + zero_dual = { + row.beneficiary_id + for row in subject + if row.beneficiary_id in dual + and row.auxiliary_payable == row.counted_against_maximum == 0 + } + if ( + len(explicit) == 1 + and zero_dual + and dual == zero_dual + and not reserve + and all( + events[bid].permanent and events[bid].payable == 0 + for bid in explicit + ) + ): + # Source conflict us:oasdi-sole-full-deduction-zero-dual-composition: + # GN 02603.050A.1's "no other deduction" can include dual entitlement + # (.040A); A.2 disregards zero dual rows regardless of other deductions. + # Neither composition is adopted when their actual payments differ. + alternative = _readjust_deduction_rows(*arguments, explicit) + alternative_rows = alternative.by_id() + if any( + row.auxiliary_payable + != alternative_rows[row.beneficiary_id].auxiliary_payable + for row in result.beneficiaries + if row.subject_to_family_maximum + ): + raise _computed( + FamilyConfigurationUnsupported, + UnsupportedReason.SOLE_FULL_DEDUCTION_ZERO_DUAL_COMPOSITION, + "GN 02603.050A.1 and A.2 do not settle how a sole full " + "permanent deduction composes with a zero-rate dual row; " + "the competing readings produce different payments", + ) + return result + + +def _readjust_deduction_rows( + state, + beneficiaries, + payment_month, + params, + baseline, + events, + households, + worker_deductions, + disregard_full, +): + """Use GN 02603.050C-D with one explicit A.1 disregard decision.""" + subject = [ + row for row in baseline.beneficiaries if row.subject_to_family_maximum + ] + explicit = { + row.beneficiary_id for row in subject if row.beneficiary_id in events + } + dual = { + row.beneficiary_id for row in subject if row.own_benefit is not None + } + permanent = dual | {bid for bid in explicit if events[bid].permanent} + members = {b.beneficiary_id: b for b in beneficiaries} + reserve = sum( + ( + worker_deductions.get(row.beneficiary_id, Fraction(0)) + for row in subject + ), + Fraction(0), + ) results = [] for old in baseline.beneficiaries: bid = old.beneficiary_id diff --git a/src/populace_dynamics/track_b/ret_ledger.py b/src/populace_dynamics/track_b/ret_ledger.py index 67f674b55..0086de01b 100644 --- a/src/populace_dynamics/track_b/ret_ledger.py +++ b/src/populace_dynamics/track_b/ret_ledger.py @@ -29,6 +29,12 @@ Applied own delayed credits establish FRA by the supplied context month; age reductions and the deceased worker's credits do not establish a survivor's current age. Contradictions error before coverage refusals. +Every known cohort for one person agrees across monthly contexts, +including record and own-benefit fields; missing cohorts add no constraint. +Declared NH entitlement and spouse eligibility under the raw own-PIA +threshold agree with RET before any G computation or held coverage refusal. +NH original benefits and DIB gross benefits copy the declared PIA directly; +those comparisons also precede G computation. Every raw month-set element must be an integer month before deduplication; malformed input raises before a coverage refusal can become an outcome. @@ -566,6 +572,19 @@ def __post_init__(self): }[self.kind] contextual_people = set() contextual_two_records = set() + cohorts: dict[str, int] = {} + + def remember_cohort(person: str, cohort: int | None) -> None: + # As in G's household check: one identity has one SSA cohort + # (402(q)(6); RS 00615.003/.010). Omission is not disagreement. + if cohort is None: + return + if person in cohorts and cohorts[person] != cohort: + raise InvalidFamilyInput( + f"{person}'s birth_year differs across monthly contexts" + ) + cohorts[person] = cohort + for month, context in self.family_months.items(): if context.state.kind is not expected_kind: raise InvalidFamilyInput("G and RET record kinds differ") @@ -601,6 +620,9 @@ def __post_init__(self): context.state.worker, context.params, ) + remember_cohort(self.nh_id, context.state.worker_birth_year) + if context.state.worker is not None: + remember_cohort(self.nh_id, context.state.worker.birth_year) for auxiliary in context.beneficiaries: _check_fra_facts( ret_people[auxiliary.beneficiary_id], @@ -610,6 +632,12 @@ def __post_init__(self): auxiliary.own_benefit, context.params, ) + remember_cohort(auxiliary.beneficiary_id, auxiliary.birth_year) + if auxiliary.own_benefit is not None: + remember_cohort( + auxiliary.beneficiary_id, + auxiliary.own_benefit.birth_year, + ) contextual_people.add(auxiliary.beneficiary_id) if auxiliary.own_benefit is not None: contextual_two_records.add(auxiliary.beneficiary_id) @@ -1142,6 +1170,49 @@ def apply_ret_year( raise InvalidFamilyInput("Use an explicit NESE proration policy") if parameters is not None and not isinstance(parameters, RETParameters): raise InvalidFamilyInput("Use R1 RETParameters") + # Entitlement is a declared fact, including a zero-rate entitlement. + # Check every context before computing any G money or holding a refusal. + if record.kind is not RecordKind.DECEASED: + nh = next( + b for b in record.beneficiaries if b.beneficiary_id == record.nh_id + ) + for month, context in record.family_months.items(): + if g._declared_worker_entitled(context.state) != ( + month in nh.entitled_months + ): + raise InvalidFamilyInput( + "G and RET NH entitlement facts differ" + ) + if month in nh.entitled_months: + # G copies these NH facts directly from the declared PIA. + # RIB gross still needs G's age/DRC computation. + if nh.original_rates[month - 1] != context.state.pia: + raise InvalidFamilyInput( + "G context does not match RET rates" + ) + if ( + record.kind is RecordKind.DISABILITY + and nh.gross_rates[month - 1] != context.state.pia + ): + raise InvalidFamilyInput( + "G context does not match RET rates" + ) + # Act 202(b)(1)(D), (c)(1)(D); RS 00202.005: spouse eligibility uses + # raw own PIA, not a computed own MBA. Other own-benefit roles need G's + # computed MBA/OB, so their entitlement comparison stays after G. + for context in record.family_months.values(): + for auxiliary in context.beneficiaries: + if ( + auxiliary.own_benefit is None + or auxiliary.role in g._SPOUSE_ROLES + ): + entitled, _ = g._is_entitled( + auxiliary, context.state.pia, None + ) + if not entitled: + raise InvalidFamilyInput( + "G and RET auxiliary entitlement facts differ" + ) # Retain the G facts needed for money-changing readjustment. A caller's # reduced rates cannot identify age reductions or dual entitlement. held_family_refusals = [] @@ -1160,18 +1231,6 @@ def apply_ret_year( held_family_refusals.append(error) continue baseline_rows = {b.beneficiary_id: b for b in baseline.beneficiaries} - if record.kind is not RecordKind.DECEASED: - nh = next( - b - for b in record.beneficiaries - if b.beneficiary_id == record.nh_id - ) - if (baseline.worker_benefit is not None) != ( - month in nh.entitled_months - ): - raise InvalidFamilyInput( - "G and RET NH entitlement facts differ" - ) if baseline.family_maximum_binding != ( month in record.family_maximum_binding_months ): diff --git a/tests/README-tiers.md b/tests/README-tiers.md index 3b0a41cc5..5d0b93d3c 100644 --- a/tests/README-tiers.md +++ b/tests/README-tiers.md @@ -39,9 +39,9 @@ pytest --collect-only -q -m oracle_policyengine | tail -1 | Tier | Tests at HEAD | |---|---:| -| `unit` | 19,858 | +| `unit` | 20,495 | | `artifact` | 4,271 | | `integration_psid` | 1,471 | | `reproduction_legacy` | 520 | | `oracle_policyengine` | 308 | -| **Total** | **26,428** | +| **Total** | **27,065** | diff --git a/tests/test_track_b_gross_benefits.py b/tests/test_track_b_gross_benefits.py index 1e126c56a..4418dd470 100644 --- a/tests/test_track_b_gross_benefits.py +++ b/tests/test_track_b_gross_benefits.py @@ -1934,6 +1934,9 @@ def _unsupported_cases(): ) ), g.UnsupportedReason.SAVINGS_CLAUSE: lambda: _savings_clause_case(), + g.UnsupportedReason.SOLE_FULL_DEDUCTION_ZERO_DUAL_COMPOSITION: ( + lambda: _zero_dual_composition_case() + ), g.UnsupportedReason.SAVINGS_CLAUSE_HISTORY_UNKNOWN: lambda: ( _guard(NOV, unknown=True).admit(_review_m2_path()[0]) ), @@ -2046,6 +2049,30 @@ def _unsupported_cases(): } +def _zero_dual_composition_case(): + return g.family_benefits_after_deductions( + _retired(400, 600), + ( + g.Beneficiary( + "B", g.Role.SPOUSE, birth_year=1960, reduction_months=36 + ), + g.Beneficiary("C", g.Role.CHILD), + g.Beneficiary( + "Z", + g.Role.CHILD, + own_benefit=g.OwnBenefit(DISABILITY, F(400)), + ), + ), + payment_month=NOW, + params=PARAMS, + deductions={ + "B": g.BenefitDeduction(g.DeductionReason.OWN_EARNINGS_TEST) + }, + households={}, + standalone=True, + ) + + def _savings_clause_case(): guard = _guard() before, after = _two_months(F("1000.10"), F(1500)) diff --git a/tests/test_track_b_gross_benefits_conformance_report.py b/tests/test_track_b_gross_benefits_conformance_report.py index 8ab0478bf..1c1ce7163 100644 --- a/tests/test_track_b_gross_benefits_conformance_report.py +++ b/tests/test_track_b_gross_benefits_conformance_report.py @@ -188,11 +188,11 @@ def test_every_retained_refusal_has_an_executed_named_witness(reason): def test_named_witness_denominator_is_separate_from_the_lattice(regenerated): witnesses = regenerated["supplemental_refusal_witnesses"] - assert len(g.UnsupportedReason) == 37 + assert len(g.UnsupportedReason) == 38 assert witnesses["denominator"] == { - "rows": 37, + "rows": 38, "supported": 0, - "refused": 37, + "refused": 38, "invalid": 0, } expected = {reason.value for reason in g.UnsupportedReason} diff --git a/tests/test_track_b_gross_benefits_fix_round_4_composition.py b/tests/test_track_b_gross_benefits_fix_round_4_composition.py new file mode 100644 index 000000000..340d00705 --- /dev/null +++ b/tests/test_track_b_gross_benefits_fix_round_4_composition.py @@ -0,0 +1,736 @@ +"""Statutory conformance: outside deductions and A.1/A.2 composition. + +Invented families only; no population, behavioral or forecast claim. +Act 203(a)(3)(C) and GN 02603.020B exclude outside beneficiaries from +readjustment. The ruled GN 02603.050A.1/A.2 conflict refuses only when +the two readings change payments. +""" + +import hashlib +from dataclasses import replace +from fractions import Fraction as F +from pathlib import Path + +import pytest +from hypothesis import Phase, assume, example, given, settings +from hypothesis import strategies as st + +from populace_dynamics.track_b import gross_benefits as g +from tests.track_b_gross_benefit_support import source_text, ssa_params +from tests.track_b_ret_ledger_support import manifest as deduction_manifest +from tests.track_b_ret_ledger_support import source_text as deduction_text + +PARAMS = ssa_params() +MONTH = g.YearMonth(2024, 1) +COMPOSITION = "sole_full_deduction_zero_dual_composition" + + +def state_and_members( + pia, maximum, *, survivor=False, children=1, reduction=36, disability=False +): + state = g.RecordState( + ( + g.FamilyKind.SURVIVOR + if survivor + else ( + g.FamilyKind.DISABILITY + if disability + else g.FamilyKind.RETIREMENT + ) + ), + pia, + maximum, + worker=( + None + if survivor or disability + else g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, pia) + ), + widow_drc_savings_clause=False, + first_dib_entitlement=g.YearMonth(2024, 1) if disability else None, + ) + members = [ + g.Beneficiary( + "B", + g.Role.WIDOW if survivor else g.Role.SPOUSE, + birth_year=1960, + reduction_months=reduction, + reduction_period_months=80 if survivor else None, + child_in_care=False if survivor else None, + ) + ] + [g.Beneficiary(f"C{i}", g.Role.CHILD) for i in range(children)] + return state, members + + +def outside_member(survivor=False): + return g.Beneficiary( + "D", + ( + g.Role.SURVIVING_DIVORCED_SPOUSE + if survivor + else g.Role.DIVORCED_SPOUSE + ), + birth_year=1962, + reduction_months=60, + reduction_period_months=84 if survivor else None, + child_in_care=False, + first_entitlement_child_in_care=None if survivor else False, + ) + + +def compute( + state, members, events, *, household=False, reverse=False, **kwargs +): + members = tuple(reversed(members)) if reverse else tuple(members) + arguments = dict( + payment_month=MONTH, + params=PARAMS, + deductions=events, + households={b.beneficiary_id: "home" for b in members}, + **kwargs, + ) + if household: + return g.household_benefits_after_deductions( + {"r": g.HouseholdRecord("nh", state, members)}, **arguments + ) + return g.family_benefits_after_deductions( + state, members, standalone=True, **arguments + ) + + +def outcome(state, members, events, **kwargs): + value = g.evaluate_family( + "invented family", 7, lambda: compute(state, members, events, **kwargs) + ) + counts = g.count_family_outcomes([value]) + assert counts.rows == 1 + assert counts.supported_weight + counts.unsupported_weight == 7 + return value + + +def family(value, household=False): + assert value.supported + counts = g.count_family_outcomes([value]) + assert counts.supported_weight == 7 + return value.benefits.records["r"] if household else value.benefits + + +def subject_payments(result): + return ( + result.worker_benefit, + { + b.beneficiary_id: (b.auxiliary_payable, b.whole_dollar_auxiliary) + for b in result.beneficiaries + if b.subject_to_family_maximum + }, + ) + + +@pytest.mark.parametrize("household", (False, True)) +@pytest.mark.parametrize("reverse", (False, True)) +def test_outside_only_event_cannot_activate_subject_nh_deduction( + household, reverse +): + state, _ = state_and_members(F(400), F(600)) + members = [g.Beneficiary(name, g.Role.CHILD) for name in ("B", "C0")] + plain = family( + outcome( + state, + members, + {}, + household=household, + worker_deductions={"B": F(10)}, + ), + household, + ) + paid = family( + outcome( + state, + members + [outside_member()], + {"D": g.BenefitDeduction(g.DeductionReason.OWN_EARNINGS_TEST)}, + household=household, + reverse=reverse, + worker_deductions={"B": F(10)}, + ), + household, + ) + assert subject_payments(plain) == subject_payments(paid) + assert plain.by_id()["B"].auxiliary_payable == 90 + assert plain.by_id()["C0"].auxiliary_payable == 100 + + +@pytest.mark.parametrize("household", (False, True)) +@given( + n=st.integers(1, 500), + share=st.sampled_from((F(0), F(1, 4), F(1, 2), F(1))), + charged=st.booleans(), +) +@example(n=1, share=F(1), charged=True) +@settings( + max_examples=6, deadline=None, phases=(Phase.explicit, Phase.generate) +) +def test_outside_independence_with_nh_only_reservations( + household, n, share, charged +): + state, _ = state_and_members(F(4 * n, 10), F(6 * n, 10)) + members = [g.Beneficiary(name, g.Role.CHILD) for name in ("B", "C0")] + gross = F(n, 10) + reserve = gross * share + plain = family( + outcome( + state, + members, + {}, + household=household, + worker_deductions={"B": reserve}, + ), + household, + ) + assert plain.by_id()["B"].auxiliary_payable == gross - reserve + assert plain.by_id()["C0"].auxiliary_payable == gross + assert plain.by_id()["B"].counted_against_maximum == gross + assert plain.by_id()["B"].reserved_work_deduction == reserve + for reverse in (False, True): + paid = family( + outcome( + state, + members + [outside_member()], + ( + { + "D": g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST + ) + } + if charged + else {} + ), + household=household, + reverse=reverse, + worker_deductions={"B": reserve}, + ), + household, + ) + assert subject_payments(paid) == subject_payments(plain) + + +@pytest.mark.parametrize("household", (False, True)) +@pytest.mark.parametrize("held", (False, True)) +def test_nh_only_acceptance_still_rejects_impossible_reservation( + household, held +): + state, _ = state_and_members(F(400), F(600)) + if held: + state = replace( + state, conditions={g.RecordCondition.ADMINISTRATIVE_FINALITY} + ) + members = [g.Beneficiary(name, g.Role.CHILD) for name in ("B", "C0")] + for outside in (False, True): + outcomes = [] + with pytest.raises(g.InvalidFamilyInput): + outcomes.append( + outcome( + state, + members + ([outside_member()] if outside else []), + ( + { + "D": g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST + ) + } + if outside + else {} + ), + household=household, + worker_deductions={"B": F(201)}, + ) + ) + assert g.count_family_outcomes(outcomes).rows == 0 + + +@pytest.mark.parametrize("household", (False, True)) +@pytest.mark.parametrize("reverse", (False, True)) +@pytest.mark.parametrize("outside_reserve", (False, True)) +def test_outside_age_and_nh_reservation_do_not_trigger_subject_coverage( + household, reverse, outside_reserve +): + state, members = state_and_members(F(400), F(600)) + if not outside_reserve: + members = [g.Beneficiary(name, g.Role.CHILD) for name in ("B", "C0")] + events = {"B": g.BenefitDeduction(g.DeductionReason.OWN_EARNINGS_TEST)} + reserve = {} if outside_reserve else {"C0": F(10)} + plain = family( + outcome( + state, + members, + events, + household=household, + worker_deductions=reserve, + ), + household, + ) + paid = family( + outcome( + state, + members + [outside_member()], + events + | {"D": g.BenefitDeduction(g.DeductionReason.OWN_EARNINGS_TEST)}, + household=household, + reverse=reverse, + worker_deductions=reserve + | ({"D": F(10)} if outside_reserve else {}), + ), + household, + ) + assert subject_payments(paid) == subject_payments(plain) + + +@pytest.mark.parametrize("household", (False, True)) +def test_subject_nh_reservation_with_subject_age_still_refuses_without_events( + household, +): + state, members = state_and_members(F(400), F(600)) + for outside in (False, True): + value = outcome( + state, + members + ([outside_member()] if outside else []), + {}, + household=household, + worker_deductions={"C0": F(10)}, + ) + assert not value.supported + assert ( + value.unsupported.reason + is g.UnsupportedReason.DEDUCTION_AGE_WORK_INTERACTION + ) + assert g.count_family_outcomes([value]).unsupported_weight == 7 + + +@pytest.mark.parametrize("pia", (F(".8"), F(400))) +@pytest.mark.parametrize("household", (False, True)) +@pytest.mark.parametrize("reverse", (False, True)) +def test_review_outside_deduction_cannot_lower_governed_child( + pia, household, reverse +): + state, members = state_and_members(pia, 3 * pia / 2) + events = {"B": g.BenefitDeduction(g.DeductionReason.OWN_EARNINGS_TEST)} + plain = family( + outcome(state, members, events, household=household), household + ) + for outside_event in (False, True): + augmented = events | ( + {"D": g.BenefitDeduction(g.DeductionReason.OWN_EARNINGS_TEST)} + if outside_event + else {} + ) + paid = family( + outcome( + state, + members + [outside_member()], + augmented, + household=household, + reverse=reverse, + ), + household, + ) + assert subject_payments(paid) == subject_payments(plain) + assert paid.worker_benefit == pia + assert paid.by_id()["B"].auxiliary_payable == 0 + assert paid.by_id()["C0"].auxiliary_payable == pia / 2 + if outside_event: + assert paid.by_id()["D"].auxiliary_payable == 0 + assert paid.by_id()["D"].deduction == ( + F(".2") if pia == F(".8") else F(130) + ) + assert paid.record_total == 3 * pia / 2 + + +@pytest.mark.parametrize("household", (False, True)) +@pytest.mark.parametrize("reverse", (False, True)) +def test_surviving_divorced_deduction_cannot_lower_governed_children( + household, reverse +): + state, members = state_and_members( + F(400), F(600), survivor=True, children=3 + ) + events = {"B": g.BenefitDeduction(g.DeductionReason.OWN_EARNINGS_TEST)} + plain = family( + outcome(state, members, events, household=household), household + ) + for charged in (False, True): + paid = family( + outcome( + state, + members + [outside_member(True)], + events + | ( + { + "D": g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST + ) + } + if charged + else {} + ), + household=household, + reverse=reverse, + ), + household, + ) + assert subject_payments(paid) == subject_payments(plain) + assert all( + paid.by_id()[f"C{i}"].auxiliary_payable == 200 for i in range(3) + ) + if charged: + assert paid.record_total == 600 + assert paid.by_id()["D"].auxiliary_payable == 0 + + +@pytest.mark.parametrize("kind", tuple(g.FamilyKind)) +@pytest.mark.parametrize("household", (False, True)) +@given( + pia=st.integers(8, 1000).map(F), + maximum_share=st.integers(6, 12).map(lambda n: F(n, 5)), + children=st.integers(1, 3), + reduction=st.integers(0, 60), + permanent=st.booleans(), + partial=st.booleans(), +) +@example( + pia=F(400), + maximum_share=F(3, 2), + children=1, + reduction=36, + permanent=True, + partial=False, +) +@example( + pia=F(400), + maximum_share=F(3, 2), + children=3, + reduction=36, + permanent=True, + partial=False, +) +@settings( + max_examples=8, deadline=None, phases=(Phase.explicit, Phase.generate) +) +def test_outside_independence_in_any_beneficiary_order( + kind, + household, + pia, + maximum_share, + children, + reduction, + permanent, + partial, +): + """Valid supported outside facts cannot alter governed payment rows. + + Invalid declarations and an outside event with its own named coverage + refusal still invalidate/refuse the complete public result by design. + """ + survivor = kind is g.FamilyKind.SURVIVOR + state, members = state_and_members( + pia, + pia * maximum_share, + survivor=survivor, + children=children, + reduction=reduction, + disability=kind is g.FamilyKind.DISABILITY, + ) + baseline = family( + outcome(state, members, {}, household=household), household + ) + gross = baseline.by_id()["B"].auxiliary_payable + assume(gross > 0) + payable = g.floor_dime(gross / 2) if partial else F(0) + events = { + "B": g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST, payable, permanent + ) + } + plain = family( + outcome(state, members, events, household=household), household + ) + outside = outside_member(survivor) + for charged in (False, True): + augmented = events | ( + { + "D": g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST, F(0), permanent + ) + } + if charged + else {} + ) + for reverse in (False, True): + paid = family( + outcome( + state, + members + [outside], + augmented, + household=household, + reverse=reverse, + ), + household, + ) + assert subject_payments(paid) == subject_payments(plain) + assert not paid.by_id()["D"].subject_to_family_maximum + + +def zero_dual(pia, name="Z"): + return g.Beneficiary( + name, + g.Role.CHILD, + own_benefit=g.OwnBenefit(g.OwnBenefitKind.DISABILITY, pia), + ) + + +def competing_payments(state, members, events, *, household=False): + """Execute A.2-first publicly and compute strict A.1 from GN .050C. + + All remaining nondeductees here are unreduced children. The strict + reading reserves B's pre-deduction age amount; A.2-first removes Z + before the ordinary public sole-full-permanent calculation. + """ + ordinary = g.family_benefits( + state, members, payment_month=MONTH, params=PARAMS, standalone=True + ) + b = ordinary.by_id()["B"] + assert b.auxiliary_payable > 0 + zero_ids = { + row.beneficiary_id + for row in ordinary.beneficiaries + if row.subject_to_family_maximum + and row.own_benefit is not None + and row.auxiliary_payable == row.counted_against_maximum == 0 + } + retained = [b for b in members if b.beneficiary_id not in zero_ids] + a2_first = family( + outcome(state, retained, events, household=household), household + ) + children = [ + row + for row in ordinary.beneficiaries + if row.role is g.Role.CHILD and row.beneficiary_id not in zero_ids + ] + total_ob = sum((row.original_benefit for row in children), F(0)) + reserve = max(F(0), b.counted_against_maximum - b.auxiliary_payable) + pool = max(F(0), ordinary.available_for_auxiliaries - reserve) + strict = { + row.beneficiary_id: ( + g.floor_dime( + min( + row.original_benefit, + row.original_benefit * pool / total_ob, + ) + ) + if ordinary.family_maximum_binding + else row.auxiliary_payable + ) + for row in children + } | {"B": F(0)} + alternative = { + bid: a2_first.by_id()[bid].auxiliary_payable for bid in strict + } + return strict, alternative + + +@pytest.mark.parametrize("pia", (F(".8"), F(400))) +@pytest.mark.parametrize("household", (False, True)) +@pytest.mark.parametrize("reverse", (False, True)) +@pytest.mark.parametrize("marker", (False, True)) +def test_review_zero_dual_composition_refuses_with_preserved_denominator( + pia, household, reverse, marker +): + state, members = state_and_members(pia, 3 * pia / 2) + members += [zero_dual(pia)] + events = {"B": g.BenefitDeduction(g.DeductionReason.OWN_EARNINGS_TEST)} + if marker: + events["Z"] = g.BenefitDeduction(g.DeductionReason.DUAL_ENTITLEMENT) + reference_events = {"B": events["B"]} + strict, alternative = competing_payments( + state, members, reference_events, household=household + ) + assert strict["C0"] == (F(".3") if pia == F(".8") else F(175)) + assert alternative["C0"] == pia / 2 + value = outcome( + state, members, events, household=household, reverse=reverse + ) + assert not value.supported + assert value.unsupported.reason.value == COMPOSITION + assert g.count_family_outcomes([value]).unsupported_weight == 7 + + +@pytest.mark.parametrize("household", (False, True)) +@given( + n=st.integers(8, 5000), + extra=st.integers(0, 10000), + reduction=st.integers(0, 60), + children=st.integers(1, 3), + zeros=st.integers(1, 3), + reverse=st.booleans(), +) +@example(n=4000, extra=2000, reduction=36, children=1, zeros=1, reverse=False) +@example(n=4000, extra=5000, reduction=36, children=1, zeros=2, reverse=True) +@example(n=4000, extra=2000, reduction=0, children=1, zeros=3, reverse=False) +@settings( + max_examples=12, deadline=None, phases=(Phase.explicit, Phase.generate) +) +def test_composition_refusal_exactly_matches_competing_payment_readings( + household, n, extra, reduction, children, zeros, reverse +): + pia, maximum = F(n, 10), F(n + extra, 10) + state, members = state_and_members( + pia, maximum, children=children, reduction=reduction + ) + members += [zero_dual(pia, f"Z{i}") for i in range(zeros)] + baseline = g.family_benefits( + state, members, payment_month=MONTH, params=PARAMS, standalone=True + ) + assume(baseline.by_id()["B"].auxiliary_payable > 0) + events = {"B": g.BenefitDeduction(g.DeductionReason.OWN_EARNINGS_TEST)} + strict, alternative = competing_payments( + state, members, events, household=household + ) + value = outcome( + state, members, events, household=household, reverse=reverse + ) + assert (not value.supported) == (strict != alternative) + if value.supported: + paid = family(value, household) + assert { + bid: paid.by_id()[bid].auxiliary_payable for bid in strict + } == strict + else: + assert value.unsupported.reason.value == COMPOSITION + assert g.count_family_outcomes([value]).unsupported_weight == 7 + + +@pytest.mark.parametrize("household", (False, True)) +@pytest.mark.parametrize("reverse", (False, True)) +@pytest.mark.parametrize( + "control", + ( + "unbound", + "unreduced", + "partial", + "temporary", + "positive_dual", + "positive_dual_with_zero", + "nh_reservation", + "two_events", + ), +) +def test_composition_valid_controls_keep_computing( + household, reverse, control +): + state, members = state_and_members( + F(400), + F(900 if control == "unbound" else 600), + reduction=0 if control in ("unreduced", "nh_reservation") else 36, + ) + z = zero_dual(F(400)) + if control == "positive_dual": + z = replace( + z, own_benefit=g.OwnBenefit(g.OwnBenefitKind.DISABILITY, F(20)) + ) + members += [z] + if control == "positive_dual_with_zero": + members += [ + replace( + z, + beneficiary_id="P", + own_benefit=g.OwnBenefit(g.OwnBenefitKind.DISABILITY, F(20)), + ) + ] + events = { + "B": g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST, + F(1) if control == "partial" else F(0), + control != "temporary", + ) + } + if control == "two_events": + events["C0"] = g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST, F(1) + ) + paid = family( + outcome( + state, + members, + events, + household=household, + reverse=reverse, + worker_deductions=( + {"C0": F(10)} if control == "nh_reservation" else {} + ), + ), + household, + ) + assert paid.by_id()["Z"].auxiliary_payable == ( + F("46.6") if control == "positive_dual" else 0 + ) + if control in ("unbound", "unreduced"): + assert paid.by_id()["C0"].auxiliary_payable == 200 + if control == "positive_dual_with_zero": + assert paid.by_id()["P"].auxiliary_payable > 0 + if control == "nh_reservation": + assert paid.by_id()["C0"].auxiliary_payable == 190 + + +@pytest.mark.parametrize("household", (False, True)) +@pytest.mark.parametrize("reverse", (False, True)) +def test_composition_agrees_when_only_counted_reservation_changes( + household, reverse +): + state, members = state_and_members(F(400), F(500), children=0) + members += [zero_dual(F(400))] + paid = family( + outcome( + state, + members, + {"B": g.BenefitDeduction(g.DeductionReason.OWN_EARNINGS_TEST)}, + household=household, + reverse=reverse, + ), + household, + ) + assert paid.family_maximum_binding + assert paid.record_total == 400 + assert paid.by_id()["B"].counted_against_maximum == 25 + assert ( + paid.by_id()["B"].auxiliary_payable + == paid.by_id()["Z"].auxiliary_payable + == 0 + ) + + +def test_composition_and_outside_rules_are_verbatim_in_hashed_captures(): + rules = { + "poms_gn_02603_020": ( + "When any auxiliary or survivor is entitled to benefits that are not subject to the family maximum; i.e., a divorced spouse or surviving divorced spouse, consider only the auxiliaries or survivors who are subject to the maximum in calculating a benefit readjustment.", + ), + "poms_gn_02603_050": ( + "If a beneficiary is subject to a full permanent deduction for any reason and no other deduction is involved for any beneficiary, disregard that beneficiary when distributing the family maximum.", + "If dual entitlement reduces a beneficiary's rate to $0.00 (technically entitled) regardless of other deductions that may apply for any other beneficiary on record disregard the dually entitled beneficiary when distributing the family maximum.", + ), + "poms_gn_02603_040": ( + "Deduction because of entitlement to a benefit on another record", + ), + } + folder = ( + Path(__file__).with_name("data") / "track_b" / "ret_ledger_sources" + ) + for source_id, quotes in rules.items(): + entry = next( + row + for row in deduction_manifest()["sources"] + if row["id"] == source_id + ) + raw = (folder / entry["file"]).read_bytes() + assert hashlib.sha256(raw).hexdigest() == entry["sha256"] + for quote in quotes: + assert quote in deduction_text(source_id) + assert "consider only the benefit actually payable" in source_text( + "poms_gn_02603_045" + ) diff --git a/tests/test_track_b_refusal_notes.py b/tests/test_track_b_refusal_notes.py index 9be2110b1..88abc7187 100644 --- a/tests/test_track_b_refusal_notes.py +++ b/tests/test_track_b_refusal_notes.py @@ -54,3 +54,25 @@ def test_missing_refusal_notes_deletion_keeps_attribute_error(layer): refusal = _outcome(layer, refused=True).unsupported with pytest.raises(AttributeError): type(refusal).__delattr__(refusal, "__notes__") + + +@settings(max_examples=10, deadline=None, derandomize=True) +@given(notes=st.lists(st.text(), min_size=1, max_size=4)) +def test_zero_dual_composition_refusal_notes_preserve_reason_and_weight(notes): + from scripts.track_b_g_conformance_report import ( + _zero_dual_composition_witness, + ) + + row = g.evaluate_family("composition", 7, _zero_dual_composition_witness) + refusal = row.unsupported + reason = g.UnsupportedReason.SOLE_FULL_DEDUCTION_ZERO_DUAL_COMPOSITION + assert refusal.reason is reason + for note in notes: + refusal.add_note(note) + assert refusal.__notes__ == notes + type(refusal).__delattr__(refusal, "__notes__") + assert not hasattr(refusal, "__notes__") + counts = g.count_family_outcomes((row,)) + assert counts.rows == counts.unsupported_rows == 1 + assert counts.weight == counts.unsupported_weight == 7 + assert counts.unsupported_by_reason == {reason: (1, 7)} diff --git a/tests/test_track_b_ret_ledger_fix_round_4.py b/tests/test_track_b_ret_ledger_fix_round_4.py new file mode 100644 index 000000000..50ad3adfd --- /dev/null +++ b/tests/test_track_b_ret_ledger_fix_round_4.py @@ -0,0 +1,970 @@ +"""RET round 4: statutory conformance on invented declarations only. + +Contradictory entitlement or one person with two known SSA cohorts is an +input error before coverage, with no outcome row. Missing cohorts remain +valid. No population, behavioral, or forecast claim is admitted. +""" + +from __future__ import annotations + +import hashlib +import html +import json +import re +from dataclasses import replace +from fractions import Fraction as F + +import pytest +from hypothesis import example, given, settings +from hypothesis import strategies as st + +from populace_dynamics.track_b import gross_benefits as g +from populace_dynamics.track_b import ret_ledger as r +from populace_dynamics.track_b.ret_grace import BenefitType as T +from populace_dynamics.track_b.ret_params import load_ret_parameters +from tests.track_b_gross_benefit_support import ( + SOURCES, + manifest, + source_text, + ssa_params, +) + +PARAMS = load_ret_parameters() +HELD_CONDITIONS = ( + g.RecordCondition.ADMINISTRATIVE_FINALITY, + g.RecordCondition.NON_AIME_FORMULA_PIA, + g.RecordCondition.WORKERS_COMPENSATION_OFFSET, + "fiscal_year", + "short_taxable_year", + "foreign_work", + "vocational_rehabilitation_refusal", + r.SuspensionMethod.PRORATED, + r.SuspensionMethod.DEFERRED, + r.SuspensionMethod.PROTEST_PARTIAL, +) + + +def _person(key, kind, money, months, *, entitled=True): + return r.RETBeneficiary( + key, + (kind,) * 12, + set(months) if entitled else (), + tuple( + F(money) if entitled and m in months else F(0) + for m in range(1, 13) + ), + (F(money),) * 12, + fra_month=0, + ) + + +def _entitlement_case( + month, money, ret_entitled, held=None, *, matching=False +): + g_entitled = ret_entitled if matching else not ret_entitled + conditions = {held} if isinstance(held, g.RecordCondition) else set() + if not g_entitled: + conditions.add(g.RecordCondition.WORKER_NOT_ENTITLED) + state = g.RecordState( + g.FamilyKind.RETIREMENT, + F(money), + F(3 * money, 2), + worker=( + g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, F(money)) + if g_entitled + else None + ), + worker_birth_year=1950, + conditions=conditions, + ) + return r.RecordYear( + 2024, + "nh", + beneficiaries=( + _person("nh", T.RIB, money, {month}, entitled=ret_entitled), + ), + family_months={month: r.RETFamilyMonth(state, (), ssa_params(), {})}, + **( + {held: True} + if isinstance(held, str) + else ( + {"suspension_method": held} + if isinstance(held, r.SuspensionMethod) + else {} + ) + ), + ) + + +def _expect_no_row(compute, match): + outcomes = [] + with pytest.raises(g.InvalidFamilyInput, match=match): + outcomes.append(r.evaluate_ret("contradiction", 7, compute)) + denominator = r.count_ret_outcomes(outcomes) + assert (denominator.rows, denominator.weight) == (0, 0) + assert g.count_family_outcomes(outcomes).rows == 0 + + +@pytest.mark.parametrize("month", range(1, 13)) +@pytest.mark.parametrize("money", [0, 4]) +@pytest.mark.parametrize("ret_entitled", [False, True]) +@pytest.mark.parametrize( + "held", [None, g.RecordCondition.ADMINISTRATIVE_FINALITY] +) +def test_nh_entitlement_contradiction_never_becomes_held_refusal( + month, money, ret_entitled, held +): + _expect_no_row( + lambda: r.apply_ret_year( + _entitlement_case(month, money, ret_entitled, held), PARAMS + ), + "G and RET NH entitlement facts differ", + ) + + +@pytest.mark.parametrize("ret_entitled", [False, True]) +@pytest.mark.parametrize("money", [0, 4]) +@pytest.mark.parametrize("held", [None, *HELD_CONDITIONS]) +def test_matching_nh_entitlement_preserves_computation_or_counted_refusal( + ret_entitled, money, held +): + outcome = r.evaluate_ret( + "consistent", + 7, + lambda: r.apply_ret_year( + _entitlement_case(1, money, ret_entitled, held, matching=True), + PARAMS, + ), + ) + denominator = r.count_ret_outcomes([outcome]) + assert (denominator.rows, denominator.weight) == (1, 7) + assert outcome.supported == (held is None) + assert denominator.unsupported_weight == (0 if held is None else 7) + if held is None: + assert sum(row.payment for row in outcome.ledger.months) == ( + money if ret_entitled else 0 + ) + + +@settings(max_examples=70, deadline=None) +@given( + month=st.integers(1, 12), + money=st.integers(0, 1000), + ret_entitled=st.booleans(), + held=st.sampled_from(HELD_CONDITIONS), +) +@example( + month=1, + money=0, + ret_entitled=False, + held=g.RecordCondition.ADMINISTRATIVE_FINALITY, +) +@example( + month=12, + money=4, + ret_entitled=True, + held=g.RecordCondition.ADMINISTRATIVE_FINALITY, +) +def test_no_held_coverage_condition_masks_nh_contradiction( + month, money, ret_entitled, held +): + for condition in (None, held): + _expect_no_row( + lambda condition=condition: r.apply_ret_year( + _entitlement_case(month, money, ret_entitled, condition), + PARAMS, + ), + "G and RET NH entitlement facts differ", + ) + + +@pytest.mark.parametrize("ret_entitled", [False, True]) +def test_later_nh_contradiction_precedes_every_g_computation( + monkeypatch, ret_entitled +): + first = _entitlement_case( + 1, + 4, + ret_entitled, + g.RecordCondition.ADMINISTRATIVE_FINALITY, + matching=True, + ) + last = _entitlement_case(12, 4, ret_entitled) + case = replace( + first, + beneficiaries=( + _person("nh", T.RIB, 4, {1, 12}, entitled=ret_entitled), + ), + family_months={**first.family_months, **last.family_months}, + ) + calls = [] + + def unexpected(*args, **kwargs): + calls.append(args) + pytest.fail("G computation ran before declared NH validation") + + monkeypatch.setattr(g, "_family_benefits_validated", unexpected) + _expect_no_row( + lambda: r.apply_ret_year(case, PARAMS), + "G and RET NH entitlement facts differ", + ) + assert calls == [] + + +@pytest.mark.parametrize("money", [0, 4]) +def test_disability_nh_entitlement_comes_from_record_kind(money): + state = g.RecordState(g.FamilyKind.DISABILITY, F(money), F(money)) + record = r.RecordYear( + 2024, + "nh", + r.RecordKind.DISABILITY, + (_person("nh", T.DIB, money, {1}),), + family_months={1: r.RETFamilyMonth(state, (), ssa_params(), {})}, + ) + outcome = r.evaluate_ret( + "dib", 7, lambda: r.apply_ret_year(record, PARAMS) + ) + assert outcome.supported + assert r.count_ret_outcomes([outcome]).supported_weight == 7 + assert sum(row.payment for row in outcome.ledger.months) == money + + +def _cohort_case( + nh, + fields, + years, + *, + months=(1, 2), + money=1, + held="none", + reverse=False, + unclaimed=False, +): + key = "nh" if nh else "w" + contexts = {} + entries = list(zip(months, fields, years, strict=True)) + if reverse: + entries.reverse() + for month, field, cohort in entries: + own = g.OwnBenefit( + g.OwnBenefitKind.OLD_AGE if nh else g.OwnBenefitKind.DISABILITY, + F(money if nh else 0), + birth_year=cohort if field == "own" else None, + ) + conditions = ( + {g.RecordCondition.ADMINISTRATIVE_FINALITY} + if held == "g" + else set() + ) + if unclaimed: + conditions.add(g.RecordCondition.WORKER_NOT_ENTITLED) + state = g.RecordState( + g.FamilyKind.RETIREMENT if nh else g.FamilyKind.SURVIVOR, + F(money if nh else 4 * money), + F(money if nh else 4 * money), + worker=own if nh and not unclaimed else None, + worker_birth_year=cohort if nh and field == "record" else None, + conditions=conditions, + widow_drc_savings_clause=False, + ) + members = ( + () + if nh + else ( + g.Beneficiary( + key, + g.Role.CHILD, + birth_year=cohort if field == "beneficiary" else None, + own_benefit=own if field == "own" else None, + ), + ) + ) + contexts[month] = r.RETFamilyMonth( + state, members, ssa_params(), {} if nh else {key: "h"} + ) + return r.RecordYear( + 2024, + "nh", + r.RecordKind.RETIREMENT if nh else r.RecordKind.DECEASED, + ( + replace( + _person( + key, + T.RIB if nh else T.CHILD, + money if nh else 3 * money, + set(months), + entitled=not unclaimed, + ), + original_rates=(F(money if nh else 3 * money),) * 12, + ), + ), + fiscal_year=held == "ret", + family_months=contexts, + ) + + +@pytest.mark.parametrize("held", [False, True]) +@pytest.mark.parametrize("field", ["birth", "own", "mixed"]) +def test_review_widow_cross_month_probe_has_no_row(field, held): + def compute(): + contexts = {} + for month, cohort in ((1, 1950), (2, 1951)): + is_own = field == "own" or (field == "mixed" and month == 1) + own = g.OwnBenefit( + g.OwnBenefitKind.OLD_AGE, + F(0), + birth_year=cohort if is_own else None, + ) + state = g.RecordState( + g.FamilyKind.SURVIVOR, + F(1), + F(1), + widow_drc_savings_clause=False, + ) + member = g.Beneficiary( + "w", + g.Role.WIDOW, + birth_year=None if is_own else cohort, + own_benefit=own if is_own else None, + ) + contexts[month] = r.RETFamilyMonth( + state, (member,), ssa_params(), {"w": "h"} + ) + return r.apply_ret_year( + r.RecordYear( + 2024, + "nh", + r.RecordKind.DECEASED, + (_person("w", T.WIDOW, 1, {1, 2}),), + fiscal_year=held, + family_months=contexts, + ), + PARAMS, + ) + + _expect_no_row(compute, "birth_year differs across monthly contexts") + + +FIELD_PAIRS = ( + (False, ("beneficiary", "beneficiary")), + (False, ("own", "own")), + (False, ("beneficiary", "own")), + (False, ("own", "beneficiary")), + (True, ("record", "record")), + (True, ("own", "own")), + (True, ("record", "own")), + (True, ("own", "record")), +) + + +@pytest.mark.parametrize("nh,fields", FIELD_PAIRS) +@pytest.mark.parametrize("money", [0, 1]) +@pytest.mark.parametrize("held", ["none", "g", "ret"]) +@pytest.mark.parametrize("reverse", [False, True]) +def test_two_known_monthly_cohorts_are_input_error_before_any_refusal( + nh, fields, money, held, reverse +): + _expect_no_row( + lambda: r.apply_ret_year( + _cohort_case( + nh, + fields, + (1950, 1951), + money=money, + held=held, + reverse=reverse, + ), + PARAMS, + ), + "birth_year differs across monthly contexts", + ) + + +@pytest.mark.parametrize("held", ["none", "g", "ret"]) +def test_unclaimed_nh_keeps_cross_month_worker_cohort_identity(held): + _expect_no_row( + lambda: r.apply_ret_year( + _cohort_case( + True, + ("record", "record"), + (1950, 1951), + money=0, + held=held, + unclaimed=True, + ), + PARAMS, + ), + "birth_year differs across monthly contexts", + ) + + +@pytest.mark.parametrize("nh,fields", FIELD_PAIRS) +@pytest.mark.parametrize( + "years", [(1950, 1950), (1950, None), (None, 1950), (None, None)] +) +@pytest.mark.parametrize("money", [0, 1]) +@pytest.mark.parametrize("held", ["none", "g", "ret"]) +def test_same_and_missing_monthly_cohorts_remain_valid( + nh, fields, years, money, held +): + outcome = r.evaluate_ret( + "valid-cohort", + 7, + lambda: r.apply_ret_year( + _cohort_case( + nh, + fields, + years, + money=money, + held=held, + ), + PARAMS, + ), + ) + denominator = r.count_ret_outcomes([outcome]) + assert (denominator.rows, denominator.weight) == (1, 7) + assert outcome.supported == (held == "none") + assert denominator.unsupported_weight == (0 if held == "none" else 7) + if held == "none": + assert sum(row.payment for row in outcome.ledger.months) == ( + 2 * money if nh else 6 * money + ) + + +@settings(max_examples=100, deadline=None) +@given( + identity=st.sampled_from(FIELD_PAIRS), + months=st.lists(st.integers(1, 12), min_size=2, max_size=2, unique=True), + cohorts=st.lists( + st.integers(1930, 1956), min_size=2, max_size=2, unique=True + ), + money=st.integers(0, 100), + held=st.sampled_from(("none", "g", "ret")), + unclaimed=st.booleans(), +) +@example( + identity=(False, ("own", "own")), + months=[1, 2], + cohorts=[1950, 1951], + money=1, + held="ret", + unclaimed=False, +) +@example( + identity=(True, ("record", "record")), + months=[1, 12], + cohorts=[1950, 1951], + money=0, + held="g", + unclaimed=True, +) +def test_one_cohort_across_every_month_and_field_pair( + identity, months, cohorts, money, held, unclaimed +): + nh, fields = identity + unclaimed = nh and unclaimed + if unclaimed: + fields = ("record", "record") + for reverse in (False, True): + _expect_no_row( + lambda reverse=reverse: r.apply_ret_year( + _cohort_case( + nh, + fields, + cohorts, + months=months, + money=money, + held=held, + reverse=reverse, + unclaimed=unclaimed, + ), + PARAMS, + ), + "birth_year differs across monthly contexts", + ) + + +@settings(max_examples=70, deadline=None) +@given( + nh=st.booleans(), + cohort=st.integers(1930, 1956), + months=st.lists(st.integers(1, 12), min_size=2, max_size=12, unique=True), + data=st.data(), +) +def test_one_known_cohort_with_gaps_never_errors(nh, cohort, months, data): + options = ("record", "own") if nh else ("beneficiary", "own") + fields = tuple(data.draw(st.sampled_from(options)) for _ in months) + known_index = data.draw(st.integers(0, len(months) - 1)) + years = tuple( + cohort if index == known_index else None + for index in range(len(months)) + ) + result = r.evaluate_ret( + "gapped-cohort", + 7, + lambda: r.apply_ret_year( + _cohort_case( + nh, + fields, + years, + months=months, + money=1, + ), + PARAMS, + ), + ) + assert result.supported + assert r.count_ret_outcomes([result]).supported_weight == 7 + assert sum(row.payment for row in result.ledger.months) == ( + len(months) if nh else 3 * len(months) + ) + + +SPOUSE_ROLES = ( + g.Role.SPOUSE, + g.Role.SPOUSE_CHILD_IN_CARE, + g.Role.DIVORCED_SPOUSE, +) + + +def _spouse_entitlement_case( + role, + money, + *, + month=1, + held=None, + reverse=False, + own_kind=g.OwnBenefitKind.OLD_AGE, + own_amount=None, + own_present=True, +): + """Own PIA settles spouse eligibility before any monthly rate math.""" + amount = F(money, 2) if own_amount is None else F(own_amount) + conditions = {held} if isinstance(held, g.RecordCondition) else () + state = g.RecordState( + g.FamilyKind.RETIREMENT, + F(money), + F(3 * money, 2), + worker=g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, F(money)), + conditions=conditions, + ) + own = g.OwnBenefit(own_kind, amount) if own_present else None + spouse = g.Beneficiary( + "s", + role, + own_benefit=own, + own_benefit_first=True if own_present else None, + **( + {"child_in_care": False, "first_entitlement_child_in_care": False} + if role is g.Role.DIVORCED_SPOUSE + else {} + ), + ) + spouse_rate = max(F(0), F(money, 2) - (amount if own_present else 0)) + people = ( + replace(_person("nh", T.RIB, money, {month}), fra_month=None), + replace( + _person( + "s", + ( + T.DIVORCED_SPOUSE + if role is g.Role.DIVORCED_SPOUSE + else T.SPOUSE + ), + spouse_rate, + {month}, + ), + original_rates=(F(money, 2),) * 12, + fra_month=None, + ), + ) + return r.RecordYear( + 2024, + "nh", + beneficiaries=people[::-1] if reverse else people, + family_months={ + month: r.RETFamilyMonth( + state, + (spouse,), + ssa_params(), + {"s": "h"}, + ) + }, + **( + {held: True} + if isinstance(held, str) + else ( + {"suspension_method": held} + if isinstance(held, r.SuspensionMethod) + else {} + ) + ), + ) + + +@pytest.mark.parametrize("role", SPOUSE_ROLES) +@pytest.mark.parametrize("own_kind", list(g.OwnBenefitKind)) +@pytest.mark.parametrize("money", [0, 4]) +@pytest.mark.parametrize( + "held", [None, g.RecordCondition.ADMINISTRATIVE_FINALITY] +) +@pytest.mark.parametrize("reverse", [False, True]) +def test_declared_spouse_pia_disqualification_precedes_held_refusal( + role, own_kind, money, held, reverse +): + _expect_no_row( + lambda: r.apply_ret_year( + _spouse_entitlement_case( + role, + money, + held=held, + reverse=reverse, + own_kind=own_kind, + ), + PARAMS, + ), + "G and RET auxiliary entitlement facts differ", + ) + + +@pytest.mark.parametrize("role", SPOUSE_ROLES) +@pytest.mark.parametrize("own_kind", list(g.OwnBenefitKind)) +@pytest.mark.parametrize( + "held", [None, g.RecordCondition.ADMINISTRATIVE_FINALITY] +) +def test_strictly_lower_spouse_own_pia_preserves_eligible_entitlement( + role, own_kind, held +): + outcome = r.evaluate_ret( + "strict", + 7, + lambda: r.apply_ret_year( + _spouse_entitlement_case( + role, 4, own_kind=own_kind, own_amount=1, held=held + ), + PARAMS, + ), + ) + denominator = r.count_ret_outcomes([outcome]) + assert (denominator.rows, denominator.weight) == (1, 7) + assert outcome.supported == (held is None) + if held is None: + assert sum(row.payment for row in outcome.ledger.months) == 5 + + +@pytest.mark.parametrize("role", SPOUSE_ROLES) +@pytest.mark.parametrize("money", [0, 4]) +def test_spouse_without_own_entitlement_keeps_zero_and_positive_payments( + role, money +): + outcome = r.evaluate_ret( + "no-own", + 7, + lambda: r.apply_ret_year( + _spouse_entitlement_case(role, money, own_present=False), PARAMS + ), + ) + assert outcome.supported + assert r.count_ret_outcomes([outcome]).supported_weight == 7 + assert sum(row.payment for row in outcome.ledger.months) == F(3 * money, 2) + + +@settings(max_examples=70, deadline=None) +@given( + role=st.sampled_from(SPOUSE_ROLES), + own_kind=st.sampled_from(list(g.OwnBenefitKind)), + scale=st.integers(0, 100), + extra=st.integers(0, 100), + month=st.integers(1, 12), + held=st.sampled_from(HELD_CONDITIONS), + reverse=st.booleans(), +) +@example( + role=g.Role.SPOUSE, + own_kind=g.OwnBenefitKind.OLD_AGE, + scale=0, + extra=0, + month=1, + held=g.RecordCondition.ADMINISTRATIVE_FINALITY, + reverse=False, +) +def test_no_held_coverage_condition_masks_spouse_pia_contradiction( + role, own_kind, scale, extra, month, held, reverse +): + for condition in (None, held): + _expect_no_row( + lambda condition=condition: r.apply_ret_year( + _spouse_entitlement_case( + role, + 4 * scale, + own_kind=own_kind, + own_amount=2 * scale + extra, + month=month, + held=condition, + reverse=reverse, + ), + PARAMS, + ), + "G and RET auxiliary entitlement facts differ", + ) + + +@settings(max_examples=45, deadline=None) +@given( + role=st.sampled_from(SPOUSE_ROLES), + own_kind=st.sampled_from(list(g.OwnBenefitKind)), + scale=st.integers(1, 100), + month=st.integers(1, 12), +) +def test_own_pia_strictly_below_half_never_triggers_spouse_preflight( + role, own_kind, scale, month +): + outcome = r.evaluate_ret( + "eligible", + 7, + lambda: r.apply_ret_year( + _spouse_entitlement_case( + role, + 4 * scale, + own_kind=own_kind, + own_amount=scale, + month=month, + ), + PARAMS, + ), + ) + assert outcome.supported + assert r.count_ret_outcomes([outcome]).supported_weight == 7 + assert sum(row.payment for row in outcome.ledger.months) == 5 * scale + + +def test_spouse_entitlement_premise_is_verbatim_and_capture_hashes_match(): + quotes = { + "ssa_act_202_215": "based on a primary insurance amount which is less than one-half of the primary insurance amount of such individual", + "poms_rs_00202_005": "not be entitled to an RIB or DIB based on a PIA which equals or exceeds one-half the PIA of the worker.", + } + for source_id, quote in quotes.items(): + entry = next(s for s in manifest()["sources"] if s["id"] == source_id) + assert ( + hashlib.sha256((SOURCES / entry["file"]).read_bytes()).hexdigest() + == entry["sha256"] + ) + assert quote in source_text(source_id) + + +def _direct_nh_rate_case(kind, pia, declared, *, month=1, held=None): + disability = kind == "dib_gross" + state = g.RecordState( + g.FamilyKind.DISABILITY if disability else g.FamilyKind.RETIREMENT, + F(pia), + F(pia) if disability else F(3 * pia, 2), + worker=( + None + if disability + else g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, F(pia)) + ), + conditions=({held} if isinstance(held, g.RecordCondition) else ()), + ) + person = replace( + _person( + "nh", + T.DIB if disability else T.RIB, + declared if disability else pia, + {month}, + ), + original_rates=(F(pia) if disability else F(declared),) * 12, + ) + return r.RecordYear( + 2024, + "nh", + r.RecordKind.DISABILITY if disability else r.RecordKind.RETIREMENT, + (person,), + family_months={month: r.RETFamilyMonth(state, (), ssa_params(), {})}, + **( + {held: True} + if isinstance(held, str) + else ( + {"suspension_method": held} + if isinstance(held, r.SuspensionMethod) + else {} + ) + ), + ) + + +@pytest.mark.parametrize("pia", [0, 4]) +@pytest.mark.parametrize("month", [1, 12]) +@pytest.mark.parametrize( + "held", [None, g.RecordCondition.ADMINISTRATIVE_FINALITY] +) +def test_declared_nh_original_pia_mismatch_precedes_held_refusal( + pia, month, held +): + _expect_no_row( + lambda: r.apply_ret_year( + _direct_nh_rate_case( + "original", + pia, + F(pia) + F(1, 10), + month=month, + held=held, + ), + PARAMS, + ), + "G context does not match RET rates", + ) + + +@pytest.mark.parametrize("gross", [0, 3]) +@pytest.mark.parametrize("month", [1, 12]) +@pytest.mark.parametrize( + "held", [None, g.RecordCondition.ADMINISTRATIVE_FINALITY] +) +def test_declared_dib_nh_gross_pia_mismatch_precedes_held_refusal( + gross, month, held +): + _expect_no_row( + lambda: r.apply_ret_year( + _direct_nh_rate_case( + "dib_gross", + 4, + gross, + month=month, + held=held, + ), + PARAMS, + ), + "G context does not match RET rates", + ) + + +@pytest.mark.parametrize("kind", ["original", "dib_gross"]) +@pytest.mark.parametrize("money", [0, 4]) +@pytest.mark.parametrize( + "held", [None, g.RecordCondition.ADMINISTRATIVE_FINALITY] +) +def test_matching_direct_nh_rates_keep_zero_and_positive_payments( + kind, money, held +): + outcome = r.evaluate_ret( + "matching-rates", + 7, + lambda: r.apply_ret_year( + _direct_nh_rate_case(kind, money, money, held=held), PARAMS + ), + ) + denominator = r.count_ret_outcomes([outcome]) + assert (denominator.rows, denominator.weight) == (1, 7) + assert outcome.supported == (held is None) + if held is None: + assert sum(row.payment for row in outcome.ledger.months) == money + + +def test_unentitled_nh_original_share_is_not_a_payable_rate_declaration(): + case = _entitlement_case(1, 4, False, matching=True) + case = replace( + case, + beneficiaries=( + replace( + case.beneficiaries[0], + original_rates=(F(5),) * 12, + ), + ), + ) + outcome = r.evaluate_ret( + "unentitled-original", 7, lambda: r.apply_ret_year(case, PARAMS) + ) + assert outcome.supported + assert r.count_ret_outcomes([outcome]).supported_weight == 7 + assert sum(row.payment for row in outcome.ledger.months) == 0 + + +@settings(max_examples=70, deadline=None) +@given( + kind=st.sampled_from(("original", "dib_gross")), + scale=st.integers(1, 100), + gap=st.integers(1, 9), + direction=st.sampled_from((-1, 1)), + month=st.integers(1, 12), + held=st.sampled_from(HELD_CONDITIONS), +) +@example( + kind="original", + scale=1, + gap=1, + direction=1, + month=1, + held=g.RecordCondition.ADMINISTRATIVE_FINALITY, +) +@example( + kind="dib_gross", + scale=1, + gap=1, + direction=-1, + month=12, + held=g.RecordCondition.ADMINISTRATIVE_FINALITY, +) +def test_no_held_coverage_condition_masks_direct_nh_rate_contradiction( + kind, scale, gap, direction, month, held +): + pia = 4 * scale + declared = F(pia) + direction * F(gap, 10) + for condition in (None, held): + _expect_no_row( + lambda condition=condition: r.apply_ret_year( + _direct_nh_rate_case( + kind, pia, declared, month=month, held=condition + ), + PARAMS, + ), + "G context does not match RET rates", + ) + + +@settings(max_examples=40, deadline=None) +@given( + kind=st.sampled_from(("original", "dib_gross")), + scale=st.integers(0, 100), + month=st.integers(1, 12), +) +def test_direct_nh_rate_preflight_preserves_every_matching_declaration( + kind, scale, month +): + outcome = r.evaluate_ret( + "valid-direct-rates", + 7, + lambda: r.apply_ret_year( + _direct_nh_rate_case( + kind, + 4 * scale, + 4 * scale, + month=month, + ), + PARAMS, + ), + ) + assert outcome.supported + assert r.count_ret_outcomes([outcome]).supported_weight == 7 + assert sum(row.payment for row in outcome.ledger.months) == 4 * scale + + +def test_direct_nh_rate_premises_are_verbatim_and_capture_hashes_match(): + source_id = "ssa_ssb_v75n3_family_maximum" + entry = next(s for s in manifest()["sources"] if s["id"] == source_id) + assert ( + hashlib.sha256((SOURCES / entry["file"]).read_bytes()).hexdigest() + == entry["sha256"] + ) + assert "100% of the worker's PIA" in source_text(source_id) + + folder = SOURCES.parent / "ret_ledger_sources" + evidence = json.loads((folder / "manifest.json").read_text()) + entry = next( + s for s in evidence["sources"] if s["id"] == "poms_rs_02501_110" + ) + raw = (folder / entry["file"]).read_bytes() + assert hashlib.sha256(raw).hexdigest() == entry["sha256"] + text = re.sub( + r"\s+", " ", html.unescape(re.sub(r"<[^>]+>", " ", raw.decode())) + ) + assert "because their original benefit is equal to 100% of the PIA" in text diff --git a/tests/tier_counts.json b/tests/tier_counts.json index 1c8aaa47b..0e47318ad 100644 --- a/tests/tier_counts.json +++ b/tests/tier_counts.json @@ -1,7 +1,7 @@ { "schema_version": 1, "counts": { - "unit": 19858, + "unit": 20495, "artifact": 4271, "integration_psid": 1471, "reproduction_legacy": 520, From a135519fbfb2a3ebf9fd9c052a4619cdcedff2ca Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 31 Oct 2026 21:08:01 -0400 Subject: [PATCH 10/17] Check only settled G facts before RET coverage refusals (#563 round 5) Sol's fourth review found that a held G refusal still masked contradictions in RIB gross, auxiliary original rates and widow eligibility. Reproducing it showed round 4's preflight had already gone too far the other way: RS 00615.754A.3's first example under administrative finality raised InvalidFamilyInput, though the capture says "the rate to the NH is protected by administrative finality and cannot be changed". A protected rate rests on another PIA, so that mismatch isn't a contradiction. A preflight now compares a fact before a held refusal only when nothing declared on the record or that beneficiary can lawfully change it. One table classifies every RecordCondition, BeneficiaryCondition and UnsupportedReason against six facts: NH original, DIB gross, RIB gross, auxiliary original, spouse raw own-PIA eligibility and other own-benefit entitlement. _check_settled_family_facts compares settled facts only, through G's own validated helpers, and catches only FamilyConfigurationUnsupported. Unsettled facts keep their refusal, one row and the weight. Settled contradictions raise with no row. The ordinary OB deduction bound follows the same table. Strict withholding of actual gross still runs after G, and no money moves. Two historical bounds carry new reasons: a declared legacy widow can exceed ordinary OB under RS 00615.010's sole-survivor alternative, so that row keeps its refusal, and an unresolved parent keeps the one-parent 82.5% bound. Nine tests under round 4's reading split into a protected case with its exact refusal, row and weight, and a settled case that keeps the input error. Co-Authored-By: Claude Opus 5.5 --- docs/design/track_b_g2_r2b_mutations.json | 1697 +++- docs/design/track_b_g2_r2b_verification.json | 7254 ++++++++++++++++- docs/design/track_b_g_gross_benefits.md | 92 +- docs/design/track_b_r2_ret_ledger.md | 309 +- .../track_b/gross_benefits.py | 532 +- src/populace_dynamics/track_b/ret_ledger.py | 175 +- tests/README-tiers.md | 4 +- ...st_track_b_gross_benefits_deduction_cap.py | 92 +- ..._gross_benefits_fix_round_4_composition.py | 64 +- tests/test_track_b_ret_ledger_fix_round_4.py | 36 +- tests/test_track_b_ret_ledger_fix_round_5.py | 1910 +++++ tests/tier_counts.json | 2 +- 12 files changed, 11963 insertions(+), 204 deletions(-) create mode 100644 tests/test_track_b_ret_ledger_fix_round_5.py diff --git a/docs/design/track_b_g2_r2b_mutations.json b/docs/design/track_b_g2_r2b_mutations.json index c3fa52227..3d90c73c3 100644 --- a/docs/design/track_b_g2_r2b_mutations.json +++ b/docs/design/track_b_g2_r2b_mutations.json @@ -2,12 +2,13 @@ "schema_version": 1, "verification_class": "statutory_conformance", "admitted_scope": "Mutation sensitivity of statutory rules on invented and captured worked cases only; no population, behavioral or forecast claim.", - "confirmed_mutation_count": 50, + "confirmed_mutation_count": 80, "counts_by_layer": { - "shared_provenance": 1, "g_deductions": 18, - "r2": 19, - "g_savings": 12 + "g_preflight": 21, + "g_savings": 12, + "r2": 28, + "shared_provenance": 1 }, "environment_contract": { "OMP_NUM_THREADS": "1", @@ -2720,6 +2721,1686 @@ "reverted": true, "final_source_sha256": "e9b01a765a7951937a7035da3ab2ef29b13dc1efa663e35e224ae558d622515b" } + }, + { + "id": "round5-differential_f1_equality", + "round": 5, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": { + "before": "if settled(\"F1\") and nh.original_rates[month - 1] != state.pia:", + "after": "if settled(\"F1\") and nh.original_rates[month - 1] == state.pia:" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "-x", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_preflight_changes_no_valid_outcome_or_refusal" + ], + "outer_command": [ + "python", + "scratch/review/round5_mutation_check.py", + "differential_f1_equality" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-mutation-differential_f1_equality/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-mutation-differential_f1_equality", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-mutation-differential_f1_equality" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_preflight_changes_no_valid_outcome_or_refusal" + ], + "log": { + "path": "scratch/review/round5-mutation-differential_f1_equality.log", + "sha256": "0330f494aca44f0ebdc67c8670a8a2a30b35ed06ef78b3d7aaa2a67a04559a3d", + "failure_summary": "1 failed in 271.17s (0:04:31)" + }, + "mutation_method": "One-line semantic mutation in an isolated named-source overlay; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + }, + "layer": "r2" + }, + { + "id": "round5-drop_beneficiary_finality", + "round": 5, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": "BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY: frozenset({'F4', 'F5', 'F6'})\nUnsupportedReason.ADMINISTRATIVE_FINALITY: frozenset({'F1', 'F2', 'F3', 'F4', 'F5', 'F6'})", + "after": "for _hold in (BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY, UnsupportedReason.ADMINISTRATIVE_FINALITY): _PREFLIGHT_FACT_UNSETTLERS[_hold] = frozenset()" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "-x", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_beneficiary_finality_protects_its_own_unsettled_fact" + ], + "outer_command": [ + "python", + "scratch/review/round5_mutation_check.py", + "drop_beneficiary_finality" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-mutation-drop_beneficiary_finality/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-mutation-drop_beneficiary_finality", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-mutation-drop_beneficiary_finality" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_beneficiary_finality_protects_its_own_unsettled_fact[F4]" + ], + "log": { + "path": "scratch/review/round5-mutation-drop_beneficiary_finality.log", + "sha256": "c76c7069b28fd5578f75a16eac23fd006614f8dda69df8af4acd13deca55efee", + "failure_summary": "1 failed in 19.53s" + }, + "mutation_method": "One-line semantic mutation in an isolated named-source overlay; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + }, + "layer": "g_preflight" + }, + { + "id": "round5-drop_beneficiary_widow_drc_survivor_scope", + "round": 5, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": " BeneficiaryCondition.WIDOW_DRC_SAVINGS_CLAUSE,\n", + "after": "" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "-x", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_widow_drc_condition_on_a_living_child_keeps_ob_settled" + ], + "outer_command": [ + "python", + "scratch/review/round5_mutation_check.py", + "drop_beneficiary_widow_drc_survivor_scope" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-mutation-drop_beneficiary_widow_drc_survivor_scope/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-mutation-drop_beneficiary_widow_drc_survivor_scope", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-mutation-drop_beneficiary_widow_drc_survivor_scope" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_widow_drc_condition_on_a_living_child_keeps_ob_settled[True-0]" + ], + "log": { + "path": "scratch/review/round5-mutation-drop_beneficiary_widow_drc_survivor_scope.log", + "sha256": "8a8ef510e8d082ad777c3561a88707ceea58a96d9d09f1dcbfdfc0d054b295dd", + "failure_summary": "1 failed, 2 passed in 11.74s" + }, + "mutation_method": "One-line semantic mutation in an isolated named-source overlay; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + } + }, + "layer": "g_preflight" + }, + { + "id": "round5-drop_dib_after_rib_f2", + "round": 5, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": "RecordCondition.DIB_AFTER_REDUCED_RIB: frozenset({'F2'})", + "after": "_PREFLIGHT_FACT_UNSETTLERS[RecordCondition.DIB_AFTER_REDUCED_RIB] = frozenset()" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "-x", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_lawful_dib_gross_changes_remain_counted_refusals" + ], + "outer_command": [ + "python", + "scratch/review/round5_mutation_check.py", + "drop_dib_after_rib_f2" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-mutation-drop_dib_after_rib_f2/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-mutation-drop_dib_after_rib_f2", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-mutation-drop_dib_after_rib_f2" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_lawful_dib_gross_changes_remain_counted_refusals[RecordCondition.DIB_AFTER_REDUCED_RIB-800]" + ], + "log": { + "path": "scratch/review/round5-mutation-drop_dib_after_rib_f2.log", + "sha256": "78c16f4a31f1bb93e403f07df97b75f66cbbb6b9b5d0a7ea6330da0e3378fd38", + "failure_summary": "1 failed in 19.41s" + }, + "mutation_method": "One-line semantic mutation in an isolated named-source overlay; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + }, + "layer": "g_preflight" + }, + { + "id": "round5-drop_finality_f1", + "round": 5, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": "RecordCondition.ADMINISTRATIVE_FINALITY: frozenset({'F1', 'F2', 'F3', 'F4', 'F5', 'F6'})", + "after": "_PREFLIGHT_FACT_UNSETTLERS[RecordCondition.ADMINISTRATIVE_FINALITY] -= {\"F1\"}" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "-x", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_first_administrative_finality_example_keeps_nh_rate" + ], + "outer_command": [ + "python", + "scratch/review/round5_mutation_check.py", + "drop_finality_f1" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-mutation-drop_finality_f1/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-mutation-drop_finality_f1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-mutation-drop_finality_f1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_first_administrative_finality_example_keeps_nh_rate" + ], + "log": { + "path": "scratch/review/round5-mutation-drop_finality_f1.log", + "sha256": "a0032cd62fcedfa4205a2471c92ab3cebc21800df2e89fb244569d2868f82401", + "failure_summary": "1 failed in 12.26s" + }, + "mutation_method": "One-line semantic mutation in an isolated named-source overlay; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + }, + "layer": "g_preflight" + }, + { + "id": "round5-drop_historical_child_ob_uncertainty", + "round": 5, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": "\n < FIRST_SUPPORTED_PAYMENT_MONTH", + "after": "\n < (1900, 1)" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "-x", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_child_ob_uncertainty_preserves_old_refusals_for_odd_dime_pias" + ], + "outer_command": [ + "python", + "scratch/review/round5_mutation_check.py", + "drop_historical_child_ob_uncertainty" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-mutation-drop_historical_child_ob_uncertainty/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-mutation-drop_historical_child_ob_uncertainty", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-mutation-drop_historical_child_ob_uncertainty" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_child_ob_uncertainty_preserves_old_refusals_for_odd_dime_pias" + ], + "log": { + "path": "scratch/review/round5-mutation-drop_historical_child_ob_uncertainty.log", + "sha256": "94466ac946113e91a6425c4512d5f444c9e57fead91a2acbdb8f49bb4728530b", + "failure_summary": "1 failed in 8.09s" + }, + "mutation_method": "One-line semantic mutation in an isolated named-source overlay; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "d51f5d77c7aa7cf6004392e27187ce89523151fef12148088565226f7444fb64", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + } + }, + "layer": "g_preflight" + }, + { + "id": "round5-drop_historical_wib_carryover_f6", + "round": 5, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": " and own.pia > 0", + "after": " and False" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "-x", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover" + ], + "outer_command": [ + "python", + "scratch/review/round5_mutation_check.py", + "drop_historical_wib_carryover_f6" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-mutation-drop_historical_wib_carryover_f6/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-mutation-drop_historical_wib_carryover_f6", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-mutation-drop_historical_wib_carryover_f6" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[None-4-1920]" + ], + "log": { + "path": "scratch/review/round5-mutation-drop_historical_wib_carryover_f6.log", + "sha256": "249a7a6038a9a735a42423c9d67f1898c0c50c17dd445ac047455926c5d5c8ab", + "failure_summary": "1 failed, 2 passed in 8.45s" + }, + "mutation_method": "One-line semantic mutation in an isolated named-source overlay; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "73ebc6a9dac1d9d05d2ef1aca002dc0505755d466b2c0153fb1f929cd0f1b690", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + }, + "layer": "g_preflight" + }, + { + "id": "round5-drop_historical_widow_gross_uncertainty", + "round": 5, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": ") or _historical_widow_gross_bound_unsettled(", + "after": ") or False and _historical_widow_gross_bound_unsettled(" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "-x", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_gross_uncertainty_preserves_refusals_across_months" + ], + "outer_command": [ + "python", + "scratch/review/round5_mutation_check.py", + "drop_historical_widow_gross_uncertainty" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-mutation-drop_historical_widow_gross_uncertainty/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-mutation-drop_historical_widow_gross_uncertainty", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-mutation-drop_historical_widow_gross_uncertainty" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_gross_uncertainty_preserves_refusals_across_months" + ], + "log": { + "path": "scratch/review/round5-mutation-drop_historical_widow_gross_uncertainty.log", + "sha256": "089fd3a8047e231460f8f715fe52d5e7980a35d64f8045193dd9ad9fff23e5ac", + "failure_summary": "1 failed in 7.89s" + }, + "mutation_method": "One-line semantic mutation in an isolated named-source overlay; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "d51f5d77c7aa7cf6004392e27187ce89523151fef12148088565226f7444fb64", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + } + }, + "layer": "g_preflight" + }, + { + "id": "round5-drop_historical_widow_original_fact_hold", + "round": 5, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": " ) < (1973, 1)", + "after": " ) < (1900, 1)" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "-x", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_original_benefit_uses_the_payment_period" + ], + "outer_command": [ + "python", + "scratch/review/round5_mutation_check.py", + "drop_historical_widow_original_fact_hold" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-mutation-drop_historical_widow_original_fact_hold/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-mutation-drop_historical_widow_original_fact_hold", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-mutation-drop_historical_widow_original_fact_hold" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_original_benefit_uses_the_payment_period[1972]" + ], + "log": { + "path": "scratch/review/round5-mutation-drop_historical_widow_original_fact_hold.log", + "sha256": "52a6159eb672808735efe563f71de2c38b0140c5227fad9c14cb63e36cab9f90", + "failure_summary": "1 failed in 8.00s" + }, + "mutation_method": "One-line semantic mutation in an isolated named-source overlay; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "d51f5d77c7aa7cf6004392e27187ce89523151fef12148088565226f7444fb64", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + } + }, + "layer": "g_preflight" + }, + { + "id": "round5-drop_missing_widow_cohort_guard", + "round": 5, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": " and resolved.birth_year is None", + "after": " and False" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "-x", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_missing_both_widow_cohorts_remains_canonical_input_error" + ], + "outer_command": [ + "python", + "scratch/review/round5_mutation_check.py", + "drop_missing_widow_cohort_guard" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-mutation-drop_missing_widow_cohort_guard/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-mutation-drop_missing_widow_cohort_guard", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-mutation-drop_missing_widow_cohort_guard" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_missing_both_widow_cohorts_remains_canonical_input_error[None]" + ], + "log": { + "path": "scratch/review/round5-mutation-drop_missing_widow_cohort_guard.log", + "sha256": "9c0339b2b61bf160d9a95063dd14ee4e6149f6eee4adf2b8530bbac873491e66", + "failure_summary": "1 failed in 13.99s" + }, + "mutation_method": "One-line semantic mutation in an isolated named-source overlay; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "73ebc6a9dac1d9d05d2ef1aca002dc0505755d466b2c0153fb1f929cd0f1b690", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + }, + "layer": "g_preflight" + }, + { + "id": "round5-drop_parent_upper_bound_context", + "round": 5, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": " if original_benefit_upper_bound:", + "after": " if False:" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "-x", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_parent_upper_bound_holds_across_scales_months_and_deferred_holds" + ], + "outer_command": [ + "python", + "scratch/review/round5_mutation_check.py", + "drop_parent_upper_bound_context" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-mutation-drop_parent_upper_bound_context/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-mutation-drop_parent_upper_bound_context", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-mutation-drop_parent_upper_bound_context" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_parent_upper_bound_holds_across_scales_months_and_deferred_holds" + ], + "log": { + "path": "scratch/review/round5-mutation-drop_parent_upper_bound_context.log", + "sha256": "d3cd25bdbcf7fce7dce44f6b7c3fc18fd858f41ea35a29d9b6d5216f66d2ce11", + "failure_summary": "1 failed in 7.54s" + }, + "mutation_method": "One-line semantic mutation in an isolated named-source overlay; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "d51f5d77c7aa7cf6004392e27187ce89523151fef12148088565226f7444fb64", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + } + }, + "layer": "g_preflight" + }, + { + "id": "round5-drop_wc_f2", + "round": 5, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": "RecordCondition.WORKERS_COMPENSATION_OFFSET: frozenset({'F2', 'F3'})", + "after": "_PREFLIGHT_FACT_UNSETTLERS[RecordCondition.WORKERS_COMPENSATION_OFFSET] -= {\"F2\"}" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "-x", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_lawful_dib_gross_changes_remain_counted_refusals" + ], + "outer_command": [ + "python", + "scratch/review/round5_mutation_check.py", + "drop_wc_f2" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-mutation-drop_wc_f2/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-mutation-drop_wc_f2", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-mutation-drop_wc_f2" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_lawful_dib_gross_changes_remain_counted_refusals[RecordCondition.WORKERS_COMPENSATION_OFFSET-600]" + ], + "log": { + "path": "scratch/review/round5-mutation-drop_wc_f2.log", + "sha256": "c0e8153a9fec972835c071e7ec7c32e0278ce9cf1a8549bc183de68837670e4a", + "failure_summary": "1 failed, 1 passed in 16.26s" + }, + "mutation_method": "One-line semantic mutation in an isolated named-source overlay; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + }, + "layer": "g_preflight" + }, + { + "id": "round5-drop_wc_f3", + "round": 5, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": "RecordCondition.WORKERS_COMPENSATION_OFFSET: frozenset({'F2', 'F3'})", + "after": "_PREFLIGHT_FACT_UNSETTLERS[RecordCondition.WORKERS_COMPENSATION_OFFSET] -= {\"F3\"}" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "-x", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_held_against_unheld_fact_classification" + ], + "outer_command": [ + "python", + "scratch/review/round5_mutation_check.py", + "drop_wc_f3" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-mutation-drop_wc_f3/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-mutation-drop_wc_f3", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-mutation-drop_wc_f3" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_held_against_unheld_fact_classification" + ], + "log": { + "path": "scratch/review/round5-mutation-drop_wc_f3.log", + "sha256": "d72fc8ee34fb4fc18386304a22ba4d910a118bfe26504b586d50575db92c97df", + "failure_summary": "1 failed in 16.60s" + }, + "mutation_method": "One-line semantic mutation in an isolated named-source overlay; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + }, + "layer": "g_preflight" + }, + { + "id": "round5-exclude_protected_widow_by_ordinary_entitlement", + "round": 5, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": " if not _fact_is_settled(", + "after": " if False and not _fact_is_settled(" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "-x", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history" + ], + "outer_command": [ + "python", + "scratch/review/round5_mutation_check.py", + "exclude_protected_widow_by_ordinary_entitlement" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-mutation-exclude_protected_widow_by_ordinary_entitlement/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-mutation-exclude_protected_widow_by_ordinary_entitlement", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-mutation-exclude_protected_widow_by_ordinary_entitlement" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[None-basis0-ret]" + ], + "log": { + "path": "scratch/review/round5-mutation-exclude_protected_widow_by_ordinary_entitlement.log", + "sha256": "1c2914de95c03952f9328ae2ad11c518abf4fb61bea3a6d2b7ebfc12b066693e", + "failure_summary": "1 failed in 18.30s" + }, + "mutation_method": "One-line semantic mutation in an isolated named-source overlay; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + }, + "layer": "g_preflight" + }, + { + "id": "round5-f6_without_own_mba", + "round": 5, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": { + "before": "auxiliary, state.pia, own_mba, parent_ob=original", + "after": "auxiliary, state.pia, None, parent_ob=original" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "-x", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling" + ], + "outer_command": [ + "python", + "scratch/review/round5_mutation_check.py", + "f6_without_own_mba" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-mutation-f6_without_own_mba/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-mutation-f6_without_own_mba", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-mutation-f6_without_own_mba" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-0-F6]" + ], + "log": { + "path": "scratch/review/round5-mutation-f6_without_own_mba.log", + "sha256": "d63844ddf4159f8bbf87f2aea8e2269420415cf7c0f3da475825e9a37ba16a4b", + "failure_summary": "1 failed, 8 passed in 12.27s" + }, + "mutation_method": "One-line semantic mutation in an isolated named-source overlay; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + }, + "layer": "r2" + }, + { + "id": "round5-matching_declarations_f1_equality", + "round": 5, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": { + "before": "if settled(\"F1\") and nh.original_rates[month - 1] != state.pia:", + "after": "if settled(\"F1\") and nh.original_rates[month - 1] == state.pia:" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "-x", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_matching_declarations_never_raise_input_errors" + ], + "outer_command": [ + "python", + "scratch/review/round5_mutation_check.py", + "matching_declarations_f1_equality" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-mutation-matching_declarations_f1_equality/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-mutation-matching_declarations_f1_equality", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-mutation-matching_declarations_f1_equality" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_matching_declarations_never_raise_input_errors" + ], + "log": { + "path": "scratch/review/round5-mutation-matching_declarations_f1_equality.log", + "sha256": "f0e6fbe0169248ed4367344945d5361db7ecebdad131308433357d908e5d89ad", + "failure_summary": "1 failed in 125.43s (0:02:05)" + }, + "mutation_method": "One-line semantic mutation in an isolated named-source overlay; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + }, + "layer": "r2" + }, + { + "id": "round5-restore_blanket_dual_f6_hold", + "round": 5, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": " if beneficiary is None:", + "after": " if True:" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "-x", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled" + ], + "outer_command": [ + "python", + "scratch/review/round5_mutation_check.py", + "restore_blanket_dual_f6_hold" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-mutation-restore_blanket_dual_f6_hold/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-mutation-restore_blanket_dual_f6_hold", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-mutation-restore_blanket_dual_f6_hold" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[None-0]" + ], + "log": { + "path": "scratch/review/round5-mutation-restore_blanket_dual_f6_hold.log", + "sha256": "8cb072244d70f320b9a6a51d05ba3bbbf110ab5e983982bbedf41a5656384914", + "failure_summary": "1 failed in 6.92s" + }, + "mutation_method": "One-line semantic mutation in an isolated named-source overlay; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "73ebc6a9dac1d9d05d2ef1aca002dc0505755d466b2c0153fb1f929cd0f1b690", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + }, + "layer": "g_preflight" + }, + { + "id": "round5-restore_global_own_history_hold", + "round": 5, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": " _own_monthly_benefit_validated(own, params)\n except FamilyConfigurationUnsupported:\n return True\n return False", + "after": " _own_monthly_benefit_validated(own, params)\n except FamilyConfigurationUnsupported:\n return True\n return True" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "-x", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope" + ], + "outer_command": [ + "python", + "scratch/review/round5_mutation_check.py", + "restore_global_own_history_hold" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-mutation-restore_global_own_history_hold/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-mutation-restore_global_own_history_hold", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-mutation-restore_global_own_history_hold" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F3-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]" + ], + "log": { + "path": "scratch/review/round5-mutation-restore_global_own_history_hold.log", + "sha256": "86a24ffec78d4d4af24bef3a76d6852aeebb0226d9fbf98d6b038c6c49567ff4", + "failure_summary": "1 failed, 19 passed in 9.75s" + }, + "mutation_method": "One-line semantic mutation in an isolated named-source overlay; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cd71ea6dd462b711f3341ce8fec2c8a0b15214672989b831cd0e0d7e780542ca", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + }, + "layer": "g_preflight" + }, + { + "id": "round5-restore_global_parent_hold", + "round": 5, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": " if beneficiary is None or beneficiary.role is not Role.PARENT:\n return False", + "after": " if beneficiary is None or beneficiary.role is not Role.PARENT:\n return True" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "-x", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope" + ], + "outer_command": [ + "python", + "scratch/review/round5_mutation_check.py", + "restore_global_parent_hold" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-mutation-restore_global_parent_hold/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-mutation-restore_global_parent_hold", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-mutation-restore_global_parent_hold" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F4-UnsupportedReason.PARENT_BENEFIT]" + ], + "log": { + "path": "scratch/review/round5-mutation-restore_global_parent_hold.log", + "sha256": "51ad54bad77bbc8d468a4eddfde1ee725e00e7c7e8347e72826c9813b784c9f9", + "failure_summary": "1 failed, 18 passed in 9.77s" + }, + "mutation_method": "One-line semantic mutation in an isolated named-source overlay; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cd71ea6dd462b711f3341ce8fec2c8a0b15214672989b831cd0e0d7e780542ca", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + }, + "layer": "g_preflight" + }, + { + "id": "round5-restore_global_payment_hold", + "round": 5, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": "\n < FIRST_SUPPORTED_PAYMENT_MONTH", + "after": "\n < (9999, 1)" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "-x", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope" + ], + "outer_command": [ + "python", + "scratch/review/round5_mutation_check.py", + "restore_global_payment_hold" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-mutation-restore_global_payment_hold/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-mutation-restore_global_payment_hold", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-mutation-restore_global_payment_hold" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F3-UnsupportedReason.PAYMENT_MONTH_BEFORE_1983]" + ], + "log": { + "path": "scratch/review/round5-mutation-restore_global_payment_hold.log", + "sha256": "46b9198f9fa953c24a59ffccac24a51ec336f43e71f584317bbe7e092b14a988", + "failure_summary": "1 failed, 23 passed in 8.36s" + }, + "mutation_method": "One-line semantic mutation in an isolated named-source overlay; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "d51f5d77c7aa7cf6004392e27187ce89523151fef12148088565226f7444fb64", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + } + }, + "layer": "g_preflight" + }, + { + "id": "round5-restore_global_widow_drc_hold", + "round": 5, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": " return state.kind is FamilyKind.SURVIVOR", + "after": " return True" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "-x", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope" + ], + "outer_command": [ + "python", + "scratch/review/round5_mutation_check.py", + "restore_global_widow_drc_hold" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-mutation-restore_global_widow_drc_hold/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-mutation-restore_global_widow_drc_hold", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-mutation-restore_global_widow_drc_hold" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F4-UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE]" + ], + "log": { + "path": "scratch/review/round5-mutation-restore_global_widow_drc_hold.log", + "sha256": "44705e1a3599b8bb9709ab0f01307430af6e847b098fe99a9ed19f5f6baa23b1", + "failure_summary": "1 failed, 25 passed in 10.48s" + }, + "mutation_method": "One-line semantic mutation in an isolated named-source overlay; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cd71ea6dd462b711f3341ce8fec2c8a0b15214672989b831cd0e0d7e780542ca", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + }, + "layer": "g_preflight" + }, + { + "id": "round5-share_beneficiary_finality_recordwide", + "round": 5, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": { + "before": " return g._fact_is_settled(", + "after": " return not any(g.BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY in b.conditions for b in context.beneficiaries) and g._fact_is_settled(" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "-x", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_one_beneficiary_finality_does_not_protect_the_nh" + ], + "outer_command": [ + "python", + "scratch/review/round5_mutation_check.py", + "share_beneficiary_finality_recordwide" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-mutation-share_beneficiary_finality_recordwide/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-mutation-share_beneficiary_finality_recordwide", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-mutation-share_beneficiary_finality_recordwide" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_one_beneficiary_finality_does_not_protect_the_nh[F1]" + ], + "log": { + "path": "scratch/review/round5-mutation-share_beneficiary_finality_recordwide.log", + "sha256": "6e96ef3a01d0b3f2dcb77aa0091beb86bd4c68b586b50b7e682c2d88fe374d1f", + "failure_summary": "1 failed in 11.10s" + }, + "mutation_method": "One-line semantic mutation in an isolated named-source overlay; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + }, + "layer": "r2" + }, + { + "id": "round5-skip_f3", + "round": 5, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": { + "before": "elif settled(\"F3\"):", + "after": "elif False:" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "-x", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling" + ], + "outer_command": [ + "python", + "scratch/review/round5_mutation_check.py", + "skip_f3" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-mutation-skip_f3/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-mutation-skip_f3", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-mutation-skip_f3" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-0-F3]" + ], + "log": { + "path": "scratch/review/round5-mutation-skip_f3.log", + "sha256": "c02b583a9b6131ad4ce8c505e9f19ed20a246801d4a30764167a4159cc143a9c", + "failure_summary": "1 failed, 6 passed in 9.27s" + }, + "mutation_method": "One-line semantic mutation in an isolated named-source overlay; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + }, + "layer": "r2" + }, + { + "id": "round5-skip_f4", + "round": 5, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": { + "before": " settled(\"F4\", auxiliary)\n and original is not None", + "after": " False\n and original is not None" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "-x", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling" + ], + "outer_command": [ + "python", + "scratch/review/round5_mutation_check.py", + "skip_f4" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-mutation-skip_f4/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-mutation-skip_f4", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-mutation-skip_f4" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-0-F4]" + ], + "log": { + "path": "scratch/review/round5-mutation-skip_f4.log", + "sha256": "64bf193af89d43a12adc5195f037927310c806eb3250a823252c49a107497059", + "failure_summary": "1 failed, 7 passed in 8.30s" + }, + "mutation_method": "One-line semantic mutation in an isolated named-source overlay; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + }, + "layer": "r2" + }, + { + "id": "round5-skip_f6", + "round": 5, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": { + "before": " if settled(fact, auxiliary) and not (", + "after": " if fact != \"F6\" and settled(fact, auxiliary) and not (" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "-x", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling" + ], + "outer_command": [ + "python", + "scratch/review/round5_mutation_check.py", + "skip_f6" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-mutation-skip_f6/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-mutation-skip_f6", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-mutation-skip_f6" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-0-F6]" + ], + "log": { + "path": "scratch/review/round5-mutation-skip_f6.log", + "sha256": "18dc9de306bcc978aa19d1ca368b82db5a9928098a139e997eb418e99b53cd90", + "failure_summary": "1 failed, 8 passed in 7.43s" + }, + "mutation_method": "One-line semantic mutation in an isolated named-source overlay; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + } + }, + "layer": "r2" + }, + { + "id": "round5-skip_specific_auxiliary_entitlement_error", + "round": 5, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": { + "before": " if not entitled:", + "after": " if not entitled and fact != \"F5\":" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "-x", + "--tb=short", + "tests/test_track_b_ret_ledger_deductions.py::test_family_context_invalidity_precedes_record_refusal" + ], + "outer_command": [ + "python", + "scratch/review/round5_mutation_check.py", + "skip_specific_auxiliary_entitlement_error" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-mutation-skip_specific_auxiliary_entitlement_error/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-mutation-skip_specific_auxiliary_entitlement_error", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-mutation-skip_specific_auxiliary_entitlement_error" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_deductions.py::test_family_context_invalidity_precedes_record_refusal" + ], + "log": { + "path": "scratch/review/round5-mutation-skip_specific_auxiliary_entitlement_error.log", + "sha256": "740ec64585a6e799fc5fd68ca96336d6d4db0c5ad4ca586e8a332254ede8aebc", + "failure_summary": "1 failed in 10.77s" + }, + "mutation_method": "One-line semantic mutation in an isolated named-source overlay; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + } + }, + "layer": "r2" + }, + { + "id": "round5-swallow_input_error", + "round": 5, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": { + "before": "except FamilyConfigurationUnsupported:\n pass", + "after": "except (FamilyConfigurationUnsupported, InvalidFamilyInput):\n pass" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "-x", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_canonical_input_error_is_never_caught_as_a_coverage_refusal" + ], + "outer_command": [ + "python", + "scratch/review/round5_mutation_check.py", + "swallow_input_error" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-mutation-swallow_input_error/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-mutation-swallow_input_error", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-mutation-swallow_input_error" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_canonical_input_error_is_never_caught_as_a_coverage_refusal[F3-_own_monthly_benefit_validated]" + ], + "log": { + "path": "scratch/review/round5-mutation-swallow_input_error.log", + "sha256": "061bb72ae2ff6631a0daeaa4b6124576f2eabdac962d64f03b5c89bc33d9f6fe", + "failure_summary": "1 failed in 5.50s" + }, + "mutation_method": "One-line semantic mutation in an isolated named-source overlay; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + }, + "layer": "r2" + }, + { + "id": "round5-table_completeness_missing_reason", + "round": 5, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": "UnsupportedReason.PENALTY_DEDUCTION: frozenset()", + "after": "del _PREFLIGHT_FACT_UNSETTLERS[UnsupportedReason.PENALTY_DEDUCTION]" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "-x", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_fact_table_explicitly_covers_all_conditions_and_held_g_reasons" + ], + "outer_command": [ + "python", + "scratch/review/round5_mutation_check.py", + "table_completeness_missing_reason" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-mutation-table_completeness_missing_reason/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-mutation-table_completeness_missing_reason", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-mutation-table_completeness_missing_reason" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_fact_table_explicitly_covers_all_conditions_and_held_g_reasons" + ], + "log": { + "path": "scratch/review/round5-mutation-table_completeness_missing_reason.log", + "sha256": "957a945dbef81ed6bb62ef8b493a995ea90a955b33f4f6332b63a9db0b832618", + "failure_summary": "1 failed in 10.26s" + }, + "mutation_method": "One-line semantic mutation in an isolated named-source overlay; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + }, + "layer": "g_preflight" + }, + { + "id": "round5-unconditional_deduction_ob_bound", + "round": 5, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": " if not _fact_is_settled(", + "after": " if False and not _fact_is_settled(" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "-x", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob" + ], + "outer_command": [ + "python", + "scratch/review/round5_mutation_check.py", + "unconditional_deduction_ob_bound" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-mutation-unconditional_deduction_ob_bound/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-mutation-unconditional_deduction_ob_bound", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-mutation-unconditional_deduction_ob_bound" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable0-reserved0-RecordCondition.ADMINISTRATIVE_FINALITY-False]" + ], + "log": { + "path": "scratch/review/round5-mutation-unconditional_deduction_ob_bound.log", + "sha256": "0c1273291a0f21e3faaf9f888b3dfde5997a29682ce5519da53bb4f165f5f2fc", + "failure_summary": "1 failed in 9.37s" + }, + "mutation_method": "One-line semantic mutation in an isolated named-source overlay; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + }, + "layer": "g_preflight" + }, + { + "id": "round5-unsettle_non_aime_f1", + "round": 5, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": { + "before": "RecordCondition.NON_AIME_FORMULA_PIA: frozenset()", + "after": "_PREFLIGHT_FACT_UNSETTLERS[RecordCondition.NON_AIME_FORMULA_PIA] = frozenset({\"F1\"})" + }, + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "-x", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition" + ], + "outer_command": [ + "python", + "scratch/review/round5_mutation_check.py", + "unsettle_non_aime_f1" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-mutation-unsettle_non_aime_f1/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-mutation-unsettle_non_aime_f1", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-mutation-unsettle_non_aime_f1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-0-F1]" + ], + "log": { + "path": "scratch/review/round5-mutation-unsettle_non_aime_f1.log", + "sha256": "678857dece286ef8d5e7748ed667d1155cf54373a5d836b4336ff2330135fb33", + "failure_summary": "1 failed, 24 passed in 8.52s" + }, + "mutation_method": "One-line semantic mutation in an isolated named-source overlay; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + }, + "layer": "g_preflight" } ], "restoration_verification_snapshot": { @@ -2763,5 +4444,11 @@ "src/populace_dynamics/track_b/gross_benefits.py": "6ed10a1f4c637ab136511792d574dc49236acb726818532c4a3c865781af14d0", "src/populace_dynamics/track_b/ret_ledger.py": "e9b01a765a7951937a7035da3ab2ef29b13dc1efa663e35e224ae558d622515b" }, - "round_4_environment_note": "The older isolated-source imports contract describes historical rounds. Round 4 records identify foreground, reversible workspace mutations and their environments. Final restoration hashes include the completed declared-fact audit extension." + "round_4_environment_note": "The older isolated-source imports contract describes historical rounds. Round 4 records identify foreground, reversible workspace mutations and their environments. Final restoration hashes include the completed declared-fact audit extension.", + "round_5_head": "e3315bafb592e29031d72b5ef368ca428e4a0b55", + "round_5_note": "30 fresh one-line semantic mutations caught by named public-path tests; isolated copied rules restored, production sources unchanged. Earlier records remain historical.", + "round_5_restoration_snapshot": { + "src/populace_dynamics/track_b/gross_benefits.py": "d51f5d77c7aa7cf6004392e27187ce89523151fef12148088565226f7444fb64", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + } } diff --git a/docs/design/track_b_g2_r2b_verification.json b/docs/design/track_b_g2_r2b_verification.json index a5daeb53c..813fe0b54 100644 --- a/docs/design/track_b_g2_r2b_verification.json +++ b/docs/design/track_b_g2_r2b_verification.json @@ -5746,5 +5746,7257 @@ "scratch/review/round4-adversarial-audit.md" ] }, - "round_4_current_evidence_note": "Earlier records remain historical. The round_4 section is the current evidence for the final rules, declarations, report inputs and artifact." + "round_4_current_evidence_note": "Earlier records remain historical. The round_4 section is the current evidence for the final rules, declarations, report inputs and artifact.", + "round_5": { + "reviewed_head": "e3315bafb592e29031d72b5ef368ca428e4a0b55", + "workspace": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "verification_class": "statutory_conformance", + "admitted_scope": "Invented declarations and captured published examples only; no population, behavioral or forecast claim.", + "original_conformance_report_sha256": "17d144575b38bb85080d8cbed28fad470ec93fd6eb6803b48729bb26a78b3d45", + "tier_policy": "Left to CI; no tier recount or whole-suite collection.", + "birth_evidence": "Left to CI; not run locally.", + "named_test_modules": [ + "tests/test_track_b_arf.py", + "tests/test_track_b_arf_properties.py", + "tests/test_track_b_gross_benefits.py", + "tests/test_track_b_gross_benefits_conformance_report.py", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py", + "tests/test_track_b_gross_benefits_deduction_cap.py", + "tests/test_track_b_gross_benefits_deductions.py", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", + "tests/test_track_b_gross_benefits_dwb.py", + "tests/test_track_b_gross_benefits_fix_round_1.py", + "tests/test_track_b_gross_benefits_fix_round_10_api.py", + "tests/test_track_b_gross_benefits_fix_round_10_helpers.py", + "tests/test_track_b_gross_benefits_fix_round_10_objects.py", + "tests/test_track_b_gross_benefits_fix_round_10_parameters.py", + "tests/test_track_b_gross_benefits_fix_round_11_roles.py", + "tests/test_track_b_gross_benefits_fix_round_11_seals.py", + "tests/test_track_b_gross_benefits_fix_round_12_contract.py", + "tests/test_track_b_gross_benefits_fix_round_13_audit.py", + "tests/test_track_b_gross_benefits_fix_round_13_boundary.py", + "tests/test_track_b_gross_benefits_fix_round_13_guard.py", + "tests/test_track_b_gross_benefits_fix_round_15_arguments.py", + "tests/test_track_b_gross_benefits_fix_round_15_collections.py", + "tests/test_track_b_gross_benefits_fix_round_15_receivers.py", + "tests/test_track_b_gross_benefits_fix_round_2_care.py", + "tests/test_track_b_gross_benefits_fix_round_2_history.py", + "tests/test_track_b_gross_benefits_fix_round_2_periods.py", + "tests/test_track_b_gross_benefits_fix_round_3_rates.py", + "tests/test_track_b_gross_benefits_fix_round_4_care_floor.py", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py", + "tests/test_track_b_gross_benefits_fix_round_4_divorced_care.py", + "tests/test_track_b_gross_benefits_fix_round_5_care_history.py", + "tests/test_track_b_gross_benefits_fix_round_5_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_6_care_note.py", + "tests/test_track_b_gross_benefits_fix_round_6_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_boundary.py", + "tests/test_track_b_gross_benefits_fix_round_7_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_history.py", + "tests/test_track_b_gross_benefits_fix_round_8_entries.py", + "tests/test_track_b_gross_benefits_fix_round_8_history.py", + "tests/test_track_b_gross_benefits_fix_round_9_citations.py", + "tests/test_track_b_gross_benefits_fix_round_9_outcomes.py", + "tests/test_track_b_gross_benefits_fix_round_9_validation.py", + "tests/test_track_b_gross_benefits_oracle.py", + "tests/test_track_b_gross_benefits_own_input_order.py", + "tests/test_track_b_gross_benefits_parents_ieds.py", + "tests/test_track_b_gross_benefits_parisi.py", + "tests/test_track_b_gross_benefits_payment_review.py", + "tests/test_track_b_gross_benefits_properties.py", + "tests/test_track_b_gross_benefits_registry.py", + "tests/test_track_b_gross_benefits_review.py", + "tests/test_track_b_gross_benefits_saving_absence.py", + "tests/test_track_b_gross_benefits_savings.py", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py", + "tests/test_track_b_gross_benefits_sources_20261011.py", + "tests/test_track_b_gross_benefits_ssfa.py", + "tests/test_track_b_input_schema.py", + "tests/test_track_b_r3_fix_round_13.py", + "tests/test_track_b_r3_provenance.py", + "tests/test_track_b_r3_sources.py", + "tests/test_track_b_r3_validation_once.py", + "tests/test_track_b_recompute.py", + "tests/test_track_b_recompute_properties.py", + "tests/test_track_b_refusal_notes.py", + "tests/test_track_b_ret_differential.py", + "tests/test_track_b_ret_fra_facts.py", + "tests/test_track_b_ret_grace.py", + "tests/test_track_b_ret_grace_differential.py", + "tests/test_track_b_ret_grace_provenance.py", + "tests/test_track_b_ret_ledger.py", + "tests/test_track_b_ret_ledger_deductions.py", + "tests/test_track_b_ret_ledger_fix_round_2.py", + "tests/test_track_b_ret_ledger_fix_round_4.py", + "tests/test_track_b_ret_ledger_properties.py", + "tests/test_track_b_ret_ledger_readings.py", + "tests/test_track_b_ret_ledger_sources.py", + "tests/test_track_b_ret_params.py", + "tests/test_track_b_ret_ledger_fix_round_5.py" + ], + "gate_runs": { + "g_boundary": { + "partition": "g_boundary", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=short", + "tests/test_track_b_gross_benefits_fix_round_1.py", + "tests/test_track_b_gross_benefits_fix_round_10_api.py", + "tests/test_track_b_gross_benefits_fix_round_10_helpers.py", + "tests/test_track_b_gross_benefits_fix_round_10_objects.py", + "tests/test_track_b_gross_benefits_fix_round_10_parameters.py", + "tests/test_track_b_gross_benefits_fix_round_11_roles.py", + "tests/test_track_b_gross_benefits_fix_round_11_seals.py", + "tests/test_track_b_gross_benefits_fix_round_12_contract.py", + "tests/test_track_b_gross_benefits_fix_round_13_audit.py", + "tests/test_track_b_gross_benefits_fix_round_13_boundary.py", + "tests/test_track_b_gross_benefits_fix_round_13_guard.py", + "tests/test_track_b_gross_benefits_fix_round_15_arguments.py", + "tests/test_track_b_gross_benefits_fix_round_15_collections.py", + "tests/test_track_b_gross_benefits_fix_round_15_receivers.py", + "tests/test_track_b_gross_benefits_fix_round_2_care.py", + "tests/test_track_b_gross_benefits_fix_round_2_history.py", + "tests/test_track_b_gross_benefits_fix_round_2_periods.py", + "tests/test_track_b_gross_benefits_fix_round_3_rates.py", + "tests/test_track_b_gross_benefits_fix_round_4_care_floor.py", + "tests/test_track_b_gross_benefits_fix_round_4_divorced_care.py", + "tests/test_track_b_gross_benefits_fix_round_5_care_history.py", + "tests/test_track_b_gross_benefits_fix_round_5_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_6_care_note.py", + "tests/test_track_b_gross_benefits_fix_round_6_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_boundary.py", + "tests/test_track_b_gross_benefits_fix_round_7_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_history.py", + "tests/test_track_b_gross_benefits_fix_round_8_entries.py", + "tests/test_track_b_gross_benefits_fix_round_8_history.py", + "tests/test_track_b_gross_benefits_fix_round_9_citations.py", + "tests/test_track_b_gross_benefits_fix_round_9_outcomes.py", + "tests/test_track_b_gross_benefits_fix_round_9_validation.py" + ], + "environment": { + "OMP_NUM_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-g_boundary", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-g_boundary" + }, + "named_modules": [ + "tests/test_track_b_gross_benefits_fix_round_1.py", + "tests/test_track_b_gross_benefits_fix_round_10_api.py", + "tests/test_track_b_gross_benefits_fix_round_10_helpers.py", + "tests/test_track_b_gross_benefits_fix_round_10_objects.py", + "tests/test_track_b_gross_benefits_fix_round_10_parameters.py", + "tests/test_track_b_gross_benefits_fix_round_11_roles.py", + "tests/test_track_b_gross_benefits_fix_round_11_seals.py", + "tests/test_track_b_gross_benefits_fix_round_12_contract.py", + "tests/test_track_b_gross_benefits_fix_round_13_audit.py", + "tests/test_track_b_gross_benefits_fix_round_13_boundary.py", + "tests/test_track_b_gross_benefits_fix_round_13_guard.py", + "tests/test_track_b_gross_benefits_fix_round_15_arguments.py", + "tests/test_track_b_gross_benefits_fix_round_15_collections.py", + "tests/test_track_b_gross_benefits_fix_round_15_receivers.py", + "tests/test_track_b_gross_benefits_fix_round_2_care.py", + "tests/test_track_b_gross_benefits_fix_round_2_history.py", + "tests/test_track_b_gross_benefits_fix_round_2_periods.py", + "tests/test_track_b_gross_benefits_fix_round_3_rates.py", + "tests/test_track_b_gross_benefits_fix_round_4_care_floor.py", + "tests/test_track_b_gross_benefits_fix_round_4_divorced_care.py", + "tests/test_track_b_gross_benefits_fix_round_5_care_history.py", + "tests/test_track_b_gross_benefits_fix_round_5_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_6_care_note.py", + "tests/test_track_b_gross_benefits_fix_round_6_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_boundary.py", + "tests/test_track_b_gross_benefits_fix_round_7_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_history.py", + "tests/test_track_b_gross_benefits_fix_round_8_entries.py", + "tests/test_track_b_gross_benefits_fix_round_8_history.py", + "tests/test_track_b_gross_benefits_fix_round_9_citations.py", + "tests/test_track_b_gross_benefits_fix_round_9_outcomes.py", + "tests/test_track_b_gross_benefits_fix_round_9_validation.py" + ], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "test_sha256_before": { + "tests/test_track_b_gross_benefits_fix_round_1.py": "9275a8a4963ce7ed086482644d044a927100efcbeb5a05315d9cc6394168ee8c", + "tests/test_track_b_gross_benefits_fix_round_10_api.py": "227fde023692f1c73a3eeb6de75213468c8e5e160ade3536bf5b7fb688c4ded6", + "tests/test_track_b_gross_benefits_fix_round_10_helpers.py": "e5014776670ca9b552de756c63976e606290fb4fad85a1501b017700a05c8fdb", + "tests/test_track_b_gross_benefits_fix_round_10_objects.py": "7576cc18923ad3ff38d0f44379637e822008a92cc9968d52f47b991e56fb9cfb", + "tests/test_track_b_gross_benefits_fix_round_10_parameters.py": "981eced43d10a6720ccab0292c4a8c281b9ac9bf7d83132f6666254d7a4b72ee", + "tests/test_track_b_gross_benefits_fix_round_11_roles.py": "d26fd86d7067eb7f4f97e1537110eab5223104ad817c3470a9eae022a90dfc73", + "tests/test_track_b_gross_benefits_fix_round_11_seals.py": "937b07b094816eade9bf072595ede18b1b109db527de9805c3a3cb3d333ba4b5", + "tests/test_track_b_gross_benefits_fix_round_12_contract.py": "9779ae3b22cf12daf6727cd21a6bcb12afbf3cfd34c84209bd406942a0c089e1", + "tests/test_track_b_gross_benefits_fix_round_13_audit.py": "fb04098e3982aca18b439f2df148bee6333ce20406fe773da0858731a6c94ff0", + "tests/test_track_b_gross_benefits_fix_round_13_boundary.py": "acac7951783a0e11140e717feab3924973e290e58857396dfab9c0b4319a5e8d", + "tests/test_track_b_gross_benefits_fix_round_13_guard.py": "e5fabfda3fcab2ba9e0347449278a21b9cfc1f89645e1ab148cb4a23da9e7c2e", + "tests/test_track_b_gross_benefits_fix_round_15_arguments.py": "16d5a875f4271839799738a89f2b904084bc0847eb25cd397168cea570be6d54", + "tests/test_track_b_gross_benefits_fix_round_15_collections.py": "2206b9734458774d581d3d20bfb50f1d517fd1b7d8191225cf5cacbca6561e58", + "tests/test_track_b_gross_benefits_fix_round_15_receivers.py": "3de91e8701ab82a3063be9eb859e6cd0058c7d3a35ac93dce9e110e0959061ff", + "tests/test_track_b_gross_benefits_fix_round_2_care.py": "7e983b28cdd1ba2c03935858610788754de66fb9489fef46672ebbf3d566225e", + "tests/test_track_b_gross_benefits_fix_round_2_history.py": "17fb81a1d18ad90ccf99cc841360aec524822cc2404e03d33cfbbab3a830b3a5", + "tests/test_track_b_gross_benefits_fix_round_2_periods.py": "21030c220e1b4690ac3d6754dcd9baddc23b33e824e07a842673c4128b7e6b09", + "tests/test_track_b_gross_benefits_fix_round_3_rates.py": "1c638ac3d5f0b0d25b49d1abf4924d9fff45bcf5ce25366616a60d3f060faa16", + "tests/test_track_b_gross_benefits_fix_round_4_care_floor.py": "d137d59fb7af48f21fda7b4e3aaf9a991d43b295930b5f341cc7cd595b875401", + "tests/test_track_b_gross_benefits_fix_round_4_divorced_care.py": "cd50249e8d84a2bbb61901f08b84310d48b8d390495beadfe5112144143b4fd7", + "tests/test_track_b_gross_benefits_fix_round_5_care_history.py": "a3e73482553c5fb804adaba8ed0d5e4d1520470f384bb58a0fe46cb41e58eb07", + "tests/test_track_b_gross_benefits_fix_round_5_cohorts.py": "f5be483a533e47edcb58dc05bc202390e959e6ece7eca3ff11728aa46b00409d", + "tests/test_track_b_gross_benefits_fix_round_6_care_note.py": "b2d158f37d35aaa63a6a1293345010bc4445c3b20c480c035932bf9725a91eca", + "tests/test_track_b_gross_benefits_fix_round_6_cohorts.py": "b06e95d0a8a93af3e60b96222381b46377673e407385958b5120817bc60c2e84", + "tests/test_track_b_gross_benefits_fix_round_7_boundary.py": "b2c875f010c402e4f373be5712a39affd87b6533805ed33bf63dbea60b1e6ae5", + "tests/test_track_b_gross_benefits_fix_round_7_cohorts.py": "0eb73d51e1f7a61f76917df670f89bdade0e5f45f4c044be30673dff2494ca31", + "tests/test_track_b_gross_benefits_fix_round_7_history.py": "fc6a7b5281e2f429a8e9f92c595b4491aa2de4229630fc5ca15eab333bacab26", + "tests/test_track_b_gross_benefits_fix_round_8_entries.py": "4589caceb3f7996a6175d6f15f8038805450d8c448c56a8d95e4ccc9a5f872e5", + "tests/test_track_b_gross_benefits_fix_round_8_history.py": "cf4d84edf72b150dd343d408d84e60ebd70500c8e219bc00b1552d6292af4e91", + "tests/test_track_b_gross_benefits_fix_round_9_citations.py": "2ce5f13cd58a929583f659ec5bea6b2fbfa7216edd00291400773882118b9b4e", + "tests/test_track_b_gross_benefits_fix_round_9_outcomes.py": "139a90841182ca8a1bbece8acd3b30df68f7d88cef833fd092c202b22017a3e6", + "tests/test_track_b_gross_benefits_fix_round_9_validation.py": "0d420e98106ffe4ce7d9f1f0ae121488c4aca9ce1e1a3d941bc5aff0083efd92" + }, + "exit_code": 1, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "test_sha256_after": { + "tests/test_track_b_gross_benefits_fix_round_1.py": "9275a8a4963ce7ed086482644d044a927100efcbeb5a05315d9cc6394168ee8c", + "tests/test_track_b_gross_benefits_fix_round_10_api.py": "227fde023692f1c73a3eeb6de75213468c8e5e160ade3536bf5b7fb688c4ded6", + "tests/test_track_b_gross_benefits_fix_round_10_helpers.py": "e5014776670ca9b552de756c63976e606290fb4fad85a1501b017700a05c8fdb", + "tests/test_track_b_gross_benefits_fix_round_10_objects.py": "7576cc18923ad3ff38d0f44379637e822008a92cc9968d52f47b991e56fb9cfb", + "tests/test_track_b_gross_benefits_fix_round_10_parameters.py": "981eced43d10a6720ccab0292c4a8c281b9ac9bf7d83132f6666254d7a4b72ee", + "tests/test_track_b_gross_benefits_fix_round_11_roles.py": "d26fd86d7067eb7f4f97e1537110eab5223104ad817c3470a9eae022a90dfc73", + "tests/test_track_b_gross_benefits_fix_round_11_seals.py": "937b07b094816eade9bf072595ede18b1b109db527de9805c3a3cb3d333ba4b5", + "tests/test_track_b_gross_benefits_fix_round_12_contract.py": "9779ae3b22cf12daf6727cd21a6bcb12afbf3cfd34c84209bd406942a0c089e1", + "tests/test_track_b_gross_benefits_fix_round_13_audit.py": "fb04098e3982aca18b439f2df148bee6333ce20406fe773da0858731a6c94ff0", + "tests/test_track_b_gross_benefits_fix_round_13_boundary.py": "acac7951783a0e11140e717feab3924973e290e58857396dfab9c0b4319a5e8d", + "tests/test_track_b_gross_benefits_fix_round_13_guard.py": "e5fabfda3fcab2ba9e0347449278a21b9cfc1f89645e1ab148cb4a23da9e7c2e", + "tests/test_track_b_gross_benefits_fix_round_15_arguments.py": "16d5a875f4271839799738a89f2b904084bc0847eb25cd397168cea570be6d54", + "tests/test_track_b_gross_benefits_fix_round_15_collections.py": "2206b9734458774d581d3d20bfb50f1d517fd1b7d8191225cf5cacbca6561e58", + "tests/test_track_b_gross_benefits_fix_round_15_receivers.py": "3de91e8701ab82a3063be9eb859e6cd0058c7d3a35ac93dce9e110e0959061ff", + "tests/test_track_b_gross_benefits_fix_round_2_care.py": "7e983b28cdd1ba2c03935858610788754de66fb9489fef46672ebbf3d566225e", + "tests/test_track_b_gross_benefits_fix_round_2_history.py": "17fb81a1d18ad90ccf99cc841360aec524822cc2404e03d33cfbbab3a830b3a5", + "tests/test_track_b_gross_benefits_fix_round_2_periods.py": "21030c220e1b4690ac3d6754dcd9baddc23b33e824e07a842673c4128b7e6b09", + "tests/test_track_b_gross_benefits_fix_round_3_rates.py": "1c638ac3d5f0b0d25b49d1abf4924d9fff45bcf5ce25366616a60d3f060faa16", + "tests/test_track_b_gross_benefits_fix_round_4_care_floor.py": "d137d59fb7af48f21fda7b4e3aaf9a991d43b295930b5f341cc7cd595b875401", + "tests/test_track_b_gross_benefits_fix_round_4_divorced_care.py": "cd50249e8d84a2bbb61901f08b84310d48b8d390495beadfe5112144143b4fd7", + "tests/test_track_b_gross_benefits_fix_round_5_care_history.py": "a3e73482553c5fb804adaba8ed0d5e4d1520470f384bb58a0fe46cb41e58eb07", + "tests/test_track_b_gross_benefits_fix_round_5_cohorts.py": "f5be483a533e47edcb58dc05bc202390e959e6ece7eca3ff11728aa46b00409d", + "tests/test_track_b_gross_benefits_fix_round_6_care_note.py": "b2d158f37d35aaa63a6a1293345010bc4445c3b20c480c035932bf9725a91eca", + "tests/test_track_b_gross_benefits_fix_round_6_cohorts.py": "b06e95d0a8a93af3e60b96222381b46377673e407385958b5120817bc60c2e84", + "tests/test_track_b_gross_benefits_fix_round_7_boundary.py": "b2c875f010c402e4f373be5712a39affd87b6533805ed33bf63dbea60b1e6ae5", + "tests/test_track_b_gross_benefits_fix_round_7_cohorts.py": "0eb73d51e1f7a61f76917df670f89bdade0e5f45f4c044be30673dff2494ca31", + "tests/test_track_b_gross_benefits_fix_round_7_history.py": "fc6a7b5281e2f429a8e9f92c595b4491aa2de4229630fc5ca15eab333bacab26", + "tests/test_track_b_gross_benefits_fix_round_8_entries.py": "4589caceb3f7996a6175d6f15f8038805450d8c448c56a8d95e4ccc9a5f872e5", + "tests/test_track_b_gross_benefits_fix_round_8_history.py": "cf4d84edf72b150dd343d408d84e60ebd70500c8e219bc00b1552d6292af4e91", + "tests/test_track_b_gross_benefits_fix_round_9_citations.py": "2ce5f13cd58a929583f659ec5bea6b2fbfa7216edd00291400773882118b9b4e", + "tests/test_track_b_gross_benefits_fix_round_9_outcomes.py": "139a90841182ca8a1bbece8acd3b30df68f7d88cef833fd092c202b22017a3e6", + "tests/test_track_b_gross_benefits_fix_round_9_validation.py": "0d420e98106ffe4ce7d9f1f0ae121488c4aca9ce1e1a3d941bc5aff0083efd92" + }, + "log": { + "path": "scratch/review/round5-g_boundary.log", + "sha256": "ce0312836fe1342a937f8a5d0fa9f03133f9999a14712ed68249792dc78fac8f" + }, + "summary": "1 failed, 7240 passed in 1961.73s (0:32:41)", + "audit": { + "processes": 1, + "counts": { + "open": 2684, + "restricted_open": 0, + "restricted_import": 0, + "subprocess.Popen": 0, + "os.system": 0 + } + }, + "source_changed_during_run": true, + "source_epoch_note": "Only invalid aged own-RIB widow declarations missing both cohort fields reach the added canonical input-error guard. Valid declarations add no validation; public G rejects these inputs before the helper. Broad gates imported the before source; final targeted runs exercise the after source.", + "tests_changed_during_run": false + }, + "g_rules": { + "partition": "g_rules", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=short", + "tests/test_track_b_gross_benefits.py", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py", + "tests/test_track_b_gross_benefits_deduction_cap.py", + "tests/test_track_b_gross_benefits_deductions.py", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", + "tests/test_track_b_gross_benefits_dwb.py", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py", + "tests/test_track_b_gross_benefits_oracle.py", + "tests/test_track_b_gross_benefits_own_input_order.py", + "tests/test_track_b_gross_benefits_parents_ieds.py", + "tests/test_track_b_gross_benefits_parisi.py", + "tests/test_track_b_gross_benefits_payment_review.py", + "tests/test_track_b_gross_benefits_properties.py", + "tests/test_track_b_gross_benefits_registry.py", + "tests/test_track_b_gross_benefits_review.py", + "tests/test_track_b_gross_benefits_saving_absence.py", + "tests/test_track_b_gross_benefits_savings.py", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py", + "tests/test_track_b_gross_benefits_sources_20261011.py", + "tests/test_track_b_gross_benefits_ssfa.py", + "tests/test_track_b_input_schema.py", + "tests/test_track_b_refusal_notes.py" + ], + "environment": { + "OMP_NUM_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-g_rules", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-g_rules" + }, + "named_modules": [ + "tests/test_track_b_gross_benefits.py", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py", + "tests/test_track_b_gross_benefits_deduction_cap.py", + "tests/test_track_b_gross_benefits_deductions.py", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", + "tests/test_track_b_gross_benefits_dwb.py", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py", + "tests/test_track_b_gross_benefits_oracle.py", + "tests/test_track_b_gross_benefits_own_input_order.py", + "tests/test_track_b_gross_benefits_parents_ieds.py", + "tests/test_track_b_gross_benefits_parisi.py", + "tests/test_track_b_gross_benefits_payment_review.py", + "tests/test_track_b_gross_benefits_properties.py", + "tests/test_track_b_gross_benefits_registry.py", + "tests/test_track_b_gross_benefits_review.py", + "tests/test_track_b_gross_benefits_saving_absence.py", + "tests/test_track_b_gross_benefits_savings.py", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py", + "tests/test_track_b_gross_benefits_sources_20261011.py", + "tests/test_track_b_gross_benefits_ssfa.py", + "tests/test_track_b_input_schema.py", + "tests/test_track_b_refusal_notes.py" + ], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "test_sha256_before": { + "tests/test_track_b_gross_benefits.py": "de0946a014d054bd47f30dadaf675105aebb1dd562209c4002dee05354628286", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py": "5d9fe8c5cb052d39c82249d6efcf4d88dace5ec68538340e7000f73af5e016df", + "tests/test_track_b_gross_benefits_deduction_cap.py": "6965d3e258ad31ad9ee496eb745885d3f6fa7b7c4ec2a48e441d0318588ec30e", + "tests/test_track_b_gross_benefits_deductions.py": "b6f0493ecbb19434c09de42ff7e62a87b85818ea6dc8a5cde78963d780598e02", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py": "5cebe4f986fa7d01d7769c1d1db0581b54ae88e7c4710409285e12393244fdab", + "tests/test_track_b_gross_benefits_dwb.py": "61b6270fdd9a6d156d31194535797d1f59c092943ecdb3773787d1471e2bb80a", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py": "bc1b396f0cc729d56d06cafc0e8a5e196864268ec948f9833039a53cb034c1f4", + "tests/test_track_b_gross_benefits_oracle.py": "d4b88ec7a6945e76499e50266448894e99809737b1bc2a55de060bf03f591d24", + "tests/test_track_b_gross_benefits_own_input_order.py": "3bb4bd7fb3b7567109ed3f132f6b8a775e43e90a04aa4a2a0fa8542c78575291", + "tests/test_track_b_gross_benefits_parents_ieds.py": "98e5f81c99b3b80332db203c07db680b09a633c3d34bc58d15ee986f252bf73c", + "tests/test_track_b_gross_benefits_parisi.py": "4f446013cc7bd9f2ae8dc4dfe3ee59d952a9f5e7d2aaa2f104497dfe36425c1a", + "tests/test_track_b_gross_benefits_payment_review.py": "4c239c468e06a0c522151e182693a91024f61b7f38e49bbd7f03c66b01889dd7", + "tests/test_track_b_gross_benefits_properties.py": "483d502f88457f89cbc4f13b2904718eae59997a81a1189f51b0fbe635c54cfb", + "tests/test_track_b_gross_benefits_registry.py": "93dd3a5d3750cea367ddfe6ccc42f08084ae2f09e6278a1de728baf6a8ddc4df", + "tests/test_track_b_gross_benefits_review.py": "e602dfbf58ec57e25a1270d0e26bb3c5204045e43ab726266e0ef805abe2cd7c", + "tests/test_track_b_gross_benefits_saving_absence.py": "e6078f978ee7bf1d0802dde67c2de94397fd3e9cd142b2c96d6d504ceb0a6862", + "tests/test_track_b_gross_benefits_savings.py": "607bf6cb7415d03bd7b863673d7b9d403841d175a1684f211a562536f4f4755b", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py": "d84130cc73468a8b3f8223c5526f0e982597e552c40e714d691608d32da59233", + "tests/test_track_b_gross_benefits_sources_20261011.py": "e3291d0b6bf497a20835800c4d6ee833854e5edf5b25229932e7a142f8e51a13", + "tests/test_track_b_gross_benefits_ssfa.py": "07fee44e63376a58508296b6f66d1fc20adfa1c88c8cd110a1d5fc45dc4f1ebf", + "tests/test_track_b_input_schema.py": "d638f55a4de888d49cf236e5b58086ef773e63365e5f5ba5578aef3b9d7a8d32", + "tests/test_track_b_refusal_notes.py": "5c765432752317684e4059f2d45a2a95fd03ff327fb1225f853267588fc76abe" + }, + "exit_code": 1, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "test_sha256_after": { + "tests/test_track_b_gross_benefits.py": "de0946a014d054bd47f30dadaf675105aebb1dd562209c4002dee05354628286", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py": "5d9fe8c5cb052d39c82249d6efcf4d88dace5ec68538340e7000f73af5e016df", + "tests/test_track_b_gross_benefits_deduction_cap.py": "6965d3e258ad31ad9ee496eb745885d3f6fa7b7c4ec2a48e441d0318588ec30e", + "tests/test_track_b_gross_benefits_deductions.py": "b6f0493ecbb19434c09de42ff7e62a87b85818ea6dc8a5cde78963d780598e02", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py": "5cebe4f986fa7d01d7769c1d1db0581b54ae88e7c4710409285e12393244fdab", + "tests/test_track_b_gross_benefits_dwb.py": "61b6270fdd9a6d156d31194535797d1f59c092943ecdb3773787d1471e2bb80a", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py": "bc1b396f0cc729d56d06cafc0e8a5e196864268ec948f9833039a53cb034c1f4", + "tests/test_track_b_gross_benefits_oracle.py": "d4b88ec7a6945e76499e50266448894e99809737b1bc2a55de060bf03f591d24", + "tests/test_track_b_gross_benefits_own_input_order.py": "3bb4bd7fb3b7567109ed3f132f6b8a775e43e90a04aa4a2a0fa8542c78575291", + "tests/test_track_b_gross_benefits_parents_ieds.py": "98e5f81c99b3b80332db203c07db680b09a633c3d34bc58d15ee986f252bf73c", + "tests/test_track_b_gross_benefits_parisi.py": "4f446013cc7bd9f2ae8dc4dfe3ee59d952a9f5e7d2aaa2f104497dfe36425c1a", + "tests/test_track_b_gross_benefits_payment_review.py": "4c239c468e06a0c522151e182693a91024f61b7f38e49bbd7f03c66b01889dd7", + "tests/test_track_b_gross_benefits_properties.py": "483d502f88457f89cbc4f13b2904718eae59997a81a1189f51b0fbe635c54cfb", + "tests/test_track_b_gross_benefits_registry.py": "93dd3a5d3750cea367ddfe6ccc42f08084ae2f09e6278a1de728baf6a8ddc4df", + "tests/test_track_b_gross_benefits_review.py": "e602dfbf58ec57e25a1270d0e26bb3c5204045e43ab726266e0ef805abe2cd7c", + "tests/test_track_b_gross_benefits_saving_absence.py": "e6078f978ee7bf1d0802dde67c2de94397fd3e9cd142b2c96d6d504ceb0a6862", + "tests/test_track_b_gross_benefits_savings.py": "607bf6cb7415d03bd7b863673d7b9d403841d175a1684f211a562536f4f4755b", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py": "d84130cc73468a8b3f8223c5526f0e982597e552c40e714d691608d32da59233", + "tests/test_track_b_gross_benefits_sources_20261011.py": "e3291d0b6bf497a20835800c4d6ee833854e5edf5b25229932e7a142f8e51a13", + "tests/test_track_b_gross_benefits_ssfa.py": "07fee44e63376a58508296b6f66d1fc20adfa1c88c8cd110a1d5fc45dc4f1ebf", + "tests/test_track_b_input_schema.py": "d638f55a4de888d49cf236e5b58086ef773e63365e5f5ba5578aef3b9d7a8d32", + "tests/test_track_b_refusal_notes.py": "5c765432752317684e4059f2d45a2a95fd03ff327fb1225f853267588fc76abe" + }, + "log": { + "path": "scratch/review/round5-g_rules.log", + "sha256": "6fe3d37f582782b5a2e36db2d7e359eb2f4ccc6065e404ddffb6fcd4a79fb8f6" + }, + "summary": "2 failed, 1616 passed in 1568.16s (0:26:08)", + "audit": { + "processes": 2, + "counts": { + "open": 3101, + "restricted_open": 0, + "restricted_import": 0, + "subprocess.Popen": 2, + "os.system": 0 + } + }, + "source_changed_during_run": true, + "source_epoch_note": "Only invalid aged own-RIB widow declarations missing both cohort fields reach the added canonical input-error guard. Valid declarations add no validation; public G rejects these inputs before the helper. Broad gates imported the before source; final targeted runs exercise the after source.", + "tests_changed_during_run": false + }, + "ret_r3": { + "partition": "ret_r3", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=short", + "tests/test_track_b_arf.py", + "tests/test_track_b_arf_properties.py", + "tests/test_track_b_r3_fix_round_13.py", + "tests/test_track_b_r3_provenance.py", + "tests/test_track_b_r3_sources.py", + "tests/test_track_b_r3_validation_once.py", + "tests/test_track_b_recompute.py", + "tests/test_track_b_recompute_properties.py", + "tests/test_track_b_ret_differential.py", + "tests/test_track_b_ret_fra_facts.py", + "tests/test_track_b_ret_grace.py", + "tests/test_track_b_ret_grace_differential.py", + "tests/test_track_b_ret_grace_provenance.py", + "tests/test_track_b_ret_ledger.py", + "tests/test_track_b_ret_ledger_deductions.py", + "tests/test_track_b_ret_ledger_fix_round_2.py", + "tests/test_track_b_ret_ledger_fix_round_4.py", + "tests/test_track_b_ret_ledger_properties.py", + "tests/test_track_b_ret_ledger_readings.py", + "tests/test_track_b_ret_ledger_sources.py", + "tests/test_track_b_ret_params.py", + "tests/test_track_b_ret_ledger_fix_round_5.py" + ], + "environment": { + "OMP_NUM_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-ret_r3", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-ret_r3" + }, + "named_modules": [ + "tests/test_track_b_arf.py", + "tests/test_track_b_arf_properties.py", + "tests/test_track_b_r3_fix_round_13.py", + "tests/test_track_b_r3_provenance.py", + "tests/test_track_b_r3_sources.py", + "tests/test_track_b_r3_validation_once.py", + "tests/test_track_b_recompute.py", + "tests/test_track_b_recompute_properties.py", + "tests/test_track_b_ret_differential.py", + "tests/test_track_b_ret_fra_facts.py", + "tests/test_track_b_ret_grace.py", + "tests/test_track_b_ret_grace_differential.py", + "tests/test_track_b_ret_grace_provenance.py", + "tests/test_track_b_ret_ledger.py", + "tests/test_track_b_ret_ledger_deductions.py", + "tests/test_track_b_ret_ledger_fix_round_2.py", + "tests/test_track_b_ret_ledger_fix_round_4.py", + "tests/test_track_b_ret_ledger_properties.py", + "tests/test_track_b_ret_ledger_readings.py", + "tests/test_track_b_ret_ledger_sources.py", + "tests/test_track_b_ret_params.py", + "tests/test_track_b_ret_ledger_fix_round_5.py" + ], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "test_sha256_before": { + "tests/test_track_b_arf.py": "292587c9ee1d160ad6c66da6e388e3a0b2bf4c9831f8ad3b18853c802f5bd68e", + "tests/test_track_b_arf_properties.py": "d1346b68bd07b469cea6357e1881d743e3a90c66e04080fc19fd66b44da7b68e", + "tests/test_track_b_r3_fix_round_13.py": "bfb81d8316574e9df0e2e7cb9f890e1b9f584cac2cd17e025825580e219cebc7", + "tests/test_track_b_r3_provenance.py": "58243309d56acb9dc38e9bf5a701e79ac961ac062e0d37690b12a561592245c9", + "tests/test_track_b_r3_sources.py": "6300b1a4075a0f2549cce4db0aab25d6908eba9071a5a2da3bbfc6d020dd04ba", + "tests/test_track_b_r3_validation_once.py": "ad28687b52c6386e7c5e28525eac12dc9a4ba62b75d18e066d5bdac1252624c0", + "tests/test_track_b_recompute.py": "06db2b43c6c13d679a71a6d2176dc3ee13fce8fc1645684fcbe7c582f9e54f9c", + "tests/test_track_b_recompute_properties.py": "ced431cb4fd0de82a7cde6ff63c6a38eaad1649939d364b1023dcc81aff30759", + "tests/test_track_b_ret_differential.py": "8e38e1040d61d9f0262bbe25c5c17e0f608c433cb29ab898b7f954358bcf1e12", + "tests/test_track_b_ret_fra_facts.py": "7bfb53be6660bbfad0831904d5b39a3e8d997216308b136959ece10bb04c72a8", + "tests/test_track_b_ret_grace.py": "772f6b94187593549cd21a2dbb19a75f998fb840f6b6eb3a97bbeca3f36636dc", + "tests/test_track_b_ret_grace_differential.py": "fbf01f2c6e76f2cc8a60bad5e9c9ac5c4da0c68013578b91de9488aa2623abf5", + "tests/test_track_b_ret_grace_provenance.py": "8cf4446fb0bb6da77a7b84815caafe595ec81b9b7a2cc1e56f686cd25f0e77a5", + "tests/test_track_b_ret_ledger.py": "6d6684e63aa3d56874fb0fd174867d1e2b41e54119ad8077c2e6b689ca723065", + "tests/test_track_b_ret_ledger_deductions.py": "a3fcc50166b867f9d3d719bcf611880cba169b3b99f6bf695ff397a36b2fcd2e", + "tests/test_track_b_ret_ledger_fix_round_2.py": "62a81110909ddebfa77f65078d685464f553c37de89cb88efd743ca406b1aa70", + "tests/test_track_b_ret_ledger_fix_round_4.py": "0c304d939709da534e89c374ff9687548531796c4716d51dd5e7e232346b6681", + "tests/test_track_b_ret_ledger_properties.py": "803433fd9d3aa7601b45e2f5346d716254409710e9f9d3ac61f1a42d87cc7d64", + "tests/test_track_b_ret_ledger_readings.py": "630bdd1d5f53d93c63674192f205e17edff601f8dcc8d941348db98cf094bdad", + "tests/test_track_b_ret_ledger_sources.py": "ab6b6d66d370c93e5b2cc82b88670f48eb5bceeb0d313c36550986c3ff1844b6", + "tests/test_track_b_ret_params.py": "57a1be52d32c3549d711aba4f88f42cdb0affd98bc3b3d5bf7e607fc0b2c3514", + "tests/test_track_b_ret_ledger_fix_round_5.py": "0bb49fe3cc7898c435615d9c0f33bf0cfec1a8e8cba8f88a66a5e45d1938f6b5" + }, + "exit_code": 1, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "test_sha256_after": { + "tests/test_track_b_arf.py": "292587c9ee1d160ad6c66da6e388e3a0b2bf4c9831f8ad3b18853c802f5bd68e", + "tests/test_track_b_arf_properties.py": "d1346b68bd07b469cea6357e1881d743e3a90c66e04080fc19fd66b44da7b68e", + "tests/test_track_b_r3_fix_round_13.py": "bfb81d8316574e9df0e2e7cb9f890e1b9f584cac2cd17e025825580e219cebc7", + "tests/test_track_b_r3_provenance.py": "58243309d56acb9dc38e9bf5a701e79ac961ac062e0d37690b12a561592245c9", + "tests/test_track_b_r3_sources.py": "6300b1a4075a0f2549cce4db0aab25d6908eba9071a5a2da3bbfc6d020dd04ba", + "tests/test_track_b_r3_validation_once.py": "ad28687b52c6386e7c5e28525eac12dc9a4ba62b75d18e066d5bdac1252624c0", + "tests/test_track_b_recompute.py": "06db2b43c6c13d679a71a6d2176dc3ee13fce8fc1645684fcbe7c582f9e54f9c", + "tests/test_track_b_recompute_properties.py": "ced431cb4fd0de82a7cde6ff63c6a38eaad1649939d364b1023dcc81aff30759", + "tests/test_track_b_ret_differential.py": "8e38e1040d61d9f0262bbe25c5c17e0f608c433cb29ab898b7f954358bcf1e12", + "tests/test_track_b_ret_fra_facts.py": "7bfb53be6660bbfad0831904d5b39a3e8d997216308b136959ece10bb04c72a8", + "tests/test_track_b_ret_grace.py": "772f6b94187593549cd21a2dbb19a75f998fb840f6b6eb3a97bbeca3f36636dc", + "tests/test_track_b_ret_grace_differential.py": "fbf01f2c6e76f2cc8a60bad5e9c9ac5c4da0c68013578b91de9488aa2623abf5", + "tests/test_track_b_ret_grace_provenance.py": "8cf4446fb0bb6da77a7b84815caafe595ec81b9b7a2cc1e56f686cd25f0e77a5", + "tests/test_track_b_ret_ledger.py": "6d6684e63aa3d56874fb0fd174867d1e2b41e54119ad8077c2e6b689ca723065", + "tests/test_track_b_ret_ledger_deductions.py": "a3fcc50166b867f9d3d719bcf611880cba169b3b99f6bf695ff397a36b2fcd2e", + "tests/test_track_b_ret_ledger_fix_round_2.py": "62a81110909ddebfa77f65078d685464f553c37de89cb88efd743ca406b1aa70", + "tests/test_track_b_ret_ledger_fix_round_4.py": "0c304d939709da534e89c374ff9687548531796c4716d51dd5e7e232346b6681", + "tests/test_track_b_ret_ledger_properties.py": "803433fd9d3aa7601b45e2f5346d716254409710e9f9d3ac61f1a42d87cc7d64", + "tests/test_track_b_ret_ledger_readings.py": "630bdd1d5f53d93c63674192f205e17edff601f8dcc8d941348db98cf094bdad", + "tests/test_track_b_ret_ledger_sources.py": "ab6b6d66d370c93e5b2cc82b88670f48eb5bceeb0d313c36550986c3ff1844b6", + "tests/test_track_b_ret_params.py": "57a1be52d32c3549d711aba4f88f42cdb0affd98bc3b3d5bf7e607fc0b2c3514", + "tests/test_track_b_ret_ledger_fix_round_5.py": "add7304293c593394d0112bf4d92e77acb1a7c49140cc51bfcd81a758c4dc8d9" + }, + "log": { + "path": "scratch/review/round5-ret_r3.log", + "sha256": "d550be5ab9dcdba9e80f1d5c8e0c971928b84955a2dde9c1dc706ac47f21a517" + }, + "summary": "1 failed, 3246 passed in 2496.03s (0:41:36)", + "audit": { + "processes": 1, + "counts": { + "open": 1468, + "restricted_open": 0, + "restricted_import": 0, + "subprocess.Popen": 1, + "os.system": 0 + } + }, + "source_changed_during_run": true, + "source_epoch_note": "Only invalid aged own-RIB widow declarations missing both cohort fields reach the added canonical input-error guard. Valid declarations add no validation; public G rejects these inputs before the helper. Broad gates imported the before source; final targeted runs exercise the after source.", + "tests_changed_during_run": true + }, + "g_report": { + "partition": "g_report", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=short", + "tests/test_track_b_gross_benefits_conformance_report.py" + ], + "environment": { + "OMP_NUM_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-g_report", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-g_report" + }, + "named_modules": [ + "tests/test_track_b_gross_benefits_conformance_report.py" + ], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "test_sha256_before": { + "tests/test_track_b_gross_benefits_conformance_report.py": "7ec6f605783c15c88abbb0834ff894645fe14e2956239c83532cd88132e699c8" + }, + "exit_code": 0, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "73ebc6a9dac1d9d05d2ef1aca002dc0505755d466b2c0153fb1f929cd0f1b690", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "test_sha256_after": { + "tests/test_track_b_gross_benefits_conformance_report.py": "7ec6f605783c15c88abbb0834ff894645fe14e2956239c83532cd88132e699c8" + }, + "log": { + "path": "scratch/review/round5-g_report.log", + "sha256": "2ebf34f92405857f9abd3c95804d8a0f9a713d25ad3eae626012ed01f8d9ae79" + }, + "summary": "54 passed in 2686.60s (0:44:46)", + "audit": { + "processes": 1, + "counts": { + "open": 872, + "restricted_open": 0, + "restricted_import": 0, + "subprocess.Popen": 0, + "os.system": 0 + } + }, + "source_changed_during_run": true, + "source_epoch_note": "Only invalid aged own-RIB widow declarations missing both cohort fields reach the added canonical input-error guard. Valid declarations add no validation; public G rejects these inputs before the helper. Broad gates imported the before source; final targeted runs exercise the after source.", + "tests_changed_during_run": false + }, + "g_boundary_retry": { + "partition": "g_boundary_retry", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=short", + "tests/test_track_b_gross_benefits_fix_round_15_collections.py::test_membership_months_collapse_equivalent_month_encodings" + ], + "environment": { + "OMP_NUM_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-g_boundary_retry", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-g_boundary_retry" + }, + "named_modules": [ + "tests/test_track_b_gross_benefits_fix_round_15_collections.py" + ], + "selected_nodes": [ + "tests/test_track_b_gross_benefits_fix_round_15_collections.py::test_membership_months_collapse_equivalent_month_encodings" + ], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "73ebc6a9dac1d9d05d2ef1aca002dc0505755d466b2c0153fb1f929cd0f1b690", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "test_sha256_before": { + "tests/test_track_b_gross_benefits_fix_round_15_collections.py": "2206b9734458774d581d3d20bfb50f1d517fd1b7d8191225cf5cacbca6561e58" + }, + "exit_code": 0, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "73ebc6a9dac1d9d05d2ef1aca002dc0505755d466b2c0153fb1f929cd0f1b690", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "test_sha256_after": { + "tests/test_track_b_gross_benefits_fix_round_15_collections.py": "2206b9734458774d581d3d20bfb50f1d517fd1b7d8191225cf5cacbca6561e58" + }, + "log": { + "path": "scratch/review/round5-g_boundary_retry.log", + "sha256": "8eb0752aea8d989b194bf3c71432fb2517158c4923b561c044acd3afccdd0cc6" + }, + "summary": "4 passed in 25.76s", + "audit": { + "processes": 1, + "counts": { + "open": 929, + "restricted_open": 0, + "restricted_import": 0, + "subprocess.Popen": 0, + "os.system": 0 + } + }, + "source_changed_during_run": false, + "source_epoch_note": "Only invalid aged own-RIB widow declarations missing both cohort fields reach the added canonical input-error guard. Valid declarations add no validation; public G rejects these inputs before the helper. Broad gates imported the before source; final targeted runs exercise the after source.", + "tests_changed_during_run": false + }, + "composition_corrected": { + "partition": "composition_corrected", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=short", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py" + ], + "environment": { + "OMP_NUM_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-composition_corrected", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-composition_corrected" + }, + "named_modules": [ + "tests/test_track_b_gross_benefits_fix_round_4_composition.py" + ], + "selected_nodes": [ + "tests/test_track_b_gross_benefits_fix_round_4_composition.py" + ], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "73ebc6a9dac1d9d05d2ef1aca002dc0505755d466b2c0153fb1f929cd0f1b690", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "test_sha256_before": { + "tests/test_track_b_gross_benefits_fix_round_4_composition.py": "b6b46422ea05cdfc79537d406aee5b2589732c6fb3dad5165a2a6cd807df25cf" + }, + "exit_code": 0, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "73ebc6a9dac1d9d05d2ef1aca002dc0505755d466b2c0153fb1f929cd0f1b690", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "test_sha256_after": { + "tests/test_track_b_gross_benefits_fix_round_4_composition.py": "b6b46422ea05cdfc79537d406aee5b2589732c6fb3dad5165a2a6cd807df25cf" + }, + "log": { + "path": "scratch/review/round5-composition_corrected.log", + "sha256": "903ad8196b44fca8fa6ccc5c0eee074cc80bf6bfc774150c44360bd8327ae955" + }, + "summary": "95 passed in 89.79s (0:01:29)", + "audit": { + "processes": 1, + "counts": { + "open": 893, + "restricted_open": 0, + "restricted_import": 0, + "subprocess.Popen": 0, + "os.system": 0 + } + }, + "source_changed_during_run": false, + "source_epoch_note": "Only invalid aged own-RIB widow declarations missing both cohort fields reach the added canonical input-error guard. Valid declarations add no validation; public G rejects these inputs before the helper. Broad gates imported the before source; final targeted runs exercise the after source.", + "tests_changed_during_run": false + }, + "composition_style": { + "partition": "composition_style", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=short", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py::test_nh_only_acceptance_still_rejects_impossible_reservation" + ], + "environment": { + "OMP_NUM_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-composition_style", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-composition_style" + }, + "named_modules": [ + "tests/test_track_b_gross_benefits_fix_round_4_composition.py" + ], + "selected_nodes": [ + "tests/test_track_b_gross_benefits_fix_round_4_composition.py::test_nh_only_acceptance_still_rejects_impossible_reservation" + ], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256_before": { + "tests/test_track_b_gross_benefits_fix_round_4_composition.py": "74105c3ab4c8c7e9e3fc0be9f4eb078a5c7913683c13974aa86fa598c2eda950" + }, + "exit_code": 0, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256_after": { + "tests/test_track_b_gross_benefits_fix_round_4_composition.py": "74105c3ab4c8c7e9e3fc0be9f4eb078a5c7913683c13974aa86fa598c2eda950" + }, + "log": { + "path": "scratch/review/round5-composition_style.log", + "sha256": "fa4140b194354645f4d684068af40ac9eedb2fae1392526b97b14b200e00526c" + }, + "summary": "6 passed in 4.20s", + "audit": { + "processes": 1, + "counts": { + "open": 842, + "restricted_open": 0, + "restricted_import": 0, + "subprocess.Popen": 0, + "os.system": 0 + } + }, + "source_changed_during_run": false, + "source_epoch_note": "Only invalid aged own-RIB widow declarations missing both cohort fields reach the added canonical input-error guard. Valid declarations add no validation; public G rejects these inputs before the helper. Broad gates imported the before source; final targeted runs exercise the after source.", + "tests_changed_during_run": false + }, + "post_guard": { + "partition": "post_guard", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py", + "tests/test_track_b_input_schema.py", + "tests/test_track_b_ret_fra_facts.py", + "tests/test_track_b_r3_validation_once.py", + "tests/test_track_b_ret_ledger_fix_round_4.py" + ], + "environment": { + "OMP_NUM_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-post_guard", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-post_guard" + }, + "named_modules": [ + "tests/test_track_b_ret_ledger_fix_round_5.py", + "tests/test_track_b_input_schema.py", + "tests/test_track_b_ret_fra_facts.py", + "tests/test_track_b_r3_validation_once.py", + "tests/test_track_b_ret_ledger_fix_round_4.py" + ], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "test_sha256_before": { + "tests/test_track_b_ret_ledger_fix_round_5.py": "36749ab4c6d9e98e49d813b659e5b6e7a5097c62df1a7dd2ab67ea874104edd9", + "tests/test_track_b_input_schema.py": "d638f55a4de888d49cf236e5b58086ef773e63365e5f5ba5578aef3b9d7a8d32", + "tests/test_track_b_ret_fra_facts.py": "7bfb53be6660bbfad0831904d5b39a3e8d997216308b136959ece10bb04c72a8", + "tests/test_track_b_r3_validation_once.py": "ad28687b52c6386e7c5e28525eac12dc9a4ba62b75d18e066d5bdac1252624c0", + "tests/test_track_b_ret_ledger_fix_round_4.py": "0c304d939709da534e89c374ff9687548531796c4716d51dd5e7e232346b6681" + }, + "exit_code": 0, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "73ebc6a9dac1d9d05d2ef1aca002dc0505755d466b2c0153fb1f929cd0f1b690", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "test_sha256_after": { + "tests/test_track_b_ret_ledger_fix_round_5.py": "8c20bd5302276af3479706c0c5e470fce6f02b0b319463bffc0f63c88b4d00ee", + "tests/test_track_b_input_schema.py": "d638f55a4de888d49cf236e5b58086ef773e63365e5f5ba5578aef3b9d7a8d32", + "tests/test_track_b_ret_fra_facts.py": "7bfb53be6660bbfad0831904d5b39a3e8d997216308b136959ece10bb04c72a8", + "tests/test_track_b_r3_validation_once.py": "ad28687b52c6386e7c5e28525eac12dc9a4ba62b75d18e066d5bdac1252624c0", + "tests/test_track_b_ret_ledger_fix_round_4.py": "0c304d939709da534e89c374ff9687548531796c4716d51dd5e7e232346b6681" + }, + "log": { + "path": "scratch/review/round5-post_guard.log", + "sha256": "16854e85fb72bedd7ae56d6ee0cb32cc57d746f8bb3c9631fee30868eac89b00" + }, + "summary": "1483 passed in 482.84s (0:08:02)", + "audit": { + "processes": 1, + "counts": { + "open": 1039, + "restricted_open": 0, + "restricted_import": 0, + "subprocess.Popen": 0, + "os.system": 0 + } + }, + "source_changed_during_run": true, + "source_epoch_note": "Only invalid aged own-RIB widow declarations missing both cohort fields reach the added canonical input-error guard. Valid declarations add no validation; public G rejects these inputs before the helper. Broad gates imported the before source; final targeted runs exercise the after source.", + "tests_changed_during_run": true + }, + "final_deferred": { + "partition": "final_deferred", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py", + "tests/test_track_b_input_schema.py", + "tests/test_track_b_ret_fra_facts.py", + "tests/test_track_b_r3_validation_once.py" + ], + "environment": { + "OMP_NUM_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-final_deferred", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-final_deferred" + }, + "named_modules": [ + "tests/test_track_b_ret_ledger_fix_round_5.py", + "tests/test_track_b_input_schema.py", + "tests/test_track_b_ret_fra_facts.py", + "tests/test_track_b_r3_validation_once.py" + ], + "selected_nodes": [ + "tests/test_track_b_ret_ledger_fix_round_5.py", + "tests/test_track_b_input_schema.py", + "tests/test_track_b_ret_fra_facts.py", + "tests/test_track_b_r3_validation_once.py" + ], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "cd71ea6dd462b711f3341ce8fec2c8a0b15214672989b831cd0e0d7e780542ca", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "test_sha256_before": { + "tests/test_track_b_ret_ledger_fix_round_5.py": "0166ad1510b8c293e19bba3b17b492cfc6205d9d7836589e77b94f5d2105ff2e", + "tests/test_track_b_input_schema.py": "d638f55a4de888d49cf236e5b58086ef773e63365e5f5ba5578aef3b9d7a8d32", + "tests/test_track_b_ret_fra_facts.py": "7bfb53be6660bbfad0831904d5b39a3e8d997216308b136959ece10bb04c72a8", + "tests/test_track_b_r3_validation_once.py": "ad28687b52c6386e7c5e28525eac12dc9a4ba62b75d18e066d5bdac1252624c0" + }, + "exit_code": 0, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "test_sha256_after": { + "tests/test_track_b_ret_ledger_fix_round_5.py": "add7304293c593394d0112bf4d92e77acb1a7c49140cc51bfcd81a758c4dc8d9", + "tests/test_track_b_input_schema.py": "d638f55a4de888d49cf236e5b58086ef773e63365e5f5ba5578aef3b9d7a8d32", + "tests/test_track_b_ret_fra_facts.py": "7bfb53be6660bbfad0831904d5b39a3e8d997216308b136959ece10bb04c72a8", + "tests/test_track_b_r3_validation_once.py": "ad28687b52c6386e7c5e28525eac12dc9a4ba62b75d18e066d5bdac1252624c0" + }, + "log": { + "path": "scratch/review/round5-final_deferred.log", + "sha256": "beae76b4517c7a3b207113e57efdace26d8260c6a72f1da23ddd61e91d9dd3c6" + }, + "summary": "1002 passed in 158.27s (0:02:38)", + "audit": { + "processes": 1, + "counts": { + "open": 1036, + "restricted_open": 0, + "restricted_import": 0, + "subprocess.Popen": 0, + "os.system": 0 + } + }, + "source_changed_during_run": true, + "source_epoch_note": "Only invalid aged own-RIB widow declarations missing both cohort fields reach the added canonical input-error guard. Valid declarations add no validation; public G rejects these inputs before the helper. Broad gates imported the before source; final targeted runs exercise the after source.", + "tests_changed_during_run": true + }, + "final_diagnostic": { + "partition": "final_diagnostic", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=short", + "tests/test_track_b_ret_ledger_deductions.py", + "tests/test_track_b_ret_ledger_fix_round_5.py", + "tests/test_track_b_input_schema.py", + "tests/test_track_b_ret_fra_facts.py", + "tests/test_track_b_r3_validation_once.py" + ], + "environment": { + "OMP_NUM_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-final_diagnostic", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-final_diagnostic" + }, + "named_modules": [ + "tests/test_track_b_ret_ledger_deductions.py", + "tests/test_track_b_ret_ledger_fix_round_5.py", + "tests/test_track_b_input_schema.py", + "tests/test_track_b_ret_fra_facts.py", + "tests/test_track_b_r3_validation_once.py" + ], + "selected_nodes": [ + "tests/test_track_b_ret_ledger_deductions.py", + "tests/test_track_b_ret_ledger_fix_round_5.py", + "tests/test_track_b_input_schema.py", + "tests/test_track_b_ret_fra_facts.py", + "tests/test_track_b_r3_validation_once.py" + ], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256_before": { + "tests/test_track_b_ret_ledger_deductions.py": "a3fcc50166b867f9d3d719bcf611880cba169b3b99f6bf695ff397a36b2fcd2e", + "tests/test_track_b_ret_ledger_fix_round_5.py": "add7304293c593394d0112bf4d92e77acb1a7c49140cc51bfcd81a758c4dc8d9", + "tests/test_track_b_input_schema.py": "d638f55a4de888d49cf236e5b58086ef773e63365e5f5ba5578aef3b9d7a8d32", + "tests/test_track_b_ret_fra_facts.py": "7bfb53be6660bbfad0831904d5b39a3e8d997216308b136959ece10bb04c72a8", + "tests/test_track_b_r3_validation_once.py": "ad28687b52c6386e7c5e28525eac12dc9a4ba62b75d18e066d5bdac1252624c0" + }, + "exit_code": 0, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256_after": { + "tests/test_track_b_ret_ledger_deductions.py": "a3fcc50166b867f9d3d719bcf611880cba169b3b99f6bf695ff397a36b2fcd2e", + "tests/test_track_b_ret_ledger_fix_round_5.py": "add7304293c593394d0112bf4d92e77acb1a7c49140cc51bfcd81a758c4dc8d9", + "tests/test_track_b_input_schema.py": "d638f55a4de888d49cf236e5b58086ef773e63365e5f5ba5578aef3b9d7a8d32", + "tests/test_track_b_ret_fra_facts.py": "7bfb53be6660bbfad0831904d5b39a3e8d997216308b136959ece10bb04c72a8", + "tests/test_track_b_r3_validation_once.py": "ad28687b52c6386e7c5e28525eac12dc9a4ba62b75d18e066d5bdac1252624c0" + }, + "log": { + "path": "scratch/review/round5-final_diagnostic.log", + "sha256": "56c3a237423163db5ef06213ff950a2a5c616047918c96e1872b4ea0e68f6c10" + }, + "summary": "1019 passed in 540.36s (0:09:00)", + "audit": { + "processes": 1, + "counts": { + "open": 1042, + "restricted_open": 0, + "restricted_import": 0, + "subprocess.Popen": 0, + "os.system": 0 + } + }, + "source_changed_during_run": false, + "source_epoch_note": "Only invalid aged own-RIB widow declarations missing both cohort fields reach the added canonical input-error guard. Valid declarations add no validation; public G rejects these inputs before the helper. Broad gates imported the before source; final targeted runs exercise the after source.", + "tests_changed_during_run": false + }, + "final_g_boundary": { + "partition": "final_g_boundary", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=short", + "tests/test_track_b_gross_benefits_fix_round_1.py", + "tests/test_track_b_gross_benefits_fix_round_10_api.py", + "tests/test_track_b_gross_benefits_fix_round_10_helpers.py", + "tests/test_track_b_gross_benefits_fix_round_10_objects.py", + "tests/test_track_b_gross_benefits_fix_round_10_parameters.py", + "tests/test_track_b_gross_benefits_fix_round_11_roles.py", + "tests/test_track_b_gross_benefits_fix_round_11_seals.py", + "tests/test_track_b_gross_benefits_fix_round_12_contract.py", + "tests/test_track_b_gross_benefits_fix_round_13_audit.py", + "tests/test_track_b_gross_benefits_fix_round_13_boundary.py", + "tests/test_track_b_gross_benefits_fix_round_13_guard.py", + "tests/test_track_b_gross_benefits_fix_round_15_arguments.py", + "tests/test_track_b_gross_benefits_fix_round_15_collections.py", + "tests/test_track_b_gross_benefits_fix_round_15_receivers.py", + "tests/test_track_b_gross_benefits_fix_round_2_care.py", + "tests/test_track_b_gross_benefits_fix_round_2_history.py", + "tests/test_track_b_gross_benefits_fix_round_2_periods.py", + "tests/test_track_b_gross_benefits_fix_round_3_rates.py", + "tests/test_track_b_gross_benefits_fix_round_4_care_floor.py", + "tests/test_track_b_gross_benefits_fix_round_4_divorced_care.py", + "tests/test_track_b_gross_benefits_fix_round_5_care_history.py", + "tests/test_track_b_gross_benefits_fix_round_5_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_6_care_note.py", + "tests/test_track_b_gross_benefits_fix_round_6_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_boundary.py", + "tests/test_track_b_gross_benefits_fix_round_7_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_history.py", + "tests/test_track_b_gross_benefits_fix_round_8_entries.py", + "tests/test_track_b_gross_benefits_fix_round_8_history.py", + "tests/test_track_b_gross_benefits_fix_round_9_citations.py", + "tests/test_track_b_gross_benefits_fix_round_9_outcomes.py", + "tests/test_track_b_gross_benefits_fix_round_9_validation.py" + ], + "environment": { + "OMP_NUM_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-final_g_boundary", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-final_g_boundary" + }, + "named_modules": [ + "tests/test_track_b_gross_benefits_fix_round_1.py", + "tests/test_track_b_gross_benefits_fix_round_10_api.py", + "tests/test_track_b_gross_benefits_fix_round_10_helpers.py", + "tests/test_track_b_gross_benefits_fix_round_10_objects.py", + "tests/test_track_b_gross_benefits_fix_round_10_parameters.py", + "tests/test_track_b_gross_benefits_fix_round_11_roles.py", + "tests/test_track_b_gross_benefits_fix_round_11_seals.py", + "tests/test_track_b_gross_benefits_fix_round_12_contract.py", + "tests/test_track_b_gross_benefits_fix_round_13_audit.py", + "tests/test_track_b_gross_benefits_fix_round_13_boundary.py", + "tests/test_track_b_gross_benefits_fix_round_13_guard.py", + "tests/test_track_b_gross_benefits_fix_round_15_arguments.py", + "tests/test_track_b_gross_benefits_fix_round_15_collections.py", + "tests/test_track_b_gross_benefits_fix_round_15_receivers.py", + "tests/test_track_b_gross_benefits_fix_round_2_care.py", + "tests/test_track_b_gross_benefits_fix_round_2_history.py", + "tests/test_track_b_gross_benefits_fix_round_2_periods.py", + "tests/test_track_b_gross_benefits_fix_round_3_rates.py", + "tests/test_track_b_gross_benefits_fix_round_4_care_floor.py", + "tests/test_track_b_gross_benefits_fix_round_4_divorced_care.py", + "tests/test_track_b_gross_benefits_fix_round_5_care_history.py", + "tests/test_track_b_gross_benefits_fix_round_5_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_6_care_note.py", + "tests/test_track_b_gross_benefits_fix_round_6_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_boundary.py", + "tests/test_track_b_gross_benefits_fix_round_7_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_history.py", + "tests/test_track_b_gross_benefits_fix_round_8_entries.py", + "tests/test_track_b_gross_benefits_fix_round_8_history.py", + "tests/test_track_b_gross_benefits_fix_round_9_citations.py", + "tests/test_track_b_gross_benefits_fix_round_9_outcomes.py", + "tests/test_track_b_gross_benefits_fix_round_9_validation.py" + ], + "selected_nodes": [ + "tests/test_track_b_gross_benefits_fix_round_1.py", + "tests/test_track_b_gross_benefits_fix_round_10_api.py", + "tests/test_track_b_gross_benefits_fix_round_10_helpers.py", + "tests/test_track_b_gross_benefits_fix_round_10_objects.py", + "tests/test_track_b_gross_benefits_fix_round_10_parameters.py", + "tests/test_track_b_gross_benefits_fix_round_11_roles.py", + "tests/test_track_b_gross_benefits_fix_round_11_seals.py", + "tests/test_track_b_gross_benefits_fix_round_12_contract.py", + "tests/test_track_b_gross_benefits_fix_round_13_audit.py", + "tests/test_track_b_gross_benefits_fix_round_13_boundary.py", + "tests/test_track_b_gross_benefits_fix_round_13_guard.py", + "tests/test_track_b_gross_benefits_fix_round_15_arguments.py", + "tests/test_track_b_gross_benefits_fix_round_15_collections.py", + "tests/test_track_b_gross_benefits_fix_round_15_receivers.py", + "tests/test_track_b_gross_benefits_fix_round_2_care.py", + "tests/test_track_b_gross_benefits_fix_round_2_history.py", + "tests/test_track_b_gross_benefits_fix_round_2_periods.py", + "tests/test_track_b_gross_benefits_fix_round_3_rates.py", + "tests/test_track_b_gross_benefits_fix_round_4_care_floor.py", + "tests/test_track_b_gross_benefits_fix_round_4_divorced_care.py", + "tests/test_track_b_gross_benefits_fix_round_5_care_history.py", + "tests/test_track_b_gross_benefits_fix_round_5_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_6_care_note.py", + "tests/test_track_b_gross_benefits_fix_round_6_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_boundary.py", + "tests/test_track_b_gross_benefits_fix_round_7_cohorts.py", + "tests/test_track_b_gross_benefits_fix_round_7_history.py", + "tests/test_track_b_gross_benefits_fix_round_8_entries.py", + "tests/test_track_b_gross_benefits_fix_round_8_history.py", + "tests/test_track_b_gross_benefits_fix_round_9_citations.py", + "tests/test_track_b_gross_benefits_fix_round_9_outcomes.py", + "tests/test_track_b_gross_benefits_fix_round_9_validation.py" + ], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256_before": { + "tests/test_track_b_gross_benefits_fix_round_1.py": "9275a8a4963ce7ed086482644d044a927100efcbeb5a05315d9cc6394168ee8c", + "tests/test_track_b_gross_benefits_fix_round_10_api.py": "227fde023692f1c73a3eeb6de75213468c8e5e160ade3536bf5b7fb688c4ded6", + "tests/test_track_b_gross_benefits_fix_round_10_helpers.py": "e5014776670ca9b552de756c63976e606290fb4fad85a1501b017700a05c8fdb", + "tests/test_track_b_gross_benefits_fix_round_10_objects.py": "7576cc18923ad3ff38d0f44379637e822008a92cc9968d52f47b991e56fb9cfb", + "tests/test_track_b_gross_benefits_fix_round_10_parameters.py": "981eced43d10a6720ccab0292c4a8c281b9ac9bf7d83132f6666254d7a4b72ee", + "tests/test_track_b_gross_benefits_fix_round_11_roles.py": "d26fd86d7067eb7f4f97e1537110eab5223104ad817c3470a9eae022a90dfc73", + "tests/test_track_b_gross_benefits_fix_round_11_seals.py": "937b07b094816eade9bf072595ede18b1b109db527de9805c3a3cb3d333ba4b5", + "tests/test_track_b_gross_benefits_fix_round_12_contract.py": "9779ae3b22cf12daf6727cd21a6bcb12afbf3cfd34c84209bd406942a0c089e1", + "tests/test_track_b_gross_benefits_fix_round_13_audit.py": "fb04098e3982aca18b439f2df148bee6333ce20406fe773da0858731a6c94ff0", + "tests/test_track_b_gross_benefits_fix_round_13_boundary.py": "acac7951783a0e11140e717feab3924973e290e58857396dfab9c0b4319a5e8d", + "tests/test_track_b_gross_benefits_fix_round_13_guard.py": "e5fabfda3fcab2ba9e0347449278a21b9cfc1f89645e1ab148cb4a23da9e7c2e", + "tests/test_track_b_gross_benefits_fix_round_15_arguments.py": "16d5a875f4271839799738a89f2b904084bc0847eb25cd397168cea570be6d54", + "tests/test_track_b_gross_benefits_fix_round_15_collections.py": "2206b9734458774d581d3d20bfb50f1d517fd1b7d8191225cf5cacbca6561e58", + "tests/test_track_b_gross_benefits_fix_round_15_receivers.py": "3de91e8701ab82a3063be9eb859e6cd0058c7d3a35ac93dce9e110e0959061ff", + "tests/test_track_b_gross_benefits_fix_round_2_care.py": "7e983b28cdd1ba2c03935858610788754de66fb9489fef46672ebbf3d566225e", + "tests/test_track_b_gross_benefits_fix_round_2_history.py": "17fb81a1d18ad90ccf99cc841360aec524822cc2404e03d33cfbbab3a830b3a5", + "tests/test_track_b_gross_benefits_fix_round_2_periods.py": "21030c220e1b4690ac3d6754dcd9baddc23b33e824e07a842673c4128b7e6b09", + "tests/test_track_b_gross_benefits_fix_round_3_rates.py": "1c638ac3d5f0b0d25b49d1abf4924d9fff45bcf5ce25366616a60d3f060faa16", + "tests/test_track_b_gross_benefits_fix_round_4_care_floor.py": "d137d59fb7af48f21fda7b4e3aaf9a991d43b295930b5f341cc7cd595b875401", + "tests/test_track_b_gross_benefits_fix_round_4_divorced_care.py": "cd50249e8d84a2bbb61901f08b84310d48b8d390495beadfe5112144143b4fd7", + "tests/test_track_b_gross_benefits_fix_round_5_care_history.py": "a3e73482553c5fb804adaba8ed0d5e4d1520470f384bb58a0fe46cb41e58eb07", + "tests/test_track_b_gross_benefits_fix_round_5_cohorts.py": "f5be483a533e47edcb58dc05bc202390e959e6ece7eca3ff11728aa46b00409d", + "tests/test_track_b_gross_benefits_fix_round_6_care_note.py": "b2d158f37d35aaa63a6a1293345010bc4445c3b20c480c035932bf9725a91eca", + "tests/test_track_b_gross_benefits_fix_round_6_cohorts.py": "b06e95d0a8a93af3e60b96222381b46377673e407385958b5120817bc60c2e84", + "tests/test_track_b_gross_benefits_fix_round_7_boundary.py": "b2c875f010c402e4f373be5712a39affd87b6533805ed33bf63dbea60b1e6ae5", + "tests/test_track_b_gross_benefits_fix_round_7_cohorts.py": "0eb73d51e1f7a61f76917df670f89bdade0e5f45f4c044be30673dff2494ca31", + "tests/test_track_b_gross_benefits_fix_round_7_history.py": "fc6a7b5281e2f429a8e9f92c595b4491aa2de4229630fc5ca15eab333bacab26", + "tests/test_track_b_gross_benefits_fix_round_8_entries.py": "4589caceb3f7996a6175d6f15f8038805450d8c448c56a8d95e4ccc9a5f872e5", + "tests/test_track_b_gross_benefits_fix_round_8_history.py": "cf4d84edf72b150dd343d408d84e60ebd70500c8e219bc00b1552d6292af4e91", + "tests/test_track_b_gross_benefits_fix_round_9_citations.py": "2ce5f13cd58a929583f659ec5bea6b2fbfa7216edd00291400773882118b9b4e", + "tests/test_track_b_gross_benefits_fix_round_9_outcomes.py": "139a90841182ca8a1bbece8acd3b30df68f7d88cef833fd092c202b22017a3e6", + "tests/test_track_b_gross_benefits_fix_round_9_validation.py": "0d420e98106ffe4ce7d9f1f0ae121488c4aca9ce1e1a3d941bc5aff0083efd92" + }, + "exit_code": 0, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256_after": { + "tests/test_track_b_gross_benefits_fix_round_1.py": "9275a8a4963ce7ed086482644d044a927100efcbeb5a05315d9cc6394168ee8c", + "tests/test_track_b_gross_benefits_fix_round_10_api.py": "227fde023692f1c73a3eeb6de75213468c8e5e160ade3536bf5b7fb688c4ded6", + "tests/test_track_b_gross_benefits_fix_round_10_helpers.py": "e5014776670ca9b552de756c63976e606290fb4fad85a1501b017700a05c8fdb", + "tests/test_track_b_gross_benefits_fix_round_10_objects.py": "7576cc18923ad3ff38d0f44379637e822008a92cc9968d52f47b991e56fb9cfb", + "tests/test_track_b_gross_benefits_fix_round_10_parameters.py": "981eced43d10a6720ccab0292c4a8c281b9ac9bf7d83132f6666254d7a4b72ee", + "tests/test_track_b_gross_benefits_fix_round_11_roles.py": "d26fd86d7067eb7f4f97e1537110eab5223104ad817c3470a9eae022a90dfc73", + "tests/test_track_b_gross_benefits_fix_round_11_seals.py": "937b07b094816eade9bf072595ede18b1b109db527de9805c3a3cb3d333ba4b5", + "tests/test_track_b_gross_benefits_fix_round_12_contract.py": "9779ae3b22cf12daf6727cd21a6bcb12afbf3cfd34c84209bd406942a0c089e1", + "tests/test_track_b_gross_benefits_fix_round_13_audit.py": "fb04098e3982aca18b439f2df148bee6333ce20406fe773da0858731a6c94ff0", + "tests/test_track_b_gross_benefits_fix_round_13_boundary.py": "acac7951783a0e11140e717feab3924973e290e58857396dfab9c0b4319a5e8d", + "tests/test_track_b_gross_benefits_fix_round_13_guard.py": "e5fabfda3fcab2ba9e0347449278a21b9cfc1f89645e1ab148cb4a23da9e7c2e", + "tests/test_track_b_gross_benefits_fix_round_15_arguments.py": "16d5a875f4271839799738a89f2b904084bc0847eb25cd397168cea570be6d54", + "tests/test_track_b_gross_benefits_fix_round_15_collections.py": "2206b9734458774d581d3d20bfb50f1d517fd1b7d8191225cf5cacbca6561e58", + "tests/test_track_b_gross_benefits_fix_round_15_receivers.py": "3de91e8701ab82a3063be9eb859e6cd0058c7d3a35ac93dce9e110e0959061ff", + "tests/test_track_b_gross_benefits_fix_round_2_care.py": "7e983b28cdd1ba2c03935858610788754de66fb9489fef46672ebbf3d566225e", + "tests/test_track_b_gross_benefits_fix_round_2_history.py": "17fb81a1d18ad90ccf99cc841360aec524822cc2404e03d33cfbbab3a830b3a5", + "tests/test_track_b_gross_benefits_fix_round_2_periods.py": "21030c220e1b4690ac3d6754dcd9baddc23b33e824e07a842673c4128b7e6b09", + "tests/test_track_b_gross_benefits_fix_round_3_rates.py": "1c638ac3d5f0b0d25b49d1abf4924d9fff45bcf5ce25366616a60d3f060faa16", + "tests/test_track_b_gross_benefits_fix_round_4_care_floor.py": "d137d59fb7af48f21fda7b4e3aaf9a991d43b295930b5f341cc7cd595b875401", + "tests/test_track_b_gross_benefits_fix_round_4_divorced_care.py": "cd50249e8d84a2bbb61901f08b84310d48b8d390495beadfe5112144143b4fd7", + "tests/test_track_b_gross_benefits_fix_round_5_care_history.py": "a3e73482553c5fb804adaba8ed0d5e4d1520470f384bb58a0fe46cb41e58eb07", + "tests/test_track_b_gross_benefits_fix_round_5_cohorts.py": "f5be483a533e47edcb58dc05bc202390e959e6ece7eca3ff11728aa46b00409d", + "tests/test_track_b_gross_benefits_fix_round_6_care_note.py": "b2d158f37d35aaa63a6a1293345010bc4445c3b20c480c035932bf9725a91eca", + "tests/test_track_b_gross_benefits_fix_round_6_cohorts.py": "b06e95d0a8a93af3e60b96222381b46377673e407385958b5120817bc60c2e84", + "tests/test_track_b_gross_benefits_fix_round_7_boundary.py": "b2c875f010c402e4f373be5712a39affd87b6533805ed33bf63dbea60b1e6ae5", + "tests/test_track_b_gross_benefits_fix_round_7_cohorts.py": "0eb73d51e1f7a61f76917df670f89bdade0e5f45f4c044be30673dff2494ca31", + "tests/test_track_b_gross_benefits_fix_round_7_history.py": "fc6a7b5281e2f429a8e9f92c595b4491aa2de4229630fc5ca15eab333bacab26", + "tests/test_track_b_gross_benefits_fix_round_8_entries.py": "4589caceb3f7996a6175d6f15f8038805450d8c448c56a8d95e4ccc9a5f872e5", + "tests/test_track_b_gross_benefits_fix_round_8_history.py": "cf4d84edf72b150dd343d408d84e60ebd70500c8e219bc00b1552d6292af4e91", + "tests/test_track_b_gross_benefits_fix_round_9_citations.py": "2ce5f13cd58a929583f659ec5bea6b2fbfa7216edd00291400773882118b9b4e", + "tests/test_track_b_gross_benefits_fix_round_9_outcomes.py": "139a90841182ca8a1bbece8acd3b30df68f7d88cef833fd092c202b22017a3e6", + "tests/test_track_b_gross_benefits_fix_round_9_validation.py": "0d420e98106ffe4ce7d9f1f0ae121488c4aca9ce1e1a3d941bc5aff0083efd92" + }, + "log": { + "path": "scratch/review/round5-final_g_boundary.log", + "sha256": "5142126cafdae4ff09f686aea39496259799675e34230110f4ae0785d926b0a9" + }, + "summary": "7241 passed in 1303.91s (0:21:43)", + "audit": { + "processes": 1, + "counts": { + "open": 2888, + "restricted_open": 0, + "restricted_import": 0, + "subprocess.Popen": 0, + "os.system": 0 + } + }, + "source_changed_during_run": false, + "source_epoch_note": "Only invalid aged own-RIB widow declarations missing both cohort fields reach the added canonical input-error guard. Valid declarations add no validation; public G rejects these inputs before the helper. Broad gates imported the before source; final targeted runs exercise the after source.", + "tests_changed_during_run": false + }, + "final_g_rules": { + "partition": "final_g_rules", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=short", + "tests/test_track_b_gross_benefits.py", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py", + "tests/test_track_b_gross_benefits_deduction_cap.py", + "tests/test_track_b_gross_benefits_deductions.py", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", + "tests/test_track_b_gross_benefits_dwb.py", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py", + "tests/test_track_b_gross_benefits_oracle.py", + "tests/test_track_b_gross_benefits_own_input_order.py", + "tests/test_track_b_gross_benefits_parents_ieds.py", + "tests/test_track_b_gross_benefits_parisi.py", + "tests/test_track_b_gross_benefits_payment_review.py", + "tests/test_track_b_gross_benefits_properties.py", + "tests/test_track_b_gross_benefits_registry.py", + "tests/test_track_b_gross_benefits_review.py", + "tests/test_track_b_gross_benefits_saving_absence.py", + "tests/test_track_b_gross_benefits_savings.py", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py", + "tests/test_track_b_gross_benefits_sources_20261011.py", + "tests/test_track_b_gross_benefits_ssfa.py", + "tests/test_track_b_refusal_notes.py" + ], + "environment": { + "OMP_NUM_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-final_g_rules", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-final_g_rules" + }, + "named_modules": [ + "tests/test_track_b_gross_benefits.py", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py", + "tests/test_track_b_gross_benefits_deduction_cap.py", + "tests/test_track_b_gross_benefits_deductions.py", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", + "tests/test_track_b_gross_benefits_dwb.py", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py", + "tests/test_track_b_gross_benefits_oracle.py", + "tests/test_track_b_gross_benefits_own_input_order.py", + "tests/test_track_b_gross_benefits_parents_ieds.py", + "tests/test_track_b_gross_benefits_parisi.py", + "tests/test_track_b_gross_benefits_payment_review.py", + "tests/test_track_b_gross_benefits_properties.py", + "tests/test_track_b_gross_benefits_registry.py", + "tests/test_track_b_gross_benefits_review.py", + "tests/test_track_b_gross_benefits_saving_absence.py", + "tests/test_track_b_gross_benefits_savings.py", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py", + "tests/test_track_b_gross_benefits_sources_20261011.py", + "tests/test_track_b_gross_benefits_ssfa.py", + "tests/test_track_b_refusal_notes.py" + ], + "selected_nodes": [ + "tests/test_track_b_gross_benefits.py", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py", + "tests/test_track_b_gross_benefits_deduction_cap.py", + "tests/test_track_b_gross_benefits_deductions.py", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", + "tests/test_track_b_gross_benefits_dwb.py", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py", + "tests/test_track_b_gross_benefits_oracle.py", + "tests/test_track_b_gross_benefits_own_input_order.py", + "tests/test_track_b_gross_benefits_parents_ieds.py", + "tests/test_track_b_gross_benefits_parisi.py", + "tests/test_track_b_gross_benefits_payment_review.py", + "tests/test_track_b_gross_benefits_properties.py", + "tests/test_track_b_gross_benefits_registry.py", + "tests/test_track_b_gross_benefits_review.py", + "tests/test_track_b_gross_benefits_saving_absence.py", + "tests/test_track_b_gross_benefits_savings.py", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py", + "tests/test_track_b_gross_benefits_sources_20261011.py", + "tests/test_track_b_gross_benefits_ssfa.py", + "tests/test_track_b_refusal_notes.py" + ], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256_before": { + "tests/test_track_b_gross_benefits.py": "de0946a014d054bd47f30dadaf675105aebb1dd562209c4002dee05354628286", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py": "5d9fe8c5cb052d39c82249d6efcf4d88dace5ec68538340e7000f73af5e016df", + "tests/test_track_b_gross_benefits_deduction_cap.py": "6965d3e258ad31ad9ee496eb745885d3f6fa7b7c4ec2a48e441d0318588ec30e", + "tests/test_track_b_gross_benefits_deductions.py": "b6f0493ecbb19434c09de42ff7e62a87b85818ea6dc8a5cde78963d780598e02", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py": "5cebe4f986fa7d01d7769c1d1db0581b54ae88e7c4710409285e12393244fdab", + "tests/test_track_b_gross_benefits_dwb.py": "61b6270fdd9a6d156d31194535797d1f59c092943ecdb3773787d1471e2bb80a", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py": "74105c3ab4c8c7e9e3fc0be9f4eb078a5c7913683c13974aa86fa598c2eda950", + "tests/test_track_b_gross_benefits_oracle.py": "d4b88ec7a6945e76499e50266448894e99809737b1bc2a55de060bf03f591d24", + "tests/test_track_b_gross_benefits_own_input_order.py": "3bb4bd7fb3b7567109ed3f132f6b8a775e43e90a04aa4a2a0fa8542c78575291", + "tests/test_track_b_gross_benefits_parents_ieds.py": "98e5f81c99b3b80332db203c07db680b09a633c3d34bc58d15ee986f252bf73c", + "tests/test_track_b_gross_benefits_parisi.py": "4f446013cc7bd9f2ae8dc4dfe3ee59d952a9f5e7d2aaa2f104497dfe36425c1a", + "tests/test_track_b_gross_benefits_payment_review.py": "4c239c468e06a0c522151e182693a91024f61b7f38e49bbd7f03c66b01889dd7", + "tests/test_track_b_gross_benefits_properties.py": "483d502f88457f89cbc4f13b2904718eae59997a81a1189f51b0fbe635c54cfb", + "tests/test_track_b_gross_benefits_registry.py": "93dd3a5d3750cea367ddfe6ccc42f08084ae2f09e6278a1de728baf6a8ddc4df", + "tests/test_track_b_gross_benefits_review.py": "e602dfbf58ec57e25a1270d0e26bb3c5204045e43ab726266e0ef805abe2cd7c", + "tests/test_track_b_gross_benefits_saving_absence.py": "e6078f978ee7bf1d0802dde67c2de94397fd3e9cd142b2c96d6d504ceb0a6862", + "tests/test_track_b_gross_benefits_savings.py": "607bf6cb7415d03bd7b863673d7b9d403841d175a1684f211a562536f4f4755b", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py": "d84130cc73468a8b3f8223c5526f0e982597e552c40e714d691608d32da59233", + "tests/test_track_b_gross_benefits_sources_20261011.py": "e3291d0b6bf497a20835800c4d6ee833854e5edf5b25229932e7a142f8e51a13", + "tests/test_track_b_gross_benefits_ssfa.py": "07fee44e63376a58508296b6f66d1fc20adfa1c88c8cd110a1d5fc45dc4f1ebf", + "tests/test_track_b_refusal_notes.py": "5c765432752317684e4059f2d45a2a95fd03ff327fb1225f853267588fc76abe" + }, + "exit_code": 0, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256_after": { + "tests/test_track_b_gross_benefits.py": "de0946a014d054bd47f30dadaf675105aebb1dd562209c4002dee05354628286", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py": "5d9fe8c5cb052d39c82249d6efcf4d88dace5ec68538340e7000f73af5e016df", + "tests/test_track_b_gross_benefits_deduction_cap.py": "6965d3e258ad31ad9ee496eb745885d3f6fa7b7c4ec2a48e441d0318588ec30e", + "tests/test_track_b_gross_benefits_deductions.py": "b6f0493ecbb19434c09de42ff7e62a87b85818ea6dc8a5cde78963d780598e02", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py": "5cebe4f986fa7d01d7769c1d1db0581b54ae88e7c4710409285e12393244fdab", + "tests/test_track_b_gross_benefits_dwb.py": "61b6270fdd9a6d156d31194535797d1f59c092943ecdb3773787d1471e2bb80a", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py": "74105c3ab4c8c7e9e3fc0be9f4eb078a5c7913683c13974aa86fa598c2eda950", + "tests/test_track_b_gross_benefits_oracle.py": "d4b88ec7a6945e76499e50266448894e99809737b1bc2a55de060bf03f591d24", + "tests/test_track_b_gross_benefits_own_input_order.py": "3bb4bd7fb3b7567109ed3f132f6b8a775e43e90a04aa4a2a0fa8542c78575291", + "tests/test_track_b_gross_benefits_parents_ieds.py": "98e5f81c99b3b80332db203c07db680b09a633c3d34bc58d15ee986f252bf73c", + "tests/test_track_b_gross_benefits_parisi.py": "4f446013cc7bd9f2ae8dc4dfe3ee59d952a9f5e7d2aaa2f104497dfe36425c1a", + "tests/test_track_b_gross_benefits_payment_review.py": "4c239c468e06a0c522151e182693a91024f61b7f38e49bbd7f03c66b01889dd7", + "tests/test_track_b_gross_benefits_properties.py": "483d502f88457f89cbc4f13b2904718eae59997a81a1189f51b0fbe635c54cfb", + "tests/test_track_b_gross_benefits_registry.py": "93dd3a5d3750cea367ddfe6ccc42f08084ae2f09e6278a1de728baf6a8ddc4df", + "tests/test_track_b_gross_benefits_review.py": "e602dfbf58ec57e25a1270d0e26bb3c5204045e43ab726266e0ef805abe2cd7c", + "tests/test_track_b_gross_benefits_saving_absence.py": "e6078f978ee7bf1d0802dde67c2de94397fd3e9cd142b2c96d6d504ceb0a6862", + "tests/test_track_b_gross_benefits_savings.py": "607bf6cb7415d03bd7b863673d7b9d403841d175a1684f211a562536f4f4755b", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py": "d84130cc73468a8b3f8223c5526f0e982597e552c40e714d691608d32da59233", + "tests/test_track_b_gross_benefits_sources_20261011.py": "e3291d0b6bf497a20835800c4d6ee833854e5edf5b25229932e7a142f8e51a13", + "tests/test_track_b_gross_benefits_ssfa.py": "07fee44e63376a58508296b6f66d1fc20adfa1c88c8cd110a1d5fc45dc4f1ebf", + "tests/test_track_b_refusal_notes.py": "5c765432752317684e4059f2d45a2a95fd03ff327fb1225f853267588fc76abe" + }, + "log": { + "path": "scratch/review/round5-final_g_rules.log", + "sha256": "fa10cc1085df63101ffd17f17226aefd268023364ce7f5bea1270e883c5d74ec" + }, + "summary": "978 passed in 1124.38s (0:18:44)", + "audit": { + "processes": 2, + "counts": { + "open": 3074, + "restricted_open": 0, + "restricted_import": 0, + "subprocess.Popen": 2, + "os.system": 0 + } + }, + "source_changed_during_run": false, + "source_epoch_note": "Only invalid aged own-RIB widow declarations missing both cohort fields reach the added canonical input-error guard. Valid declarations add no validation; public G rejects these inputs before the helper. Broad gates imported the before source; final targeted runs exercise the after source.", + "tests_changed_during_run": false + }, + "final_g_report": { + "partition": "final_g_report", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=short", + "tests/test_track_b_gross_benefits_conformance_report.py" + ], + "environment": { + "OMP_NUM_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-final_g_report", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-final_g_report" + }, + "named_modules": [ + "tests/test_track_b_gross_benefits_conformance_report.py" + ], + "selected_nodes": [ + "tests/test_track_b_gross_benefits_conformance_report.py" + ], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256_before": { + "tests/test_track_b_gross_benefits_conformance_report.py": "7ec6f605783c15c88abbb0834ff894645fe14e2956239c83532cd88132e699c8" + }, + "exit_code": 0, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256_after": { + "tests/test_track_b_gross_benefits_conformance_report.py": "7ec6f605783c15c88abbb0834ff894645fe14e2956239c83532cd88132e699c8" + }, + "log": { + "path": "scratch/review/round5-final_g_report.log", + "sha256": "f69784945a4dc0c119f699cbd15f5805f9fea5888b87272f2d1b7f3135974e73" + }, + "summary": "54 passed in 1656.30s (0:27:36)", + "audit": { + "processes": 1, + "counts": { + "open": 893, + "restricted_open": 0, + "restricted_import": 0, + "subprocess.Popen": 0, + "os.system": 0 + } + }, + "source_changed_during_run": false, + "source_epoch_note": "Only invalid aged own-RIB widow declarations missing both cohort fields reach the added canonical input-error guard. Valid declarations add no validation; public G rejects these inputs before the helper. Broad gates imported the before source; final targeted runs exercise the after source.", + "tests_changed_during_run": false + }, + "final_ret_r3": { + "partition": "final_ret_r3", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=short", + "tests/test_track_b_arf.py", + "tests/test_track_b_arf_properties.py", + "tests/test_track_b_r3_fix_round_13.py", + "tests/test_track_b_r3_provenance.py", + "tests/test_track_b_r3_sources.py", + "tests/test_track_b_recompute.py", + "tests/test_track_b_recompute_properties.py", + "tests/test_track_b_ret_differential.py", + "tests/test_track_b_ret_grace.py", + "tests/test_track_b_ret_grace_differential.py", + "tests/test_track_b_ret_grace_provenance.py", + "tests/test_track_b_ret_ledger.py", + "tests/test_track_b_ret_ledger_fix_round_2.py", + "tests/test_track_b_ret_ledger_fix_round_4.py", + "tests/test_track_b_ret_ledger_properties.py", + "tests/test_track_b_ret_ledger_readings.py", + "tests/test_track_b_ret_ledger_sources.py", + "tests/test_track_b_ret_params.py" + ], + "environment": { + "OMP_NUM_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-final_ret_r3", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-final_ret_r3" + }, + "named_modules": [ + "tests/test_track_b_arf.py", + "tests/test_track_b_arf_properties.py", + "tests/test_track_b_r3_fix_round_13.py", + "tests/test_track_b_r3_provenance.py", + "tests/test_track_b_r3_sources.py", + "tests/test_track_b_recompute.py", + "tests/test_track_b_recompute_properties.py", + "tests/test_track_b_ret_differential.py", + "tests/test_track_b_ret_grace.py", + "tests/test_track_b_ret_grace_differential.py", + "tests/test_track_b_ret_grace_provenance.py", + "tests/test_track_b_ret_ledger.py", + "tests/test_track_b_ret_ledger_fix_round_2.py", + "tests/test_track_b_ret_ledger_fix_round_4.py", + "tests/test_track_b_ret_ledger_properties.py", + "tests/test_track_b_ret_ledger_readings.py", + "tests/test_track_b_ret_ledger_sources.py", + "tests/test_track_b_ret_params.py" + ], + "selected_nodes": [ + "tests/test_track_b_arf.py", + "tests/test_track_b_arf_properties.py", + "tests/test_track_b_r3_fix_round_13.py", + "tests/test_track_b_r3_provenance.py", + "tests/test_track_b_r3_sources.py", + "tests/test_track_b_recompute.py", + "tests/test_track_b_recompute_properties.py", + "tests/test_track_b_ret_differential.py", + "tests/test_track_b_ret_grace.py", + "tests/test_track_b_ret_grace_differential.py", + "tests/test_track_b_ret_grace_provenance.py", + "tests/test_track_b_ret_ledger.py", + "tests/test_track_b_ret_ledger_fix_round_2.py", + "tests/test_track_b_ret_ledger_fix_round_4.py", + "tests/test_track_b_ret_ledger_properties.py", + "tests/test_track_b_ret_ledger_readings.py", + "tests/test_track_b_ret_ledger_sources.py", + "tests/test_track_b_ret_params.py" + ], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256_before": { + "tests/test_track_b_arf.py": "292587c9ee1d160ad6c66da6e388e3a0b2bf4c9831f8ad3b18853c802f5bd68e", + "tests/test_track_b_arf_properties.py": "d1346b68bd07b469cea6357e1881d743e3a90c66e04080fc19fd66b44da7b68e", + "tests/test_track_b_r3_fix_round_13.py": "bfb81d8316574e9df0e2e7cb9f890e1b9f584cac2cd17e025825580e219cebc7", + "tests/test_track_b_r3_provenance.py": "58243309d56acb9dc38e9bf5a701e79ac961ac062e0d37690b12a561592245c9", + "tests/test_track_b_r3_sources.py": "6300b1a4075a0f2549cce4db0aab25d6908eba9071a5a2da3bbfc6d020dd04ba", + "tests/test_track_b_recompute.py": "06db2b43c6c13d679a71a6d2176dc3ee13fce8fc1645684fcbe7c582f9e54f9c", + "tests/test_track_b_recompute_properties.py": "ced431cb4fd0de82a7cde6ff63c6a38eaad1649939d364b1023dcc81aff30759", + "tests/test_track_b_ret_differential.py": "8e38e1040d61d9f0262bbe25c5c17e0f608c433cb29ab898b7f954358bcf1e12", + "tests/test_track_b_ret_grace.py": "772f6b94187593549cd21a2dbb19a75f998fb840f6b6eb3a97bbeca3f36636dc", + "tests/test_track_b_ret_grace_differential.py": "fbf01f2c6e76f2cc8a60bad5e9c9ac5c4da0c68013578b91de9488aa2623abf5", + "tests/test_track_b_ret_grace_provenance.py": "8cf4446fb0bb6da77a7b84815caafe595ec81b9b7a2cc1e56f686cd25f0e77a5", + "tests/test_track_b_ret_ledger.py": "6d6684e63aa3d56874fb0fd174867d1e2b41e54119ad8077c2e6b689ca723065", + "tests/test_track_b_ret_ledger_fix_round_2.py": "62a81110909ddebfa77f65078d685464f553c37de89cb88efd743ca406b1aa70", + "tests/test_track_b_ret_ledger_fix_round_4.py": "0c304d939709da534e89c374ff9687548531796c4716d51dd5e7e232346b6681", + "tests/test_track_b_ret_ledger_properties.py": "803433fd9d3aa7601b45e2f5346d716254409710e9f9d3ac61f1a42d87cc7d64", + "tests/test_track_b_ret_ledger_readings.py": "630bdd1d5f53d93c63674192f205e17edff601f8dcc8d941348db98cf094bdad", + "tests/test_track_b_ret_ledger_sources.py": "ab6b6d66d370c93e5b2cc82b88670f48eb5bceeb0d313c36550986c3ff1844b6", + "tests/test_track_b_ret_params.py": "57a1be52d32c3549d711aba4f88f42cdb0affd98bc3b3d5bf7e607fc0b2c3514" + }, + "exit_code": 0, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256_after": { + "tests/test_track_b_arf.py": "292587c9ee1d160ad6c66da6e388e3a0b2bf4c9831f8ad3b18853c802f5bd68e", + "tests/test_track_b_arf_properties.py": "d1346b68bd07b469cea6357e1881d743e3a90c66e04080fc19fd66b44da7b68e", + "tests/test_track_b_r3_fix_round_13.py": "bfb81d8316574e9df0e2e7cb9f890e1b9f584cac2cd17e025825580e219cebc7", + "tests/test_track_b_r3_provenance.py": "58243309d56acb9dc38e9bf5a701e79ac961ac062e0d37690b12a561592245c9", + "tests/test_track_b_r3_sources.py": "6300b1a4075a0f2549cce4db0aab25d6908eba9071a5a2da3bbfc6d020dd04ba", + "tests/test_track_b_recompute.py": "06db2b43c6c13d679a71a6d2176dc3ee13fce8fc1645684fcbe7c582f9e54f9c", + "tests/test_track_b_recompute_properties.py": "ced431cb4fd0de82a7cde6ff63c6a38eaad1649939d364b1023dcc81aff30759", + "tests/test_track_b_ret_differential.py": "8e38e1040d61d9f0262bbe25c5c17e0f608c433cb29ab898b7f954358bcf1e12", + "tests/test_track_b_ret_grace.py": "772f6b94187593549cd21a2dbb19a75f998fb840f6b6eb3a97bbeca3f36636dc", + "tests/test_track_b_ret_grace_differential.py": "fbf01f2c6e76f2cc8a60bad5e9c9ac5c4da0c68013578b91de9488aa2623abf5", + "tests/test_track_b_ret_grace_provenance.py": "8cf4446fb0bb6da77a7b84815caafe595ec81b9b7a2cc1e56f686cd25f0e77a5", + "tests/test_track_b_ret_ledger.py": "6d6684e63aa3d56874fb0fd174867d1e2b41e54119ad8077c2e6b689ca723065", + "tests/test_track_b_ret_ledger_fix_round_2.py": "62a81110909ddebfa77f65078d685464f553c37de89cb88efd743ca406b1aa70", + "tests/test_track_b_ret_ledger_fix_round_4.py": "0c304d939709da534e89c374ff9687548531796c4716d51dd5e7e232346b6681", + "tests/test_track_b_ret_ledger_properties.py": "803433fd9d3aa7601b45e2f5346d716254409710e9f9d3ac61f1a42d87cc7d64", + "tests/test_track_b_ret_ledger_readings.py": "630bdd1d5f53d93c63674192f205e17edff601f8dcc8d941348db98cf094bdad", + "tests/test_track_b_ret_ledger_sources.py": "ab6b6d66d370c93e5b2cc82b88670f48eb5bceeb0d313c36550986c3ff1844b6", + "tests/test_track_b_ret_params.py": "57a1be52d32c3549d711aba4f88f42cdb0affd98bc3b3d5bf7e607fc0b2c3514" + }, + "log": { + "path": "scratch/review/round5-final_ret_r3.log", + "sha256": "e41c45f928ee503b4a1df1a1195767437e1a47b472dabff6978bc1d6eb514cf0" + }, + "summary": "2933 passed in 1415.95s (0:23:35)", + "audit": { + "processes": 1, + "counts": { + "open": 1387, + "restricted_open": 0, + "restricted_import": 0, + "subprocess.Popen": 1, + "os.system": 0 + } + }, + "source_changed_during_run": false, + "source_epoch_note": "Only invalid aged own-RIB widow declarations missing both cohort fields reach the added canonical input-error guard. Valid declarations add no validation; public G rejects these inputs before the helper. Broad gates imported the before source; final targeted runs exercise the after source.", + "tests_changed_during_run": false + }, + "final_closure": { + "partition": "final_closure", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=short", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py", + "tests/test_track_b_gross_benefits_deduction_cap.py", + "tests/test_track_b_gross_benefits_deductions.py", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", + "tests/test_track_b_ret_ledger_fix_round_5.py", + "tests/test_track_b_input_schema.py", + "tests/test_track_b_r3_validation_once.py" + ], + "environment": { + "OMP_NUM_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-final_closure", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-final_closure" + }, + "named_modules": [ + "tests/test_track_b_gross_benefits_deduction_age_inputs.py", + "tests/test_track_b_gross_benefits_deduction_cap.py", + "tests/test_track_b_gross_benefits_deductions.py", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", + "tests/test_track_b_ret_ledger_fix_round_5.py", + "tests/test_track_b_input_schema.py", + "tests/test_track_b_r3_validation_once.py" + ], + "selected_nodes": [ + "tests/test_track_b_gross_benefits_deduction_age_inputs.py", + "tests/test_track_b_gross_benefits_deduction_cap.py", + "tests/test_track_b_gross_benefits_deductions.py", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", + "tests/test_track_b_ret_ledger_fix_round_5.py", + "tests/test_track_b_input_schema.py", + "tests/test_track_b_r3_validation_once.py" + ], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "d51f5d77c7aa7cf6004392e27187ce89523151fef12148088565226f7444fb64", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256_before": { + "tests/test_track_b_gross_benefits_deduction_age_inputs.py": "5d9fe8c5cb052d39c82249d6efcf4d88dace5ec68538340e7000f73af5e016df", + "tests/test_track_b_gross_benefits_deduction_cap.py": "6965d3e258ad31ad9ee496eb745885d3f6fa7b7c4ec2a48e441d0318588ec30e", + "tests/test_track_b_gross_benefits_deductions.py": "b6f0493ecbb19434c09de42ff7e62a87b85818ea6dc8a5cde78963d780598e02", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py": "5cebe4f986fa7d01d7769c1d1db0581b54ae88e7c4710409285e12393244fdab", + "tests/test_track_b_ret_ledger_fix_round_5.py": "26f74adc61c076d80446965850da34a01d02744d213bb1b63921ef6b66689f5b", + "tests/test_track_b_input_schema.py": "d638f55a4de888d49cf236e5b58086ef773e63365e5f5ba5578aef3b9d7a8d32", + "tests/test_track_b_r3_validation_once.py": "ad28687b52c6386e7c5e28525eac12dc9a4ba62b75d18e066d5bdac1252624c0" + }, + "exit_code": 0, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "d51f5d77c7aa7cf6004392e27187ce89523151fef12148088565226f7444fb64", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256_after": { + "tests/test_track_b_gross_benefits_deduction_age_inputs.py": "5d9fe8c5cb052d39c82249d6efcf4d88dace5ec68538340e7000f73af5e016df", + "tests/test_track_b_gross_benefits_deduction_cap.py": "6965d3e258ad31ad9ee496eb745885d3f6fa7b7c4ec2a48e441d0318588ec30e", + "tests/test_track_b_gross_benefits_deductions.py": "b6f0493ecbb19434c09de42ff7e62a87b85818ea6dc8a5cde78963d780598e02", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py": "5cebe4f986fa7d01d7769c1d1db0581b54ae88e7c4710409285e12393244fdab", + "tests/test_track_b_ret_ledger_fix_round_5.py": "26f74adc61c076d80446965850da34a01d02744d213bb1b63921ef6b66689f5b", + "tests/test_track_b_input_schema.py": "d638f55a4de888d49cf236e5b58086ef773e63365e5f5ba5578aef3b9d7a8d32", + "tests/test_track_b_r3_validation_once.py": "ad28687b52c6386e7c5e28525eac12dc9a4ba62b75d18e066d5bdac1252624c0" + }, + "log": { + "path": "scratch/review/round5-final_closure.log", + "sha256": "8fe94434282d757694e2492d6ec3ea76fff7a1625b2dff14be76e71c6a66dbf4" + }, + "summary": "1062 passed in 230.91s (0:03:50)", + "audit": { + "processes": 1, + "counts": { + "open": 1047, + "restricted_open": 0, + "restricted_import": 0, + "subprocess.Popen": 0, + "os.system": 0 + } + }, + "source_changed_during_run": false, + "source_epoch_note": "Only invalid aged own-RIB widow declarations missing both cohort fields reach the added canonical input-error guard. Valid declarations add no validation; public G rejects these inputs before the helper. Broad gates imported the before source; final targeted runs exercise the after source.", + "tests_changed_during_run": false + } + }, + "audit_policy": "Counts-only hook installed before pytest collection; child Python inherits it. Nine restricted paths and two modules are blocked. No restricted loads expected.", + "mutation_method": "Isolated named-source overlays; no production source mutation, no alternate git metadata.", + "named_test_module_count": 77, + "failing_first": { + "reviewed_head": "e3315bafb592e29031d72b5ef368ca428e4a0b55", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py" + ], + "selected_test_nodes": [ + "tests/test_track_b_ret_ledger_fix_round_5.py" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-reviewed-head/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-reviewed-head", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-reviewed-head" + }, + "exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-0-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-0-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-0-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-4-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-4-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-4-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_lawful_dib_gross_changes_remain_counted_refusals[RecordCondition.DIB_AFTER_REDUCED_RIB-800]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_lawful_dib_gross_changes_remain_counted_refusals[RecordCondition.WORKERS_COMPENSATION_OFFSET-600]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_beneficiary_finality_protects_its_own_unsettled_fact[F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_one_beneficiary_finality_does_not_protect_the_nh[F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_first_administrative_finality_example_keeps_nh_rate", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_second_administrative_finality_example_keeps_two_protected_rates", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_fact_table_explicitly_covers_all_conditions_and_held_g_reasons", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_spouse_sequence_condition_does_not_unsettle_other_own_eligibility", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_held_against_unheld_fact_classification", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_ieds_does_not_mask_settled_auxiliary_facts[True-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_ieds_does_not_mask_settled_auxiliary_facts[True-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_preflight_changes_no_valid_outcome_or_refusal", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_two_declared_conditions_preserve_finality_protection", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_finality_is_resolved_for_each_month[False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_auxiliary_does_not_protect_another_auxiliary", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_canonical_input_error_is_never_caught_as_a_coverage_refusal[F3-_own_monthly_benefit_validated]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_canonical_input_error_is_never_caught_as_a_coverage_refusal[F4-_original_benefit_validated]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable0-reserved0-RecordCondition.ADMINISTRATIVE_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable0-reserved0-RecordCondition.ADMINISTRATIVE_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable0-reserved0-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable0-reserved0-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable1-reserved1-RecordCondition.ADMINISTRATIVE_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable1-reserved1-RecordCondition.ADMINISTRATIVE_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable1-reserved1-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable1-reserved1-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable2-reserved2-RecordCondition.ADMINISTRATIVE_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable2-reserved2-RecordCondition.ADMINISTRATIVE_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable2-reserved2-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable2-reserved2-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable3-reserved3-RecordCondition.ADMINISTRATIVE_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable3-reserved3-RecordCondition.ADMINISTRATIVE_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable3-reserved3-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable3-reserved3-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_unrelated_refused_child_does_not_invent_widow_protection[ret]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[None-basis0-deduction]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[None-None-deduction]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[False-basis0-ret]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[False-None-ret]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[None-0-1920]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[None-0-1928]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[None-4-1928]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-0-1920]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-0-1928]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-4-1928]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[None-0]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[None-4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[RecordCondition.NON_AIME_FORMULA_PIA-0]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[RecordCondition.NON_AIME_FORMULA_PIA-4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-0]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_legacy_widow_later_payment_gross_retains_eligibility_refusal[payable-False-1973]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_legacy_widow_later_payment_gross_retains_eligibility_refusal[payable-False-2024]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_legacy_widow_later_payment_gross_retains_eligibility_refusal[payable-True-1973]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_legacy_widow_later_payment_gross_retains_eligibility_refusal[payable-True-2024]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_legacy_widow_later_payment_gross_retains_eligibility_refusal[reservation-False-1973]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_legacy_widow_later_payment_gross_retains_eligibility_refusal[reservation-False-2024]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_legacy_widow_later_payment_gross_retains_eligibility_refusal[reservation-True-1973]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_legacy_widow_later_payment_gross_retains_eligibility_refusal[reservation-True-2024]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_legacy_eligibility_gross_retains_its_original_refusal[UnsupportedReason.ELIGIBILITY_BEFORE_1983-payable-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_legacy_eligibility_gross_retains_its_original_refusal[UnsupportedReason.ELIGIBILITY_BEFORE_1983-payable-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_legacy_eligibility_gross_retains_its_original_refusal[UnsupportedReason.ELIGIBILITY_BEFORE_1983-reservation-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_legacy_eligibility_gross_retains_its_original_refusal[UnsupportedReason.ELIGIBILITY_BEFORE_1983-reservation-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_legacy_eligibility_gross_retains_its_original_refusal[UnsupportedReason.DI_ENTITLEMENT_BEFORE_JULY_1980-payable-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_legacy_eligibility_gross_retains_its_original_refusal[UnsupportedReason.DI_ENTITLEMENT_BEFORE_JULY_1980-payable-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_legacy_eligibility_gross_retains_its_original_refusal[UnsupportedReason.DI_ENTITLEMENT_BEFORE_JULY_1980-reservation-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_legacy_eligibility_gross_retains_its_original_refusal[UnsupportedReason.DI_ENTITLEMENT_BEFORE_JULY_1980-reservation-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_child_ob_uncertainty_is_limited_to_pre1983_payment_months[1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_child_ob_uncertainty_preserves_old_refusals_for_odd_dime_pias", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_gross_uncertainty_retains_original_refusal[False-payable-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_gross_uncertainty_retains_original_refusal[False-payable-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_gross_uncertainty_retains_original_refusal[False-reservation-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_gross_uncertainty_retains_original_refusal[False-reservation-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_finality_keeps_its_original_refusal[payable-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_finality_keeps_its_original_refusal[payable-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_finality_keeps_its_original_refusal[reservation-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_finality_keeps_its_original_refusal[reservation-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_gross_uncertainty_preserves_refusals_across_months", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_finality_can_unsettle_the_parent_upper_bound[payable-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_finality_can_unsettle_the_parent_upper_bound[payable-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_finality_can_unsettle_the_parent_upper_bound[reservation-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_finality_can_unsettle_the_parent_upper_bound[reservation-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_widow_drc_condition_on_a_living_child_keeps_ob_settled[True-0]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_widow_drc_condition_on_a_living_child_keeps_ob_settled[True-4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F4-UnsupportedReason.PARENT_BENEFIT]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F3-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F6-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F3-UnsupportedReason.DELAYED_CREDITS_BEFORE_1917]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F6-UnsupportedReason.DELAYED_CREDITS_BEFORE_1917]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F3-UnsupportedReason.PAYMENT_MONTH_BEFORE_1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F6-UnsupportedReason.PAYMENT_MONTH_BEFORE_1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F4-UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F4-UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE_HISTORY_UNKNOWN]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F4-UnsupportedReason.PARENT_BENEFIT]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F3-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F6-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F3-UnsupportedReason.DELAYED_CREDITS_BEFORE_1917]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F6-UnsupportedReason.DELAYED_CREDITS_BEFORE_1917]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F3-UnsupportedReason.PAYMENT_MONTH_BEFORE_1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F6-UnsupportedReason.PAYMENT_MONTH_BEFORE_1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F4-UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F4-UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE_HISTORY_UNKNOWN]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_original_benefit_uses_the_payment_period[1973]" + ], + "summary": "126 failed, 159 passed in 194.49s (0:03:14)", + "test_sha256_before": "26f74adc61c076d80446965850da34a01d02744d213bb1b63921ef6b66689f5b", + "test_sha256_after": "26f74adc61c076d80446965850da34a01d02744d213bb1b63921ef6b66689f5b", + "named_copied_sources": [ + "src/populace_dynamics/__init__.py", + "src/populace_dynamics/track_b/__init__.py", + "src/populace_dynamics/track_b/_provenance.py", + "src/populace_dynamics/track_b/arf.py", + "src/populace_dynamics/track_b/b2.py", + "src/populace_dynamics/track_b/equality.py", + "src/populace_dynamics/track_b/gross_benefits.py", + "src/populace_dynamics/track_b/holdout_registry.py", + "src/populace_dynamics/track_b/recompute.py", + "src/populace_dynamics/track_b/reconstructed.py", + "src/populace_dynamics/track_b/replay.py", + "src/populace_dynamics/track_b/ret_grace.py", + "src/populace_dynamics/track_b/ret_ledger.py", + "src/populace_dynamics/track_b/ret_params.py", + "src/populace_dynamics/track_b/runner.py", + "src/populace_dynamics/track_b/parameters/__init__.py", + "src/populace_dynamics/track_b/parameters/ret_v1.yaml" + ], + "log": { + "path": "scratch/review/round5-reviewed-head.log", + "sha256": "6fd4e4cff657da6259c701f861e1782a437ab7164214d5ab365363a0e4dfe2f9" + } + }, + "late_guard_original_head_controls": { + "reviewed_head": "e3315bafb592e29031d72b5ef368ca428e4a0b55", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_missing_both_widow_cohorts_remains_canonical_input_error" + ], + "selected_test_nodes": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_missing_both_widow_cohorts_remains_canonical_input_error" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-reviewed-head/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-reviewed-head", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-reviewed-head" + }, + "exit_code": 0, + "failed_tests": [], + "summary": "3 passed in 4.70s", + "test_sha256_before": "153cafb934e6bb8ba6952b011576451a3b0a76c642a60adddfbe9c6abffe3035", + "test_sha256_after": "153cafb934e6bb8ba6952b011576451a3b0a76c642a60adddfbe9c6abffe3035", + "named_copied_sources": [ + "src/populace_dynamics/__init__.py", + "src/populace_dynamics/track_b/__init__.py", + "src/populace_dynamics/track_b/_provenance.py", + "src/populace_dynamics/track_b/arf.py", + "src/populace_dynamics/track_b/b2.py", + "src/populace_dynamics/track_b/equality.py", + "src/populace_dynamics/track_b/gross_benefits.py", + "src/populace_dynamics/track_b/holdout_registry.py", + "src/populace_dynamics/track_b/recompute.py", + "src/populace_dynamics/track_b/reconstructed.py", + "src/populace_dynamics/track_b/replay.py", + "src/populace_dynamics/track_b/ret_grace.py", + "src/populace_dynamics/track_b/ret_ledger.py", + "src/populace_dynamics/track_b/ret_params.py", + "src/populace_dynamics/track_b/runner.py", + "src/populace_dynamics/track_b/parameters/__init__.py", + "src/populace_dynamics/track_b/parameters/ret_v1.yaml" + ], + "log": { + "path": "scratch/review/round5-reviewed-head-cohort-controls.log", + "sha256": "731baa673fd65638173d66a1a72d74f12c351641a38378ca9c30e99f8784e033" + } + }, + "dual_scope_original_head_cases": { + "reviewed_head": "e3315bafb592e29031d72b5ef368ca428e4a0b55", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_eligible_disabled_widow_retains_own_sequence_refusal" + ], + "selected_test_nodes": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_eligible_disabled_widow_retains_own_sequence_refusal" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-reviewed-head/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-reviewed-head", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-reviewed-head" + }, + "exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[None-0-1920]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[None-0-1928]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[None-4-1928]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-0-1920]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-0-1928]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-4-1928]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[None-0]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[None-4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[RecordCondition.NON_AIME_FORMULA_PIA-0]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[RecordCondition.NON_AIME_FORMULA_PIA-4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-0]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-4]" + ], + "summary": "12 failed, 5 passed in 31.95s", + "test_sha256_before": "153cafb934e6bb8ba6952b011576451a3b0a76c642a60adddfbe9c6abffe3035", + "test_sha256_after": "ce4e88806d0c16158e0e5be7e0cafaefba0cff0edfc361168ad60b06a47afa87", + "named_copied_sources": [ + "src/populace_dynamics/__init__.py", + "src/populace_dynamics/track_b/__init__.py", + "src/populace_dynamics/track_b/_provenance.py", + "src/populace_dynamics/track_b/arf.py", + "src/populace_dynamics/track_b/b2.py", + "src/populace_dynamics/track_b/equality.py", + "src/populace_dynamics/track_b/gross_benefits.py", + "src/populace_dynamics/track_b/holdout_registry.py", + "src/populace_dynamics/track_b/recompute.py", + "src/populace_dynamics/track_b/reconstructed.py", + "src/populace_dynamics/track_b/replay.py", + "src/populace_dynamics/track_b/ret_grace.py", + "src/populace_dynamics/track_b/ret_ledger.py", + "src/populace_dynamics/track_b/ret_params.py", + "src/populace_dynamics/track_b/runner.py", + "src/populace_dynamics/track_b/parameters/__init__.py", + "src/populace_dynamics/track_b/parameters/ret_v1.yaml" + ], + "log": { + "path": "scratch/review/round5-reviewed-head-dual-scope.log", + "sha256": "eb1f32c29a4792f60327a6d068c31b25c652472f8599807f3e6c6eb077d4a4bb" + } + }, + "deferred_widow_drc_scope_probe": { + "description": "Executed minimized public R2 deferred widow-DRC reason scope probe; retirement record has no possible widow original benefit. Both deferred reasons counted impossible child OB2.10 against canonical OB2 from PIA4.", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-" + ], + "stdin": "from dataclasses import replace\nfrom fractions import Fraction as F\nfrom tests.test_track_b_ret_ledger_fix_round_5 import _case,_outcome,g,r\nfor reason in [g.UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE,g.UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE_HISTORY_UNKNOWN]:\n case=_case('F4',4,contradiction=True)\n context=case.family_months[1]\n case=replace(case,family_months={1:replace(context,state=replace(context.state,deferred_refusal=(reason,'scope probe')))})\n try: result=_outcome(case)\n except g.InvalidFamilyInput: print(reason.value,'INVALID')\n else:\n counts=r.count_ret_outcomes([result])\n print(reason.value,'COUNTED',result.unsupported.reason.value,counts.rows,counts.weight)\n", + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "PYTHONDONTWRITEBYTECODE": "1", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-deferred-wdrc-probe" + }, + "exit_code": 0, + "stdout": "widow_drc_savings_clause COUNTED widow_drc_savings_clause 1 7\nwidow_drc_savings_clause_history_unknown COUNTED widow_drc_savings_clause_history_unknown 1 7\n" + }, + "beneficiary_widow_drc_original_head_cases": { + "reviewed_head": "e3315bafb592e29031d72b5ef368ca428e4a0b55", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_widow_drc_condition_on_a_living_child_keeps_ob_settled", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_survivor_widow_drc_protection_keeps_its_original_refusal" + ], + "selected_test_nodes": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_widow_drc_condition_on_a_living_child_keeps_ob_settled", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_survivor_widow_drc_protection_keeps_its_original_refusal" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-reviewed-head/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-reviewed-head", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-reviewed-head" + }, + "exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_widow_drc_condition_on_a_living_child_keeps_ob_settled[True-0]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_widow_drc_condition_on_a_living_child_keeps_ob_settled[True-4]" + ], + "summary": "2 failed, 3 passed in 10.98s", + "test_sha256_before": "add7304293c593394d0112bf4d92e77acb1a7c49140cc51bfcd81a758c4dc8d9", + "test_sha256_after": "add7304293c593394d0112bf4d92e77acb1a7c49140cc51bfcd81a758c4dc8d9", + "named_copied_sources": [ + "src/populace_dynamics/__init__.py", + "src/populace_dynamics/track_b/__init__.py", + "src/populace_dynamics/track_b/_provenance.py", + "src/populace_dynamics/track_b/arf.py", + "src/populace_dynamics/track_b/b2.py", + "src/populace_dynamics/track_b/equality.py", + "src/populace_dynamics/track_b/gross_benefits.py", + "src/populace_dynamics/track_b/holdout_registry.py", + "src/populace_dynamics/track_b/recompute.py", + "src/populace_dynamics/track_b/reconstructed.py", + "src/populace_dynamics/track_b/replay.py", + "src/populace_dynamics/track_b/ret_grace.py", + "src/populace_dynamics/track_b/ret_ledger.py", + "src/populace_dynamics/track_b/ret_params.py", + "src/populace_dynamics/track_b/runner.py", + "src/populace_dynamics/track_b/parameters/__init__.py", + "src/populace_dynamics/track_b/parameters/ret_v1.yaml" + ], + "log": { + "path": "scratch/review/round5-reviewed-head-bc-scope.log", + "sha256": "a118e336dc6186941170e150f14c0e42e2be9b976c645d8ca426b097c21d8dd8" + } + }, + "final_contextual_scope_epoch": { + "description": "Final contextual deferred-reason scope and historical WIB original-rate uncertainty; no ordinary money formula changes. Broad G boundary/report/rules runs imported earlier source; final full RET plus deduction replay and final boundary subset exercise the changed path.", + "before_sha256": "73ebc6a9dac1d9d05d2ef1aca002dc0505755d466b2c0153fb1f929cd0f1b690", + "after_sha256": "cd71ea6dd462b711f3341ce8fec2c8a0b15214672989b831cd0e0d7e780542ca", + "diff": "--- before-final-contextual-scope\n+++ after-final-contextual-scope\n@@ -1739,7 +1739,7 @@\n BeneficiaryCondition.DIB_BETWEEN_SPOUSE_BENEFIT_AND_RIB: frozenset(),\n BeneficiaryCondition.WIDOW_DRC_SAVINGS_CLAUSE: frozenset({\"F4\"}),\n UnsupportedReason.ELIGIBILITY_BEFORE_1983: frozenset(),\n- UnsupportedReason.PAYMENT_MONTH_BEFORE_1983: frozenset({\"F3\", \"F6\"}),\n+ UnsupportedReason.PAYMENT_MONTH_BEFORE_1983: frozenset({\"F3\", \"F4\", \"F6\"}),\n UnsupportedReason.DI_ENTITLEMENT_BEFORE_JULY_1980: frozenset(),\n UnsupportedReason.COMBINED_FAMILY_MAXIMUM: frozenset(),\n UnsupportedReason.DEEMED_SPOUSE: frozenset(),\n@@ -1792,9 +1792,66 @@\n return holds\n \n \n-def _hold_unsettles_fact(hold, fact, state, beneficiary):\n+def _hold_unsettles_fact(\n+ hold,\n+ fact,\n+ state,\n+ beneficiary,\n+ *,\n+ payment_month,\n+ beneficiaries,\n+ params,\n+):\n if fact not in _PREFLIGHT_FACT_UNSETTLERS[hold]:\n return False\n+ if hold in (\n+ UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978,\n+ UnsupportedReason.DELAYED_CREDITS_BEFORE_1917,\n+ ):\n+ own = state.worker if beneficiary is None else beneficiary.own_benefit\n+ if own is None:\n+ return False\n+ try:\n+ _own_monthly_benefit_validated(own, params)\n+ except FamilyConfigurationUnsupported:\n+ return True\n+ return False\n+ if hold is UnsupportedReason.PARENT_BENEFIT:\n+ if beneficiary is None or beneficiary.role is not Role.PARENT:\n+ return False\n+ try:\n+ _entitled_parent_count(state, beneficiaries, params)\n+ except FamilyConfigurationUnsupported:\n+ return True\n+ return False\n+ if hold is UnsupportedReason.PAYMENT_MONTH_BEFORE_1983:\n+ if fact == \"F4\":\n+ # RS 00615.005A.2/.5: WIB became 100% of PIA in January\n+ # 1973. The current OB helper cannot settle earlier WIB.\n+ return (\n+ state.kind is FamilyKind.SURVIVOR\n+ and beneficiary is not None\n+ and beneficiary.role in _WIDOW_ROLES\n+ and (\n+ payment_month is None\n+ or (payment_month.year, payment_month.month) < (1973, 1)\n+ )\n+ )\n+ return (\n+ payment_month is None\n+ or (\n+ payment_month.year,\n+ payment_month.month,\n+ )\n+ < FIRST_SUPPORTED_PAYMENT_MONTH\n+ )\n+ if hold in (\n+ UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE,\n+ UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE_HISTORY_UNKNOWN,\n+ ):\n+ # RS 00615.712 protects survivors; a deferred reason cannot\n+ # change a living record's original benefits.\n+ return state.kind is FamilyKind.SURVIVOR\n if hold is UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE and fact == \"F6\":\n if beneficiary is None:\n return True\n@@ -1838,7 +1895,16 @@\n beneficiary = _with_effective_cohort(beneficiary)\n holds = _declared_fact_holds(state, beneficiary)\n if any(\n- _hold_unsettles_fact(hold, fact, state, beneficiary) for hold in holds\n+ _hold_unsettles_fact(\n+ hold,\n+ fact,\n+ state,\n+ beneficiary,\n+ payment_month=payment_month,\n+ beneficiaries=beneficiaries,\n+ params=params,\n+ )\n+ for hold in holds\n ):\n return False\n if (\n@@ -1885,7 +1951,16 @@\n except FamilyConfigurationUnsupported as error:\n holds.add(error.reason)\n return not any(\n- _hold_unsettles_fact(hold, fact, state, beneficiary) for hold in holds\n+ _hold_unsettles_fact(\n+ hold,\n+ fact,\n+ state,\n+ beneficiary,\n+ payment_month=payment_month,\n+ beneficiaries=beneficiaries,\n+ params=params,\n+ )\n+ for hold in holds\n )\n \n \n@@ -3728,7 +3803,15 @@\n and member.original_benefit_basis > state.pia\n )\n or any(\n- \"F4\" in _PREFLIGHT_FACT_UNSETTLERS[hold]\n+ _hold_unsettles_fact(\n+ hold,\n+ \"F4\",\n+ state,\n+ member,\n+ payment_month=payment_month,\n+ beneficiaries=beneficiaries,\n+ params=params,\n+ )\n for hold in _declared_fact_holds(state, member)\n )\n )\n" + }, + "diagnostic_order_epoch": { + "description": "Preserve the canonical auxiliary-entitlement diagnostic before an independent F4 rate mismatch. The original assertion stays unchanged. No valid money rule or classification changes.", + "before_sha256": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad", + "after_sha256": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587", + "diff": "--- before-final-narrow-guard\n+++ after-final-narrow-guard\n@@ -1239,35 +1239,32 @@\n )\n except FamilyConfigurationUnsupported:\n pass\n+ fact = \"F5\" if auxiliary.role in g._SPOUSE_ROLES else \"F6\"\n+ if settled(fact, auxiliary) and not (\n+ auxiliary.role is g.Role.PARENT and original is None\n+ ):\n+ try:\n+ own_mba = None\n+ if auxiliary.own_benefit is not None and fact == \"F6\":\n+ own_mba = g._own_monthly_benefit_validated(\n+ auxiliary.own_benefit, context.params\n+ )[1]\n+ entitled, _ = g._is_entitled(\n+ auxiliary, state.pia, own_mba, parent_ob=original\n+ )\n+ except FamilyConfigurationUnsupported:\n+ pass\n+ else:\n+ if not entitled:\n+ raise InvalidFamilyInput(\n+ \"G and RET auxiliary entitlement facts differ\"\n+ )\n if (\n settled(\"F4\", auxiliary)\n and original is not None\n and person.original_rates[month - 1] != original\n ):\n raise InvalidFamilyInput(\"G context does not match RET rates\")\n- fact = \"F5\" if auxiliary.role in g._SPOUSE_ROLES else \"F6\"\n- if not settled(fact, auxiliary):\n- continue\n- own_mba = None\n- if auxiliary.own_benefit is not None and fact == \"F6\":\n- try:\n- own_mba = g._own_monthly_benefit_validated(\n- auxiliary.own_benefit, context.params\n- )[1]\n- except FamilyConfigurationUnsupported:\n- continue\n- if auxiliary.role is g.Role.PARENT and original is None:\n- continue\n- try:\n- entitled, _ = g._is_entitled(\n- auxiliary, state.pia, own_mba, parent_ob=original\n- )\n- except FamilyConfigurationUnsupported:\n- continue\n- if not entitled:\n- raise InvalidFamilyInput(\n- \"G and RET auxiliary entitlement facts differ\"\n- )\n \n \n @_validated_entry\n" + }, + "beneficiary_scope_epoch": { + "description": "Include beneficiary widow-DRC declarations in the existing survivor-only contextual hold guard. Living child OB contradictions remain settled; survivor protection retains its refusal.", + "before_sha256": "cd71ea6dd462b711f3341ce8fec2c8a0b15214672989b831cd0e0d7e780542ca", + "after_sha256": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "diff": "--- before-final-narrow-guard\n+++ after-final-narrow-guard\n@@ -1846,6 +1846,7 @@\n < FIRST_SUPPORTED_PAYMENT_MONTH\n )\n if hold in (\n+ BeneficiaryCondition.WIDOW_DRC_SAVINGS_CLAUSE,\n UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE,\n UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE_HISTORY_UNKNOWN,\n ):\n" + }, + "reviewed_head_controls": { + "baseline": "227-case final-scope file before the last BC5 cases and strengthened property oracle", + "result": "93 failed, 134 passed in 167.64s (0:02:47)", + "functions_with_no_failed_parameters": [ + "test_finality_examples_are_verbatim_and_the_capture_hash_matches", + "test_matching_declarations_never_raise_input_errors", + "test_wep_declaration_alone_changes_none_of_the_six_facts", + "test_worker_not_entitled_declares_an_ieds_record_without_nh_rate", + "test_implicit_widow_history_remains_unsettled_behind_explicit_hold", + "test_historical_rib_gross_rule_refusal_leaves_original_reason", + "test_other_own_entitlement_uses_real_reduced_monthly_benefit", + "test_disqualified_widow_does_not_unsettle_a_child_original_benefit", + "test_widow_own_cohort_alone_matches_the_resolved_cohort_control", + "test_auxiliary_cohort_supplies_own_rib_historical_refusal", + "test_fact_table_source_quotations_and_capture_hashes", + "test_missing_both_widow_cohorts_remains_canonical_input_error", + "test_eligible_disabled_widow_retains_own_sequence_refusal" + ], + "functions_with_one_or_more_reviewed_head_failures": [ + "test_each_fact_contradiction_is_classified_by_its_declared_condition", + "test_lawful_dib_gross_changes_remain_counted_refusals", + "test_review_counterexamples_follow_finality_ruling", + "test_beneficiary_finality_protects_its_own_unsettled_fact", + "test_one_beneficiary_finality_does_not_protect_the_nh", + "test_first_administrative_finality_example_keeps_nh_rate", + "test_second_administrative_finality_example_keeps_two_protected_rates", + "test_fact_table_explicitly_covers_all_conditions_and_held_g_reasons", + "test_spouse_sequence_condition_does_not_unsettle_other_own_eligibility", + "test_held_against_unheld_fact_classification", + "test_ieds_does_not_mask_settled_auxiliary_facts", + "test_preflight_changes_no_valid_outcome_or_refusal", + "test_two_declared_conditions_preserve_finality_protection", + "test_finality_is_resolved_for_each_month", + "test_protected_auxiliary_does_not_protect_another_auxiliary", + "test_canonical_input_error_is_never_caught_as_a_coverage_refusal", + "test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob", + "test_unrelated_refused_child_does_not_invent_widow_protection", + "test_protected_widow_cannot_be_excluded_from_unknown_drc_history", + "test_aged_widow_sequence_refusal_only_unsettles_possible_carryover", + "test_modern_disabled_widow_own_rib_eligibility_is_settled", + "test_deferred_reason_unsettles_only_the_fact_within_its_scope", + "test_historical_widow_original_benefit_uses_the_payment_period" + ], + "exact_failed_nodes": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-0-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-0-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-0-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-4-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-4-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-4-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_lawful_dib_gross_changes_remain_counted_refusals[RecordCondition.DIB_AFTER_REDUCED_RIB-800]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_lawful_dib_gross_changes_remain_counted_refusals[RecordCondition.WORKERS_COMPENSATION_OFFSET-600]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_beneficiary_finality_protects_its_own_unsettled_fact[F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_one_beneficiary_finality_does_not_protect_the_nh[F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_first_administrative_finality_example_keeps_nh_rate", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_second_administrative_finality_example_keeps_two_protected_rates", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_fact_table_explicitly_covers_all_conditions_and_held_g_reasons", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_spouse_sequence_condition_does_not_unsettle_other_own_eligibility", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_held_against_unheld_fact_classification", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_ieds_does_not_mask_settled_auxiliary_facts[True-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_ieds_does_not_mask_settled_auxiliary_facts[True-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_preflight_changes_no_valid_outcome_or_refusal", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_two_declared_conditions_preserve_finality_protection", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_finality_is_resolved_for_each_month[False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_auxiliary_does_not_protect_another_auxiliary", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_canonical_input_error_is_never_caught_as_a_coverage_refusal[F3-_own_monthly_benefit_validated]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_canonical_input_error_is_never_caught_as_a_coverage_refusal[F4-_original_benefit_validated]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable0-reserved0-RecordCondition.ADMINISTRATIVE_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable0-reserved0-RecordCondition.ADMINISTRATIVE_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable0-reserved0-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable0-reserved0-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable1-reserved1-RecordCondition.ADMINISTRATIVE_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable1-reserved1-RecordCondition.ADMINISTRATIVE_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable1-reserved1-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable1-reserved1-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable2-reserved2-RecordCondition.ADMINISTRATIVE_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable2-reserved2-RecordCondition.ADMINISTRATIVE_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable2-reserved2-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable2-reserved2-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable3-reserved3-RecordCondition.ADMINISTRATIVE_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable3-reserved3-RecordCondition.ADMINISTRATIVE_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable3-reserved3-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable3-reserved3-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_unrelated_refused_child_does_not_invent_widow_protection[ret]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[None-basis0-deduction]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[None-None-deduction]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[False-basis0-ret]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[False-None-ret]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[None-0-1920]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[None-0-1928]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[None-4-1928]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-0-1920]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-0-1928]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-4-1928]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[None-0]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[None-4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[RecordCondition.NON_AIME_FORMULA_PIA-0]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[RecordCondition.NON_AIME_FORMULA_PIA-4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-0]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F4-UnsupportedReason.PARENT_BENEFIT]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F3-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F6-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F3-UnsupportedReason.DELAYED_CREDITS_BEFORE_1917]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F6-UnsupportedReason.DELAYED_CREDITS_BEFORE_1917]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F3-UnsupportedReason.PAYMENT_MONTH_BEFORE_1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F6-UnsupportedReason.PAYMENT_MONTH_BEFORE_1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F4-UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F4-UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE_HISTORY_UNKNOWN]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F4-UnsupportedReason.PARENT_BENEFIT]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F3-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F6-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F3-UnsupportedReason.DELAYED_CREDITS_BEFORE_1917]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F6-UnsupportedReason.DELAYED_CREDITS_BEFORE_1917]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F3-UnsupportedReason.PAYMENT_MONTH_BEFORE_1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F6-UnsupportedReason.PAYMENT_MONTH_BEFORE_1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F4-UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F4-UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE_HISTORY_UNKNOWN]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_original_benefit_uses_the_payment_period[1973]" + ], + "later_bc5_record": "scratch/review/round5-reviewed-head-bc-scope.json", + "note": "Final285 snapshot is executed against reviewed HEAD:126failed159passed. Older227/BC5/provisional-upper results remain historical and explicitly labeled.", + "unchanged_227_snapshot_node_ids": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-4-1920]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[None-4-1920]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_auxiliary_cohort_supplies_own_rib_historical_refusal", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_beneficiary_finality_protects_its_own_unsettled_fact[F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_beneficiary_finality_protects_its_own_unsettled_fact[F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-0-F3-UnsupportedReason.DELAYED_CREDITS_BEFORE_1917]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-0-F3-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-0-F3-UnsupportedReason.PAYMENT_MONTH_BEFORE_1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-0-F4-UnsupportedReason.PARENT_BENEFIT]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-0-F4-UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-0-F4-UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE_HISTORY_UNKNOWN]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-0-F6-UnsupportedReason.DELAYED_CREDITS_BEFORE_1917]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-0-F6-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-0-F6-UnsupportedReason.PAYMENT_MONTH_BEFORE_1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-4-F3-UnsupportedReason.DELAYED_CREDITS_BEFORE_1917]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-4-F3-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-4-F3-UnsupportedReason.PAYMENT_MONTH_BEFORE_1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-4-F4-UnsupportedReason.PARENT_BENEFIT]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-4-F4-UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-4-F4-UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE_HISTORY_UNKNOWN]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-4-F6-UnsupportedReason.DELAYED_CREDITS_BEFORE_1917]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-4-F6-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-4-F6-UnsupportedReason.PAYMENT_MONTH_BEFORE_1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_disqualified_widow_does_not_unsettle_a_child_original_benefit[False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_disqualified_widow_does_not_unsettle_a_child_original_benefit[True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-0-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-0-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-0-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-4-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-4-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-4-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-0-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-0-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-0-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-4-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-4-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-4-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-0-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-0-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-0-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-4-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-4-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-4-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_eligible_disabled_widow_retains_own_sequence_refusal", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_fact_table_source_quotations_and_capture_hashes", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_finality_examples_are_verbatim_and_the_capture_hash_matches", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_finality_is_resolved_for_each_month[True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_rib_gross_rule_refusal_leaves_original_reason", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_original_benefit_uses_the_payment_period[1972]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_ieds_does_not_mask_settled_auxiliary_facts[False-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_ieds_does_not_mask_settled_auxiliary_facts[False-0-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_ieds_does_not_mask_settled_auxiliary_facts[False-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_ieds_does_not_mask_settled_auxiliary_facts[False-4-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_ieds_does_not_mask_settled_auxiliary_facts[True-0-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_ieds_does_not_mask_settled_auxiliary_facts[True-4-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_implicit_widow_history_remains_unsettled_behind_explicit_hold", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_matching_declarations_never_raise_input_errors", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_missing_both_widow_cohorts_remains_canonical_input_error[None]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_missing_both_widow_cohorts_remains_canonical_input_error[RecordCondition.ADMINISTRATIVE_FINALITY]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_missing_both_widow_cohorts_remains_canonical_input_error[RecordCondition.NON_AIME_FORMULA_PIA]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[RecordCondition.ADMINISTRATIVE_FINALITY-0]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[RecordCondition.ADMINISTRATIVE_FINALITY-4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_one_beneficiary_finality_does_not_protect_the_nh[F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_other_own_entitlement_uses_real_reduced_monthly_benefit[None-Role.MOTHER_FATHER-BenefitType.MOTHER_FATHER]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_other_own_entitlement_uses_real_reduced_monthly_benefit[None-Role.WIDOW-BenefitType.WIDOW]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_other_own_entitlement_uses_real_reduced_monthly_benefit[RecordCondition.ADMINISTRATIVE_FINALITY-Role.MOTHER_FATHER-BenefitType.MOTHER_FATHER]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_other_own_entitlement_uses_real_reduced_monthly_benefit[RecordCondition.ADMINISTRATIVE_FINALITY-Role.WIDOW-BenefitType.WIDOW]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_other_own_entitlement_uses_real_reduced_monthly_benefit[RecordCondition.NON_AIME_FORMULA_PIA-Role.MOTHER_FATHER-BenefitType.MOTHER_FATHER]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_other_own_entitlement_uses_real_reduced_monthly_benefit[RecordCondition.NON_AIME_FORMULA_PIA-Role.WIDOW-BenefitType.WIDOW]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[False-None-deduction]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[False-basis0-deduction]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[None-None-ret]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[None-basis0-ret]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.ADMINISTRATIVE_FINALITY-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.ADMINISTRATIVE_FINALITY-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.ADMINISTRATIVE_FINALITY-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.ADMINISTRATIVE_FINALITY-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.ADMINISTRATIVE_FINALITY-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.ADMINISTRATIVE_FINALITY-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[fiscal_year-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[fiscal_year-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[fiscal_year-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[fiscal_year-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[fiscal_year-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[fiscal_year-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_unrelated_refused_child_does_not_invent_widow_protection[deduction]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_unrelated_refused_child_does_not_invent_widow_protection[deduction_disqualified_widow]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-0-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-0-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-0-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-4-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-4-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-4-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-0-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-0-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-0-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-4-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-4-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-4-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_widow_own_cohort_alone_matches_the_resolved_cohort_control[None]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_widow_own_cohort_alone_matches_the_resolved_cohort_control[RecordCondition.ADMINISTRATIVE_FINALITY]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_widow_own_cohort_alone_matches_the_resolved_cohort_control[RecordCondition.NON_AIME_FORMULA_PIA]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_worker_not_entitled_declares_an_ieds_record_without_nh_rate[0]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_worker_not_entitled_declares_an_ieds_record_without_nh_rate[4]" + ], + "unchanged_227_snapshot_node_count": 134, + "collection_record": "scratch/review/round5-new-module-collection.json", + "later_bc5_nodes": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_widow_drc_condition_on_a_living_child_keeps_ob_settled[False-0]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_widow_drc_condition_on_a_living_child_keeps_ob_settled[False-4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_widow_drc_condition_on_a_living_child_keeps_ob_settled[True-0]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_widow_drc_condition_on_a_living_child_keeps_ob_settled[True-4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_survivor_widow_drc_protection_keeps_its_original_refusal" + ], + "final_285_baseline_summary": "126 failed, 159 passed in 194.49s (0:03:14)", + "final_285_failed_nodes": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-0-1920]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-0-1928]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-4-1928]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[None-0-1920]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[None-0-1928]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[None-4-1928]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_beneficiary_finality_protects_its_own_unsettled_fact[F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_canonical_input_error_is_never_caught_as_a_coverage_refusal[F3-_own_monthly_benefit_validated]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_canonical_input_error_is_never_caught_as_a_coverage_refusal[F4-_original_benefit_validated]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_child_ob_uncertainty_is_limited_to_pre1983_payment_months[1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_child_ob_uncertainty_preserves_old_refusals_for_odd_dime_pias", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_legacy_eligibility_gross_retains_its_original_refusal[UnsupportedReason.DI_ENTITLEMENT_BEFORE_JULY_1980-payable-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_legacy_eligibility_gross_retains_its_original_refusal[UnsupportedReason.DI_ENTITLEMENT_BEFORE_JULY_1980-payable-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_legacy_eligibility_gross_retains_its_original_refusal[UnsupportedReason.DI_ENTITLEMENT_BEFORE_JULY_1980-reservation-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_legacy_eligibility_gross_retains_its_original_refusal[UnsupportedReason.DI_ENTITLEMENT_BEFORE_JULY_1980-reservation-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_legacy_eligibility_gross_retains_its_original_refusal[UnsupportedReason.ELIGIBILITY_BEFORE_1983-payable-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_legacy_eligibility_gross_retains_its_original_refusal[UnsupportedReason.ELIGIBILITY_BEFORE_1983-payable-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_legacy_eligibility_gross_retains_its_original_refusal[UnsupportedReason.ELIGIBILITY_BEFORE_1983-reservation-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_legacy_eligibility_gross_retains_its_original_refusal[UnsupportedReason.ELIGIBILITY_BEFORE_1983-reservation-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F3-UnsupportedReason.DELAYED_CREDITS_BEFORE_1917]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F3-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F3-UnsupportedReason.PAYMENT_MONTH_BEFORE_1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F4-UnsupportedReason.PARENT_BENEFIT]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F4-UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F4-UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE_HISTORY_UNKNOWN]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F6-UnsupportedReason.DELAYED_CREDITS_BEFORE_1917]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F6-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F6-UnsupportedReason.PAYMENT_MONTH_BEFORE_1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F3-UnsupportedReason.DELAYED_CREDITS_BEFORE_1917]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F3-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F3-UnsupportedReason.PAYMENT_MONTH_BEFORE_1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F4-UnsupportedReason.PARENT_BENEFIT]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F4-UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F4-UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE_HISTORY_UNKNOWN]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F6-UnsupportedReason.DELAYED_CREDITS_BEFORE_1917]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F6-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F6-UnsupportedReason.PAYMENT_MONTH_BEFORE_1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-0-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-0-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-0-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-4-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-4-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-4-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_fact_table_explicitly_covers_all_conditions_and_held_g_reasons", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_finality_can_unsettle_the_parent_upper_bound[payable-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_finality_can_unsettle_the_parent_upper_bound[payable-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_finality_can_unsettle_the_parent_upper_bound[reservation-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_finality_can_unsettle_the_parent_upper_bound[reservation-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_finality_is_resolved_for_each_month[False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_first_administrative_finality_example_keeps_nh_rate", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_held_against_unheld_fact_classification", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_finality_keeps_its_original_refusal[payable-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_finality_keeps_its_original_refusal[payable-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_finality_keeps_its_original_refusal[reservation-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_finality_keeps_its_original_refusal[reservation-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_gross_uncertainty_preserves_refusals_across_months", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_gross_uncertainty_retains_original_refusal[False-payable-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_gross_uncertainty_retains_original_refusal[False-payable-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_gross_uncertainty_retains_original_refusal[False-reservation-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_gross_uncertainty_retains_original_refusal[False-reservation-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_original_benefit_uses_the_payment_period[1973]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_ieds_does_not_mask_settled_auxiliary_facts[True-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_ieds_does_not_mask_settled_auxiliary_facts[True-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_lawful_dib_gross_changes_remain_counted_refusals[RecordCondition.DIB_AFTER_REDUCED_RIB-800]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_lawful_dib_gross_changes_remain_counted_refusals[RecordCondition.WORKERS_COMPENSATION_OFFSET-600]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_legacy_widow_later_payment_gross_retains_eligibility_refusal[payable-False-1973]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_legacy_widow_later_payment_gross_retains_eligibility_refusal[payable-False-2024]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_legacy_widow_later_payment_gross_retains_eligibility_refusal[payable-True-1973]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_legacy_widow_later_payment_gross_retains_eligibility_refusal[payable-True-2024]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_legacy_widow_later_payment_gross_retains_eligibility_refusal[reservation-False-1973]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_legacy_widow_later_payment_gross_retains_eligibility_refusal[reservation-False-2024]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_legacy_widow_later_payment_gross_retains_eligibility_refusal[reservation-True-1973]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_legacy_widow_later_payment_gross_retains_eligibility_refusal[reservation-True-2024]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-0]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[None-0]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[None-4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[RecordCondition.NON_AIME_FORMULA_PIA-0]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[RecordCondition.NON_AIME_FORMULA_PIA-4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_one_beneficiary_finality_does_not_protect_the_nh[F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_preflight_changes_no_valid_outcome_or_refusal", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_auxiliary_does_not_protect_another_auxiliary", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable0-reserved0-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable0-reserved0-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable0-reserved0-RecordCondition.ADMINISTRATIVE_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable0-reserved0-RecordCondition.ADMINISTRATIVE_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable1-reserved1-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable1-reserved1-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable1-reserved1-RecordCondition.ADMINISTRATIVE_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable1-reserved1-RecordCondition.ADMINISTRATIVE_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable2-reserved2-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable2-reserved2-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable2-reserved2-RecordCondition.ADMINISTRATIVE_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable2-reserved2-RecordCondition.ADMINISTRATIVE_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable3-reserved3-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable3-reserved3-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable3-reserved3-RecordCondition.ADMINISTRATIVE_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable3-reserved3-RecordCondition.ADMINISTRATIVE_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[False-None-ret]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[False-basis0-ret]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[None-None-deduction]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[None-basis0-deduction]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_second_administrative_finality_example_keeps_two_protected_rates", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_spouse_sequence_condition_does_not_unsettle_other_own_eligibility", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_two_declared_conditions_preserve_finality_protection", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_unrelated_refused_child_does_not_invent_widow_protection[ret]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_widow_drc_condition_on_a_living_child_keeps_ob_settled[True-0]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_widow_drc_condition_on_a_living_child_keeps_ob_settled[True-4]" + ], + "final_285_unchanged_control_nodes": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-4-1920]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[None-4-1920]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_auxiliary_cohort_supplies_own_rib_historical_refusal", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_beneficiary_finality_protects_its_own_unsettled_fact[F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_beneficiary_finality_protects_its_own_unsettled_fact[F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_child_ob_uncertainty_is_limited_to_pre1983_payment_months[1981]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-0-F3-UnsupportedReason.DELAYED_CREDITS_BEFORE_1917]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-0-F3-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-0-F3-UnsupportedReason.PAYMENT_MONTH_BEFORE_1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-0-F4-UnsupportedReason.PARENT_BENEFIT]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-0-F4-UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-0-F4-UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE_HISTORY_UNKNOWN]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-0-F6-UnsupportedReason.DELAYED_CREDITS_BEFORE_1917]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-0-F6-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-0-F6-UnsupportedReason.PAYMENT_MONTH_BEFORE_1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-4-F3-UnsupportedReason.DELAYED_CREDITS_BEFORE_1917]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-4-F3-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-4-F3-UnsupportedReason.PAYMENT_MONTH_BEFORE_1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-4-F4-UnsupportedReason.PARENT_BENEFIT]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-4-F4-UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-4-F4-UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE_HISTORY_UNKNOWN]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-4-F6-UnsupportedReason.DELAYED_CREDITS_BEFORE_1917]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-4-F6-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-4-F6-UnsupportedReason.PAYMENT_MONTH_BEFORE_1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_disqualified_widow_does_not_unsettle_a_child_original_benefit[False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_disqualified_widow_does_not_unsettle_a_child_original_benefit[True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-0-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-0-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-0-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-4-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-4-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-4-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-0-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-0-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-0-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-4-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-4-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-4-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-0-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-0-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-0-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-4-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-4-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-4-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_eligible_disabled_widow_retains_own_sequence_refusal", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_fact_table_source_quotations_and_capture_hashes", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_finality_examples_are_verbatim_and_the_capture_hash_matches", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_finality_is_resolved_for_each_month[True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_rib_gross_rule_refusal_leaves_original_reason", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_gross_uncertainty_retains_original_refusal[True-payable-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_gross_uncertainty_retains_original_refusal[True-payable-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_gross_uncertainty_retains_original_refusal[True-reservation-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_gross_uncertainty_retains_original_refusal[True-reservation-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_original_benefit_uses_the_payment_period[1972]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_ieds_does_not_mask_settled_auxiliary_facts[False-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_ieds_does_not_mask_settled_auxiliary_facts[False-0-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_ieds_does_not_mask_settled_auxiliary_facts[False-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_ieds_does_not_mask_settled_auxiliary_facts[False-4-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_ieds_does_not_mask_settled_auxiliary_facts[True-0-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_ieds_does_not_mask_settled_auxiliary_facts[True-4-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_implicit_widow_history_remains_unsettled_behind_explicit_hold", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_matching_declarations_never_raise_input_errors", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_missing_both_widow_cohorts_remains_canonical_input_error[None]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_missing_both_widow_cohorts_remains_canonical_input_error[RecordCondition.ADMINISTRATIVE_FINALITY]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_missing_both_widow_cohorts_remains_canonical_input_error[RecordCondition.NON_AIME_FORMULA_PIA]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[RecordCondition.ADMINISTRATIVE_FINALITY-0]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[RecordCondition.ADMINISTRATIVE_FINALITY-4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_old_first_dib_history_does_not_unsettle_current_child_upper_bound[payable-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_old_first_dib_history_does_not_unsettle_current_child_upper_bound[payable-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_old_first_dib_history_does_not_unsettle_current_child_upper_bound[reservation-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_old_first_dib_history_does_not_unsettle_current_child_upper_bound[reservation-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_one_beneficiary_finality_does_not_protect_the_nh[F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_other_own_entitlement_uses_real_reduced_monthly_benefit[None-Role.MOTHER_FATHER-BenefitType.MOTHER_FATHER]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_other_own_entitlement_uses_real_reduced_monthly_benefit[None-Role.WIDOW-BenefitType.WIDOW]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_other_own_entitlement_uses_real_reduced_monthly_benefit[RecordCondition.ADMINISTRATIVE_FINALITY-Role.MOTHER_FATHER-BenefitType.MOTHER_FATHER]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_other_own_entitlement_uses_real_reduced_monthly_benefit[RecordCondition.ADMINISTRATIVE_FINALITY-Role.WIDOW-BenefitType.WIDOW]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_other_own_entitlement_uses_real_reduced_monthly_benefit[RecordCondition.NON_AIME_FORMULA_PIA-Role.MOTHER_FATHER-BenefitType.MOTHER_FATHER]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_other_own_entitlement_uses_real_reduced_monthly_benefit[RecordCondition.NON_AIME_FORMULA_PIA-Role.WIDOW-BenefitType.WIDOW]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_parent_count_uncertainty_keeps_the_one_parent_upper_bound[False-payable-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_parent_count_uncertainty_keeps_the_one_parent_upper_bound[False-payable-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_parent_count_uncertainty_keeps_the_one_parent_upper_bound[False-reservation-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_parent_count_uncertainty_keeps_the_one_parent_upper_bound[False-reservation-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_parent_count_uncertainty_keeps_the_one_parent_upper_bound[True-payable-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_parent_count_uncertainty_keeps_the_one_parent_upper_bound[True-payable-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_parent_count_uncertainty_keeps_the_one_parent_upper_bound[True-reservation-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_parent_count_uncertainty_keeps_the_one_parent_upper_bound[True-reservation-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_parent_upper_bound_holds_across_scales_months_and_deferred_holds", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[False-None-deduction]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[False-basis0-deduction]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[None-None-ret]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[None-basis0-ret]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.ADMINISTRATIVE_FINALITY-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.ADMINISTRATIVE_FINALITY-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.ADMINISTRATIVE_FINALITY-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.ADMINISTRATIVE_FINALITY-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.ADMINISTRATIVE_FINALITY-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.ADMINISTRATIVE_FINALITY-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[fiscal_year-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[fiscal_year-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[fiscal_year-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[fiscal_year-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[fiscal_year-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[fiscal_year-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_survivor_widow_drc_protection_keeps_its_original_refusal", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_unrelated_refused_child_does_not_invent_widow_protection[deduction]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_unrelated_refused_child_does_not_invent_widow_protection[deduction_disqualified_widow]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-0-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-0-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-0-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-4-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-4-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-4-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-0-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-0-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-0-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-4-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-4-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-4-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_widow_drc_condition_on_a_living_child_keeps_ob_settled[False-0]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_widow_drc_condition_on_a_living_child_keeps_ob_settled[False-4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_widow_own_cohort_alone_matches_the_resolved_cohort_control[None]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_widow_own_cohort_alone_matches_the_resolved_cohort_control[RecordCondition.ADMINISTRATIVE_FINALITY]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_widow_own_cohort_alone_matches_the_resolved_cohort_control[RecordCondition.NON_AIME_FORMULA_PIA]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_worker_not_entitled_declares_an_ieds_record_without_nh_rate[0]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_worker_not_entitled_declares_an_ieds_record_without_nh_rate[4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_zero_parent_deduction_retains_parent_count_refusal[False-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_zero_parent_deduction_retains_parent_count_refusal[False-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_zero_parent_deduction_retains_parent_count_refusal[True-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_zero_parent_deduction_retains_parent_count_refusal[True-True]" + ], + "final_285_unchanged_control_count": 159, + "final_collection_record": "scratch/review/round5-new-module-collection.json" + }, + "reviewed_head_preserved_227_snapshot": { + "reviewed_head": "e3315bafb592e29031d72b5ef368ca428e4a0b55", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py" + ], + "selected_test_nodes": [ + "tests/test_track_b_ret_ledger_fix_round_5.py" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-reviewed-head/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-reviewed-head", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-reviewed-head" + }, + "exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-0-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-0-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-0-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-4-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-4-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-4-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_lawful_dib_gross_changes_remain_counted_refusals[RecordCondition.DIB_AFTER_REDUCED_RIB-800]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_lawful_dib_gross_changes_remain_counted_refusals[RecordCondition.WORKERS_COMPENSATION_OFFSET-600]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_beneficiary_finality_protects_its_own_unsettled_fact[F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_one_beneficiary_finality_does_not_protect_the_nh[F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_first_administrative_finality_example_keeps_nh_rate", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_second_administrative_finality_example_keeps_two_protected_rates", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_fact_table_explicitly_covers_all_conditions_and_held_g_reasons", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_spouse_sequence_condition_does_not_unsettle_other_own_eligibility", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_held_against_unheld_fact_classification", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_ieds_does_not_mask_settled_auxiliary_facts[True-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_ieds_does_not_mask_settled_auxiliary_facts[True-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_preflight_changes_no_valid_outcome_or_refusal", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_two_declared_conditions_preserve_finality_protection", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_finality_is_resolved_for_each_month[False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_auxiliary_does_not_protect_another_auxiliary", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_canonical_input_error_is_never_caught_as_a_coverage_refusal[F3-_own_monthly_benefit_validated]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_canonical_input_error_is_never_caught_as_a_coverage_refusal[F4-_original_benefit_validated]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable0-reserved0-RecordCondition.ADMINISTRATIVE_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable0-reserved0-RecordCondition.ADMINISTRATIVE_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable0-reserved0-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable0-reserved0-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable1-reserved1-RecordCondition.ADMINISTRATIVE_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable1-reserved1-RecordCondition.ADMINISTRATIVE_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable1-reserved1-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable1-reserved1-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable2-reserved2-RecordCondition.ADMINISTRATIVE_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable2-reserved2-RecordCondition.ADMINISTRATIVE_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable2-reserved2-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable2-reserved2-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable3-reserved3-RecordCondition.ADMINISTRATIVE_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable3-reserved3-RecordCondition.ADMINISTRATIVE_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable3-reserved3-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable3-reserved3-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_unrelated_refused_child_does_not_invent_widow_protection[ret]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[None-basis0-deduction]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[None-None-deduction]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[False-basis0-ret]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[False-None-ret]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[None-0-1920]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[None-0-1928]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[None-4-1928]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-0-1920]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-0-1928]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-4-1928]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[None-0]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[None-4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[RecordCondition.NON_AIME_FORMULA_PIA-0]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[RecordCondition.NON_AIME_FORMULA_PIA-4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-0]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F4-UnsupportedReason.PARENT_BENEFIT]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F3-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F6-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F3-UnsupportedReason.DELAYED_CREDITS_BEFORE_1917]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F6-UnsupportedReason.DELAYED_CREDITS_BEFORE_1917]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F3-UnsupportedReason.PAYMENT_MONTH_BEFORE_1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F6-UnsupportedReason.PAYMENT_MONTH_BEFORE_1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F4-UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F4-UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE_HISTORY_UNKNOWN]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F4-UnsupportedReason.PARENT_BENEFIT]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F3-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F6-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F3-UnsupportedReason.DELAYED_CREDITS_BEFORE_1917]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F6-UnsupportedReason.DELAYED_CREDITS_BEFORE_1917]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F3-UnsupportedReason.PAYMENT_MONTH_BEFORE_1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F6-UnsupportedReason.PAYMENT_MONTH_BEFORE_1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F4-UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F4-UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE_HISTORY_UNKNOWN]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_original_benefit_uses_the_payment_period[1973]" + ], + "summary": "93 failed, 134 passed in 167.64s (0:02:47)", + "test_sha256_before": "e72602a25ba020862fbef9ab31e6f9c623f86ebd3fda11cfa257659cf8553ebe", + "test_sha256_after": "e72602a25ba020862fbef9ab31e6f9c623f86ebd3fda11cfa257659cf8553ebe", + "named_copied_sources": [ + "src/populace_dynamics/__init__.py", + "src/populace_dynamics/track_b/__init__.py", + "src/populace_dynamics/track_b/_provenance.py", + "src/populace_dynamics/track_b/arf.py", + "src/populace_dynamics/track_b/b2.py", + "src/populace_dynamics/track_b/equality.py", + "src/populace_dynamics/track_b/gross_benefits.py", + "src/populace_dynamics/track_b/holdout_registry.py", + "src/populace_dynamics/track_b/recompute.py", + "src/populace_dynamics/track_b/reconstructed.py", + "src/populace_dynamics/track_b/replay.py", + "src/populace_dynamics/track_b/ret_grace.py", + "src/populace_dynamics/track_b/ret_ledger.py", + "src/populace_dynamics/track_b/ret_params.py", + "src/populace_dynamics/track_b/runner.py", + "src/populace_dynamics/track_b/parameters/__init__.py", + "src/populace_dynamics/track_b/parameters/ret_v1.yaml" + ], + "log": { + "path": "scratch/review/round5-reviewed-head.log", + "sha256": "9cfbe8e5eb0fef23ffb8e644f064b1d632a723362e0c4a53a8f2bc8d1e2c7aec" + } + }, + "named_new_module_collection": { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "--collect-only", + "-q", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "tests/test_track_b_ret_ledger_fix_round_5.py" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-final-module-collection" + }, + "exit_code": 0, + "scope": "Collection only of one explicitly named module; no tests executed and no whole-suite collection.", + "collected_nodes": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-0-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-0-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-0-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-4-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-4-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-4-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[None-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-0-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-0-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-0-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-4-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-4-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-4-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.ADMINISTRATIVE_FINALITY-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-0-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-0-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-0-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-4-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-4-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-4-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[RecordCondition.NON_AIME_FORMULA_PIA-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-0-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-0-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-0-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-4-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-4-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-4-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_each_fact_contradiction_is_classified_by_its_declared_condition[fiscal_year-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_lawful_dib_gross_changes_remain_counted_refusals[RecordCondition.DIB_AFTER_REDUCED_RIB-800]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_lawful_dib_gross_changes_remain_counted_refusals[RecordCondition.WORKERS_COMPENSATION_OFFSET-600]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.ADMINISTRATIVE_FINALITY-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.ADMINISTRATIVE_FINALITY-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.ADMINISTRATIVE_FINALITY-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.ADMINISTRATIVE_FINALITY-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.ADMINISTRATIVE_FINALITY-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.ADMINISTRATIVE_FINALITY-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[RecordCondition.NON_AIME_FORMULA_PIA-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[fiscal_year-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[fiscal_year-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[fiscal_year-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[fiscal_year-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[fiscal_year-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_review_counterexamples_follow_finality_ruling[fiscal_year-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_beneficiary_finality_protects_its_own_unsettled_fact[F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_beneficiary_finality_protects_its_own_unsettled_fact[F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_beneficiary_finality_protects_its_own_unsettled_fact[F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_one_beneficiary_finality_does_not_protect_the_nh[F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_one_beneficiary_finality_does_not_protect_the_nh[F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_first_administrative_finality_example_keeps_nh_rate", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_second_administrative_finality_example_keeps_two_protected_rates", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_finality_examples_are_verbatim_and_the_capture_hash_matches", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_fact_table_explicitly_covers_all_conditions_and_held_g_reasons", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_spouse_sequence_condition_does_not_unsettle_other_own_eligibility", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_held_against_unheld_fact_classification", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_matching_declarations_never_raise_input_errors", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-0-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-0-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-0-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-4-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-4-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-4-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[False-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-0-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-0-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-0-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-0-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-0-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-4-F1]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-4-F2]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-4-F3]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-4-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_wep_declaration_alone_changes_none_of_the_six_facts[True-4-F6]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_worker_not_entitled_declares_an_ieds_record_without_nh_rate[0]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_worker_not_entitled_declares_an_ieds_record_without_nh_rate[4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_ieds_does_not_mask_settled_auxiliary_facts[False-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_ieds_does_not_mask_settled_auxiliary_facts[False-0-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_ieds_does_not_mask_settled_auxiliary_facts[False-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_ieds_does_not_mask_settled_auxiliary_facts[False-4-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_ieds_does_not_mask_settled_auxiliary_facts[True-0-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_ieds_does_not_mask_settled_auxiliary_facts[True-0-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_ieds_does_not_mask_settled_auxiliary_facts[True-4-F4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_ieds_does_not_mask_settled_auxiliary_facts[True-4-F5]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_implicit_widow_history_remains_unsettled_behind_explicit_hold", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_preflight_changes_no_valid_outcome_or_refusal", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_rib_gross_rule_refusal_leaves_original_reason", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_two_declared_conditions_preserve_finality_protection", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_finality_is_resolved_for_each_month[False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_finality_is_resolved_for_each_month[True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_auxiliary_does_not_protect_another_auxiliary", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_canonical_input_error_is_never_caught_as_a_coverage_refusal[F3-_own_monthly_benefit_validated]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_canonical_input_error_is_never_caught_as_a_coverage_refusal[F4-_original_benefit_validated]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_other_own_entitlement_uses_real_reduced_monthly_benefit[None-Role.WIDOW-BenefitType.WIDOW]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_other_own_entitlement_uses_real_reduced_monthly_benefit[None-Role.MOTHER_FATHER-BenefitType.MOTHER_FATHER]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_other_own_entitlement_uses_real_reduced_monthly_benefit[RecordCondition.NON_AIME_FORMULA_PIA-Role.WIDOW-BenefitType.WIDOW]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_other_own_entitlement_uses_real_reduced_monthly_benefit[RecordCondition.NON_AIME_FORMULA_PIA-Role.MOTHER_FATHER-BenefitType.MOTHER_FATHER]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_other_own_entitlement_uses_real_reduced_monthly_benefit[RecordCondition.ADMINISTRATIVE_FINALITY-Role.WIDOW-BenefitType.WIDOW]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_other_own_entitlement_uses_real_reduced_monthly_benefit[RecordCondition.ADMINISTRATIVE_FINALITY-Role.MOTHER_FATHER-BenefitType.MOTHER_FATHER]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable0-reserved0-RecordCondition.ADMINISTRATIVE_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable0-reserved0-RecordCondition.ADMINISTRATIVE_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable0-reserved0-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable0-reserved0-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable1-reserved1-RecordCondition.ADMINISTRATIVE_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable1-reserved1-RecordCondition.ADMINISTRATIVE_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable1-reserved1-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable1-reserved1-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable2-reserved2-RecordCondition.ADMINISTRATIVE_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable2-reserved2-RecordCondition.ADMINISTRATIVE_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable2-reserved2-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable2-reserved2-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable3-reserved3-RecordCondition.ADMINISTRATIVE_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable3-reserved3-RecordCondition.ADMINISTRATIVE_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable3-reserved3-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob[payable3-reserved3-BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_disqualified_widow_does_not_unsettle_a_child_original_benefit[False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_disqualified_widow_does_not_unsettle_a_child_original_benefit[True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_unrelated_refused_child_does_not_invent_widow_protection[ret]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_unrelated_refused_child_does_not_invent_widow_protection[deduction]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_unrelated_refused_child_does_not_invent_widow_protection[deduction_disqualified_widow]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_widow_own_cohort_alone_matches_the_resolved_cohort_control[None]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_widow_own_cohort_alone_matches_the_resolved_cohort_control[RecordCondition.NON_AIME_FORMULA_PIA]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_widow_own_cohort_alone_matches_the_resolved_cohort_control[RecordCondition.ADMINISTRATIVE_FINALITY]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_auxiliary_cohort_supplies_own_rib_historical_refusal", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_fact_table_source_quotations_and_capture_hashes", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[None-basis0-ret]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[None-basis0-deduction]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[None-None-ret]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[None-None-deduction]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[False-basis0-ret]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[False-basis0-deduction]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[False-None-ret]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[False-None-deduction]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_missing_both_widow_cohorts_remains_canonical_input_error[None]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_missing_both_widow_cohorts_remains_canonical_input_error[RecordCondition.NON_AIME_FORMULA_PIA]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_missing_both_widow_cohorts_remains_canonical_input_error[RecordCondition.ADMINISTRATIVE_FINALITY]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[None-0-1920]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[None-0-1928]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[None-4-1920]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[None-4-1928]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-0-1920]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-0-1928]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-4-1920]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_aged_widow_sequence_refusal_only_unsettles_possible_carryover[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-4-1928]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[None-0]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[None-4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[RecordCondition.NON_AIME_FORMULA_PIA-0]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[RecordCondition.NON_AIME_FORMULA_PIA-4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[RecordCondition.ADMINISTRATIVE_FINALITY-0]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[RecordCondition.ADMINISTRATIVE_FINALITY-4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-0]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_modern_disabled_widow_own_rib_eligibility_is_settled[BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD-4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_eligible_disabled_widow_retains_own_sequence_refusal", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_legacy_widow_later_payment_gross_retains_eligibility_refusal[payable-False-1973]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_legacy_widow_later_payment_gross_retains_eligibility_refusal[payable-False-2024]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_legacy_widow_later_payment_gross_retains_eligibility_refusal[payable-True-1973]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_legacy_widow_later_payment_gross_retains_eligibility_refusal[payable-True-2024]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_legacy_widow_later_payment_gross_retains_eligibility_refusal[reservation-False-1973]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_legacy_widow_later_payment_gross_retains_eligibility_refusal[reservation-False-2024]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_legacy_widow_later_payment_gross_retains_eligibility_refusal[reservation-True-1973]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_legacy_widow_later_payment_gross_retains_eligibility_refusal[reservation-True-2024]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_legacy_eligibility_gross_retains_its_original_refusal[UnsupportedReason.ELIGIBILITY_BEFORE_1983-payable-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_legacy_eligibility_gross_retains_its_original_refusal[UnsupportedReason.ELIGIBILITY_BEFORE_1983-payable-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_legacy_eligibility_gross_retains_its_original_refusal[UnsupportedReason.ELIGIBILITY_BEFORE_1983-reservation-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_legacy_eligibility_gross_retains_its_original_refusal[UnsupportedReason.ELIGIBILITY_BEFORE_1983-reservation-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_legacy_eligibility_gross_retains_its_original_refusal[UnsupportedReason.DI_ENTITLEMENT_BEFORE_JULY_1980-payable-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_legacy_eligibility_gross_retains_its_original_refusal[UnsupportedReason.DI_ENTITLEMENT_BEFORE_JULY_1980-payable-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_legacy_eligibility_gross_retains_its_original_refusal[UnsupportedReason.DI_ENTITLEMENT_BEFORE_JULY_1980-reservation-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_legacy_eligibility_gross_retains_its_original_refusal[UnsupportedReason.DI_ENTITLEMENT_BEFORE_JULY_1980-reservation-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_old_first_dib_history_does_not_unsettle_current_child_upper_bound[payable-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_old_first_dib_history_does_not_unsettle_current_child_upper_bound[payable-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_old_first_dib_history_does_not_unsettle_current_child_upper_bound[reservation-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_old_first_dib_history_does_not_unsettle_current_child_upper_bound[reservation-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_child_ob_uncertainty_is_limited_to_pre1983_payment_months[1981]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_child_ob_uncertainty_is_limited_to_pre1983_payment_months[1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_child_ob_uncertainty_preserves_old_refusals_for_odd_dime_pias", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_gross_uncertainty_retains_original_refusal[False-payable-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_gross_uncertainty_retains_original_refusal[False-payable-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_gross_uncertainty_retains_original_refusal[False-reservation-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_gross_uncertainty_retains_original_refusal[False-reservation-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_gross_uncertainty_retains_original_refusal[True-payable-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_gross_uncertainty_retains_original_refusal[True-payable-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_gross_uncertainty_retains_original_refusal[True-reservation-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_gross_uncertainty_retains_original_refusal[True-reservation-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_finality_keeps_its_original_refusal[payable-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_finality_keeps_its_original_refusal[payable-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_finality_keeps_its_original_refusal[reservation-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_finality_keeps_its_original_refusal[reservation-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_gross_uncertainty_preserves_refusals_across_months", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_parent_count_uncertainty_keeps_the_one_parent_upper_bound[False-payable-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_parent_count_uncertainty_keeps_the_one_parent_upper_bound[False-payable-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_parent_count_uncertainty_keeps_the_one_parent_upper_bound[False-reservation-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_parent_count_uncertainty_keeps_the_one_parent_upper_bound[False-reservation-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_parent_count_uncertainty_keeps_the_one_parent_upper_bound[True-payable-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_parent_count_uncertainty_keeps_the_one_parent_upper_bound[True-payable-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_parent_count_uncertainty_keeps_the_one_parent_upper_bound[True-reservation-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_parent_count_uncertainty_keeps_the_one_parent_upper_bound[True-reservation-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_zero_parent_deduction_retains_parent_count_refusal[False-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_zero_parent_deduction_retains_parent_count_refusal[False-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_zero_parent_deduction_retains_parent_count_refusal[True-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_zero_parent_deduction_retains_parent_count_refusal[True-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_finality_can_unsettle_the_parent_upper_bound[payable-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_finality_can_unsettle_the_parent_upper_bound[payable-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_finality_can_unsettle_the_parent_upper_bound[reservation-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_finality_can_unsettle_the_parent_upper_bound[reservation-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_parent_upper_bound_holds_across_scales_months_and_deferred_holds", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_widow_drc_condition_on_a_living_child_keeps_ob_settled[False-0]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_widow_drc_condition_on_a_living_child_keeps_ob_settled[False-4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_widow_drc_condition_on_a_living_child_keeps_ob_settled[True-0]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_widow_drc_condition_on_a_living_child_keeps_ob_settled[True-4]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_survivor_widow_drc_protection_keeps_its_original_refusal", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-0-F4-UnsupportedReason.PARENT_BENEFIT]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-0-F3-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-0-F6-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-0-F3-UnsupportedReason.DELAYED_CREDITS_BEFORE_1917]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-0-F6-UnsupportedReason.DELAYED_CREDITS_BEFORE_1917]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-0-F3-UnsupportedReason.PAYMENT_MONTH_BEFORE_1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-0-F6-UnsupportedReason.PAYMENT_MONTH_BEFORE_1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-0-F4-UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-0-F4-UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE_HISTORY_UNKNOWN]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-4-F4-UnsupportedReason.PARENT_BENEFIT]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-4-F3-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-4-F6-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-4-F3-UnsupportedReason.DELAYED_CREDITS_BEFORE_1917]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-4-F6-UnsupportedReason.DELAYED_CREDITS_BEFORE_1917]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-4-F3-UnsupportedReason.PAYMENT_MONTH_BEFORE_1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-4-F6-UnsupportedReason.PAYMENT_MONTH_BEFORE_1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-4-F4-UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[False-4-F4-UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE_HISTORY_UNKNOWN]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F4-UnsupportedReason.PARENT_BENEFIT]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F3-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F6-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F3-UnsupportedReason.DELAYED_CREDITS_BEFORE_1917]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F6-UnsupportedReason.DELAYED_CREDITS_BEFORE_1917]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F3-UnsupportedReason.PAYMENT_MONTH_BEFORE_1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F6-UnsupportedReason.PAYMENT_MONTH_BEFORE_1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F4-UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-0-F4-UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE_HISTORY_UNKNOWN]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F4-UnsupportedReason.PARENT_BENEFIT]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F3-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F6-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F3-UnsupportedReason.DELAYED_CREDITS_BEFORE_1917]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F6-UnsupportedReason.DELAYED_CREDITS_BEFORE_1917]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F3-UnsupportedReason.PAYMENT_MONTH_BEFORE_1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F6-UnsupportedReason.PAYMENT_MONTH_BEFORE_1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F4-UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_deferred_reason_unsettles_only_the_fact_within_its_scope[True-4-F4-UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE_HISTORY_UNKNOWN]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_original_benefit_uses_the_payment_period[1972]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_original_benefit_uses_the_payment_period[1973]" + ], + "collected_count": 285, + "test_sha256": "26f74adc61c076d80446965850da34a01d02744d213bb1b63921ef6b66689f5b", + "log": { + "path": "scratch/review/round5-new-module-collection.log", + "sha256": "82053078838958fc46beb1eb2445ac576458b86722edf3ae13c99d895ddf3ea5" + } + }, + "required_module_coverage": { + "required_module_count": 77, + "modules": [ + { + "module": "tests/test_track_b_arf.py", + "initial_runs": [ + { + "run": "scratch/review/round5-ret_r3.json", + "summary": "1 failed, 3246 passed in 2496.03s (0:41:36)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_ret_r3.json", + "summary": "2933 passed in 1415.95s (0:23:35)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "292587c9ee1d160ad6c66da6e388e3a0b2bf4c9831f8ad3b18853c802f5bd68e" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_arf_properties.py", + "initial_runs": [ + { + "run": "scratch/review/round5-ret_r3.json", + "summary": "1 failed, 3246 passed in 2496.03s (0:41:36)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_ret_r3.json", + "summary": "2933 passed in 1415.95s (0:23:35)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "d1346b68bd07b469cea6357e1881d743e3a90c66e04080fc19fd66b44da7b68e" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_rules.json", + "summary": "2 failed, 1616 passed in 1568.16s (0:26:08)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_rules.json", + "summary": "978 passed in 1124.38s (0:18:44)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "de0946a014d054bd47f30dadaf675105aebb1dd562209c4002dee05354628286" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_conformance_report.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_report.json", + "summary": "54 passed in 2686.60s (0:44:46)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "73ebc6a9dac1d9d05d2ef1aca002dc0505755d466b2c0153fb1f929cd0f1b690", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_report.json", + "summary": "54 passed in 1656.30s (0:27:36)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "7ec6f605783c15c88abbb0834ff894645fe14e2956239c83532cd88132e699c8" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_deduction_age_inputs.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_rules.json", + "summary": "2 failed, 1616 passed in 1568.16s (0:26:08)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_rules.json", + "summary": "978 passed in 1124.38s (0:18:44)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "5d9fe8c5cb052d39c82249d6efcf4d88dace5ec68538340e7000f73af5e016df" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": true, + "final_closure_status": "passed", + "final_closure_run": { + "record": "scratch/review/round5-final_closure.json", + "summary": "1062 passed in 230.91s (0:03:50)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "d51f5d77c7aa7cf6004392e27187ce89523151fef12148088565226f7444fb64", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "d51f5d77c7aa7cf6004392e27187ce89523151fef12148088565226f7444fb64", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "5d9fe8c5cb052d39c82249d6efcf4d88dace5ec68538340e7000f73af5e016df" + }, + "latest_test_hash_still_current": true, + "effective_status": "passed on final d51f/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_deduction_cap.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_rules.json", + "summary": "2 failed, 1616 passed in 1568.16s (0:26:08)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_rules.json", + "summary": "978 passed in 1124.38s (0:18:44)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "6965d3e258ad31ad9ee496eb745885d3f6fa7b7c4ec2a48e441d0318588ec30e" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": true, + "final_closure_status": "passed", + "final_closure_run": { + "record": "scratch/review/round5-final_closure.json", + "summary": "1062 passed in 230.91s (0:03:50)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "d51f5d77c7aa7cf6004392e27187ce89523151fef12148088565226f7444fb64", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "d51f5d77c7aa7cf6004392e27187ce89523151fef12148088565226f7444fb64", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "6965d3e258ad31ad9ee496eb745885d3f6fa7b7c4ec2a48e441d0318588ec30e" + }, + "latest_test_hash_still_current": true, + "effective_status": "passed on final d51f/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_deductions.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_rules.json", + "summary": "2 failed, 1616 passed in 1568.16s (0:26:08)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_rules.json", + "summary": "978 passed in 1124.38s (0:18:44)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "b6f0493ecbb19434c09de42ff7e62a87b85818ea6dc8a5cde78963d780598e02" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": true, + "final_closure_status": "passed", + "final_closure_run": { + "record": "scratch/review/round5-final_closure.json", + "summary": "1062 passed in 230.91s (0:03:50)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "d51f5d77c7aa7cf6004392e27187ce89523151fef12148088565226f7444fb64", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "d51f5d77c7aa7cf6004392e27187ce89523151fef12148088565226f7444fb64", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "b6f0493ecbb19434c09de42ff7e62a87b85818ea6dc8a5cde78963d780598e02" + }, + "latest_test_hash_still_current": true, + "effective_status": "passed on final d51f/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_deductions_fix_round_2.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_rules.json", + "summary": "2 failed, 1616 passed in 1568.16s (0:26:08)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_rules.json", + "summary": "978 passed in 1124.38s (0:18:44)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "5cebe4f986fa7d01d7769c1d1db0581b54ae88e7c4710409285e12393244fdab" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": true, + "final_closure_status": "passed", + "final_closure_run": { + "record": "scratch/review/round5-final_closure.json", + "summary": "1062 passed in 230.91s (0:03:50)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "d51f5d77c7aa7cf6004392e27187ce89523151fef12148088565226f7444fb64", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "d51f5d77c7aa7cf6004392e27187ce89523151fef12148088565226f7444fb64", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "5cebe4f986fa7d01d7769c1d1db0581b54ae88e7c4710409285e12393244fdab" + }, + "latest_test_hash_still_current": true, + "effective_status": "passed on final d51f/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_dwb.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_rules.json", + "summary": "2 failed, 1616 passed in 1568.16s (0:26:08)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_rules.json", + "summary": "978 passed in 1124.38s (0:18:44)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "61b6270fdd9a6d156d31194535797d1f59c092943ecdb3773787d1471e2bb80a" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_fix_round_1.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_boundary.json", + "summary": "1 failed, 7240 passed in 1961.73s (0:32:41)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_boundary.json", + "summary": "7241 passed in 1303.91s (0:21:43)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "9275a8a4963ce7ed086482644d044a927100efcbeb5a05315d9cc6394168ee8c" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_fix_round_10_api.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_boundary.json", + "summary": "1 failed, 7240 passed in 1961.73s (0:32:41)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_boundary.json", + "summary": "7241 passed in 1303.91s (0:21:43)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "227fde023692f1c73a3eeb6de75213468c8e5e160ade3536bf5b7fb688c4ded6" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_fix_round_10_helpers.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_boundary.json", + "summary": "1 failed, 7240 passed in 1961.73s (0:32:41)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_boundary.json", + "summary": "7241 passed in 1303.91s (0:21:43)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "e5014776670ca9b552de756c63976e606290fb4fad85a1501b017700a05c8fdb" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_fix_round_10_objects.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_boundary.json", + "summary": "1 failed, 7240 passed in 1961.73s (0:32:41)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_boundary.json", + "summary": "7241 passed in 1303.91s (0:21:43)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "7576cc18923ad3ff38d0f44379637e822008a92cc9968d52f47b991e56fb9cfb" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_fix_round_10_parameters.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_boundary.json", + "summary": "1 failed, 7240 passed in 1961.73s (0:32:41)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_boundary.json", + "summary": "7241 passed in 1303.91s (0:21:43)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "981eced43d10a6720ccab0292c4a8c281b9ac9bf7d83132f6666254d7a4b72ee" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_fix_round_11_roles.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_boundary.json", + "summary": "1 failed, 7240 passed in 1961.73s (0:32:41)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_boundary.json", + "summary": "7241 passed in 1303.91s (0:21:43)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "d26fd86d7067eb7f4f97e1537110eab5223104ad817c3470a9eae022a90dfc73" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_fix_round_11_seals.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_boundary.json", + "summary": "1 failed, 7240 passed in 1961.73s (0:32:41)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_boundary.json", + "summary": "7241 passed in 1303.91s (0:21:43)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "937b07b094816eade9bf072595ede18b1b109db527de9805c3a3cb3d333ba4b5" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_fix_round_12_contract.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_boundary.json", + "summary": "1 failed, 7240 passed in 1961.73s (0:32:41)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_boundary.json", + "summary": "7241 passed in 1303.91s (0:21:43)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "9779ae3b22cf12daf6727cd21a6bcb12afbf3cfd34c84209bd406942a0c089e1" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_fix_round_13_audit.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_boundary.json", + "summary": "1 failed, 7240 passed in 1961.73s (0:32:41)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_boundary.json", + "summary": "7241 passed in 1303.91s (0:21:43)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "fb04098e3982aca18b439f2df148bee6333ce20406fe773da0858731a6c94ff0" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_fix_round_13_boundary.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_boundary.json", + "summary": "1 failed, 7240 passed in 1961.73s (0:32:41)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_boundary.json", + "summary": "7241 passed in 1303.91s (0:21:43)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "acac7951783a0e11140e717feab3924973e290e58857396dfab9c0b4319a5e8d" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_fix_round_13_guard.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_boundary.json", + "summary": "1 failed, 7240 passed in 1961.73s (0:32:41)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_boundary.json", + "summary": "7241 passed in 1303.91s (0:21:43)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "e5fabfda3fcab2ba9e0347449278a21b9cfc1f89645e1ab148cb4a23da9e7c2e" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_fix_round_15_arguments.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_boundary.json", + "summary": "1 failed, 7240 passed in 1961.73s (0:32:41)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_boundary.json", + "summary": "7241 passed in 1303.91s (0:21:43)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "16d5a875f4271839799738a89f2b904084bc0847eb25cd397168cea570be6d54" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_fix_round_15_collections.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_boundary.json", + "summary": "1 failed, 7240 passed in 1961.73s (0:32:41)", + "failed_nodes_in_module": [ + "tests/test_track_b_gross_benefits_fix_round_15_collections.py::test_membership_months_collapse_equivalent_month_encodings[tuple]" + ], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [ + { + "run": "scratch/review/round5-g_boundary_retry.json", + "summary": "4 passed in 25.76s", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "73ebc6a9dac1d9d05d2ef1aca002dc0505755d466b2c0153fb1f929cd0f1b690", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "73ebc6a9dac1d9d05d2ef1aca002dc0505755d466b2c0153fb1f929cd0f1b690", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_boundary.json", + "summary": "7241 passed in 1303.91s (0:21:43)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "2206b9734458774d581d3d20bfb50f1d517fd1b7d8191225cf5cacbca6561e58" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_fix_round_15_receivers.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_boundary.json", + "summary": "1 failed, 7240 passed in 1961.73s (0:32:41)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_boundary.json", + "summary": "7241 passed in 1303.91s (0:21:43)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "3de91e8701ab82a3063be9eb859e6cd0058c7d3a35ac93dce9e110e0959061ff" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_fix_round_2_care.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_boundary.json", + "summary": "1 failed, 7240 passed in 1961.73s (0:32:41)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_boundary.json", + "summary": "7241 passed in 1303.91s (0:21:43)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "7e983b28cdd1ba2c03935858610788754de66fb9489fef46672ebbf3d566225e" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_fix_round_2_history.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_boundary.json", + "summary": "1 failed, 7240 passed in 1961.73s (0:32:41)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_boundary.json", + "summary": "7241 passed in 1303.91s (0:21:43)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "17fb81a1d18ad90ccf99cc841360aec524822cc2404e03d33cfbbab3a830b3a5" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_fix_round_2_periods.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_boundary.json", + "summary": "1 failed, 7240 passed in 1961.73s (0:32:41)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_boundary.json", + "summary": "7241 passed in 1303.91s (0:21:43)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "21030c220e1b4690ac3d6754dcd9baddc23b33e824e07a842673c4128b7e6b09" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_fix_round_3_rates.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_boundary.json", + "summary": "1 failed, 7240 passed in 1961.73s (0:32:41)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_boundary.json", + "summary": "7241 passed in 1303.91s (0:21:43)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "1c638ac3d5f0b0d25b49d1abf4924d9fff45bcf5ce25366616a60d3f060faa16" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_fix_round_4_care_floor.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_boundary.json", + "summary": "1 failed, 7240 passed in 1961.73s (0:32:41)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_boundary.json", + "summary": "7241 passed in 1303.91s (0:21:43)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "d137d59fb7af48f21fda7b4e3aaf9a991d43b295930b5f341cc7cd595b875401" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_fix_round_4_composition.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_rules.json", + "summary": "2 failed, 1616 passed in 1568.16s (0:26:08)", + "failed_nodes_in_module": [ + "tests/test_track_b_gross_benefits_fix_round_4_composition.py::test_nh_only_acceptance_still_rejects_impossible_reservation[True-False]", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py::test_nh_only_acceptance_still_rejects_impossible_reservation[True-True]" + ], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [ + { + "run": "scratch/review/round5-composition_corrected.json", + "summary": "95 passed in 89.79s (0:01:29)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "73ebc6a9dac1d9d05d2ef1aca002dc0505755d466b2c0153fb1f929cd0f1b690", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "73ebc6a9dac1d9d05d2ef1aca002dc0505755d466b2c0153fb1f929cd0f1b690", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + }, + { + "run": "scratch/review/round5-composition_style.json", + "summary": "6 passed in 4.20s", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + } + } + ], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_rules.json", + "summary": "978 passed in 1124.38s (0:18:44)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "74105c3ab4c8c7e9e3fc0be9f4eb078a5c7913683c13974aa86fa598c2eda950" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_fix_round_4_divorced_care.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_boundary.json", + "summary": "1 failed, 7240 passed in 1961.73s (0:32:41)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_boundary.json", + "summary": "7241 passed in 1303.91s (0:21:43)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "cd50249e8d84a2bbb61901f08b84310d48b8d390495beadfe5112144143b4fd7" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_fix_round_5_care_history.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_boundary.json", + "summary": "1 failed, 7240 passed in 1961.73s (0:32:41)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_boundary.json", + "summary": "7241 passed in 1303.91s (0:21:43)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "a3e73482553c5fb804adaba8ed0d5e4d1520470f384bb58a0fe46cb41e58eb07" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_fix_round_5_cohorts.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_boundary.json", + "summary": "1 failed, 7240 passed in 1961.73s (0:32:41)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_boundary.json", + "summary": "7241 passed in 1303.91s (0:21:43)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "f5be483a533e47edcb58dc05bc202390e959e6ece7eca3ff11728aa46b00409d" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_fix_round_6_care_note.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_boundary.json", + "summary": "1 failed, 7240 passed in 1961.73s (0:32:41)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_boundary.json", + "summary": "7241 passed in 1303.91s (0:21:43)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "b2d158f37d35aaa63a6a1293345010bc4445c3b20c480c035932bf9725a91eca" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_fix_round_6_cohorts.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_boundary.json", + "summary": "1 failed, 7240 passed in 1961.73s (0:32:41)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_boundary.json", + "summary": "7241 passed in 1303.91s (0:21:43)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "b06e95d0a8a93af3e60b96222381b46377673e407385958b5120817bc60c2e84" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_fix_round_7_boundary.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_boundary.json", + "summary": "1 failed, 7240 passed in 1961.73s (0:32:41)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_boundary.json", + "summary": "7241 passed in 1303.91s (0:21:43)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "b2c875f010c402e4f373be5712a39affd87b6533805ed33bf63dbea60b1e6ae5" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_fix_round_7_cohorts.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_boundary.json", + "summary": "1 failed, 7240 passed in 1961.73s (0:32:41)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_boundary.json", + "summary": "7241 passed in 1303.91s (0:21:43)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "0eb73d51e1f7a61f76917df670f89bdade0e5f45f4c044be30673dff2494ca31" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_fix_round_7_history.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_boundary.json", + "summary": "1 failed, 7240 passed in 1961.73s (0:32:41)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_boundary.json", + "summary": "7241 passed in 1303.91s (0:21:43)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "fc6a7b5281e2f429a8e9f92c595b4491aa2de4229630fc5ca15eab333bacab26" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_fix_round_8_entries.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_boundary.json", + "summary": "1 failed, 7240 passed in 1961.73s (0:32:41)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_boundary.json", + "summary": "7241 passed in 1303.91s (0:21:43)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "4589caceb3f7996a6175d6f15f8038805450d8c448c56a8d95e4ccc9a5f872e5" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_fix_round_8_history.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_boundary.json", + "summary": "1 failed, 7240 passed in 1961.73s (0:32:41)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_boundary.json", + "summary": "7241 passed in 1303.91s (0:21:43)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "cf4d84edf72b150dd343d408d84e60ebd70500c8e219bc00b1552d6292af4e91" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_fix_round_9_citations.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_boundary.json", + "summary": "1 failed, 7240 passed in 1961.73s (0:32:41)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_boundary.json", + "summary": "7241 passed in 1303.91s (0:21:43)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "2ce5f13cd58a929583f659ec5bea6b2fbfa7216edd00291400773882118b9b4e" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_fix_round_9_outcomes.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_boundary.json", + "summary": "1 failed, 7240 passed in 1961.73s (0:32:41)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_boundary.json", + "summary": "7241 passed in 1303.91s (0:21:43)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "139a90841182ca8a1bbece8acd3b30df68f7d88cef833fd092c202b22017a3e6" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_fix_round_9_validation.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_boundary.json", + "summary": "1 failed, 7240 passed in 1961.73s (0:32:41)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_boundary.json", + "summary": "7241 passed in 1303.91s (0:21:43)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "0d420e98106ffe4ce7d9f1f0ae121488c4aca9ce1e1a3d941bc5aff0083efd92" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_oracle.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_rules.json", + "summary": "2 failed, 1616 passed in 1568.16s (0:26:08)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_rules.json", + "summary": "978 passed in 1124.38s (0:18:44)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "d4b88ec7a6945e76499e50266448894e99809737b1bc2a55de060bf03f591d24" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_own_input_order.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_rules.json", + "summary": "2 failed, 1616 passed in 1568.16s (0:26:08)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_rules.json", + "summary": "978 passed in 1124.38s (0:18:44)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "3bb4bd7fb3b7567109ed3f132f6b8a775e43e90a04aa4a2a0fa8542c78575291" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_parents_ieds.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_rules.json", + "summary": "2 failed, 1616 passed in 1568.16s (0:26:08)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_rules.json", + "summary": "978 passed in 1124.38s (0:18:44)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "98e5f81c99b3b80332db203c07db680b09a633c3d34bc58d15ee986f252bf73c" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_parisi.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_rules.json", + "summary": "2 failed, 1616 passed in 1568.16s (0:26:08)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_rules.json", + "summary": "978 passed in 1124.38s (0:18:44)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "4f446013cc7bd9f2ae8dc4dfe3ee59d952a9f5e7d2aaa2f104497dfe36425c1a" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_payment_review.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_rules.json", + "summary": "2 failed, 1616 passed in 1568.16s (0:26:08)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_rules.json", + "summary": "978 passed in 1124.38s (0:18:44)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "4c239c468e06a0c522151e182693a91024f61b7f38e49bbd7f03c66b01889dd7" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_properties.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_rules.json", + "summary": "2 failed, 1616 passed in 1568.16s (0:26:08)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_rules.json", + "summary": "978 passed in 1124.38s (0:18:44)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "483d502f88457f89cbc4f13b2904718eae59997a81a1189f51b0fbe635c54cfb" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_registry.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_rules.json", + "summary": "2 failed, 1616 passed in 1568.16s (0:26:08)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_rules.json", + "summary": "978 passed in 1124.38s (0:18:44)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "93dd3a5d3750cea367ddfe6ccc42f08084ae2f09e6278a1de728baf6a8ddc4df" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_review.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_rules.json", + "summary": "2 failed, 1616 passed in 1568.16s (0:26:08)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_rules.json", + "summary": "978 passed in 1124.38s (0:18:44)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "e602dfbf58ec57e25a1270d0e26bb3c5204045e43ab726266e0ef805abe2cd7c" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_saving_absence.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_rules.json", + "summary": "2 failed, 1616 passed in 1568.16s (0:26:08)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_rules.json", + "summary": "978 passed in 1124.38s (0:18:44)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "e6078f978ee7bf1d0802dde67c2de94397fd3e9cd142b2c96d6d504ceb0a6862" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_savings.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_rules.json", + "summary": "2 failed, 1616 passed in 1568.16s (0:26:08)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_rules.json", + "summary": "978 passed in 1124.38s (0:18:44)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "607bf6cb7415d03bd7b863673d7b9d403841d175a1684f211a562536f4f4755b" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_savings_fix_round_2.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_rules.json", + "summary": "2 failed, 1616 passed in 1568.16s (0:26:08)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_rules.json", + "summary": "978 passed in 1124.38s (0:18:44)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "d84130cc73468a8b3f8223c5526f0e982597e552c40e714d691608d32da59233" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_sources_20261011.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_rules.json", + "summary": "2 failed, 1616 passed in 1568.16s (0:26:08)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_rules.json", + "summary": "978 passed in 1124.38s (0:18:44)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "e3291d0b6bf497a20835800c4d6ee833854e5edf5b25229932e7a142f8e51a13" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_gross_benefits_ssfa.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_rules.json", + "summary": "2 failed, 1616 passed in 1568.16s (0:26:08)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_rules.json", + "summary": "978 passed in 1124.38s (0:18:44)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "07fee44e63376a58508296b6f66d1fc20adfa1c88c8cd110a1d5fc45dc4f1ebf" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_input_schema.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_rules.json", + "summary": "2 failed, 1616 passed in 1568.16s (0:26:08)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_diagnostic.json", + "summary": "1019 passed in 540.36s (0:09:00)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "d638f55a4de888d49cf236e5b58086ef773e63365e5f5ba5578aef3b9d7a8d32" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": true, + "final_closure_status": "passed", + "final_closure_run": { + "record": "scratch/review/round5-final_closure.json", + "summary": "1062 passed in 230.91s (0:03:50)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "d51f5d77c7aa7cf6004392e27187ce89523151fef12148088565226f7444fb64", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "d51f5d77c7aa7cf6004392e27187ce89523151fef12148088565226f7444fb64", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "d638f55a4de888d49cf236e5b58086ef773e63365e5f5ba5578aef3b9d7a8d32" + }, + "latest_test_hash_still_current": true, + "effective_status": "passed on final d51f/2aa source epoch" + }, + { + "module": "tests/test_track_b_r3_fix_round_13.py", + "initial_runs": [ + { + "run": "scratch/review/round5-ret_r3.json", + "summary": "1 failed, 3246 passed in 2496.03s (0:41:36)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_ret_r3.json", + "summary": "2933 passed in 1415.95s (0:23:35)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "bfb81d8316574e9df0e2e7cb9f890e1b9f584cac2cd17e025825580e219cebc7" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_r3_provenance.py", + "initial_runs": [ + { + "run": "scratch/review/round5-ret_r3.json", + "summary": "1 failed, 3246 passed in 2496.03s (0:41:36)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_ret_r3.json", + "summary": "2933 passed in 1415.95s (0:23:35)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "58243309d56acb9dc38e9bf5a701e79ac961ac062e0d37690b12a561592245c9" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_r3_sources.py", + "initial_runs": [ + { + "run": "scratch/review/round5-ret_r3.json", + "summary": "1 failed, 3246 passed in 2496.03s (0:41:36)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_ret_r3.json", + "summary": "2933 passed in 1415.95s (0:23:35)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "6300b1a4075a0f2549cce4db0aab25d6908eba9071a5a2da3bbfc6d020dd04ba" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_r3_validation_once.py", + "initial_runs": [ + { + "run": "scratch/review/round5-ret_r3.json", + "summary": "1 failed, 3246 passed in 2496.03s (0:41:36)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_diagnostic.json", + "summary": "1019 passed in 540.36s (0:09:00)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "ad28687b52c6386e7c5e28525eac12dc9a4ba62b75d18e066d5bdac1252624c0" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": true, + "final_closure_status": "passed", + "final_closure_run": { + "record": "scratch/review/round5-final_closure.json", + "summary": "1062 passed in 230.91s (0:03:50)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "d51f5d77c7aa7cf6004392e27187ce89523151fef12148088565226f7444fb64", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "d51f5d77c7aa7cf6004392e27187ce89523151fef12148088565226f7444fb64", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "ad28687b52c6386e7c5e28525eac12dc9a4ba62b75d18e066d5bdac1252624c0" + }, + "latest_test_hash_still_current": true, + "effective_status": "passed on final d51f/2aa source epoch" + }, + { + "module": "tests/test_track_b_recompute.py", + "initial_runs": [ + { + "run": "scratch/review/round5-ret_r3.json", + "summary": "1 failed, 3246 passed in 2496.03s (0:41:36)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_ret_r3.json", + "summary": "2933 passed in 1415.95s (0:23:35)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "06db2b43c6c13d679a71a6d2176dc3ee13fce8fc1645684fcbe7c582f9e54f9c" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_recompute_properties.py", + "initial_runs": [ + { + "run": "scratch/review/round5-ret_r3.json", + "summary": "1 failed, 3246 passed in 2496.03s (0:41:36)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_ret_r3.json", + "summary": "2933 passed in 1415.95s (0:23:35)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "ced431cb4fd0de82a7cde6ff63c6a38eaad1649939d364b1023dcc81aff30759" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_refusal_notes.py", + "initial_runs": [ + { + "run": "scratch/review/round5-g_rules.json", + "summary": "2 failed, 1616 passed in 1568.16s (0:26:08)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_g_rules.json", + "summary": "978 passed in 1124.38s (0:18:44)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "5c765432752317684e4059f2d45a2a95fd03ff327fb1225f853267588fc76abe" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_ret_differential.py", + "initial_runs": [ + { + "run": "scratch/review/round5-ret_r3.json", + "summary": "1 failed, 3246 passed in 2496.03s (0:41:36)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_ret_r3.json", + "summary": "2933 passed in 1415.95s (0:23:35)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "8e38e1040d61d9f0262bbe25c5c17e0f608c433cb29ab898b7f954358bcf1e12" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_ret_fra_facts.py", + "initial_runs": [ + { + "run": "scratch/review/round5-ret_r3.json", + "summary": "1 failed, 3246 passed in 2496.03s (0:41:36)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_diagnostic.json", + "summary": "1019 passed in 540.36s (0:09:00)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "7bfb53be6660bbfad0831904d5b39a3e8d997216308b136959ece10bb04c72a8" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_ret_grace.py", + "initial_runs": [ + { + "run": "scratch/review/round5-ret_r3.json", + "summary": "1 failed, 3246 passed in 2496.03s (0:41:36)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_ret_r3.json", + "summary": "2933 passed in 1415.95s (0:23:35)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "772f6b94187593549cd21a2dbb19a75f998fb840f6b6eb3a97bbeca3f36636dc" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_ret_grace_differential.py", + "initial_runs": [ + { + "run": "scratch/review/round5-ret_r3.json", + "summary": "1 failed, 3246 passed in 2496.03s (0:41:36)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_ret_r3.json", + "summary": "2933 passed in 1415.95s (0:23:35)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "fbf01f2c6e76f2cc8a60bad5e9c9ac5c4da0c68013578b91de9488aa2623abf5" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_ret_grace_provenance.py", + "initial_runs": [ + { + "run": "scratch/review/round5-ret_r3.json", + "summary": "1 failed, 3246 passed in 2496.03s (0:41:36)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_ret_r3.json", + "summary": "2933 passed in 1415.95s (0:23:35)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "8cf4446fb0bb6da77a7b84815caafe595ec81b9b7a2cc1e56f686cd25f0e77a5" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_ret_ledger.py", + "initial_runs": [ + { + "run": "scratch/review/round5-ret_r3.json", + "summary": "1 failed, 3246 passed in 2496.03s (0:41:36)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_ret_r3.json", + "summary": "2933 passed in 1415.95s (0:23:35)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "6d6684e63aa3d56874fb0fd174867d1e2b41e54119ad8077c2e6b689ca723065" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_ret_ledger_deductions.py", + "initial_runs": [ + { + "run": "scratch/review/round5-ret_r3.json", + "summary": "1 failed, 3246 passed in 2496.03s (0:41:36)", + "failed_nodes_in_module": [ + "tests/test_track_b_ret_ledger_deductions.py::test_family_context_invalidity_precedes_record_refusal" + ], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_diagnostic.json", + "summary": "1019 passed in 540.36s (0:09:00)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "a3fcc50166b867f9d3d719bcf611880cba169b3b99f6bf695ff397a36b2fcd2e" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_ret_ledger_fix_round_2.py", + "initial_runs": [ + { + "run": "scratch/review/round5-ret_r3.json", + "summary": "1 failed, 3246 passed in 2496.03s (0:41:36)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_ret_r3.json", + "summary": "2933 passed in 1415.95s (0:23:35)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "62a81110909ddebfa77f65078d685464f553c37de89cb88efd743ca406b1aa70" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_ret_ledger_fix_round_4.py", + "initial_runs": [ + { + "run": "scratch/review/round5-ret_r3.json", + "summary": "1 failed, 3246 passed in 2496.03s (0:41:36)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_ret_r3.json", + "summary": "2933 passed in 1415.95s (0:23:35)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "0c304d939709da534e89c374ff9687548531796c4716d51dd5e7e232346b6681" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_ret_ledger_properties.py", + "initial_runs": [ + { + "run": "scratch/review/round5-ret_r3.json", + "summary": "1 failed, 3246 passed in 2496.03s (0:41:36)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_ret_r3.json", + "summary": "2933 passed in 1415.95s (0:23:35)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "803433fd9d3aa7601b45e2f5346d716254409710e9f9d3ac61f1a42d87cc7d64" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_ret_ledger_readings.py", + "initial_runs": [ + { + "run": "scratch/review/round5-ret_r3.json", + "summary": "1 failed, 3246 passed in 2496.03s (0:41:36)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_ret_r3.json", + "summary": "2933 passed in 1415.95s (0:23:35)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "630bdd1d5f53d93c63674192f205e17edff601f8dcc8d941348db98cf094bdad" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_ret_ledger_sources.py", + "initial_runs": [ + { + "run": "scratch/review/round5-ret_r3.json", + "summary": "1 failed, 3246 passed in 2496.03s (0:41:36)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_ret_r3.json", + "summary": "2933 passed in 1415.95s (0:23:35)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "ab6b6d66d370c93e5b2cc82b88670f48eb5bceeb0d313c36550986c3ff1844b6" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_ret_params.py", + "initial_runs": [ + { + "run": "scratch/review/round5-ret_r3.json", + "summary": "1 failed, 3246 passed in 2496.03s (0:41:36)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_ret_r3.json", + "summary": "2933 passed in 1415.95s (0:23:35)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "57a1be52d32c3549d711aba4f88f42cdb0affd98bc3b3d5bf7e607fc0b2c3514" + }, + "ordinary_test_hash_still_current": true, + "final_closure_module": false, + "final_closure_status": "Ordinary06ab/2aa epoch retained under orchestrator decision.", + "effective_status": "passed at retained ordinary 06ab/2aa source epoch" + }, + { + "module": "tests/test_track_b_ret_ledger_fix_round_5.py", + "initial_runs": [ + { + "run": "scratch/review/round5-ret_r3.json", + "summary": "1 failed, 3246 passed in 2496.03s (0:41:36)", + "failed_nodes_in_module": [], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + } + } + ], + "later_runs": [], + "ordinary_passed_run": { + "record": "scratch/review/round5-final_diagnostic.json", + "summary": "1019 passed in 540.36s (0:09:00)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "add7304293c593394d0112bf4d92e77acb1a7c49140cc51bfcd81a758c4dc8d9" + }, + "ordinary_test_hash_still_current": false, + "final_closure_module": true, + "final_closure_status": "passed", + "final_closure_run": { + "record": "scratch/review/round5-final_closure.json", + "summary": "1062 passed in 230.91s (0:03:50)", + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "d51f5d77c7aa7cf6004392e27187ce89523151fef12148088565226f7444fb64", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "d51f5d77c7aa7cf6004392e27187ce89523151fef12148088565226f7444fb64", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "test_sha256": "26f74adc61c076d80446965850da34a01d02744d213bb1b63921ef6b66689f5b" + }, + "latest_test_hash_still_current": true, + "effective_status": "passed on final d51f/2aa source epoch" + } + ], + "note": "All77explicitmodules passed ordinary grids at06ab/2aa; late upper-bound and historical-uncertainty changes have final7module closure pending. No single final-source-hash claim. Expandednewmodule testhash is marked stale until that closure.", + "all_required_modules_passed": true, + "final_closure_module_count": 7, + "final_closure_record": "scratch/review/round5-final_closure.json", + "all_required_modules_ran_on_single_final_source_hash": false, + "epoch_policy": "Ordinary 77-module coverage at 06ab/2aa retained under orchestrator decision; final d51f/2aa closure reruns seven changed-path modules. All required modules passed. No claim of a single final-source sweep." + }, + "upper_scope_original_head_cases": { + "reviewed_head": "e3315bafb592e29031d72b5ef368ca428e4a0b55", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_ob_changes_do_not_raise_the_modern_upper_bound", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_finality_can_unsettle_the_upper_bound", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_upper_bound_holds_across_scales_and_months", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_parent_count_uncertainty_keeps_the_one_parent_upper_bound", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_zero_parent_deduction_retains_parent_count_refusal", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_finality_can_unsettle_the_parent_upper_bound", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_parent_upper_bound_holds_across_scales_months_and_deferred_holds", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_child_ob_uncertainty_is_limited_to_pre1983_payment_months", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_child_ob_uncertainty_preserves_old_refusals_for_odd_dime_pias" + ], + "selected_test_nodes": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_ob_changes_do_not_raise_the_modern_upper_bound", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_finality_can_unsettle_the_upper_bound", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_upper_bound_holds_across_scales_and_months", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_parent_count_uncertainty_keeps_the_one_parent_upper_bound", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_zero_parent_deduction_retains_parent_count_refusal", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_finality_can_unsettle_the_parent_upper_bound", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_parent_upper_bound_holds_across_scales_months_and_deferred_holds", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_child_ob_uncertainty_is_limited_to_pre1983_payment_months", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_child_ob_uncertainty_preserves_old_refusals_for_odd_dime_pias" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-reviewed-head/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-reviewed-head", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-reviewed-head" + }, + "exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_finality_can_unsettle_the_upper_bound[payable-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_finality_can_unsettle_the_upper_bound[payable-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_finality_can_unsettle_the_upper_bound[reservation-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_historical_widow_finality_can_unsettle_the_upper_bound[reservation-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_finality_can_unsettle_the_parent_upper_bound[payable-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_finality_can_unsettle_the_parent_upper_bound[payable-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_finality_can_unsettle_the_parent_upper_bound[reservation-False]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_finality_can_unsettle_the_parent_upper_bound[reservation-True]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_child_ob_uncertainty_is_limited_to_pre1983_payment_months[1983]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_child_ob_uncertainty_preserves_old_refusals_for_odd_dime_pias" + ], + "summary": "10 failed, 23 passed in 40.84s", + "test_sha256_before": "3b58154fbffe92964670395ee6bf8419df45ae1371b40cf9874ddd382f1aae67", + "test_sha256_after": "3b58154fbffe92964670395ee6bf8419df45ae1371b40cf9874ddd382f1aae67", + "named_copied_sources": [ + "src/populace_dynamics/__init__.py", + "src/populace_dynamics/track_b/__init__.py", + "src/populace_dynamics/track_b/_provenance.py", + "src/populace_dynamics/track_b/arf.py", + "src/populace_dynamics/track_b/b2.py", + "src/populace_dynamics/track_b/equality.py", + "src/populace_dynamics/track_b/gross_benefits.py", + "src/populace_dynamics/track_b/holdout_registry.py", + "src/populace_dynamics/track_b/recompute.py", + "src/populace_dynamics/track_b/reconstructed.py", + "src/populace_dynamics/track_b/replay.py", + "src/populace_dynamics/track_b/ret_grace.py", + "src/populace_dynamics/track_b/ret_ledger.py", + "src/populace_dynamics/track_b/ret_params.py", + "src/populace_dynamics/track_b/runner.py", + "src/populace_dynamics/track_b/parameters/__init__.py", + "src/populace_dynamics/track_b/parameters/ret_v1.yaml" + ], + "log": { + "path": "scratch/review/round5-reviewed-head-upper-scope.log", + "sha256": "662601c11e484e352e992ac2fa497625dc0bfa0b30293e8b4c8d17cf827335ec" + }, + "superseded": true, + "correction_record": "scratch/review/round5-probe-corrections.json" + }, + "final_formatting": { + "product_files": [ + "src/populace_dynamics/track_b/gross_benefits.py", + "src/populace_dynamics/track_b/ret_ledger.py", + "tests/test_track_b_ret_ledger_fix_round_4.py", + "tests/test_track_b_ret_ledger_fix_round_5.py", + "tests/test_track_b_gross_benefits_deduction_cap.py", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py" + ], + "verification_helper_files": [ + "scratch/review/round5-audit-hook/sitecustomize.py", + "scratch/review/round5_guarded.py", + "scratch/review/round5_prepare_verification.py", + "scratch/review/round5_run_gate.py", + "scratch/review/round5_run_cross_head.py", + "scratch/review/round5_run_reviewed_head.py", + "scratch/review/round5_mutation_check.py", + "scratch/review/round5_consolidate_verification.py", + "scratch/review/round5_run_affected_report.py" + ], + "runs": [ + { + "tool": "black", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "black", + "--check", + "-l", + "79", + "src/populace_dynamics/track_b/gross_benefits.py", + "src/populace_dynamics/track_b/ret_ledger.py", + "tests/test_track_b_gross_benefits_deduction_cap.py", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py", + "tests/test_track_b_ret_ledger_fix_round_4.py", + "tests/test_track_b_ret_ledger_fix_round_5.py" + ], + "environment": {}, + "exit_code": 0, + "stdout": "All done! 6 files would be left unchanged.", + "summary": "6 changed Python files clean" + }, + { + "tool": "ruff", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "ruff", + "check", + "src/populace_dynamics/track_b/gross_benefits.py", + "src/populace_dynamics/track_b/ret_ledger.py", + "tests/test_track_b_gross_benefits_deduction_cap.py", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py", + "tests/test_track_b_ret_ledger_fix_round_4.py", + "tests/test_track_b_ret_ledger_fix_round_5.py" + ], + "environment": {}, + "exit_code": 0, + "stdout": "All checks passed!", + "summary": "All checks passed" + }, + { + "tool": "black", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "black", + "--check", + "--workers", + "1", + "-l", + "79", + "scratch/review/round5-audit-hook/sitecustomize.py", + "scratch/review/round5_guarded.py", + "scratch/review/round5_prepare_verification.py", + "scratch/review/round5_run_gate.py", + "scratch/review/round5_run_cross_head.py", + "scratch/review/round5_run_reviewed_head.py", + "scratch/review/round5_mutation_check.py", + "scratch/review/round5_consolidate_verification.py", + "scratch/review/round5_run_affected_report.py" + ], + "environment": { + "BLACK_NUM_WORKERS": "1", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE" + }, + "exit_code": 0, + "stdout": "All done! \u2728 \ud83c\udf70 \u2728\n9 files would be left unchanged.\n", + "log": { + "path": "scratch/review/round5-final-helper-black.log", + "sha256": "92aa03151aac11a6a2858431d3a65e1d3a9c02b208849bad15a5d01e63497b9e" + } + }, + { + "tool": "ruff", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "ruff", + "check", + "scratch/review/round5-audit-hook/sitecustomize.py", + "scratch/review/round5_guarded.py", + "scratch/review/round5_prepare_verification.py", + "scratch/review/round5_run_gate.py", + "scratch/review/round5_run_cross_head.py", + "scratch/review/round5_run_reviewed_head.py", + "scratch/review/round5_mutation_check.py", + "scratch/review/round5_consolidate_verification.py", + "scratch/review/round5_run_affected_report.py" + ], + "environment": { + "BLACK_NUM_WORKERS": "1", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE" + }, + "exit_code": 0, + "stdout": "All checks passed!\n", + "log": { + "path": "scratch/review/round5-final-helper-ruff.log", + "sha256": "82b3e6a6c090a57601d22943bd23fca9218d1031dbe5a7b754092f9a156b4f18" + } + } + ], + "product_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "d51f5d77c7aa7cf6004392e27187ce89523151fef12148088565226f7444fb64", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587", + "tests/test_track_b_ret_ledger_fix_round_4.py": "0c304d939709da534e89c374ff9687548531796c4716d51dd5e7e232346b6681", + "tests/test_track_b_ret_ledger_fix_round_5.py": "26f74adc61c076d80446965850da34a01d02744d213bb1b63921ef6b66689f5b", + "tests/test_track_b_gross_benefits_deduction_cap.py": "6965d3e258ad31ad9ee496eb745885d3f6fa7b7c4ec2a48e441d0318588ec30e", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py": "74105c3ab4c8c7e9e3fc0be9f4eb078a5c7913683c13974aa86fa598c2eda950" + }, + "previous_14_file_format_record": "Historical earlier record superseded by final six product checks and final nine helper checks.", + "all_fifteen_files_clean": true + }, + "probe_corrections": { + "retracted_probe": { + "log": "scratch/review/round5-historical-upper-bound-first.log", + "observed_result": "5 failed, 8 passed, 249 deselected in 3.52 s", + "reason": "The new test assumption that historical widow gross cannot exceed modern PIA was unsupported. Captured RS 00615.010 gives a sole survivor $84.50 alternative and conditional carryover elimination. Historical gross stays unsettled/refused; these failures do not establish a production defect.", + "replacement": "Historical gross uncertainty refusal controls/property, including later payment months, with source quotation checks." + }, + "provisional_baseline": "scratch/review/round5-reviewed-head-upper-scope-before-historical-correction.json", + "note": "The provisional upper-scope baseline and legacy-carryover draft are superseded for bug claims. The final corrected 285-case reviewed-head replay is authoritative: 126 failed, 159 passed.", + "retracted_old_di_child_draft": { + "log": "/tmp/round5-legacy-carryover-first.log", + "observed_result": "16 failed in the draft snapshot, including four incorrect old-DI child refusal expectations.", + "reason": "An old first-DI date does not unsettle an unrelated child original-benefit upper bound. The corrected unchanged-behavior controls assert InvalidFamilyInput with no row, rather than a refusal. These four draft failures do not establish a production defect.", + "valid_replacement_evidence": "scratch/review/round5-legacy-widow-first.log", + "valid_replacement_summary": "12 failed, 269 deselected in 17.12s; clean later-payment/deferred-history widow regressions before the source patch.", + "corrected_control": "test_old_first_dib_history_does_not_unsettle_current_child_upper_bound" + } + }, + "legacy_widow_failing_first": { + "provenance": "Exact command and source epoch supplied by root; clean production-defect evidence before the final source patch.", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "-m", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py", + "-k", + "legacy_widow_later_payment or deferred_legacy_eligibility" + ], + "environment": { + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent-trackb-round5", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent-trackb-round5", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5" + }, + "exit_code": 1, + "summary": "12 failed, 269 deselected in 17.12s", + "test_snapshot_case_count": 281, + "source_epoch": { + "gross_benefits.py": "06ab2a071acbddfb531e8ad6be9ee8d088f12c17cbf56a7b7f18bf6bd202324e", + "ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "log": { + "path": "scratch/review/round5-legacy-widow-first.log", + "sha256": "e329100d380e36d51bdd79d742347c5966b3a37cfbda510f28d6da51f7921652" + }, + "excluded_draft_evidence": "The separate agent log with sixteen failures included four invalid draft child assertions; those are not production-defect evidence." + }, + "affected_report_final_check": { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_run_affected_report.py", + "--worker" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-affected-report" + }, + "exit_code": 0, + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "d51f5d77c7aa7cf6004392e27187ce89523151fef12148088565226f7444fb64", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587", + "scripts/track_b_g_conformance_report.py": "884811d5968cab6f22e7c72385bf6b14274f2273bb133ff1b12cb3bea06e6fbb" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "d51f5d77c7aa7cf6004392e27187ce89523151fef12148088565226f7444fb64", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587", + "scripts/track_b_g_conformance_report.py": "884811d5968cab6f22e7c72385bf6b14274f2273bb133ff1b12cb3bea06e6fbb" + }, + "log": { + "path": "scratch/review/round5-affected-report.log", + "sha256": "c2c6b41c454c94454f628444a8bc96f2cb368ce1a732866bd88f6b6debe441a1" + }, + "result": { + "deduction_rows": 16, + "refusal_witnesses": 38, + "affected_sections_equal": true, + "canonical_bytes_equal": true, + "sha256": "17d144575b38bb85080d8cbed28fad470ec93fd6eb6803b48729bb26a78b3d45", + "scope": "Final-source affected-section check; the unchanged lattice, registry and scalar metadata are retained from the complete 06ab report regeneration. This is not a full final-source report regeneration." + }, + "audit": { + "processes": 1, + "counts": { + "open": 76, + "restricted_open": 0, + "restricted_import": 0, + "subprocess.Popen": 0, + "os.system": 0 + } + } + }, + "final_git_checks": { + "records": [ + { + "command": [ + "git", + "rev-parse", + "HEAD" + ], + "exit_code": 0, + "stdout": "e3315bafb592e29031d72b5ef368ca428e4a0b55\n", + "stderr": "" + }, + { + "command": [ + "git", + "log", + "--oneline", + "origin/master..HEAD" + ], + "exit_code": 0, + "stdout": "e3315baf Keep outside events out of governed decisions and check declared facts first (#563 round 4)\n1ce508e5 Check FRA facts, the OB bound and as-if-absent membership (#563 round 3)\n872cebc7 Record the conformance hash refresh in the verification ledger (#563)\n7fa124e3 Refresh the G conformance report's registry hash (#563)\nbbcdf7f4 Merge master a747bafa into the G part 2 / R2 part (b) branch\n1a9c8b7e Finish and verify #563 fix round 2 (part 2)\n4493e58b Merge master 1ec57a5d into the G part 2 / R2 part (b) branch\n2f88f07e Refuse uncovered G2 and R2 part (b) paths (#563 fix round 2, part 1)\n0ccf66ff Merge master 9967dfd6 into the G part 2 / R2 part (b) branch\nf3b9a719 Regenerate the G conformance report with the deduction denominator; record mutations and verification; recount tiers\n57756aa1 G part 2 and R2 part (b): deduction before reduction; SSA's operational saving clause\n0e7a7706 Let refusal exception notes be deleted again; register guard enums before first use\n", + "stderr": "" + }, + { + "command": [ + "git", + "--no-pager", + "diff", + "--name-only", + "origin/master...HEAD" + ], + "exit_code": 0, + "stdout": "docs/design/track_b_g2_r2b_mutations.json\ndocs/design/track_b_g2_r2b_verification.json\ndocs/design/track_b_g_conformance_report.json\ndocs/design/track_b_g_gross_benefits.md\ndocs/design/track_b_r2_ret_ledger.md\nscripts/track_b_g_conformance_report.py\nscripts/track_b_r2_cross_head.py\nsrc/populace_dynamics/track_b/_provenance.py\nsrc/populace_dynamics/track_b/gross_benefits.py\nsrc/populace_dynamics/track_b/ret_ledger.py\ntests/README-tiers.md\ntests/data/track_b/gross_benefit_examples.yaml\ntests/data/track_b/gross_benefit_sources/README.md\ntests/data/track_b/gross_benefit_sources/manifest.json\ntests/test_track_b_gross_benefits.py\ntests/test_track_b_gross_benefits_conformance_report.py\ntests/test_track_b_gross_benefits_deduction_age_inputs.py\ntests/test_track_b_gross_benefits_deduction_cap.py\ntests/test_track_b_gross_benefits_deductions.py\ntests/test_track_b_gross_benefits_deductions_fix_round_2.py\ntests/test_track_b_gross_benefits_fix_round_10_api.py\ntests/test_track_b_gross_benefits_fix_round_10_helpers.py\ntests/test_track_b_gross_benefits_fix_round_10_objects.py\ntests/test_track_b_gross_benefits_fix_round_10_parameters.py\ntests/test_track_b_gross_benefits_fix_round_11_seals.py\ntests/test_track_b_gross_benefits_fix_round_12_contract.py\ntests/test_track_b_gross_benefits_fix_round_13_audit.py\ntests/test_track_b_gross_benefits_fix_round_13_guard.py\ntests/test_track_b_gross_benefits_fix_round_15_receivers.py\ntests/test_track_b_gross_benefits_fix_round_3_rates.py\ntests/test_track_b_gross_benefits_fix_round_4_composition.py\ntests/test_track_b_gross_benefits_fix_round_5_cohorts.py\ntests/test_track_b_gross_benefits_fix_round_6_cohorts.py\ntests/test_track_b_gross_benefits_fix_round_7_cohorts.py\ntests/test_track_b_gross_benefits_fix_round_7_history.py\ntests/test_track_b_gross_benefits_fix_round_8_entries.py\ntests/test_track_b_gross_benefits_fix_round_8_history.py\ntests/test_track_b_gross_benefits_fix_round_9_outcomes.py\ntests/test_track_b_gross_benefits_fix_round_9_validation.py\ntests/test_track_b_gross_benefits_properties.py\ntests/test_track_b_gross_benefits_registry.py\ntests/test_track_b_gross_benefits_review.py\ntests/test_track_b_gross_benefits_saving_absence.py\ntests/test_track_b_gross_benefits_savings.py\ntests/test_track_b_gross_benefits_savings_fix_round_2.py\ntests/test_track_b_gross_benefits_sources_20261011.py\ntests/test_track_b_input_schema.py\ntests/test_track_b_r3_fix_round_13.py\ntests/test_track_b_refusal_notes.py\ntests/test_track_b_ret_fra_facts.py\ntests/test_track_b_ret_ledger.py\ntests/test_track_b_ret_ledger_deductions.py\ntests/test_track_b_ret_ledger_fix_round_2.py\ntests/test_track_b_ret_ledger_fix_round_4.py\ntests/test_track_b_ret_ledger_sources.py\ntests/tier_counts.json\ntests/track_b_gross_benefit_support.py\n", + "stderr": "" + }, + { + "command": [ + "git", + "--no-pager", + "diff", + "--name-only", + "--no-ext-diff" + ], + "exit_code": 0, + "stdout": "docs/design/track_b_g2_r2b_mutations.json\ndocs/design/track_b_g2_r2b_verification.json\ndocs/design/track_b_g_gross_benefits.md\ndocs/design/track_b_r2_ret_ledger.md\nsrc/populace_dynamics/track_b/gross_benefits.py\nsrc/populace_dynamics/track_b/ret_ledger.py\ntests/test_track_b_gross_benefits_deduction_cap.py\ntests/test_track_b_gross_benefits_fix_round_4_composition.py\ntests/test_track_b_ret_ledger_fix_round_4.py\n", + "stderr": "" + }, + { + "command": [ + "git", + "status", + "--short" + ], + "exit_code": 0, + "stdout": " M docs/design/track_b_g2_r2b_mutations.json\n M docs/design/track_b_g2_r2b_verification.json\n M docs/design/track_b_g_gross_benefits.md\n M docs/design/track_b_r2_ret_ledger.md\n M src/populace_dynamics/track_b/gross_benefits.py\n M src/populace_dynamics/track_b/ret_ledger.py\n M tests/test_track_b_gross_benefits_deduction_cap.py\n M tests/test_track_b_gross_benefits_fix_round_4_composition.py\n M tests/test_track_b_ret_ledger_fix_round_4.py\n?? tests/test_track_b_ret_ledger_fix_round_5.py\n", + "stderr": "" + }, + { + "command": [ + "git", + "--no-pager", + "diff", + "--check", + "--no-ext-diff" + ], + "exit_code": 0, + "stdout": "", + "stderr": "" + } + ], + "worktree_protected_files_changed": false, + "branch_protected_files": [], + "tier_files_changed": false, + "g_report_sha256": "17d144575b38bb85080d8cbed28fad470ec93fd6eb6803b48729bb26a78b3d45", + "nonexistent_roots_confirmed": true + }, + "late_guard_epoch": { + "scope": "Only invalid aged own-RIB widow declarations missing both cohort fields reach the added canonical input-error guard. Valid declarations add no validation; public G rejects these inputs before the helper. Broad gates imported the before source; final targeted runs exercise the after source.", + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "before_sha256": "f5ec2a1a16572eb4997d9f8b88110d6c24b6ac9f99251067ca0022ae55603355", + "after_sha256": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "diff": "--- before_late_guard\n+++ after_late_guard\n@@ -1828,12 +1828,23 @@\n )\n if payment_month is not None:\n try:\n+ resolved = _with_effective_cohort(beneficiary)\n+ if (\n+ resolved.role in _AGED_WIDOW_ROLES\n+ and resolved.own_benefit is not None\n+ and resolved.own_benefit.kind is OwnBenefitKind.OLD_AGE\n+ and resolved.birth_year is None\n+ ):\n+ # R2 can reach this helper before G's family input\n+ # checks. Preserve their canonical error; this branch\n+ # cannot repeat validation on a valid declaration.\n+ _check_beneficiary_inputs(resolved, state, params)\n # Conditions were classified individually above. A generic\n # reason shared by several conditions must not broaden one\n # condition's scope or mask a later implicit history hold.\n _refuse_beneficiary(\n _replace_declared(\n- _with_effective_cohort(beneficiary),\n+ resolved,\n conditions=frozenset(),\n ),\n payment_month,\n" + }, + "late_guard_validation_run": { + "partition": "post_guard", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py", + "tests/test_track_b_input_schema.py", + "tests/test_track_b_ret_fra_facts.py", + "tests/test_track_b_r3_validation_once.py", + "tests/test_track_b_ret_ledger_fix_round_4.py" + ], + "environment": { + "OMP_NUM_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "PYTHONDONTWRITEBYTECODE": "1", + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "POLARS_MAX_THREADS": "1", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-post_guard", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-post_guard" + }, + "named_modules": [ + "tests/test_track_b_ret_ledger_fix_round_5.py", + "tests/test_track_b_input_schema.py", + "tests/test_track_b_ret_fra_facts.py", + "tests/test_track_b_r3_validation_once.py", + "tests/test_track_b_ret_ledger_fix_round_4.py" + ], + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "15f4afda6563e0c9b917732ba535d330f260595a663e1be788e370f88917d00c", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "test_sha256_before": { + "tests/test_track_b_ret_ledger_fix_round_5.py": "36749ab4c6d9e98e49d813b659e5b6e7a5097c62df1a7dd2ab67ea874104edd9", + "tests/test_track_b_input_schema.py": "d638f55a4de888d49cf236e5b58086ef773e63365e5f5ba5578aef3b9d7a8d32", + "tests/test_track_b_ret_fra_facts.py": "7bfb53be6660bbfad0831904d5b39a3e8d997216308b136959ece10bb04c72a8", + "tests/test_track_b_r3_validation_once.py": "ad28687b52c6386e7c5e28525eac12dc9a4ba62b75d18e066d5bdac1252624c0", + "tests/test_track_b_ret_ledger_fix_round_4.py": "0c304d939709da534e89c374ff9687548531796c4716d51dd5e7e232346b6681" + }, + "exit_code": 0, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "73ebc6a9dac1d9d05d2ef1aca002dc0505755d466b2c0153fb1f929cd0f1b690", + "src/populace_dynamics/track_b/ret_ledger.py": "dfddbc2d8f752a3df1a1f6b7e2949b0b44de0cc714b0066af852743075223bad" + }, + "test_sha256_after": { + "tests/test_track_b_ret_ledger_fix_round_5.py": "8c20bd5302276af3479706c0c5e470fce6f02b0b319463bffc0f63c88b4d00ee", + "tests/test_track_b_input_schema.py": "d638f55a4de888d49cf236e5b58086ef773e63365e5f5ba5578aef3b9d7a8d32", + "tests/test_track_b_ret_fra_facts.py": "7bfb53be6660bbfad0831904d5b39a3e8d997216308b136959ece10bb04c72a8", + "tests/test_track_b_r3_validation_once.py": "ad28687b52c6386e7c5e28525eac12dc9a4ba62b75d18e066d5bdac1252624c0", + "tests/test_track_b_ret_ledger_fix_round_4.py": "0c304d939709da534e89c374ff9687548531796c4716d51dd5e7e232346b6681" + }, + "log": { + "path": "scratch/review/round5-post_guard.log", + "sha256": "16854e85fb72bedd7ae56d6ee0cb32cc57d746f8bb3c9631fee30868eac89b00" + }, + "summary": "1483 passed in 482.84s (0:08:02)", + "audit": { + "processes": 1, + "counts": { + "open": 1039, + "restricted_open": 0, + "restricted_import": 0, + "subprocess.Popen": 0, + "os.system": 0 + } + } + }, + "cross_head_before_late_guard": { + "verification_class": "statutory conformance", + "scope": "invented cases only; no population, behavioral or forecast claim", + "seed": 53014, + "r2_stable_rows": 240, + "r3_stable_rows": 240, + "identical_declared_output_bytes": true, + "stable_sha256": "799fc9e23a902ac1ca0c2563579ceb094d0dbcd631a912305c40062cf21a5f55", + "transitions": { + "baseline": { + "rows": 6, + "supported": 0, + "refused_by_reason": { + "deduction_before_reduction_part_b": 6 + } + }, + "head": { + "rows": 6, + "supported": 6, + "refused_by_reason": {} + } + }, + "transition_rows": [ + { + "id": "binding_survivor_own_excess_1", + "own_excess": 1, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_60", + "own_excess": 60, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_99", + "own_excess": 99, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_100", + "own_excess": 100, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_555", + "own_excess": 555, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_1188", + "own_excess": 1188, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + } + ] + }, + "cross_head_before_late_guard_run": { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "cross-head", + "--baseline-root", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-baseline", + "--output", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-cross-head.json" + ], + "exit_code": 0, + "log": { + "path": "scratch/review/round5-cross-head-pre-guard.log", + "sha256": "a945d2f0bb2f6b8918e052063aa41a730eb24e9331fb16a1164c45de3810fe3d" + }, + "audit": { + "processes": 3, + "counts": { + "open": 271, + "restricted_open": 0, + "restricted_import": 0, + "subprocess.Popen": 2, + "os.system": 0 + } + }, + "baseline_named_files": [ + "src/populace_dynamics/__init__.py", + "src/populace_dynamics/ss/__init__.py", + "src/populace_dynamics/ss/params.py", + "src/populace_dynamics/ss/benefits.py", + "tests/__init__.py", + "tests/track_b_gross_benefit_support.py", + "tests/data/track_b/ret_history.json", + "src/populace_dynamics/track_b/__init__.py", + "src/populace_dynamics/track_b/_provenance.py", + "src/populace_dynamics/track_b/arf.py", + "src/populace_dynamics/track_b/b2.py", + "src/populace_dynamics/track_b/equality.py", + "src/populace_dynamics/track_b/gross_benefits.py", + "src/populace_dynamics/track_b/holdout_registry.py", + "src/populace_dynamics/track_b/recompute.py", + "src/populace_dynamics/track_b/reconstructed.py", + "src/populace_dynamics/track_b/replay.py", + "src/populace_dynamics/track_b/ret_grace.py", + "src/populace_dynamics/track_b/ret_ledger.py", + "src/populace_dynamics/track_b/ret_params.py", + "src/populace_dynamics/track_b/runner.py", + "src/populace_dynamics/track_b/parameters/__init__.py", + "src/populace_dynamics/track_b/parameters/ret_v1.yaml" + ], + "verification_epoch": "Before late invalid-cohort guard; valid 240/240+6 inputs unchanged." + }, + "additional_original_head_cases": { + "reviewed_head": "e3315bafb592e29031d72b5ef368ca428e4a0b55", + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "pytest", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=short", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history" + ], + "selected_test_nodes": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-reviewed-head/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-reviewed-head", + "HYPOTHESIS_STORAGE_DIRECTORY": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-hypothesis-reviewed-head" + }, + "exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[None-basis0-deduction]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[None-None-deduction]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[False-basis0-ret]", + "tests/test_track_b_ret_ledger_fix_round_5.py::test_protected_widow_cannot_be_excluded_from_unknown_drc_history[False-None-ret]" + ], + "summary": "4 failed, 4 passed in 16.99s", + "test_sha256_before": "0bb49fe3cc7898c435615d9c0f33bf0cfec1a8e8cba8f88a66a5e45d1938f6b5", + "test_sha256_after": "0bb49fe3cc7898c435615d9c0f33bf0cfec1a8e8cba8f88a66a5e45d1938f6b5", + "named_copied_sources": [ + "src/populace_dynamics/__init__.py", + "src/populace_dynamics/track_b/__init__.py", + "src/populace_dynamics/track_b/_provenance.py", + "src/populace_dynamics/track_b/arf.py", + "src/populace_dynamics/track_b/b2.py", + "src/populace_dynamics/track_b/equality.py", + "src/populace_dynamics/track_b/gross_benefits.py", + "src/populace_dynamics/track_b/holdout_registry.py", + "src/populace_dynamics/track_b/recompute.py", + "src/populace_dynamics/track_b/reconstructed.py", + "src/populace_dynamics/track_b/replay.py", + "src/populace_dynamics/track_b/ret_grace.py", + "src/populace_dynamics/track_b/ret_ledger.py", + "src/populace_dynamics/track_b/ret_params.py", + "src/populace_dynamics/track_b/runner.py", + "src/populace_dynamics/track_b/parameters/__init__.py", + "src/populace_dynamics/track_b/parameters/ret_v1.yaml" + ], + "log": { + "path": "scratch/review/round5-reviewed-head-extra.log", + "sha256": "70e52911249a4fd71ca0e05f7f1c4e0206ff03e936a3d5b02a493ac4d3b78bd4" + } + }, + "intermediate_adversarial_probes": { + "scope": "Read-only public-path probes executed against the intermediate round-5 implementation; these observations are not represented as e3315baf baseline test results.", + "execution": "Commands were executed as shell heredocs into python stdin; no original script or output file existed. This record preserves observed outputs and reproduction payloads.", + "command": "env PYTHONPATH=$PWD/src:$PWD OMP_NUM_THREADS=1 POLARS_MAX_THREADS=1 OMP_WAIT_POLICY=PASSIVE POPULACE_DYNAMICS_EPUF_DIR=/nonexistent-trackb-round5-audit POPULACE_DYNAMICS_PSID_DIR=/nonexistent-trackb-round5-audit /Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python -", + "common_stdin": "from fractions import Fraction as F\nfrom populace_dynamics.track_b import gross_benefits as g, ret_ledger as r\nfrom populace_dynamics.track_b.ret_grace import BenefitType as T\nfrom tests.track_b_gross_benefit_support import ssa_params\n\ndef person(key,kind,gross,original):\n return r.RETBeneficiary(key,(kind,)*12,{1},(F(gross),)+(F(0),)*11,(F(original),)*12,fra_month=0)\ndef run(state,aux,people):\n case=r.RecordYear(2024,'nh',r.RecordKind.DECEASED,people,family_months={1:r.RETFamilyMonth(state,aux,ssa_params(),{b.beneficiary_id:'h' for b in aux})})\n return r.evaluate_ret('audit',7,lambda:r.apply_ret_year(case))\n", + "observations": [ + { + "name": "unrelated own-DIB refusal invents widow protection", + "stdin_suffix": "state=g.RecordState(g.FamilyKind.SURVIVOR,F(4),F(8),eligibility_year=2024)\naux=(g.Beneficiary('a',g.Role.CHILD,own_benefit=g.OwnBenefit(g.OwnBenefitKind.DISABILITY,F(1),reduction_months=1)),g.Beneficiary('b',g.Role.CHILD))\nresult=run(state,aux,(person('a',T.CHILD,0,3),person('b',T.CHILD,3,F(31,10))))\nprint('COUNTED',result.unsupported.reason.value,r.count_ret_outcomes([result]).rows)\n", + "observed_before": "COUNTED dib_after_reduced_rib 1", + "observed_after": "InvalidFamilyInput", + "regression": "test_unrelated_refused_child_does_not_invent_widow_protection" + }, + { + "name": "own-cohort-only widow crashes implicit refusal inspection", + "executed_declaration": "Survivor PIA4/MAX8 eligibility2024; children a ownDIB PIA1/reduction1 and b wrongOB3.10; widow w own old-age PIA5 birth_year1950, auxiliary birth_year omitted, OBbasis5, child_in_care=False.", + "observed_before": "TypeError: '<' not supported between instances of 'NoneType' and 'int'", + "traceback_location": "src/populace_dynamics/track_b/gross_benefits.py, _refuse_beneficiary, beneficiary.birth_year < _FIRST_METHOD_B_WIDOW_BIRTH_YEAR", + "independent_valid_control_stdin_suffix": "state=g.RecordState(g.FamilyKind.SURVIVOR,F(4),F(8),widow_drc_savings_clause=False)\naux=(g.Beneficiary('w',g.Role.WIDOW,own_benefit=g.OwnBenefit(g.OwnBenefitKind.OLD_AGE,F(1),birth_year=1950),child_in_care=False),)\noutcome=run(state,aux,(person('w',T.WIDOW,3,4),))\nassert outcome.supported\n", + "observed_after": "Matching sole widow with cohort only on own benefit computes supported; combined disqualified-widow variant raises InvalidFamilyInput at F6.", + "regression": "test_widow_own_cohort_alone_matches_the_resolved_cohort_control" + } + ], + "final_repeat_stdout": [ + "PASS: unrelated refused child cannot hide other child OB contradiction", + "PASS: own-cohort-only matching widow computes without TypeError" + ] + }, + "cross_head_run": { + "command": [ + "/Users/maxghenis/PolicyEngine/microcosm-dynamics/.venv/bin/python", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5_guarded.py", + "cross-head", + "--baseline-root", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-baseline", + "--output", + "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-cross-head.json" + ], + "environment": { + "PYTHONPATH": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-hook:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/src:/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1", + "OMP_WAIT_POLICY": "PASSIVE", + "POPULACE_DYNAMICS_PSID_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "POPULACE_DYNAMICS_EPUF_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/nonexistent", + "TRACK_B_AUDIT_DIR": "/Users/maxghenis/.subfleet/worktrees/20261031-181530-trackb-fix-g2-5/scratch/review/round5-audit-cross-head" + }, + "source_sha256_before": { + "src/populace_dynamics/track_b/gross_benefits.py": "d51f5d77c7aa7cf6004392e27187ce89523151fef12148088565226f7444fb64", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587", + "scripts/track_b_r2_cross_head.py": "4f2a1bea264d906ea0fb4cec08a2b233b458bb3a0ca0d09dbe580d6cc78e8178" + }, + "source_sha256_after": { + "src/populace_dynamics/track_b/gross_benefits.py": "d51f5d77c7aa7cf6004392e27187ce89523151fef12148088565226f7444fb64", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587", + "scripts/track_b_r2_cross_head.py": "4f2a1bea264d906ea0fb4cec08a2b233b458bb3a0ca0d09dbe580d6cc78e8178" + }, + "baseline_head": "a747bafabb088570f2a8be896f264065e9c0754a", + "exit_code": 0, + "log": { + "path": "scratch/review/round5-cross-head.log", + "sha256": "a945d2f0bb2f6b8918e052063aa41a730eb24e9331fb16a1164c45de3810fe3d" + }, + "audit": { + "processes": 3, + "counts": { + "open": 271, + "restricted_open": 0, + "restricted_import": 0, + "subprocess.Popen": 2, + "os.system": 0 + } + }, + "baseline_named_files": [ + "src/populace_dynamics/__init__.py", + "src/populace_dynamics/ss/__init__.py", + "src/populace_dynamics/ss/params.py", + "src/populace_dynamics/ss/benefits.py", + "tests/__init__.py", + "tests/track_b_gross_benefit_support.py", + "tests/data/track_b/ret_history.json", + "src/populace_dynamics/track_b/__init__.py", + "src/populace_dynamics/track_b/_provenance.py", + "src/populace_dynamics/track_b/arf.py", + "src/populace_dynamics/track_b/b2.py", + "src/populace_dynamics/track_b/equality.py", + "src/populace_dynamics/track_b/gross_benefits.py", + "src/populace_dynamics/track_b/holdout_registry.py", + "src/populace_dynamics/track_b/recompute.py", + "src/populace_dynamics/track_b/reconstructed.py", + "src/populace_dynamics/track_b/replay.py", + "src/populace_dynamics/track_b/ret_grace.py", + "src/populace_dynamics/track_b/ret_ledger.py", + "src/populace_dynamics/track_b/ret_params.py", + "src/populace_dynamics/track_b/runner.py", + "src/populace_dynamics/track_b/parameters/__init__.py", + "src/populace_dynamics/track_b/parameters/ret_v1.yaml" + ] + }, + "cross_head": { + "verification_class": "statutory conformance", + "scope": "invented cases only; no population, behavioral or forecast claim", + "seed": 53014, + "r2_stable_rows": 240, + "r3_stable_rows": 240, + "identical_declared_output_bytes": true, + "stable_sha256": "799fc9e23a902ac1ca0c2563579ceb094d0dbcd631a912305c40062cf21a5f55", + "transitions": { + "baseline": { + "rows": 6, + "supported": 0, + "refused_by_reason": { + "deduction_before_reduction_part_b": 6 + } + }, + "head": { + "rows": 6, + "supported": 6, + "refused_by_reason": {} + } + }, + "transition_rows": [ + { + "id": "binding_survivor_own_excess_1", + "own_excess": 1, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_60", + "own_excess": 60, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_99", + "own_excess": 99, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_100", + "own_excess": 100, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_555", + "own_excess": 555, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + }, + { + "id": "binding_survivor_own_excess_1188", + "own_excess": 1188, + "baseline": "deduction_before_reduction_part_b", + "head": "supported" + } + ] + }, + "final_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "d51f5d77c7aa7cf6004392e27187ce89523151fef12148088565226f7444fb64", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "final_test_sha256": { + "tests/test_track_b_arf.py": "292587c9ee1d160ad6c66da6e388e3a0b2bf4c9831f8ad3b18853c802f5bd68e", + "tests/test_track_b_arf_properties.py": "d1346b68bd07b469cea6357e1881d743e3a90c66e04080fc19fd66b44da7b68e", + "tests/test_track_b_gross_benefits.py": "de0946a014d054bd47f30dadaf675105aebb1dd562209c4002dee05354628286", + "tests/test_track_b_gross_benefits_conformance_report.py": "7ec6f605783c15c88abbb0834ff894645fe14e2956239c83532cd88132e699c8", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py": "5d9fe8c5cb052d39c82249d6efcf4d88dace5ec68538340e7000f73af5e016df", + "tests/test_track_b_gross_benefits_deduction_cap.py": "6965d3e258ad31ad9ee496eb745885d3f6fa7b7c4ec2a48e441d0318588ec30e", + "tests/test_track_b_gross_benefits_deductions.py": "b6f0493ecbb19434c09de42ff7e62a87b85818ea6dc8a5cde78963d780598e02", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py": "5cebe4f986fa7d01d7769c1d1db0581b54ae88e7c4710409285e12393244fdab", + "tests/test_track_b_gross_benefits_dwb.py": "61b6270fdd9a6d156d31194535797d1f59c092943ecdb3773787d1471e2bb80a", + "tests/test_track_b_gross_benefits_fix_round_1.py": "9275a8a4963ce7ed086482644d044a927100efcbeb5a05315d9cc6394168ee8c", + "tests/test_track_b_gross_benefits_fix_round_10_api.py": "227fde023692f1c73a3eeb6de75213468c8e5e160ade3536bf5b7fb688c4ded6", + "tests/test_track_b_gross_benefits_fix_round_10_helpers.py": "e5014776670ca9b552de756c63976e606290fb4fad85a1501b017700a05c8fdb", + "tests/test_track_b_gross_benefits_fix_round_10_objects.py": "7576cc18923ad3ff38d0f44379637e822008a92cc9968d52f47b991e56fb9cfb", + "tests/test_track_b_gross_benefits_fix_round_10_parameters.py": "981eced43d10a6720ccab0292c4a8c281b9ac9bf7d83132f6666254d7a4b72ee", + "tests/test_track_b_gross_benefits_fix_round_11_roles.py": "d26fd86d7067eb7f4f97e1537110eab5223104ad817c3470a9eae022a90dfc73", + "tests/test_track_b_gross_benefits_fix_round_11_seals.py": "937b07b094816eade9bf072595ede18b1b109db527de9805c3a3cb3d333ba4b5", + "tests/test_track_b_gross_benefits_fix_round_12_contract.py": "9779ae3b22cf12daf6727cd21a6bcb12afbf3cfd34c84209bd406942a0c089e1", + "tests/test_track_b_gross_benefits_fix_round_13_audit.py": "fb04098e3982aca18b439f2df148bee6333ce20406fe773da0858731a6c94ff0", + "tests/test_track_b_gross_benefits_fix_round_13_boundary.py": "acac7951783a0e11140e717feab3924973e290e58857396dfab9c0b4319a5e8d", + "tests/test_track_b_gross_benefits_fix_round_13_guard.py": "e5fabfda3fcab2ba9e0347449278a21b9cfc1f89645e1ab148cb4a23da9e7c2e", + "tests/test_track_b_gross_benefits_fix_round_15_arguments.py": "16d5a875f4271839799738a89f2b904084bc0847eb25cd397168cea570be6d54", + "tests/test_track_b_gross_benefits_fix_round_15_collections.py": "2206b9734458774d581d3d20bfb50f1d517fd1b7d8191225cf5cacbca6561e58", + "tests/test_track_b_gross_benefits_fix_round_15_receivers.py": "3de91e8701ab82a3063be9eb859e6cd0058c7d3a35ac93dce9e110e0959061ff", + "tests/test_track_b_gross_benefits_fix_round_2_care.py": "7e983b28cdd1ba2c03935858610788754de66fb9489fef46672ebbf3d566225e", + "tests/test_track_b_gross_benefits_fix_round_2_history.py": "17fb81a1d18ad90ccf99cc841360aec524822cc2404e03d33cfbbab3a830b3a5", + "tests/test_track_b_gross_benefits_fix_round_2_periods.py": "21030c220e1b4690ac3d6754dcd9baddc23b33e824e07a842673c4128b7e6b09", + "tests/test_track_b_gross_benefits_fix_round_3_rates.py": "1c638ac3d5f0b0d25b49d1abf4924d9fff45bcf5ce25366616a60d3f060faa16", + "tests/test_track_b_gross_benefits_fix_round_4_care_floor.py": "d137d59fb7af48f21fda7b4e3aaf9a991d43b295930b5f341cc7cd595b875401", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py": "74105c3ab4c8c7e9e3fc0be9f4eb078a5c7913683c13974aa86fa598c2eda950", + "tests/test_track_b_gross_benefits_fix_round_4_divorced_care.py": "cd50249e8d84a2bbb61901f08b84310d48b8d390495beadfe5112144143b4fd7", + "tests/test_track_b_gross_benefits_fix_round_5_care_history.py": "a3e73482553c5fb804adaba8ed0d5e4d1520470f384bb58a0fe46cb41e58eb07", + "tests/test_track_b_gross_benefits_fix_round_5_cohorts.py": "f5be483a533e47edcb58dc05bc202390e959e6ece7eca3ff11728aa46b00409d", + "tests/test_track_b_gross_benefits_fix_round_6_care_note.py": "b2d158f37d35aaa63a6a1293345010bc4445c3b20c480c035932bf9725a91eca", + "tests/test_track_b_gross_benefits_fix_round_6_cohorts.py": "b06e95d0a8a93af3e60b96222381b46377673e407385958b5120817bc60c2e84", + "tests/test_track_b_gross_benefits_fix_round_7_boundary.py": "b2c875f010c402e4f373be5712a39affd87b6533805ed33bf63dbea60b1e6ae5", + "tests/test_track_b_gross_benefits_fix_round_7_cohorts.py": "0eb73d51e1f7a61f76917df670f89bdade0e5f45f4c044be30673dff2494ca31", + "tests/test_track_b_gross_benefits_fix_round_7_history.py": "fc6a7b5281e2f429a8e9f92c595b4491aa2de4229630fc5ca15eab333bacab26", + "tests/test_track_b_gross_benefits_fix_round_8_entries.py": "4589caceb3f7996a6175d6f15f8038805450d8c448c56a8d95e4ccc9a5f872e5", + "tests/test_track_b_gross_benefits_fix_round_8_history.py": "cf4d84edf72b150dd343d408d84e60ebd70500c8e219bc00b1552d6292af4e91", + "tests/test_track_b_gross_benefits_fix_round_9_citations.py": "2ce5f13cd58a929583f659ec5bea6b2fbfa7216edd00291400773882118b9b4e", + "tests/test_track_b_gross_benefits_fix_round_9_outcomes.py": "139a90841182ca8a1bbece8acd3b30df68f7d88cef833fd092c202b22017a3e6", + "tests/test_track_b_gross_benefits_fix_round_9_validation.py": "0d420e98106ffe4ce7d9f1f0ae121488c4aca9ce1e1a3d941bc5aff0083efd92", + "tests/test_track_b_gross_benefits_oracle.py": "d4b88ec7a6945e76499e50266448894e99809737b1bc2a55de060bf03f591d24", + "tests/test_track_b_gross_benefits_own_input_order.py": "3bb4bd7fb3b7567109ed3f132f6b8a775e43e90a04aa4a2a0fa8542c78575291", + "tests/test_track_b_gross_benefits_parents_ieds.py": "98e5f81c99b3b80332db203c07db680b09a633c3d34bc58d15ee986f252bf73c", + "tests/test_track_b_gross_benefits_parisi.py": "4f446013cc7bd9f2ae8dc4dfe3ee59d952a9f5e7d2aaa2f104497dfe36425c1a", + "tests/test_track_b_gross_benefits_payment_review.py": "4c239c468e06a0c522151e182693a91024f61b7f38e49bbd7f03c66b01889dd7", + "tests/test_track_b_gross_benefits_properties.py": "483d502f88457f89cbc4f13b2904718eae59997a81a1189f51b0fbe635c54cfb", + "tests/test_track_b_gross_benefits_registry.py": "93dd3a5d3750cea367ddfe6ccc42f08084ae2f09e6278a1de728baf6a8ddc4df", + "tests/test_track_b_gross_benefits_review.py": "e602dfbf58ec57e25a1270d0e26bb3c5204045e43ab726266e0ef805abe2cd7c", + "tests/test_track_b_gross_benefits_saving_absence.py": "e6078f978ee7bf1d0802dde67c2de94397fd3e9cd142b2c96d6d504ceb0a6862", + "tests/test_track_b_gross_benefits_savings.py": "607bf6cb7415d03bd7b863673d7b9d403841d175a1684f211a562536f4f4755b", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py": "d84130cc73468a8b3f8223c5526f0e982597e552c40e714d691608d32da59233", + "tests/test_track_b_gross_benefits_sources_20261011.py": "e3291d0b6bf497a20835800c4d6ee833854e5edf5b25229932e7a142f8e51a13", + "tests/test_track_b_gross_benefits_ssfa.py": "07fee44e63376a58508296b6f66d1fc20adfa1c88c8cd110a1d5fc45dc4f1ebf", + "tests/test_track_b_input_schema.py": "d638f55a4de888d49cf236e5b58086ef773e63365e5f5ba5578aef3b9d7a8d32", + "tests/test_track_b_r3_fix_round_13.py": "bfb81d8316574e9df0e2e7cb9f890e1b9f584cac2cd17e025825580e219cebc7", + "tests/test_track_b_r3_provenance.py": "58243309d56acb9dc38e9bf5a701e79ac961ac062e0d37690b12a561592245c9", + "tests/test_track_b_r3_sources.py": "6300b1a4075a0f2549cce4db0aab25d6908eba9071a5a2da3bbfc6d020dd04ba", + "tests/test_track_b_r3_validation_once.py": "ad28687b52c6386e7c5e28525eac12dc9a4ba62b75d18e066d5bdac1252624c0", + "tests/test_track_b_recompute.py": "06db2b43c6c13d679a71a6d2176dc3ee13fce8fc1645684fcbe7c582f9e54f9c", + "tests/test_track_b_recompute_properties.py": "ced431cb4fd0de82a7cde6ff63c6a38eaad1649939d364b1023dcc81aff30759", + "tests/test_track_b_refusal_notes.py": "5c765432752317684e4059f2d45a2a95fd03ff327fb1225f853267588fc76abe", + "tests/test_track_b_ret_differential.py": "8e38e1040d61d9f0262bbe25c5c17e0f608c433cb29ab898b7f954358bcf1e12", + "tests/test_track_b_ret_fra_facts.py": "7bfb53be6660bbfad0831904d5b39a3e8d997216308b136959ece10bb04c72a8", + "tests/test_track_b_ret_grace.py": "772f6b94187593549cd21a2dbb19a75f998fb840f6b6eb3a97bbeca3f36636dc", + "tests/test_track_b_ret_grace_differential.py": "fbf01f2c6e76f2cc8a60bad5e9c9ac5c4da0c68013578b91de9488aa2623abf5", + "tests/test_track_b_ret_grace_provenance.py": "8cf4446fb0bb6da77a7b84815caafe595ec81b9b7a2cc1e56f686cd25f0e77a5", + "tests/test_track_b_ret_ledger.py": "6d6684e63aa3d56874fb0fd174867d1e2b41e54119ad8077c2e6b689ca723065", + "tests/test_track_b_ret_ledger_deductions.py": "a3fcc50166b867f9d3d719bcf611880cba169b3b99f6bf695ff397a36b2fcd2e", + "tests/test_track_b_ret_ledger_fix_round_2.py": "62a81110909ddebfa77f65078d685464f553c37de89cb88efd743ca406b1aa70", + "tests/test_track_b_ret_ledger_fix_round_4.py": "0c304d939709da534e89c374ff9687548531796c4716d51dd5e7e232346b6681", + "tests/test_track_b_ret_ledger_properties.py": "803433fd9d3aa7601b45e2f5346d716254409710e9f9d3ac61f1a42d87cc7d64", + "tests/test_track_b_ret_ledger_readings.py": "630bdd1d5f53d93c63674192f205e17edff601f8dcc8d941348db98cf094bdad", + "tests/test_track_b_ret_ledger_sources.py": "ab6b6d66d370c93e5b2cc82b88670f48eb5bceeb0d313c36550986c3ff1844b6", + "tests/test_track_b_ret_params.py": "57a1be52d32c3549d711aba4f88f42cdb0affd98bc3b3d5bf7e607fc0b2c3514", + "tests/test_track_b_ret_ledger_fix_round_5.py": "26f74adc61c076d80446965850da34a01d02744d213bb1b63921ef6b66689f5b" + }, + "final_conformance_report_sha256": "17d144575b38bb85080d8cbed28fad470ec93fd6eb6803b48729bb26a78b3d45", + "conformance_report_byte_identical": true, + "completed_gate_count": 15, + "all_raw_gate_runs_passed": false, + "gate_status_note": "Raw failures and source epochs are preserved. Effective completion must be assessed from the named correction/retry runs and final affected-path replay, not by treating old raw failures as passes.", + "gate_resolutions": { + "g_boundary": { + "resolved": true, + "raw_run": "round5-g_boundary.json", + "raw_result": "1failed7240passed; sole failure was reproducible-as-fast Hypothesis timing fluctuation, no assertion failure", + "retry": "round5-g_boundary_retry.json", + "retry_result": "4passed25.76s; same property variants, unchanged deadline/settings" + }, + "g_rules": { + "resolved": true, + "raw_run": "round5-g_rules.json", + "raw_result": "2failed1616passed; only protected-OB finality assertions explicitly within authorized expectation class", + "correction": "Existing composition assertions split finality refusal from settled/unheld InvalidFamilyInput and add NON_AIME controls; no production money rule changed.", + "replay": "round5-composition_corrected.json", + "replay_result": "Entire corrected file95passed89.79s" + }, + "g_report": { + "resolved": true, + "run": "round5-g_report.json", + "result": "54passed2686.60s; committed conformance report byte-identical" + }, + "ret_r3": { + "resolved": true, + "raw_run": "round5-ret_r3.json", + "raw_result": "1failed3246passed; same InvalidFamilyInput classification but general F4-rate diagnostic replaced canonical auxiliary-entitlement diagnostic", + "fix": "Reorder settled canonical F5/F6 eligibility error before F4 comparison; assertion unchanged. Roster identity independently prevents included RET-unentitled beneficiaries.", + "replay": "round5-final_diagnostic.json", + "replay_result": "Final G06ab/R22aa full deductions,new232,schema,FRA,validation-once five-module replay1019passed540.36s; unchanged original regex assertion passes." + }, + "final_r2": { + "resolved": true, + "status": "interrupted; not counted as a pass", + "record": "round5-final_r2-before-final-diagnostic-interrupted.json", + "replacement": "Five completed disjoint ordinary groups cover 77 required modules; final seven-module closure covers changed paths on final sources.", + "result": "Interrupted prior replay superseded by fresh completed ordinary groups:7241+978+2933+54 and final_diagnostic1019. It is not counted as a pass." + }, + "final_changed_paths": { + "resolved": true, + "run": "round5-final_diagnostic.json", + "result": "1019passed540.36s; source/test hashes identical before/after final both-source run.", + "final_closure": "round5-final_closure.json", + "final_result": "1062 passed in 230.91s (0:03:50)" + }, + "late_upper_bound_context": { + "resolved": true, + "first_evidence": [ + "round5-parent-upper-bound-first.log", + "round5-historical-child-uncertainty-first.log" + ], + "closure": "round5-final_closure.json", + "result": "1062 passed in 230.91s; seven explicit final-source modules, including all 285 new-module cases. Mutations 28-30 each caught by the new invariant property; production unchanged after isolated overlays.", + "retracted_probe": "round5-probe-corrections.json", + "final_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "d51f5d77c7aa7cf6004392e27187ce89523151fef12148088565226f7444fb64", + "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + } + } + }, + "all_named_gate_tests_passed": true, + "source_stable_final_coverage": { + "completed_groups": [ + "final_diagnostic", + "final_g_boundary", + "final_g_rules", + "final_g_report", + "final_ret_r3" + ], + "named_module_count": 77, + "required_module_count": 77, + "all_final_runs_passed_unchanged": false + }, + "effective_final_coverage": { + "policy": "The orchestrator retained the complete ordinary grids at the 06ab/2aa epoch. Final closure reruns four G deduction modules, the expanded new RET module, schema and R3 validation-once. The upper-bound flag defaults False; deduction bounds alone opt in. Historical nonwidow uncertainty has its own final regression. No claim that all modules ran on one final source hash.", + "all_required_modules_passed": true, + "named_module_count": 77, + "module_to_latest_run": { + "tests/test_track_b_ret_ledger_deductions.py": "final_diagnostic", + "tests/test_track_b_ret_ledger_fix_round_5.py": "final_closure", + "tests/test_track_b_input_schema.py": "final_closure", + "tests/test_track_b_ret_fra_facts.py": "final_diagnostic", + "tests/test_track_b_r3_validation_once.py": "final_closure", + "tests/test_track_b_gross_benefits_fix_round_1.py": "final_g_boundary", + "tests/test_track_b_gross_benefits_fix_round_10_api.py": "final_g_boundary", + "tests/test_track_b_gross_benefits_fix_round_10_helpers.py": "final_g_boundary", + "tests/test_track_b_gross_benefits_fix_round_10_objects.py": "final_g_boundary", + "tests/test_track_b_gross_benefits_fix_round_10_parameters.py": "final_g_boundary", + "tests/test_track_b_gross_benefits_fix_round_11_roles.py": "final_g_boundary", + "tests/test_track_b_gross_benefits_fix_round_11_seals.py": "final_g_boundary", + "tests/test_track_b_gross_benefits_fix_round_12_contract.py": "final_g_boundary", + "tests/test_track_b_gross_benefits_fix_round_13_audit.py": "final_g_boundary", + "tests/test_track_b_gross_benefits_fix_round_13_boundary.py": "final_g_boundary", + "tests/test_track_b_gross_benefits_fix_round_13_guard.py": "final_g_boundary", + "tests/test_track_b_gross_benefits_fix_round_15_arguments.py": "final_g_boundary", + "tests/test_track_b_gross_benefits_fix_round_15_collections.py": "final_g_boundary", + "tests/test_track_b_gross_benefits_fix_round_15_receivers.py": "final_g_boundary", + "tests/test_track_b_gross_benefits_fix_round_2_care.py": "final_g_boundary", + "tests/test_track_b_gross_benefits_fix_round_2_history.py": "final_g_boundary", + "tests/test_track_b_gross_benefits_fix_round_2_periods.py": "final_g_boundary", + "tests/test_track_b_gross_benefits_fix_round_3_rates.py": "final_g_boundary", + "tests/test_track_b_gross_benefits_fix_round_4_care_floor.py": "final_g_boundary", + "tests/test_track_b_gross_benefits_fix_round_4_divorced_care.py": "final_g_boundary", + "tests/test_track_b_gross_benefits_fix_round_5_care_history.py": "final_g_boundary", + "tests/test_track_b_gross_benefits_fix_round_5_cohorts.py": "final_g_boundary", + "tests/test_track_b_gross_benefits_fix_round_6_care_note.py": "final_g_boundary", + "tests/test_track_b_gross_benefits_fix_round_6_cohorts.py": "final_g_boundary", + "tests/test_track_b_gross_benefits_fix_round_7_boundary.py": "final_g_boundary", + "tests/test_track_b_gross_benefits_fix_round_7_cohorts.py": "final_g_boundary", + "tests/test_track_b_gross_benefits_fix_round_7_history.py": "final_g_boundary", + "tests/test_track_b_gross_benefits_fix_round_8_entries.py": "final_g_boundary", + "tests/test_track_b_gross_benefits_fix_round_8_history.py": "final_g_boundary", + "tests/test_track_b_gross_benefits_fix_round_9_citations.py": "final_g_boundary", + "tests/test_track_b_gross_benefits_fix_round_9_outcomes.py": "final_g_boundary", + "tests/test_track_b_gross_benefits_fix_round_9_validation.py": "final_g_boundary", + "tests/test_track_b_gross_benefits.py": "final_g_rules", + "tests/test_track_b_gross_benefits_deduction_age_inputs.py": "final_closure", + "tests/test_track_b_gross_benefits_deduction_cap.py": "final_closure", + "tests/test_track_b_gross_benefits_deductions.py": "final_closure", + "tests/test_track_b_gross_benefits_deductions_fix_round_2.py": "final_closure", + "tests/test_track_b_gross_benefits_dwb.py": "final_g_rules", + "tests/test_track_b_gross_benefits_fix_round_4_composition.py": "final_g_rules", + "tests/test_track_b_gross_benefits_oracle.py": "final_g_rules", + "tests/test_track_b_gross_benefits_own_input_order.py": "final_g_rules", + "tests/test_track_b_gross_benefits_parents_ieds.py": "final_g_rules", + "tests/test_track_b_gross_benefits_parisi.py": "final_g_rules", + "tests/test_track_b_gross_benefits_payment_review.py": "final_g_rules", + "tests/test_track_b_gross_benefits_properties.py": "final_g_rules", + "tests/test_track_b_gross_benefits_registry.py": "final_g_rules", + "tests/test_track_b_gross_benefits_review.py": "final_g_rules", + "tests/test_track_b_gross_benefits_saving_absence.py": "final_g_rules", + "tests/test_track_b_gross_benefits_savings.py": "final_g_rules", + "tests/test_track_b_gross_benefits_savings_fix_round_2.py": "final_g_rules", + "tests/test_track_b_gross_benefits_sources_20261011.py": "final_g_rules", + "tests/test_track_b_gross_benefits_ssfa.py": "final_g_rules", + "tests/test_track_b_refusal_notes.py": "final_g_rules", + "tests/test_track_b_gross_benefits_conformance_report.py": "final_g_report", + "tests/test_track_b_arf.py": "final_ret_r3", + "tests/test_track_b_arf_properties.py": "final_ret_r3", + "tests/test_track_b_r3_fix_round_13.py": "final_ret_r3", + "tests/test_track_b_r3_provenance.py": "final_ret_r3", + "tests/test_track_b_r3_sources.py": "final_ret_r3", + "tests/test_track_b_recompute.py": "final_ret_r3", + "tests/test_track_b_recompute_properties.py": "final_ret_r3", + "tests/test_track_b_ret_differential.py": "final_ret_r3", + "tests/test_track_b_ret_grace.py": "final_ret_r3", + "tests/test_track_b_ret_grace_differential.py": "final_ret_r3", + "tests/test_track_b_ret_grace_provenance.py": "final_ret_r3", + "tests/test_track_b_ret_ledger.py": "final_ret_r3", + "tests/test_track_b_ret_ledger_fix_round_2.py": "final_ret_r3", + "tests/test_track_b_ret_ledger_fix_round_4.py": "final_ret_r3", + "tests/test_track_b_ret_ledger_properties.py": "final_ret_r3", + "tests/test_track_b_ret_ledger_readings.py": "final_ret_r3", + "tests/test_track_b_ret_ledger_sources.py": "final_ret_r3", + "tests/test_track_b_ret_params.py": "final_ret_r3" + }, + "final_closure_source_and_tests_stable": true + }, + "full_command_index": "scratch/review/round5-full-commands.json", + "mutations": { + "count": 30, + "ids": [ + "round5-differential_f1_equality", + "round5-drop_beneficiary_finality", + "round5-drop_beneficiary_widow_drc_survivor_scope", + "round5-drop_dib_after_rib_f2", + "round5-drop_finality_f1", + "round5-drop_historical_child_ob_uncertainty", + "round5-drop_historical_wib_carryover_f6", + "round5-drop_historical_widow_gross_uncertainty", + "round5-drop_historical_widow_original_fact_hold", + "round5-drop_missing_widow_cohort_guard", + "round5-drop_parent_upper_bound_context", + "round5-drop_wc_f2", + "round5-drop_wc_f3", + "round5-exclude_protected_widow_by_ordinary_entitlement", + "round5-f6_without_own_mba", + "round5-matching_declarations_f1_equality", + "round5-restore_blanket_dual_f6_hold", + "round5-restore_global_own_history_hold", + "round5-restore_global_parent_hold", + "round5-restore_global_payment_hold", + "round5-restore_global_widow_drc_hold", + "round5-share_beneficiary_finality_recordwide", + "round5-skip_f3", + "round5-skip_f4", + "round5-skip_f6", + "round5-skip_specific_auxiliary_entitlement_error", + "round5-swallow_input_error", + "round5-table_completeness_missing_reason", + "round5-unconditional_deduction_ob_bound", + "round5-unsettle_non_aime_f1" + ], + "ledger": "docs/design/track_b_g2_r2b_mutations.json" + } + }, + "round_5_current_evidence_note": "Fresh reviewed-head failing-first, named module gates, cross-head diagnostic and isolated mutation evidence is under round_5. Earlier heads, counts and commands remain historical. No tier-policy or birth-evidence local run and no whole-suite collection." } diff --git a/docs/design/track_b_g_gross_benefits.md b/docs/design/track_b_g_gross_benefits.md index 1cdcda46d..ceee8370e 100644 --- a/docs/design/track_b_g_gross_benefits.md +++ b/docs/design/track_b_g_gross_benefits.md @@ -3141,15 +3141,18 @@ Verification class: statutory conformance on invented cases and captured rules. This round adds no population, behavioral or forecast claim. The own-work input bound applies before either family or household -coverage refusal. `OWN_EARNINGS_TEST` requires payable plus NH reservation -strictly below the original-benefit upper bound: equality leaves no room -for a positive own deduction. GN 02603.050A says "In all cases, +coverage refusal only when the original-benefit bound is settled. +`OWN_EARNINGS_TEST` requires payable plus NH reservation strictly below +that upper bound: equality leaves no room for a positive own deduction. GN 02603.050A says "In all cases, beneficiaries are still limited to the original benefit amount." The -deduction entry points take `RecordState` and compute ordinary G before -any `SavingsClauseGuard`; a carried protected payment cannot enter this -check. A future combined protected-payment/deduction procedure would need -its own bound. Current above-OB protected-rate requests already refuse as -`savings_clause_rate_procedure` rather than entering this path. +deduction entry points take `RecordState` before a `SavingsClauseGuard`, +but can receive an administrative-finality condition. RS 00615.754A.3 +protects rates established using another PIA and maximum; those rates can +exceed the OB from the correct declared PIA. The round-5 fact table in the +RET design note therefore suppresses this early bound when record finality +or the affected beneficiary's protection unsettles F4. G then retains the +original named coverage refusal. The source-conflict identifier is +`us:oasdi-finality-protected-rates-before-coverage`. The bound uses a widow's supplied larger OB basis and a parent's conservative one-parent OB (Act 202(e)/(f)(2), 202(h)(2)). On PIA $4, a @@ -3167,18 +3170,21 @@ rounds have these premises. RET uses the same table in its design note. | RET NH or auxiliary FRA declaration lies outside every possible attainment month in the supplied G cohort | Act 203(f)(8)(E), (9); 20 CFR 404.430(b), 404.434(c); RS 02501.021B.3; cohort/attainment conventions in RS 00615.003/.010 | A birthday within the cohort whose RIB FRA satisfies the declaration; every such intersecting declaration remains admitted | | An auxiliary and that same person's own benefit supply different SSA birth cohorts, even if their FRA declaration fits both separately | Act 202(q)(6); RS 00615.003/.010; G's existing single-person cohort-consistency contract | The fields describe different people or different declared cohort conventions; this interface permits neither | | RET declaration places FRA after a supplied own DRC-increased G snapshot | Act 202(w)(2); RS 00615.692 | Credits belonging only to the deceased NH, or an own age reduction without own delayed credits; neither proves the survivor's age | -| Own-work payable plus NH reservation equals the applicable OB upper bound | GN 02603.050A's OB limit and a strictly positive own-work deduction | A supported entry route carrying gross above that OB; this API has none, and larger widow OBs and one-parent rates are explicitly preserved | +| Own-work payable plus NH reservation equals the applicable settled OB upper bound | GN 02603.050A's OB limit and a strictly positive own-work deduction | Administrative finality can protect a rate based on another PIA; the early bound is skipped for that affected scope. Larger widow OBs and one-parent rates remain preserved | | G and RET declare opposite NH entitlement for the same person and month | Act 202(a), 203(b); `WORKER_NOT_ENTITLED` explicitly declares no RIB/DIB entitlement, while RET `entitled_months` declares entitlement; G's record kind also determines whether an NH benefit exists | Different people or months, or a declaration about cash rather than entitlement; this interface distinguishes zero cash from absence of entitlement | | A person's known SSA cohort differs between monthly contexts, including between an explicit cohort and an own-benefit cohort | Act 202(q)(6); RS 00615.003/.010 define one birth cohort for one person; G already requires the same identity across household records | Different people or cohort conventions; neither is allowed for one identifier. Missing cohort facts do not imply a conflicting cohort | -| RET declares an entitled spouse whose declared own RIB/DIB PIA equals or exceeds half the insured person's PIA | Act 202(b)(1)(D), (c)(1)(D); RS 00202.005; G's canonical spouse entitlement predicate compares the declared PIAs directly | No own entitlement in that month, a different person's own PIA, or a different PIA basis; the supplied G own benefit describes this person's current entitlement | -| An entitled NH's RET original rate differs from G's declared PIA, or a DIB NH's gross rate differs from that PIA | RS 02501.110 states the NH original benefit is 100% of PIA; Social Security Bulletin 75(3), Table 2 shows DIB worker benefit at 100% of PIA; the G/RET interface copies these declared rates directly | An unentitled month, a different person/month, or a different rate definition; unentitled original-rate declarations remain unconstrained by this comparison | +| RET declares an entitled spouse whose declared own RIB/DIB PIA equals or exceeds half the insured person's PIA, with F5 settled | Act 202(b)(1)(D), (c)(1)(D); RS 00202.005; G's canonical spouse entitlement predicate compares the declared PIAs directly | No own entitlement in that month, a different person's own PIA, or administrative finality protecting a rate based on another PIA | +| An entitled NH's RET original rate differs from G's declared PIA, or a DIB NH's gross rate differs from that PIA, with F1/F2 settled | RS 02501.110 states the NH original benefit is 100% of PIA; Social Security Bulletin 75(3), Table 2 shows DIB worker benefit at 100% of PIA; the G/RET interface copies these declared rates directly | An unentitled month, a different person/month, or an unsettler in the round-5 fact table: finality, prior reduced RIB or WC offset as applicable | ### Reproduced cases and invariants With survivor PIA $4/MAX $6 and child OB $3, own-work payable $3, or NH -reservation $1 plus payable $2, is invalid even with administrative finality -or another-record entitlement. PIA/MAX/OB $0 with payable $0 is also -invalid. Both public forms produce no outcome or denominator row. The +reservation $1 plus payable $2, is invalid with another-record entitlement +or another condition that leaves F4 settled. With administrative finality, +the ordinary-PIA bound is unsettled and the named refusal retains its row +and weight. PIA/MAX/OB $0 with payable $0 is also +invalid when F4 is settled; protected-rate conditions retain their named +refusal. Both public forms produce no outcome or denominator row. The test `test_own_event_at_ob_cap_errors_before_coverage_and_has_no_row` pins actual and estimated events; Hypothesis `test_upper_bound_equality_is_invalid_for_every_exact_reservation` varies @@ -3314,3 +3320,61 @@ readings remain in effect. Only named Track B test modules are run locally. Tier-policy and birth-evidence checks remain with CI. The conformance report is regenerated after the final rule, witness and report-input edits. + + +## PR 563 round 5: protected rates and early deduction bounds + +Verification class remains statutory conformance on invented declarations +and captured rules. No population, behavioral or forecast claim is added. + +The ordinary OB bound in `_check_deduction_amount_bounds` now uses G's +shared `_PREFLIGHT_FACT_UNSETTLERS` table and `_fact_is_settled` predicate, +with a separate request for a conservative upper bound rather than an +exact original rate. +The full fact and refusal table, source quotations and input-error audit +are in the RET design note's round-5 section. Administrative finality can +protect a rate based on a different PIA and maximum (RS 00615.754A.3). +Accordingly an amount exceeding, or an own-work amount equal to, the OB +from the correct PIA is not necessarily impossible. The early bound skips +that affected scope and G retains its named coverage refusal, outcome row +and full declared weight. Protection on one auxiliary does not exempt an +unprotected auxiliary from the bound. + +Deferred reason labels retain their actual role, record-kind and date +scope. A parent reason does not change a child's OB, and widow DRC +protection applies to survivors (RS 00615.712). An unresolved parent count +leaves the exact rate uncertain between 75% and 82.5%, while the one-parent +82.5% upper bound remains usable (RS 00209.001/.015). Both direct and +household paths reject a reservation or payable above that bound unless +a separate rate protection unsettles it. + +Historical gross and exact OB require different inferences. Before January +1973, the modern widow OB is unsettled: RS 00615.005A.2/.5 records the +change from 82.5% to 100% of PIA. After that date the exact ordinary OB +remains checked. But RS 00615.010 gives a sole surviving widow(er) +"$84.50 reduced for months of entitlement" or the higher ordinary WIB, +and says the sole-survivor rate was eliminated when the NH "died after +1981 and was not eligible for RIB or DIB". Ordinary OB therefore does not +establish a gross upper bound on a declared historical path. Old payment, +eligibility or first-DIB metadata, or an expressly deferred historical +eligibility or pre-1980 DIB refusal, keep that bound unsettled, including in +a later payment month. The original coverage refusal remains. This is conservative +handling of declared historical paths, not a complete adjudication of +RS 00615.650; no minimum or protected payment formula is added. Undated +current-domain snapshots retain their existing admitted scope. + +For nonwidow auxiliaries in actual pre-1983 payment months, the captures +do not establish that the modern dime-floored OB is unchanged across the +historical rounding rules. Their F4 comparison therefore remains unsettled. +Modern payment dates keep that comparison, even with an older maximum +eligibility refusal. + +This changes the inference from a potentially wrong OB basis. It preserves +the strict own-work requirement against actual computed gross, the +canonical one-parent upper bound, larger widow OBs, all positive-withholding +money rules and every post-G amount check. The direct and household paths +are pinned by +`test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob` in +`tests/test_track_b_ret_ledger_fix_round_5.py`. The source conflict is +`us:oasdi-finality-protected-rates-before-coverage`, following the delegated +ruling. No protected cash payment is newly implemented. diff --git a/docs/design/track_b_r2_ret_ledger.md b/docs/design/track_b_r2_ret_ledger.md index 2d455ccc8..590bbbbec 100644 --- a/docs/design/track_b_r2_ret_ledger.md +++ b/docs/design/track_b_r2_ret_ledger.md @@ -1890,8 +1890,8 @@ no FRA date for the survivor. | FRA is declared after a snapshot carrying that person's positive own delayed credits | Act 202(w)(2); RS 00615.692 | Only age-reduction months or inherited deceased-worker credits were supplied; these do not constrain the person's current FRA | | G and RET declare opposite NH entitlement for the same person and month | Act 202(a), 203(b); G's record kind and `WORKER_NOT_ENTITLED` state entitlement independently of cash, while RET `entitled_months` states the same month's entitlement | Different people or months, or confusion between zero payment and no entitlement; neither applies to these fields | | One person's known SSA cohort differs across monthly contexts or across explicit and own-benefit cohort fields | Act 202(q)(6); RS 00615.003/.010; G's existing single-person cohort-consistency contract | Different people or cohort conventions; neither is admitted for one identifier. A missing cohort remains unknown | -| RET declares an entitled spouse whose own RIB/DIB PIA is at least half the NH's PIA | Act 202(b)(1)(D), (c)(1)(D); RS 00202.005; G's spouse entitlement test uses the declared PIAs without an own-MBA calculation | No own entitlement that month, a different person's benefit, or a different PIA basis; none matches these fields | -| An entitled NH's original RET rate, or a DIB NH's gross RET rate, differs from G's declared PIA | RS 02501.110's 100%-of-PIA NH original share; Social Security Bulletin 75(3), Table 2's DIB worker benefit at 100% of PIA; G's direct PIA assignments | An unentitled month or a different person/month/rate concept; original rates for unentitled months remain valid without this constraint | +| RET declares an entitled spouse whose own RIB/DIB PIA is at least half the NH's PIA, with F5 settled | Act 202(b)(1)(D), (c)(1)(D); RS 00202.005; G's spouse entitlement test uses the declared PIAs without an own-MBA calculation | Administrative finality or that beneficiary's protected rate can rest on another PIA; the round-5 table below keeps the coverage refusal | +| An entitled NH's original RET rate, or a DIB NH's gross RET rate, differs from G's declared PIA, with F1 or F2 settled | RS 02501.110's 100%-of-PIA NH original share; Social Security Bulletin 75(3), Table 2's DIB worker benefit at 100% of PIA; G's direct PIA assignments | Finality can protect a different PIA; prior reduced RIB and WC can change DIB gross. The round-5 table below records the exceptions | ### Examples and executed invariants @@ -1981,10 +1981,12 @@ The former NH entitlement check depended only on declarations and now runs in a separate pass before any G computation. The audit also found a spouse subcase of the auxiliary entitlement check: own PIA at least half the NH PIA rules out spouse entitlement without computing own MBA. That -subcase uses G's canonical `_is_entitled` predicate before any held -refusal. At PIA/MAX $0/$0 with own PIA $0, and at $4/$6 with own PIA $2, -administrative finality previously changed this contradiction from an -input error into one refused row of weight 7; it now produces zero rows. +subcase uses G's canonical `_is_entitled` predicate before a held +refusal only when F5 is settled under the round-5 table below. At PIA/MAX +$0/$0 with own PIA $0, and at $4/$6 with own PIA $2, a held maximum-only +refusal cannot mask the contradiction. Administrative finality can protect +a rate established using another PIA, so those declarations retain one +refused row of weight 7. This also covers spouse-with-child-in-care and divorced-spouse roles and both own RIB and DIB. A spouse with no own entitlement is not subject to that threshold, so matching zero-cash entitlement remains valid. @@ -1992,19 +1994,23 @@ that threshold, so matching zero-cash entitlement remains valid. The NH original-rate comparison also reads a declaration directly: G supplies `state.pia` as the original rate. The DIB NH gross rate is the same direct PIA assignment. Both validate before a held refusal, only in -entitled months. RS 02501.110 states that the NH original benefit is 100% +entitled months and only when the corresponding fact is settled under the +round-5 table below. RS 02501.110 states that the NH original benefit is 100% of PIA; the captured Bulletin Table 2 shows the DIB worker benefit at 100% of PIA before and after the maximum. An original rate $.10 against -PIA $0, or $4.10 against PIA $4, is therefore an input error even with -administrative finality. A DIB gross rate $3 against PIA $4 is likewise -an input error. Unentitled-month original rates retain their existing +PIA $0, or $4.10 against PIA $4, is an input error when F1 is settled. +Administrative finality can protect a rate established using a different +PIA, so it preserves the named refusal. A DIB gross rate $3 against PIA $4 +is an input error only when F2 is settled; prior reduced RIB and WC offset +can also explain the difference. Unentitled-month original rates retain their existing freedom because the original post-G comparison did not constrain them. -Maximum binding requires statutory original and payable rates. Other -auxiliary entitlement branches need computed own MBA and, for parents, -the original-benefit threshold. Retirement NH gross and auxiliary gross -and original rates need G's monetary computation. Those checks stay after successful G -computation. Record-kind, monthly roster, +Maximum binding and auxiliary gross depend on the whole family +computation, including maximum allocation, age reduction, dual entitlement +and redistribution, so those comparisons stay after successful G. +Round 5 checks the remaining settled facts early using G's canonical own +MBA, original-benefit and entitlement helpers. Parent OBs additionally +need an entitled-parent count that computes without a coverage refusal. Record-kind, monthly roster, role/type, cohort, FRA and explicit dual-entitlement consistency checks already run in `RecordYear` before coverage. R1 year availability remains an input requirement checked before re-raising a held G refusal. @@ -2028,9 +2034,9 @@ retain their independently declared coverage refusal and weight. | Invariant | Executing test | | --- | --- | | No held coverage condition masks an NH entitlement contradiction; no outcome row is constructed | `test_nh_entitlement_contradiction_never_becomes_held_refusal`; Hypothesis `test_no_held_coverage_condition_masks_nh_contradiction` | -| No held coverage condition masks a spouse's disqualifying declared own PIA | `test_declared_spouse_pia_disqualification_precedes_held_refusal`; Hypothesis `test_no_held_coverage_condition_masks_spouse_pia_contradiction` | +| No held coverage condition that leaves F5 settled masks a spouse's disqualifying declared own PIA; finality retains its refusal | `test_declared_spouse_pia_disqualification_precedes_held_refusal`; Hypothesis `test_no_held_coverage_condition_masks_spouse_pia_contradiction` | | A spouse's own PIA strictly below half the NH PIA retains eligibility, and absence of own entitlement retains valid zero cash | `test_strictly_lower_spouse_own_pia_preserves_eligible_entitlement`; `test_spouse_without_own_entitlement_keeps_zero_and_positive_payments`; Hypothesis `test_own_pia_strictly_below_half_never_triggers_spouse_preflight` | -| Entitled NH original rates and DIB gross rates agree with their directly declared PIA before any held refusal | `test_declared_nh_original_pia_mismatch_precedes_held_refusal`; `test_declared_dib_nh_gross_pia_mismatch_precedes_held_refusal`; Hypothesis `test_no_held_coverage_condition_masks_direct_nh_rate_contradiction` | +| Entitled NH original rates and DIB gross rates agree with their directly declared PIA before a held refusal when F1/F2 remain settled | `test_declared_nh_original_pia_mismatch_precedes_held_refusal`; `test_declared_dib_nh_gross_pia_mismatch_precedes_held_refusal`; Hypothesis `test_no_held_coverage_condition_masks_direct_nh_rate_contradiction` | | Matching direct NH rates and unentitled-month original-rate declarations retain their existing outcomes | `test_matching_direct_nh_rates_keep_zero_and_positive_payments`; `test_unentitled_nh_original_share_is_not_a_payable_rate_declaration`; Hypothesis `test_direct_nh_rate_preflight_preserves_every_matching_declaration` | | All monthly NH declarations validate before the first G computation | `test_later_nh_contradiction_precedes_every_g_computation` | | Record kind determines DIB entitlement even without an own RIB declaration | `test_disability_nh_entitlement_comes_from_record_kind` | @@ -2042,3 +2048,272 @@ The premise table above records each new fact-pattern input error and its falsifier. This round introduces no additional RET statutory reading. The A.1/A.2 G composition refusal and its two source quotations are recorded in the G design note. Earlier statutory readings stand. + +## PR 563 round 5: facts settled before a coverage refusal + +Verification class remains statutory conformance on invented declarations +and captured published examples. No population, behavioral or forecast +claim is admitted. + +The preflight compares a monetary or monetary-entitlement fact only when +nothing declared on the record or that beneficiary can lawfully change +it. A condition that changes the comparison's PIA, rate or entitlement +basis makes that fact unsettled. In that case the preflight skips the +comparison and the existing G coverage refusal keeps its original place, +reason, one outcome row and full declared weight. If the capture does not +establish that a condition leaves a fact unchanged, the preflight treats +that fact as unsettled. A genuine contradiction still raises +`InvalidFamilyInput`, without an outcome row. Zero payable remains distinct +from no entitlement. + +### The six facts and their canonical rules + +| Fact | Comparison | Existing G rule reused | +| --- | --- | --- | +| F1 | Entitled NH original rate equals the declared PIA | `state.pia`, the NH original share in RS 02501.110: "their original benefit is equal to 100% of the PIA" | +| F2 | DIB NH gross equals the declared PIA | G's disability worker rate, before the separately declared prior-RIB reduction or WC offset | +| F3 | RIB NH gross equals the worker's own monthly benefit | `_own_monthly_benefit_validated`, including the declared age reduction and own delayed credits; RS 00615.101: "The MBA is equal to the PIA reduced by 5/9 of 1%" | +| F4 | An entitled auxiliary's original rate equals its role/PIA/basis OB | `_original_benefit_validated`; parent OB additionally requires `_entitled_parent_count` to complete without a refusal | +| F5 | Spouse entitlement passes the raw own-PIA test | `_is_entitled` for all spouse roles; Act 202(b)(1)(D), (c)(1)(D), RS 00202.005 | +| F6 | Other own-benefit entitlement: widow(er), mother/father, parent | `_own_monthly_benefit_validated` supplies the real own MBA to `_is_entitled`; parent entitlement also receives the resolved parent OB | + +The helpers perform no second monetary implementation. A canonical helper +that raises `FamilyConfigurationUnsupported` leaves that fact unsettled +for that row. The preflight catches only that coverage refusal; +`InvalidFamilyInput` continues to propagate. NH entitlement against RET, +cohort identity, RIB FRA, monthly roster and record-kind agreement remain +unconditional: each compares two declarations of one person's fact, and +none of the monetary conditions reconciles opposite declarations. + +### Declared-condition table + +G's `_PREFLIGHT_FACT_UNSETTLERS` table has explicit entries for every +`RecordCondition`, `BeneficiaryCondition` and G `UnsupportedReason`; +`_fact_is_settled` applies it to each fact and beneficiary. +An empty fact set is an affirmative statement that the condition acts on +a different quantity. Multiple conditions combine by union. Record-level +conditions apply to the whole context; beneficiary conditions apply only +to that beneficiary. A protected beneficiary does not exempt the NH or +another auxiliary. The table is consulted separately in each monthly +context, so a condition in one month does not exempt another month. + +The following quotations are from the existing manifest-listed captures +in `tests/data/track_b/gross_benefit_sources/`, except the separately +identified RET capture. The columns describe F1–F6 only; maximum binding +and auxiliary gross remain comparisons against a completed G result. + +| Declared condition | Facts unsettled | Captured quotation and inference | +| --- | --- | --- | +| `ADMINISTRATIVE_FINALITY` | F1–F6 for the record | RS 00615.754A.3 says "the rate to the NH is protected by administrative finality and cannot be changed" and requires recording "the PIA and maximum used to arrive at those rates". The second example protects both NH and child on "the protected PIA and maximum". The declared correct PIA need not be the protected-rate basis. | +| `DIB_AFTER_REDUCED_RIB` | F2 | Captured Act 202(q)(2): "such disability insurance benefit for each month shall be reduced by the amount such old-age insurance benefit would be reduced". This changes the DIB payable rather than its original PIA share. | +| `WORKERS_COMPENSATION_OFFSET` | F2, F3 | Captured Act 215(g) places rounding "after any reduction under sections 203(a) and 224". GN 02603.050C separately lists the "Workers’ compensation (WC) or public disability benefit (PDB) offset amount" after defining OB. The ordinary own-benefit amount cannot establish the offset amount. | +| `DIB_GUARANTEE_PIA` | None | RS 00615.736B.2 begins "To establish a family maximum for a DIB Guarantee PIA". G is supplied the applicable PIA; the refused calculation is its maximum. | +| `NON_AIME_FORMULA_PIA` | None | RS 00615.740B.1 says "The PIA is an AIME, OS, Special Minimum or Frozen Minimum PIA." The page concerns "determining the total amount of the family maximum benefit"; it does not replace the declared applicable PIA. | +| `WORKER_NOT_ENTITLED` | None | RS 00202.100 says "the NH is eligible but has not filed for benefits". This changes the declared NH entitlement and permitted roster; those identities are checked separately before money. | +| `WINDFALL_ELIMINATION_PROVISION` | None | RS 00202.100 says an IEDS "is subject to the number holder’s (NH) WEP PIA although the NH is not yet entitled". The supplied applicable PIA remains the OB basis; unsupported pre-repeal IEDS processing keeps its refusal. | +| `RATE_PROTECTED_BY_FINALITY` | F4–F6 for that beneficiary | RS 00615.754A.3 directs SSA to document "which rates are protected by administrative finality". Protection is specific to the beneficiary declared with this condition; the NH and other auxiliary facts remain subject to their own settlement checks. | +| `WIDOW_DRC_SAVINGS_CLAUSE` | F4 for that survivor | RS 00615.712 protects "beneficiaries who were entitled for the month of 5/78"; its example says "the child is protected by the savings clause and the child's rate will remain at $300". The protected rate basis is not silently reconstructed. | +| `ENTITLED_ON_ANOTHER_RECORD` | None | RS 00615.770: "Maximums from all SSNs that the child is entitled on may be combined on the SSN where payment is actually made." This changes the maximum allocation rather than the role's OB or own-PIA eligibility test. | +| `DEEMED_OR_PUTATIVE_SPOUSE` | None | RS 00615.684: "The deemed or putative spouse and all other beneficiaries on the record are reduced for the maximum." Its original spouse rate and raw own-PIA test remain the same quantities. | +| `LEGAL_SPOUSE_WITH_DEEMED_SPOUSE` | None | RS 00615.684: "the legal spouse is paid outside the family maximum" and "the legal spouse will receive the OB" when DMAX applies. This changes maximum membership. | +| `GOVERNMENT_PENSION_OFFSET` | None | GN 02608.100 defines offset as "a reduction of spouse's benefits due to the receipt of a federal, state, or local government pension". It separately defines entitlement as having "proven his or her rights to them for a given period". The offset changes payable, not the raw own-PIA entitlement test. The existing repeal boundary remains January 2024. | +| `DIB_BETWEEN_SPOUSE_BENEFIT_AND_RIB` | None | RS 00615.260B.2: "Reduce the spouse's reduced benefit further by the amount of the RIB reduction." Its example retains OB 400 while changing the excess from 30 to 20. The excess is not F1–F6. | + +The finality scope follows the delegated ruling +`us:oasdi-finality-protected-rates-before-coverage`, marked by that exact +source-conflict identifier in code. It explicitly permits the protected +rate to differ from a rate obtained from the declared correct PIA. This +is a classification decision, not implementation of protected payments. +The original `administrative_finality` refusal remains. + +### Refusals without a declared condition + +A held refusal can originate from G's own-benefit helper, record history, +beneficiary history or an explicitly deferred reason. The table includes +those reasons as well. A reason is never a blanket exemption for facts +which its capture leaves unchanged. The following groups record the +source basis for the decisions; the executable table contains every enum +member separately. + +| Held refusal or origin | Facts whose comparison can be unsettled | Captured basis | +| --- | --- | --- | +| `_refuse_own_benefit`: reduced own DIB; historical own RIB; pre-1917 delayed credits | The affected own MBA used for F3 or F6; F2 for the NH reduced-DIB reason | Act 202(q)(2) expressly reduces DIB. RS 00615.005C.2 requires the money-history method in "all cases involving single entitlement to actuarially reduced benefits prior to 1/78". RS 00615.692D gives "Before 01/02/17" a "1/12%" monthly credit. The canonical helper refuses rather than fabricating an MBA. | +| `PAYMENT_MONTH_BEFORE_1983` | Historical own MBA used for F3/F6; nonwidow auxiliary OB in actual pre-1983 months; survivor widow OB before January 1973 | RS 00615.101 says "Round the result down to the next dime for benefits after 5/82 and up to the next dime for benefits prior to 6/82." The captures do not establish unchanged modern dime-floored nonwidow OB throughout G's refused historical interval. RS 00615.005A.2 says "Raised the unreduced benefit amount for widow(er)s to 82 1/2% at age 62." Its A.5 says "Changed WIB to 100% of the deceased worker's PIA" effective January 1973. Actual payment dates determine which exact facts remain unsettled; a deferred payment reason cannot manufacture an earlier date. | +| `ELIGIBILITY_BEFORE_1983`, `DI_ENTITLEMENT_BEFORE_JULY_1980` | None | RS 00615.736 gives the historical maximum procedure; RS 00615.740B.2 says DMAX does not apply when "The NH was ever entitled to DIB before July 1980". These maximum histories do not replace role OB or current own-benefit facts. | +| `PARENT_BENEFIT` | F4/F6 when parent count refuses | RS 00209.001 excludes own RIB "equal to or exceeding the amount of the parent's original benefit (One parent = 82 1/2%; Two parents = 75%)". RS 00209.015 states "Benefit rate equals 75% of the worker's PIA for each month both are entitled." An unresolved entitled-parent count leaves both threshold and OB unsettled. | +| `DISABLED_WIDOW_UNDER_60` | No additional fact beyond a separately refusing own MBA | RS 00615.310C first says "Determine the WIB OB", then separately determines and subtracts reductions. The historical extra reduction changes gross, not F4's OB. | +| `DUAL_ENTITLEMENT_SEQUENCE` | F6 only where historical carryover can change own RIB | RS 00615.005A.8 says "Eliminated the carry-over reduction in RIB or DIB due to WIB before age 62" and applies the RIB change to workers born January 2, 1928 or later. RS 00615.010 preserves the earlier rule: "If there was prior entitlement to a reduced WIB in any month before the month of attainment of age 62 reduce the RIB per RS 00615.160 and RS 00615.170." The schema omits that history. Modern WIB/DWB election instead requires "if all eligibility requirements are met" and preserves "the PIA and the reduction factors remain the same" (RS 00615.315). It does not waive F6. A nonnegative own RIB cannot be less than a zero deemed-death PIA. The spouse raw own-PIA test stays F5. | +| `REDUCED_BENEFIT_HISTORY_BEFORE_1978` | No additional fact beyond a separately refusing own MBA | RS 00615.005C.2 requires historical money reductions. That does not change the original benefit determined before reduction. | +| `INDEPENDENT_DIVORCED_SPOUSE` | None | RS 00202.100 identifies the unfiled NH and requires the applicable WEP PIA; the declared PIA and eligibility facts are still the inputs. | +| `COMBINED_FAMILY_MAXIMUM`, `MULTIPLE_AUXILIARY_RECORDS`, `DEEMED_SPOUSE`, `NON_AIME_FORMULA_PIA`, `DIB_GUARANTEE_PIA`, `GOVERNMENT_PENSION_OFFSET` | None | The condition table's captured maximum-membership, maximum-formula and payable-offset rules apply equally when the reason is deferred. | +| `PARISI_AMBIGUOUS`, `PARISI_BEFORE_OCTOBER_1999` | None | RS 00615.768E says the change affects benefits "after reduction for the maximum" and "Beneficiaries will still be limited by the original benefit amount." | +| `WIDOW_DRC_SAVINGS_CLAUSE`, `WIDOW_DRC_SAVINGS_CLAUSE_HISTORY_UNKNOWN` | F4 for the potentially protected survivor | RS 00615.712's protection is specific to May 1978 survivors and can preserve a different original rate basis. Unknown history does not establish absence of that protection. | +| `WIDOW_CHILD_IN_CARE_UNKNOWN`, `DIVORCED_SPOUSE_CHILD_IN_CARE_UNKNOWN`, `DIVORCED_SPOUSE_CARE_HISTORY` | None | RS 00615.340 begins with a person already "receiving a reduced widow(er) benefit" and says "The benefit amount is raised for all months the child is in care." RS 00615.201 changes age reduction/conversion when care ends. These change gross or reduction history after OB and entitlement. | +| `SAVINGS_CLAUSE`, `SAVINGS_CLAUSE_HISTORY_UNKNOWN`, `SAVINGS_CLAUSE_MEMBERSHIP_CHANGE`, `SAVINGS_CLAUSE_RATE_PROCEDURE` | None for F1–F6 | RS 00630.400 says "Any person's benefit may not exceed the original benefit (OB)" and adds "the new PIA in a life case" to the savings maximum. The refusal concerns carried allocation/rate procedure rather than the ordinary OB, NH own benefit or raw own-benefit entitlement. | +| `PRISONER_SUSPENSION`, `DRUG_ADDICTION_SUSPENSION`, `FOREIGN_WORK_DEDUCTION`, `PENALTY_DEDUCTION`, `MARITIME_DEDUCTION`, `ELECTION_CERTIFICATE_SUSPENSION` | None | GN 02603.040 calls these "deductions" and suspensions. GN 02603.050B first applies the maximum, then deductions, then redistribution. They do not alter the pre-reduction facts F1–F6. | +| `DEDUCTION_AGE_WORK_INTERACTION`, `SOLE_FULL_DEDUCTION_ZERO_DUAL_COMPOSITION` | None | GN 02603.050A and C concern deduction exceptions and reserved age reductions during redistribution. The unresolved composition changes family cash after the original rates and entitlement tests. | +| Deferred `ADMINISTRATIVE_FINALITY`, `DIB_AFTER_REDUCED_RIB`, `WORKERS_COMPENSATION_OFFSET` | Same scoped facts as the named condition | Deferring a known reason does not turn its potentially lawful monetary difference into an input error. | + +Maximum binding and auxiliary gross deliberately stay after G. Maximum +binding depends on all entitled subject OBs, the available maximum and +worker entitlement. Auxiliary gross additionally depends on maximum +allocation, age reduction, dual entitlement, care floors and Parisi +redistribution. An early local check cannot settle these family outcomes. +The shared `_original_entitlement_rows` helper resolves only original +benefits and own-benefit entitlement for G and the preflight. Its +`_possible_widow_drc_protection` predicate counts entitled subject rows, +so a disqualified own-RIB widow cannot create protected-history uncertainty +for a child. `_widow_drc_history_unknown` is shared with G; an omitted +attestation does not exempt modern metadata that rules out protection. +`_declared_widow_drc_protection_possible` first bounds protection from +the declared roster, then resolves each relevant member independently +through the same canonical original/entitlement rows. A roster with no +possible DRC widow or fewer than two possible subject survivors establishes +absence before unrelated own-MBA refusals are consulted. An unresolved +entitlement remains possible without hiding another member's independently +settled disqualification. Beneficiary and own-benefit cohorts first use G's +`_with_effective_cohort` normalization in both directions. +Implicit beneficiary history is inspected with conditions cleared after +classifying every explicit condition, so an earlier condition cannot hide +a later implicit hold or broaden a condition through a shared reason code. +Deferred own-RIB and delayed-credit history reasons unsettle an own MBA +only when its canonical helper refuses that person's actual declaration. +A deferred parent reason cannot unsettle a child's OB, and parent +uncertainty requires a canonical parent-count refusal. Widow DRC +protection applies to survivor records; its reason cannot change a living +record's child OB. An expressly deferred survivor protection is not +excluded merely because no widow is currently on the roster: the capture +does not rule out carried protection. These contextual checks preserve +the table's possible fact sets without extending a reason to unrelated +people, record kinds or dates. +The preflight adds no maximum-allocation computation and changes no +refusal precedence. +When a settled auxiliary entitlement test fails, its existing entitlement +diagnostic precedes a consequent original-rate mismatch. G reports zero +OB for an ineligible row, so comparing that declared zero with the role's +raw OB first would hide the more specific contradiction. The monthly +roster requires every G auxiliary to be declared entitled in RET; an +ineligible auxiliary cannot instead be admitted as an unentitled matching +row. `test_family_context_invalidity_precedes_record_refusal` retains its +unchanged assertion for this ordering. + +### Audit of new input errors before a refusal + +The audit covers every PR-added `InvalidFamilyInput` check that can run +before a held refusal in the declared-input and monthly computation paths. +Sealed result identities run after computation and are not preflights over +caller declarations. + +| Check or input-error family | Can a declared condition make the forbidden input lawful? | Round-5 action | +| --- | --- | --- | +| NH original/PIA; DIB gross/PIA; RIB gross/own MBA; auxiliary OB; spouse own-PIA eligibility; other own-benefit eligibility | Yes, for exactly the unsettlers in the fact table | Compare only settled F1–F6 with the canonical G helper; skip only a canonical coverage refusal | +| `_check_deduction_amount_bounds`: NH reservation above OB; payable plus reservation above OB | Yes. RS 00615.754A.3 protects rates based on another PIA/maximum; RS 00615.010's historical sole-survivor minimum can also exceed ordinary OB | Classify whether OB is a conservative gross upper bound, separately from exact F4. An unresolved parent count still permits the 82.5% upper bound; historical widow gross can remain unsettled even when exact post-1972 OB is known. Preserve the named refusal when the upper bound is unsettled | +| `_check_deduction_amount_bounds`: own-work payable plus reservation equals OB | Yes, when the gross upper bound is unsettled. Equality to ordinary OB need not mean zero withholding from a larger protected or historical rate | Apply the strict early bound only when its upper-bound premise is settled. After successful G, the strict actual-gross bound remains unconditional | +| `_check_fra_facts`: cohort/FRA interval has no intersection; own DRCs require FRA by the snapshot | No. These are the same person's dated age facts, not rate protection; Act 203(f)(9), RS 02501.021B.3 and Act 202(w)(2) still govern | Keep unchanged before every refusal; inherited credits and age reductions still prove no current FRA | +| `RecordYear`: one person's explicit/own-benefit cohorts disagree within or across months | No. One identifier and the same SSA cohort convention describe one birth cohort | Keep unchanged, including missing-cohort uncertainty | +| G versus RET NH entitlement, record kind, monthly auxiliary roster and role/type | No. These are opposite declarations of one person's same-month entitlement/type | Keep unchanged before all monetary computation; zero cash remains entitled | +| Explicit two-record boolean disagrees with G own-benefit presence | No. The fields declare whether own entitlement exists; offsets/finality do not delete that declaration | Keep unchanged; actual or estimated two-record earnings remain the existing named refusal | +| Nonzero gross without declared entitlement, or positive gross with a zero declared original share | No. These compare the person's own entitlement and actual declared rate basis, including any protected basis. Protection may change the PIA used for that original share; it cannot produce a positive benefit from a zero original share | Keep unchanged in the beneficiary declaration; this does not compare either rate to `state.pia` | +| Deduction keys/household identities; missing own benefit for a dual marker; no-care role, age, under-FRA status or current-care contradictions; negative reservations/payables | No. These are schema, event-kind and dated factual contradictions independent of the disputed monetary basis | Keep unchanged before coverage; a supported no-care attestation never overrides supplied cohort/credit facts | +| Exact scalar/enum/container schemas, raw month memberships, one-time snapshots and sealed result provenance | No. A statutory condition does not change the API's declaration or provenance contract | Keep unchanged; validation still runs once per public call | +| Supported R1 year availability | No. It is an input requirement, independent of G's supported money scope | Keep the existing lookup before re-raising a held G refusal | + +The strict own-earnings rule itself is unchanged: a declared own-work event +must withhold a positive amount from actual gross after NH reservations. +Only the premature inference from an unsettled OB has changed. The +outside-beneficiary independence fix, A.1/A.2 composition refusal, NH-only +cash correction, saving-clause default/literal reading and cohort checks +remain in force. + +The deduction audit distinguishes exact rate from a conservative upper +bound. Parent count uncertainty cannot raise a rate above the one-parent +82.5% OB (RS 00209.001/.015). At PIA $4, two unresolved parent own benefits +of $3.10 leave the exact count uncertain, but neither a $3.40 payable nor +NH reservation is lawful against the $3.30 upper bound. Finality still +unsettles this bound independently. + +For historical widow gross, RS 00615.010 instead gives "Sole Surviving +Widow(er) $84.50 reduced for months of entitlement, if any, prior to age +62 or, if higher, the WIB computed without regard to this sole survivor's +provision". It states "The sole survivor's rate was eliminated when NH +died after 1981 and was not eligible for RIB or DIB". The captured condition +does not establish ordinary OB as a gross upper bound on a declared legacy +path. Old eligibility, payment or first-DIB metadata and an explicitly +deferred old-eligibility or pre-1980 DIB refusal keep that inference +unsettled, even for a modern payment. This preserves the original refusal and does not compute +the minimum or expand G's historical cash scope. The exact widow OB remains +100% after January 1973. Current-domain omitted cohorts retain the existing +scope; this helper does not purport to adjudicate every undated historical +award. The rejected ordinary-OB upper-bound inference and conservative +coverage treatment, including the unsupported initial probe, are recorded +in the round-5 report. + +### Published finality examples + +RS 00615.754A.3's first example declares correct PIA $750.00 and maximum +$1,312.50, protected NH rate $1,000.00, new child rate $375.50 and total +$1,375.50. The capture says "the correct PIA is really $750.00" and the +NH rate "cannot be changed". Its printed $375.50 child figure is retained +verbatim even though half of $750.00 is $375.00. This test preserves the +published declaration and its coverage refusal; it does not assert that +the refused path computes that arithmetic. + +The second example starts with NH $1,000.00, old maximum $1,750.00 and +first child $500.00. Correct PIA/maximum become $750.00/$1,312.50. The +protected first child is recomputed using the old PIA/maximum to $375.00; +the new child's correct-rate share is $281.20. The published resulting +rates $1,000.00/$375.00/$281.20 sum to $1,656.20. Both examples retain +`administrative_finality`, one row and the full declared weight. Every +quoted phrase and figure is checked against the unchanged capture. + +The invented DIB declarations PIA $1,000/gross $800 with +`DIB_AFTER_REDUCED_RIB` and PIA $1,000/gross $600 with +`WORKERS_COMPENSATION_OFFSET` likewise retain the original named refusal. +Matching declarations at zero and positive money remain valid under every +condition. Contradictory settled declarations error with or without an +unrelated held refusal. + +### New executed invariants + +The round-5 public-path tests execute these invariants beside named +examples and Hypothesis properties: + +| Invariant | Executing tests in `test_track_b_ret_ledger_fix_round_5.py` | +| --- | --- | +| Every record condition, beneficiary condition and G refusal reason is classified explicitly | `test_fact_table_explicitly_covers_all_conditions_and_held_g_reasons` | +| A settled contradiction errors held and unheld with zero rows; an unsettled declaration retains its named refusal, row and weight | `test_each_fact_contradiction_is_classified_by_its_declared_condition`; Hypothesis `test_held_against_unheld_fact_classification`; `test_review_counterexamples_follow_finality_ruling` | +| Canonically matching zero and positive declarations never raise a preflight input error under any condition | Hypothesis `test_matching_declarations_never_raise_input_errors` | +| Valid outcomes and refusal reasons equal the path with preflight removed, exactly | Hypothesis `test_preflight_changes_no_valid_outcome_or_refusal` | +| Deferred reason labels do not unsettle unrelated canonical facts, roles, record kinds or actual payment dates | `test_deferred_reason_unsettles_only_the_fact_within_its_scope` | +| Widow DRC protection applies to survivors; its beneficiary flag leaves a living child's OB settled | `test_widow_drc_condition_on_a_living_child_keeps_ob_settled`; `test_survivor_widow_drc_protection_keeps_its_original_refusal`; explicit Hypothesis example in `test_held_against_unheld_fact_classification` | +| A pre-1973 widow's 82.5% OB preserves the historical refusal; the same declaration contradicts the 100% OB from January 1973 | `test_historical_widow_original_benefit_uses_the_payment_period` | +| Protection remains local to its declared beneficiary, month and condition union | `test_beneficiary_finality_protects_its_own_unsettled_fact`; `test_one_beneficiary_finality_does_not_protect_the_nh`; `test_protected_auxiliary_does_not_protect_another_auxiliary`; `test_finality_is_resolved_for_each_month`; `test_two_declared_conditions_preserve_finality_protection` | +| A shared reason does not broaden an explicit condition or hide a later implicit sequence refusal | `test_spouse_sequence_condition_does_not_unsettle_other_own_eligibility`; `test_implicit_widow_history_remains_unsettled_behind_explicit_hold` | +| Generic dual-sequence refusal leaves F6 unsettled only for genuinely possible historical carryover; modern DWB and cohort 1928 retain the own-RIB eligibility check | `test_aged_widow_sequence_refusal_only_unsettles_possible_carryover`; `test_modern_disabled_widow_own_rib_eligibility_is_settled`; `test_eligible_disabled_widow_retains_own_sequence_refusal` | +| A disqualified widow or unrelated refusing child cannot create DRC-protection uncertainty for another auxiliary | `test_disqualified_widow_does_not_unsettle_a_child_original_benefit`; `test_unrelated_refused_child_does_not_invent_widow_protection` | +| Ordinary eligibility or OB cannot exclude a protected widow from independently unknown DRC history; an explicit no-protection declaration still settles that absence | `test_protected_widow_cannot_be_excluded_from_unknown_drc_history` | +| A cohort supplied only by the beneficiary or own-benefit field receives the same canonical normalization as G | `test_widow_own_cohort_alone_matches_the_resolved_cohort_control`; `test_auxiliary_cohort_supplies_own_rib_historical_refusal` | +| Missing both aged own-RIB widow cohorts remains G's canonical input error before implicit coverage inspection | `test_missing_both_widow_cohorts_remains_canonical_input_error` | +| WEP and IEDS preserve settled auxiliary facts while keeping the declared NH unentitled | `test_wep_declaration_alone_changes_none_of_the_six_facts`; `test_worker_not_entitled_declares_an_ieds_record_without_nh_rate`; `test_ieds_does_not_mask_settled_auxiliary_facts` | +| Canonical money-rule refusals remain refusals; input errors propagate | `test_historical_rib_gross_rule_refusal_leaves_original_reason`; `test_canonical_input_error_is_never_caught_as_a_coverage_refusal` | +| F6 uses real own MBA, including reductions, rather than `None` or raw PIA | `test_other_own_entitlement_uses_real_reduced_monthly_benefit` | +| Direct and household deduction paths retain protected rates that exceed the correct-PIA OB bound | `test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob` | +| Unresolved parent count retains the conservative one-parent upper bound; independent finality and zero events keep their original refusals | `test_parent_count_uncertainty_keeps_the_one_parent_upper_bound`; Hypothesis `test_parent_upper_bound_holds_across_scales_months_and_deferred_holds`; `test_zero_parent_deduction_retains_parent_count_refusal`; `test_finality_can_unsettle_the_parent_upper_bound` | +| Historical nonwidow rounding uncertainty retains the old refusal only in actual historical payment months | `test_child_ob_uncertainty_is_limited_to_pre1983_payment_months`; Hypothesis `test_child_ob_uncertainty_preserves_old_refusals_for_odd_dime_pias` | +| Historical widow gross uncertainty is distinct from exact post-1972 OB and preserves the original refusal across payment months | `test_historical_widow_gross_uncertainty_retains_original_refusal`; Hypothesis `test_historical_widow_gross_uncertainty_preserves_refusals_across_months`; later-payment carryover controls in the same module | +| Published finality figures, all table quotations and capture hashes remain verbatim | `test_finality_examples_are_verbatim_and_the_capture_hash_matches`; `test_fact_table_source_quotations_and_capture_hashes` | + +Protected eligibility can affect another survivor indirectly: an ordinary +own-RIB disqualification cannot exclude a finality-protected widow from +possible May 1978 DRC protection. A protected OB likewise cannot establish +absence of a larger protected basis. Unknown history therefore retains the +original finality refusal. An explicit `widow_drc_savings_clause=False` +settles that absence and leaves the other child's F4 checked. This is a +dependency through independently unknown history, not a record-wide +finality exemption (RS 00615.712 and .754A.3). + +Maximum binding and auxiliary gross comparisons remain after successful +G. Public validation still runs once; no monetary rule is reimplemented. +The exact first-failure evidence, deliberate mutations and adversarial +cases are recorded in `scratch/review/fix-round-5-report.md` and the +existing machine-readable verification and mutation records. diff --git a/src/populace_dynamics/track_b/gross_benefits.py b/src/populace_dynamics/track_b/gross_benefits.py index 3695c20f5..d7f7a7483 100644 --- a/src/populace_dynamics/track_b/gross_benefits.py +++ b/src/populace_dynamics/track_b/gross_benefits.py @@ -11,8 +11,12 @@ 20 CFR 404.421(a)). Own-work events must withhold a positive amount; a zero deduction is an input error and never changes the family-maximum computation. Payable plus -NH reservation must therefore be strictly below the original-benefit upper -bound, including before a held coverage refusal. +NH reservation must therefore be strictly below a settled original-benefit +upper bound. Protected rates can depend on a different PIA; their coverage +refusal precedes comparisons with the ordinary original benefit. +An unresolved parent count still permits the one-parent upper bound. +Historical widow gross can exceed ordinary OB under the sole-survivor +provision; declared legacy history keeps that early bound unsettled. Outside-maximum beneficiaries and their events do not enter governed readjustment decisions (203(a)(3)(C); GN 02603.020B). Their own deductions still apply. GN 02603.050A.1 and A.2's sole-full and zero-dual exceptions @@ -419,6 +423,9 @@ #: expanded sequence coverage; cohort 1928 is a known over-refusal, not #: a method-D source requirement or ambiguity in the SSA cohort input. _FIRST_METHOD_B_WIDOW_BIRTH_YEAR = 1929 +# RS 00615.005A.8/.010: RIB no longer carries a prior reduced WIB's +# reduction for SSA cohorts beginning January 2, 1928. +_FIRST_OWN_RIB_WITHOUT_WIB_CARRYOVER_BIRTH_YEAR = 1928 # --------------------------------------------------------------------------- @@ -1710,6 +1717,279 @@ class BeneficiaryCondition(Enum): } +# Each row explicitly classifies a possible hold, including those that leave +# all six facts settled. Completeness tests require a decision for new enums. +# F1 NH OB; F2 DIB gross; F3 RIB gross; F4 auxiliary OB; +# F5 raw spouse own-PIA eligibility; F6 other own-benefit eligibility. +_PREFLIGHT_FACT_UNSETTLERS = { + RecordCondition.DIB_GUARANTEE_PIA: frozenset(), + RecordCondition.DIB_AFTER_REDUCED_RIB: frozenset({"F2"}), + RecordCondition.WORKERS_COMPENSATION_OFFSET: frozenset({"F2", "F3"}), + # Source conflict us:oasdi-finality-protected-rates-before-coverage + RecordCondition.ADMINISTRATIVE_FINALITY: frozenset( + {"F1", "F2", "F3", "F4", "F5", "F6"} + ), + RecordCondition.WORKER_NOT_ENTITLED: frozenset(), + RecordCondition.WINDFALL_ELIMINATION_PROVISION: frozenset(), + RecordCondition.NON_AIME_FORMULA_PIA: frozenset(), + BeneficiaryCondition.ENTITLED_ON_ANOTHER_RECORD: frozenset(), + BeneficiaryCondition.DEEMED_OR_PUTATIVE_SPOUSE: frozenset(), + BeneficiaryCondition.LEGAL_SPOUSE_WITH_DEEMED_SPOUSE: frozenset(), + BeneficiaryCondition.GOVERNMENT_PENSION_OFFSET: frozenset(), + BeneficiaryCondition.RATE_PROTECTED_BY_FINALITY: frozenset( + {"F4", "F5", "F6"} + ), + BeneficiaryCondition.DIB_BETWEEN_SPOUSE_BENEFIT_AND_RIB: frozenset(), + BeneficiaryCondition.WIDOW_DRC_SAVINGS_CLAUSE: frozenset({"F4"}), + UnsupportedReason.ELIGIBILITY_BEFORE_1983: frozenset(), + UnsupportedReason.PAYMENT_MONTH_BEFORE_1983: frozenset({"F3", "F4", "F6"}), + UnsupportedReason.DI_ENTITLEMENT_BEFORE_JULY_1980: frozenset(), + UnsupportedReason.COMBINED_FAMILY_MAXIMUM: frozenset(), + UnsupportedReason.DEEMED_SPOUSE: frozenset(), + UnsupportedReason.PARENT_BENEFIT: frozenset({"F4", "F6"}), + UnsupportedReason.DISABLED_WIDOW_UNDER_60: frozenset(), + UnsupportedReason.DIB_GUARANTEE_PIA: frozenset(), + UnsupportedReason.DIB_AFTER_REDUCED_RIB: frozenset({"F2"}), + UnsupportedReason.WORKERS_COMPENSATION_OFFSET: frozenset({"F2", "F3"}), + UnsupportedReason.GOVERNMENT_PENSION_OFFSET: frozenset(), + UnsupportedReason.ADMINISTRATIVE_FINALITY: frozenset( + {"F1", "F2", "F3", "F4", "F5", "F6"} + ), + UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE: frozenset({"F6"}), + UnsupportedReason.PARISI_AMBIGUOUS: frozenset(), + UnsupportedReason.PARISI_BEFORE_OCTOBER_1999: frozenset(), + UnsupportedReason.INDEPENDENT_DIVORCED_SPOUSE: frozenset(), + UnsupportedReason.NON_AIME_FORMULA_PIA: frozenset(), + UnsupportedReason.MULTIPLE_AUXILIARY_RECORDS: frozenset(), + UnsupportedReason.SAVINGS_CLAUSE: frozenset(), + UnsupportedReason.SAVINGS_CLAUSE_HISTORY_UNKNOWN: frozenset(), + UnsupportedReason.SAVINGS_CLAUSE_MEMBERSHIP_CHANGE: frozenset(), + UnsupportedReason.SAVINGS_CLAUSE_RATE_PROCEDURE: frozenset(), + UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE: frozenset({"F4"}), + UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE_HISTORY_UNKNOWN: frozenset( + {"F4"} + ), + UnsupportedReason.WIDOW_CHILD_IN_CARE_UNKNOWN: frozenset(), + UnsupportedReason.DIVORCED_SPOUSE_CHILD_IN_CARE_UNKNOWN: frozenset(), + UnsupportedReason.DIVORCED_SPOUSE_CARE_HISTORY: frozenset(), + UnsupportedReason.DELAYED_CREDITS_BEFORE_1917: frozenset({"F3", "F6"}), + UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978: frozenset({"F3", "F6"}), + UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978: frozenset(), + UnsupportedReason.PRISONER_SUSPENSION: frozenset(), + UnsupportedReason.DRUG_ADDICTION_SUSPENSION: frozenset(), + UnsupportedReason.FOREIGN_WORK_DEDUCTION: frozenset(), + UnsupportedReason.PENALTY_DEDUCTION: frozenset(), + UnsupportedReason.MARITIME_DEDUCTION: frozenset(), + UnsupportedReason.ELECTION_CERTIFICATE_SUSPENSION: frozenset(), + UnsupportedReason.DEDUCTION_AGE_WORK_INTERACTION: frozenset(), + UnsupportedReason.SOLE_FULL_DEDUCTION_ZERO_DUAL_COMPOSITION: frozenset(), +} + + +def _declared_fact_holds(state, beneficiary=None): + holds = set(state.conditions) + if state.deferred_refusal is not None: + holds.add(state.deferred_refusal[0]) + if beneficiary is not None: + holds.update(beneficiary.conditions) + return holds + + +def _hold_unsettles_fact( + hold, + fact, + state, + beneficiary, + *, + payment_month, + beneficiaries, + params, + original_benefit_upper_bound=False, +): + if fact not in _PREFLIGHT_FACT_UNSETTLERS[hold]: + return False + if hold in ( + UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978, + UnsupportedReason.DELAYED_CREDITS_BEFORE_1917, + ): + own = state.worker if beneficiary is None else beneficiary.own_benefit + if own is None: + return False + try: + _own_monthly_benefit_validated(own, params) + except FamilyConfigurationUnsupported: + return True + return False + if hold is UnsupportedReason.PARENT_BENEFIT: + if beneficiary is None or beneficiary.role is not Role.PARENT: + return False + # RS 00209.001/.015: count changes 82.5% to 75%, so uncertainty + # about exact OB cannot invalidate the one-parent upper bound. + if original_benefit_upper_bound: + return False + try: + _entitled_parent_count(state, beneficiaries, params) + except FamilyConfigurationUnsupported: + return True + return False + if hold is UnsupportedReason.PAYMENT_MONTH_BEFORE_1983: + if fact == "F4": + if ( + state.kind is FamilyKind.SURVIVOR + and beneficiary is not None + and beneficiary.role in _WIDOW_ROLES + ): + # RS 00615.005A.2/.5: exact ordinary WIB became 100% + # of PIA in January 1973. A gross upper bound additionally + # needs the separate historical-minimum check below. + return payment_month is None or ( + payment_month.year, + payment_month.month, + ) < (1973, 1) + # Historical rounding is outside G's supported interval. + # The captures do not settle modern dime-floored nonwidow OB + # for every refused historical month (RS 00615.101). + return ( + payment_month is None + or ( + payment_month.year, + payment_month.month, + ) + < FIRST_SUPPORTED_PAYMENT_MONTH + ) + return ( + payment_month is None + or ( + payment_month.year, + payment_month.month, + ) + < FIRST_SUPPORTED_PAYMENT_MONTH + ) + if hold in ( + BeneficiaryCondition.WIDOW_DRC_SAVINGS_CLAUSE, + UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE, + UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE_HISTORY_UNKNOWN, + ): + # RS 00615.712 protects survivors; a deferred reason cannot + # change a living record's original benefits. + return state.kind is FamilyKind.SURVIVOR + if hold is UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE and fact == "F6": + if beneficiary is None: + return True + own = beneficiary.own_benefit + # RS 00615.005A.8/.010 can change the own RIB before cohort 1928. + # Modern DWB election still requires eligibility and keeps the + # PIA/RFs unchanged (RS 00615.315). A nonnegative RIB cannot be + # less than a zero deemed-death PIA (402(e)(1)(D)). + return ( + beneficiary.role in _WIDOW_ROLES + and own is not None + and own.kind is OwnBenefitKind.OLD_AGE + and own.pia > 0 + and (beneficiary.original_benefit_basis or state.pia) > 0 + and ( + beneficiary.birth_year is None + or beneficiary.birth_year + < _FIRST_OWN_RIB_WITHOUT_WIB_CARRYOVER_BIRTH_YEAR + ) + ) + return True + + +def _fact_is_settled( + fact, + state, + beneficiary=None, + *, + payment_month=None, + beneficiaries=(), + params=None, + original_benefit_upper_bound=False, +): + """Whether ordinary G can establish this fact before a coverage hold. + + Record conditions apply to everyone; beneficiary conditions and their + implicit coverage holds apply only to that person. Inspect every + declared condition even when another condition would refuse first. + Canonical money helpers may still refuse a fact that passes this test. + The upper-bound request permits the conservative one-parent bound + without asserting that the exact parent OB or count is settled. + """ + if beneficiary is not None: + beneficiary = _with_effective_cohort(beneficiary) + holds = _declared_fact_holds(state, beneficiary) + if any( + _hold_unsettles_fact( + hold, + fact, + state, + beneficiary, + payment_month=payment_month, + beneficiaries=beneficiaries, + params=params, + original_benefit_upper_bound=original_benefit_upper_bound, + ) + for hold in holds + ): + return False + if ( + payment_month is not None + and (payment_month.year, payment_month.month) + < FIRST_SUPPORTED_PAYMENT_MONTH + ): + holds.add(UnsupportedReason.PAYMENT_MONTH_BEFORE_1983) + if beneficiary is not None: + if state.kind is FamilyKind.SURVIVOR: + if state.widow_drc_savings_clause is True: + holds.add(UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE) + elif state.widow_drc_savings_clause is None and fact == "F4": + possible = _declared_widow_drc_protection_possible( + state, beneficiaries, params, payment_month + ) + if _widow_drc_history_unknown(state, possible): + holds.add( + UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE_HISTORY_UNKNOWN + ) + if payment_month is not None: + try: + resolved = _with_effective_cohort(beneficiary) + if ( + resolved.role in _AGED_WIDOW_ROLES + and resolved.own_benefit is not None + and resolved.own_benefit.kind is OwnBenefitKind.OLD_AGE + and resolved.birth_year is None + ): + # R2 can reach this helper before G's family input + # checks. Preserve their canonical error; this branch + # cannot repeat validation on a valid declaration. + _check_beneficiary_inputs(resolved, state, params) + # Conditions were classified individually above. A generic + # reason shared by several conditions must not broaden one + # condition's scope or mask a later implicit history hold. + _refuse_beneficiary( + _replace_declared( + resolved, + conditions=frozenset(), + ), + payment_month, + ) + except FamilyConfigurationUnsupported as error: + holds.add(error.reason) + return not any( + _hold_unsettles_fact( + hold, + fact, + state, + beneficiary, + payment_month=payment_month, + beneficiaries=beneficiaries, + params=params, + original_benefit_upper_bound=original_benefit_upper_bound, + ) + for hold in holds + ) + + class OwnBenefitKind(Enum): OLD_AGE = "old_age" DISABILITY = "disability" @@ -3498,12 +3778,20 @@ def _refuse_widow_drc_savings_clause( ) if state.widow_drc_savings_clause is False: return - subject = [row for row in rows if row.subject] - possible_drc_protection = len(subject) > 1 and any( - row.beneficiary.role in _WIDOW_ROLES and row.ob > state.pia - for row in subject - ) - if ( + possible_drc_protection = _possible_widow_drc_protection(rows, state.pia) + if _widow_drc_history_unknown(state, possible_drc_protection): + raise _computed( + FamilyConfigurationUnsupported, + UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE_HISTORY_UNKNOWN, + "a survivor snapshot must attest whether May 1978 " + "entitlement and widow(er) deceased-worker DRCs invoke " + "RS 00615.712; an omitted first DIB date is unknown history", + ) + + +def _widow_drc_history_unknown(state, possible_drc_protection): + """The same protected-history predicate for G and its fact preflight.""" + return ( state.eligibility_year is None or state.eligibility_year < FIRST_SUPPORTED_ELIGIBILITY_YEAR or ( @@ -3512,15 +3800,123 @@ def _refuse_widow_drc_savings_clause( <= _construct_declared(YearMonth, 1978, 5) ) or (state.first_dib_entitlement is None and possible_drc_protection) - ): - raise _computed( - FamilyConfigurationUnsupported, - UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE_HISTORY_UNKNOWN, - "a survivor snapshot must attest whether May 1978 " - "entitlement and widow(er) deceased-worker DRCs invoke " - "RS 00615.712; an omitted first DIB date is unknown history", + ) + + +def _possible_widow_drc_protection(rows, pia): + subject = [row for row in rows if row.subject] + return len(subject) > 1 and any( + row.beneficiary.role in _WIDOW_ROLES and row.ob > pia + for row in subject + ) + + +def _declared_widow_drc_protection_possible( + state, beneficiaries, params, payment_month +): + """Bound protection from the roster, then resolve each relevant row. + + One person's unresolved own benefit cannot invent a protected widow + or hide another person's independently settled disqualification. + Unresolved entitlement remains possible, using the canonical G rule. + """ + candidates = [b for b in beneficiaries if b.role not in _OUTSIDE_MAXIMUM] + + def possible_drc_basis(member): + return member.role in _WIDOW_ROLES and ( + ( + member.original_benefit_basis is not None + and member.original_benefit_basis > state.pia + ) + or any( + _hold_unsettles_fact( + hold, + "F4", + state, + member, + payment_month=payment_month, + beneficiaries=beneficiaries, + params=params, + ) + for hold in _declared_fact_holds(state, member) + ) ) + if len(candidates) <= 1 or not any(map(possible_drc_basis, candidates)): + return False + possible_count = 0 + possible_widow = False + for member in candidates: + try: + if not _fact_is_settled( + "F6", + state, + member, + payment_month=payment_month, + beneficiaries=beneficiaries, + params=params, + ): + possible_count += 1 + possible_widow |= possible_drc_basis(member) + continue + parent_count = ( + _entitled_parent_count(state, beneficiaries, params) + if member.role is Role.PARENT + else 1 + ) + row = _original_entitlement_rows( + state, + (_with_effective_cohort(member),), + params, + parent_count, + )[0] + subject = row.subject + except FamilyConfigurationUnsupported: + subject = True + if subject: + possible_count += 1 + possible_widow |= possible_drc_basis(member) + return possible_count > 1 and possible_widow + + +def _original_entitlement_rows( + state, beneficiaries, params, parent_count=None +): + """G's OB and own-benefit entitlement, before any family allocation.""" + if parent_count is None: + parent_count = _entitled_parent_count(state, beneficiaries, params) + rows = [] + for beneficiary in beneficiaries: + own_base = own_mba = None + if beneficiary.own_benefit is not None: + own_base, own_mba = _own_monthly_benefit_validated( + beneficiary.own_benefit, params + ) + ob = _original_benefit_validated( + beneficiary.role, + state.kind, + state.pia, + beneficiary.original_benefit_basis, + parent_count=( + parent_count if beneficiary.role is Role.PARENT else None + ), + ) + entitled, note = _is_entitled( + beneficiary, state.pia, own_mba, parent_ob=ob + ) + rows.append( + _Row( + beneficiary=beneficiary, + entitled=entitled, + subject=entitled and beneficiary.role not in _OUTSIDE_MAXIMUM, + ob=ob if entitled else Fraction(0), + own_base=own_base, + own_mba=own_mba, + note=note, + ) + ) + return rows + def _declared_worker_entitled(state: RecordState) -> bool: """Resolve NH entitlement from the record kind and declared condition. @@ -3588,36 +3984,9 @@ def _family_benefits( else: worker_benefit = state.pia - rows: list[_Row] = [] - for beneficiary in beneficiaries: - own_base = own_mba = None - if beneficiary.own_benefit is not None: - own_base, own_mba = _own_monthly_benefit_validated( - beneficiary.own_benefit, params - ) - ob = _original_benefit_validated( - beneficiary.role, - state.kind, - state.pia, - beneficiary.original_benefit_basis, - parent_count=( - parent_count if beneficiary.role is Role.PARENT else None - ), - ) - entitled, note = _is_entitled( - beneficiary, state.pia, own_mba, parent_ob=ob - ) - rows.append( - _Row( - beneficiary=beneficiary, - entitled=entitled, - subject=entitled and beneficiary.role not in _OUTSIDE_MAXIMUM, - ob=ob if entitled else Fraction(0), - own_base=own_base, - own_mba=own_mba, - note=note, - ) - ) + rows = _original_entitlement_rows( + state, beneficiaries, params, parent_count + ) _refuse_widow_drc_savings_clause(state, rows) available = state.family_maximum - (state.pia if life_case else 0) @@ -3920,20 +4289,65 @@ def _check_deduction_inputs( raise InvalidFamilyInput("Worker deductions must be nonnegative") +def _historical_widow_gross_bound_unsettled(state, member, payment_month): + """Declared legacy history does not establish an ordinary-OB gross cap. + + RS 00615.010's sole-survivor alternative can exceed ordinary WIB. + Its elimination depends on NH death and eligibility history, not just + the payment month. Preserve the existing refusal on a declared legacy + path; this does not compute that minimum or expand G's cash scope. + """ + if ( + state.kind is not FamilyKind.SURVIVOR + or member.role not in _WIDOW_ROLES + ): + return False + return ( + (state.eligibility_year is not None and state.eligibility_year < 1983) + or (payment_month.year, payment_month.month) < (1983, 1) + or ( + state.first_dib_entitlement is not None + and state.first_dib_entitlement + < _construct_declared(YearMonth, 1982, 1) + ) + or ( + state.deferred_refusal is not None + and state.deferred_refusal[0] + in { + UnsupportedReason.ELIGIBILITY_BEFORE_1983, + UnsupportedReason.DI_ENTITLEMENT_BEFORE_JULY_1980, + } + ) + ) + + def _check_deduction_amount_bounds( - state, beneficiaries, deductions, worker_deductions + state, beneficiaries, deductions, worker_deductions, params, payment_month ): """Reject impossible amounts before any statutory coverage refusal. - These entry points compute ordinary G from RecordState, before any - saving-clause guard. They cannot receive a carried protected rate. - The original benefit is therefore an upper bound on gross here - (GN 02603.050A). For a parent, the one-parent OB is the conservative - upper bound until a supported computation resolves entitlement/count. + Ordinary OB bounds gross only when the declared conditions settle + that upper bound (GN 02603.050A). Administrative finality can protect + a rate based on another PIA (RS 00615.754A.3); the historical + sole-survivor alternative can also exceed ordinary OB (RS 00615.010). + For a parent, the one-parent OB is the conservative upper bound until + a supported computation resolves entitlement/count. Own-work events need strictly positive withholding after NH reserves; - equality to this upper bound is impossible even on a refused record. + equality to a settled upper bound is impossible on a refused record. """ for member in beneficiaries: + if not _fact_is_settled( + "F4", + state, + member, + beneficiaries=beneficiaries, + params=params, + payment_month=payment_month, + original_benefit_upper_bound=True, + ) or _historical_widow_gross_bound_unsettled( + state, member, payment_month + ): + continue bid = member.beneficiary_id original = _original_benefit_validated( member.role, state.kind, state.pia, member.original_benefit_basis @@ -3999,7 +4413,12 @@ def family_benefits_after_deductions( params, ) _check_deduction_amount_bounds( - state, beneficiaries, deductions, worker_deductions + state, + beneficiaries, + deductions, + worker_deductions, + params, + payment_month, ) return _after_deductions( state, @@ -4663,7 +5082,12 @@ def household_benefits_after_deductions( record.state, record.beneficiaries, payment_month, params ) _check_deduction_amount_bounds( - record.state, record.beneficiaries, deductions, worker_deductions + record.state, + record.beneficiaries, + deductions, + worker_deductions, + params, + payment_month, ) results = {} family_refusals = [] diff --git a/src/populace_dynamics/track_b/ret_ledger.py b/src/populace_dynamics/track_b/ret_ledger.py index 0086de01b..11c27608c 100644 --- a/src/populace_dynamics/track_b/ret_ledger.py +++ b/src/populace_dynamics/track_b/ret_ledger.py @@ -31,10 +31,11 @@ survivor's current age. Contradictions error before coverage refusals. Every known cohort for one person agrees across monthly contexts, including record and own-benefit fields; missing cohorts add no constraint. -Declared NH entitlement and spouse eligibility under the raw own-PIA -threshold agree with RET before any G computation or held coverage refusal. -NH original benefits and DIB gross benefits copy the declared PIA directly; -those comparisons also precede G computation. +Declared NH entitlement agrees with RET before any coverage refusal. +Rate and own-benefit eligibility comparisons precede a held refusal only +when no declared condition can change that fact. G's explicit fact table +and canonical benefit helpers establish those comparisons; protected or +otherwise unresolved facts retain their original coverage refusal. Every raw month-set element must be an integer month before deduplication; malformed input raises before a coverage refusal can become an outcome. @@ -1144,6 +1145,128 @@ def _divorced_excluded(b: RETBeneficiary, month: int) -> bool: ) +def _check_settled_family_facts(record: RecordYear) -> None: + """Compare declarations only where G can establish the underlying fact. + + Entitlement to the NH benefit is an identity between declarations. + Money and own-benefit eligibility use G's canonical rules and its + condition table. A rule's coverage refusal leaves that fact unsettled; + an input error always propagates. Whole-family allocations stay after G. + """ + people = {b.beneficiary_id: b for b in record.beneficiaries} + # These identities hold even under protected monetary rates. + if record.kind is not RecordKind.DECEASED: + nh = people[record.nh_id] + for month, context in record.family_months.items(): + if g._declared_worker_entitled(context.state) != ( + month in nh.entitled_months + ): + raise InvalidFamilyInput( + "G and RET NH entitlement facts differ" + ) + for month, context in record.family_months.items(): + state = context.state + payment_month = _construct_declared(g.YearMonth, record.year, month) + + def settled( + fact, + member=None, + *, + state=state, + payment_month=payment_month, + context=context, + ): + return g._fact_is_settled( + fact, + state, + member, + payment_month=payment_month, + beneficiaries=context.beneficiaries, + params=context.params, + ) + + if record.kind is not RecordKind.DECEASED: + nh = people[record.nh_id] + if month in nh.entitled_months: + if settled("F1") and nh.original_rates[month - 1] != state.pia: + raise InvalidFamilyInput( + "G context does not match RET rates" + ) + if record.kind is RecordKind.DISABILITY: + if ( + settled("F2") + and nh.gross_rates[month - 1] != state.pia + ): + raise InvalidFamilyInput( + "G context does not match RET rates" + ) + elif settled("F3"): + try: + gross = g._own_monthly_benefit_validated( + state.worker, context.params + )[1] + except FamilyConfigurationUnsupported: + pass + else: + if nh.gross_rates[month - 1] != gross: + raise InvalidFamilyInput( + "G context does not match RET rates" + ) + parent_count = None + parent_count_known = False + for auxiliary in context.beneficiaries: + auxiliary = g._with_effective_cohort(auxiliary) + person = people[auxiliary.beneficiary_id] + original = None + if settled("F4", auxiliary) or settled("F6", auxiliary): + try: + if auxiliary.role is g.Role.PARENT: + if not parent_count_known: + parent_count = g._entitled_parent_count( + state, context.beneficiaries, context.params + ) + parent_count_known = True + original = g._original_benefit_validated( + auxiliary.role, + state.kind, + state.pia, + auxiliary.original_benefit_basis, + parent_count=( + parent_count + if auxiliary.role is g.Role.PARENT + else None + ), + ) + except FamilyConfigurationUnsupported: + pass + fact = "F5" if auxiliary.role in g._SPOUSE_ROLES else "F6" + if settled(fact, auxiliary) and not ( + auxiliary.role is g.Role.PARENT and original is None + ): + try: + own_mba = None + if auxiliary.own_benefit is not None and fact == "F6": + own_mba = g._own_monthly_benefit_validated( + auxiliary.own_benefit, context.params + )[1] + entitled, _ = g._is_entitled( + auxiliary, state.pia, own_mba, parent_ob=original + ) + except FamilyConfigurationUnsupported: + pass + else: + if not entitled: + raise InvalidFamilyInput( + "G and RET auxiliary entitlement facts differ" + ) + if ( + settled("F4", auxiliary) + and original is not None + and person.original_rates[month - 1] != original + ): + raise InvalidFamilyInput("G context does not match RET rates") + + @_validated_entry def apply_ret_year( record: RecordYear, @@ -1170,49 +1293,7 @@ def apply_ret_year( raise InvalidFamilyInput("Use an explicit NESE proration policy") if parameters is not None and not isinstance(parameters, RETParameters): raise InvalidFamilyInput("Use R1 RETParameters") - # Entitlement is a declared fact, including a zero-rate entitlement. - # Check every context before computing any G money or holding a refusal. - if record.kind is not RecordKind.DECEASED: - nh = next( - b for b in record.beneficiaries if b.beneficiary_id == record.nh_id - ) - for month, context in record.family_months.items(): - if g._declared_worker_entitled(context.state) != ( - month in nh.entitled_months - ): - raise InvalidFamilyInput( - "G and RET NH entitlement facts differ" - ) - if month in nh.entitled_months: - # G copies these NH facts directly from the declared PIA. - # RIB gross still needs G's age/DRC computation. - if nh.original_rates[month - 1] != context.state.pia: - raise InvalidFamilyInput( - "G context does not match RET rates" - ) - if ( - record.kind is RecordKind.DISABILITY - and nh.gross_rates[month - 1] != context.state.pia - ): - raise InvalidFamilyInput( - "G context does not match RET rates" - ) - # Act 202(b)(1)(D), (c)(1)(D); RS 00202.005: spouse eligibility uses - # raw own PIA, not a computed own MBA. Other own-benefit roles need G's - # computed MBA/OB, so their entitlement comparison stays after G. - for context in record.family_months.values(): - for auxiliary in context.beneficiaries: - if ( - auxiliary.own_benefit is None - or auxiliary.role in g._SPOUSE_ROLES - ): - entitled, _ = g._is_entitled( - auxiliary, context.state.pia, None - ) - if not entitled: - raise InvalidFamilyInput( - "G and RET auxiliary entitlement facts differ" - ) + _check_settled_family_facts(record) # Retain the G facts needed for money-changing readjustment. A caller's # reduced rates cannot identify age reductions or dual entitlement. held_family_refusals = [] diff --git a/tests/README-tiers.md b/tests/README-tiers.md index 5d0b93d3c..f71dfc565 100644 --- a/tests/README-tiers.md +++ b/tests/README-tiers.md @@ -39,9 +39,9 @@ pytest --collect-only -q -m oracle_policyengine | tail -1 | Tier | Tests at HEAD | |---|---:| -| `unit` | 20,495 | +| `unit` | 20,804 | | `artifact` | 4,271 | | `integration_psid` | 1,471 | | `reproduction_legacy` | 520 | | `oracle_policyengine` | 308 | -| **Total** | **27,065** | +| **Total** | **27,374** | diff --git a/tests/test_track_b_gross_benefits_deduction_cap.py b/tests/test_track_b_gross_benefits_deduction_cap.py index a91342c0c..a510f5fd6 100644 --- a/tests/test_track_b_gross_benefits_deduction_cap.py +++ b/tests/test_track_b_gross_benefits_deduction_cap.py @@ -1,7 +1,8 @@ """Statutory conformance: positive own-work events on invented records. -GN 02603.050A caps deduction-before-reduction rates at OB. Invalid events -precede coverage refusals and never enter the shared denominator. No +GN 02603.050A caps ordinary rates at a settled OB. Finality can protect a +rate based on another PIA (RS 00615.754A.3); those cases retain their named +refusal. Settled invalid events never enter the shared denominator. No population, behavioral or forecast claim. """ @@ -71,32 +72,49 @@ def compute( ) +def _expect_cap_classification(call, protected): + outcomes = [] + if protected: + outcomes.append(g.evaluate_family("protected cap", 7, call)) + assert outcomes[0].unsupported.reason is ( + g.UnsupportedReason.ADMINISTRATIVE_FINALITY + ) + counts = g.count_family_outcomes(outcomes) + assert (counts.rows, counts.weight, counts.unsupported_weight) == ( + 1, + 7, + 7, + ) + else: + with pytest.raises(g.InvalidFamilyInput, match="positive"): + outcomes.append(g.evaluate_family("settled cap", 7, call)) + counts = g.count_family_outcomes(outcomes) + assert (counts.rows, counts.weight) == (0, 0) + + @pytest.mark.parametrize("household", (False, True)) @pytest.mark.parametrize("combined", (False, True)) @pytest.mark.parametrize("reservation", (F(0), F(1))) @pytest.mark.parametrize("permanent", (False, True)) +@pytest.mark.parametrize("held", (False, True)) def test_own_event_at_ob_cap_errors_before_coverage_and_has_no_row( - household, combined, reservation, permanent + household, combined, reservation, permanent, held ): - outcomes = [] - with pytest.raises(g.InvalidFamilyInput, match="positive"): - outcomes.append( - g.evaluate_family( - "zero cap", - 7, - lambda: compute( - household=household, - combined=combined, - reservation=reservation, - permanent=permanent, - ), - ) - ) - assert g.count_family_outcomes(outcomes).rows == 0 + _expect_cap_classification( + lambda: compute( + household=household, + combined=combined, + reservation=reservation, + permanent=permanent, + held=held, + ), + protected=held and not combined, + ) @pytest.mark.parametrize("household", (False, True)) @pytest.mark.parametrize("combined", (False, True)) +@pytest.mark.parametrize("held", (False, True)) @settings(max_examples=20, deadline=None) @given( pia=st.integers(0, 100), @@ -104,31 +122,29 @@ def test_own_event_at_ob_cap_errors_before_coverage_and_has_no_row( reserved_fraction=st.fractions(min_value=0, max_value=1), ) def test_upper_bound_equality_is_invalid_for_every_exact_reservation( - household, combined, pia, role, reserved_fraction + household, combined, held, pia, role, reserved_fraction ): upper = g.original_benefit(role, g.FamilyKind.SURVIVOR, F(pia)) - outcomes = [] - with pytest.raises(g.InvalidFamilyInput, match="positive"): - outcomes.append( - g.evaluate_family( - "exact cap", - 7, - lambda: compute( - household=household, - combined=combined, - pia=F(pia), - role=role, - reservation=upper * reserved_fraction, - ), - ) - ) - assert g.count_family_outcomes(outcomes).rows == 0 + _expect_cap_classification( + lambda: compute( + household=household, + combined=combined, + pia=F(pia), + role=role, + reservation=upper * reserved_fraction, + held=held, + ), + protected=held and not combined, + ) @pytest.mark.parametrize("household", (False, True)) -def test_zero_pia_maximum_and_ob_cannot_hide_own_event(household): - with pytest.raises(g.InvalidFamilyInput, match="positive"): - compute(household=household, pia=F(0)) +@pytest.mark.parametrize("held", (False, True)) +def test_zero_pia_maximum_and_ob_cannot_hide_own_event(household, held): + _expect_cap_classification( + lambda: compute(household=household, pia=F(0), held=held), + protected=held, + ) @pytest.mark.parametrize("household", (False, True)) diff --git a/tests/test_track_b_gross_benefits_fix_round_4_composition.py b/tests/test_track_b_gross_benefits_fix_round_4_composition.py index 340d00705..ca79bb655 100644 --- a/tests/test_track_b_gross_benefits_fix_round_4_composition.py +++ b/tests/test_track_b_gross_benefits_fix_round_4_composition.py @@ -213,37 +213,61 @@ def test_outside_independence_with_nh_only_reservations( @pytest.mark.parametrize("household", (False, True)) -@pytest.mark.parametrize("held", (False, True)) +@pytest.mark.parametrize( + "held", (False, True, g.RecordCondition.NON_AIME_FORMULA_PIA) +) def test_nh_only_acceptance_still_rejects_impossible_reservation( household, held ): state, _ = state_and_members(F(400), F(600)) if held: state = replace( - state, conditions={g.RecordCondition.ADMINISTRATIVE_FINALITY} + state, + conditions={ + ( + g.RecordCondition.ADMINISTRATIVE_FINALITY + if held is True + else held + ) + }, ) members = [g.Beneficiary(name, g.Role.CHILD) for name in ("B", "C0")] for outside in (False, True): outcomes = [] - with pytest.raises(g.InvalidFamilyInput): - outcomes.append( - outcome( - state, - members + ([outside_member()] if outside else []), - ( - { - "D": g.BenefitDeduction( - g.DeductionReason.OWN_EARNINGS_TEST - ) - } - if outside - else {} - ), - household=household, - worker_deductions={"B": F(201)}, - ) + + def evaluate(outside=outside): + return outcome( + state, + members + ([outside_member()] if outside else []), + ( + { + "D": g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST + ) + } + if outside + else {} + ), + household=household, + worker_deductions={"B": F(201)}, + ) + + if held is True: + outcomes.append(evaluate()) + assert outcomes[0].unsupported.reason is ( + g.UnsupportedReason.ADMINISTRATIVE_FINALITY + ) + counts = g.count_family_outcomes(outcomes) + assert (counts.rows, counts.weight, counts.unsupported_weight) == ( + 1, + 7, + 7, ) - assert g.count_family_outcomes(outcomes).rows == 0 + else: + with pytest.raises(g.InvalidFamilyInput): + outcomes.append(evaluate()) + counts = g.count_family_outcomes(outcomes) + assert (counts.rows, counts.weight) == (0, 0) @pytest.mark.parametrize("household", (False, True)) diff --git a/tests/test_track_b_ret_ledger_fix_round_4.py b/tests/test_track_b_ret_ledger_fix_round_4.py index 50ad3adfd..8ba1d5a02 100644 --- a/tests/test_track_b_ret_ledger_fix_round_4.py +++ b/tests/test_track_b_ret_ledger_fix_round_4.py @@ -602,6 +602,22 @@ def _spouse_entitlement_case( ) +def _expect_fact_classification(call, fact, held, message): + """Round 5: a protected fact retains its precise counted refusal.""" + unsettled = held is g.RecordCondition.ADMINISTRATIVE_FINALITY or ( + held is g.RecordCondition.WORKERS_COMPENSATION_OFFSET and fact == "F2" + ) + if not unsettled: + _expect_no_row(call, message) + return + outcome = r.evaluate_ret("protected-fact", 7, call) + denominator = r.count_ret_outcomes([outcome]) + assert not outcome.supported + assert outcome.unsupported.reason is g._RECORD_CONDITION_REASONS[held][0] + assert (denominator.rows, denominator.weight) == (1, 7) + assert denominator.unsupported_weight == 7 + + @pytest.mark.parametrize("role", SPOUSE_ROLES) @pytest.mark.parametrize("own_kind", list(g.OwnBenefitKind)) @pytest.mark.parametrize("money", [0, 4]) @@ -612,7 +628,7 @@ def _spouse_entitlement_case( def test_declared_spouse_pia_disqualification_precedes_held_refusal( role, own_kind, money, held, reverse ): - _expect_no_row( + _expect_fact_classification( lambda: r.apply_ret_year( _spouse_entitlement_case( role, @@ -623,6 +639,8 @@ def test_declared_spouse_pia_disqualification_precedes_held_refusal( ), PARAMS, ), + "F5", + held, "G and RET auxiliary entitlement facts differ", ) @@ -692,7 +710,7 @@ def test_no_held_coverage_condition_masks_spouse_pia_contradiction( role, own_kind, scale, extra, month, held, reverse ): for condition in (None, held): - _expect_no_row( + _expect_fact_classification( lambda condition=condition: r.apply_ret_year( _spouse_entitlement_case( role, @@ -705,6 +723,8 @@ def test_no_held_coverage_condition_masks_spouse_pia_contradiction( ), PARAMS, ), + "F5", + condition, "G and RET auxiliary entitlement facts differ", ) @@ -800,7 +820,7 @@ def _direct_nh_rate_case(kind, pia, declared, *, month=1, held=None): def test_declared_nh_original_pia_mismatch_precedes_held_refusal( pia, month, held ): - _expect_no_row( + _expect_fact_classification( lambda: r.apply_ret_year( _direct_nh_rate_case( "original", @@ -811,6 +831,8 @@ def test_declared_nh_original_pia_mismatch_precedes_held_refusal( ), PARAMS, ), + "F1", + held, "G context does not match RET rates", ) @@ -823,7 +845,7 @@ def test_declared_nh_original_pia_mismatch_precedes_held_refusal( def test_declared_dib_nh_gross_pia_mismatch_precedes_held_refusal( gross, month, held ): - _expect_no_row( + _expect_fact_classification( lambda: r.apply_ret_year( _direct_nh_rate_case( "dib_gross", @@ -834,6 +856,8 @@ def test_declared_dib_nh_gross_pia_mismatch_precedes_held_refusal( ), PARAMS, ), + "F2", + held, "G context does not match RET rates", ) @@ -910,13 +934,15 @@ def test_no_held_coverage_condition_masks_direct_nh_rate_contradiction( pia = 4 * scale declared = F(pia) + direction * F(gap, 10) for condition in (None, held): - _expect_no_row( + _expect_fact_classification( lambda condition=condition: r.apply_ret_year( _direct_nh_rate_case( kind, pia, declared, month=month, held=condition ), PARAMS, ), + ("F1" if kind == "original" else "F2"), + condition, "G context does not match RET rates", ) diff --git a/tests/test_track_b_ret_ledger_fix_round_5.py b/tests/test_track_b_ret_ledger_fix_round_5.py new file mode 100644 index 000000000..895d2036c --- /dev/null +++ b/tests/test_track_b_ret_ledger_fix_round_5.py @@ -0,0 +1,1910 @@ +"""Round 5: settled facts before coverage, invented-data conformance only. + +Protected rates remain counted refusals. Contradictions in settled facts +never become rows. No population, behavioral or forecast claim is admitted. +""" + +from __future__ import annotations + +import hashlib +import html +import json +import re +from dataclasses import replace +from fractions import Fraction as F +from pathlib import Path + +import pytest +from hypothesis import example, given, settings +from hypothesis import strategies as st + +from populace_dynamics.track_b import gross_benefits as g +from populace_dynamics.track_b import ret_ledger as r +from populace_dynamics.track_b.ret_grace import BenefitType as T +from populace_dynamics.track_b.ret_params import load_ret_parameters +from tests.track_b_gross_benefit_support import ( + SOURCES, + manifest, + source_text, + ssa_params, +) + +PARAMS = load_ret_parameters() +FACTS = ("F1", "F2", "F3", "F4", "F5", "F6") +RC = g.RecordCondition +BC = g.BeneficiaryCondition +UR = g.UnsupportedReason +RECORD_HOLDS = ( + RC.ADMINISTRATIVE_FINALITY, + RC.DIB_AFTER_REDUCED_RIB, + RC.WORKERS_COMPENSATION_OFFSET, + RC.DIB_GUARANTEE_PIA, + RC.NON_AIME_FORMULA_PIA, +) +BENEFICIARY_HOLDS = tuple(BC) + + +def _person(key, kind, gross, original, month): + return r.RETBeneficiary( + key, + (kind,) * 12, + {month}, + tuple(F(gross) if m == month else F(0) for m in range(1, 13)), + (F(original),) * 12, + fra_month=0, + ) + + +def _case(fact, money=4, *, month=1, held=None, contradiction=False): + """Keep every declaration except the selected fact consistent.""" + pia = F(money) + if contradiction and money == 0 and fact in ("F2", "F3"): + # The minimized review row has zero gross against a $.10 PIA. + pia = F(1, 10) + deceased = fact == "F6" + disability = fact == "F2" + kind = ( + g.FamilyKind.SURVIVOR + if deceased + else ( + g.FamilyKind.DISABILITY if disability else g.FamilyKind.RETIREMENT + ) + ) + conditions = {held} if isinstance(held, RC) else set() + state = g.RecordState( + kind, + pia, + g.floor_dime(pia * (2 if deceased else F(3, 2))), + worker=( + g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, pia) + if kind is g.FamilyKind.RETIREMENT + else None + ), + widow_drc_savings_clause=False if deceased else None, + conditions=conditions, + ) + people = [] + members = [] + if not deceased: + gross = pia + original = pia + if contradiction and fact == "F1": + original += F(1, 10) + if contradiction and fact in ("F2", "F3"): + # Zero money still admits a rate contradiction without a + # positive-gross/zero-original constructor contradiction. + gross = pia - (F(1) if fact == "F3" and money else F(1, 10)) + people.append( + _person( + "nh", T.DIB if disability else T.RIB, gross, original, month + ) + ) + if fact in ("F4", "F5", "F6") or isinstance(held, BC): + role = ( + g.Role.WIDOW + if deceased + else (g.Role.SPOUSE if fact == "F5" else g.Role.CHILD) + ) + own = None + if contradiction and fact in ("F5", "F6"): + own = g.OwnBenefit( + g.OwnBenefitKind.OLD_AGE, + pia / 2 if fact == "F5" else pia, + ) + member = g.Beneficiary( + "a", + role, + own_benefit=own, + own_benefit_first=( + True if own is not None and fact == "F5" else None + ), + birth_year=1950 if deceased else None, + child_in_care=False if deceased else None, + conditions={held} if isinstance(held, BC) else (), + ) + members.append(member) + original = pia if deceased else g.floor_dime(pia / 2) + gross = F(0) if own is not None else original + if contradiction and fact == "F4": + original += F(1, 10) + people.append( + _person( + "a", + ( + T.WIDOW + if deceased + else (T.SPOUSE if fact == "F5" else T.CHILD) + ), + gross, + original, + month, + ) + ) + return r.RecordYear( + 2023 if held is BC.GOVERNMENT_PENSION_OFFSET else 2024, + "nh", + ( + r.RecordKind.DECEASED + if deceased + else ( + r.RecordKind.DISABILITY + if disability + else r.RecordKind.RETIREMENT + ) + ), + tuple(people), + family_months={ + month: r.RETFamilyMonth( + state, + tuple(members), + ssa_params(), + {m.beneficiary_id: "h" for m in members}, + ) + }, + fiscal_year=held == "fiscal_year", + ) + + +def _outcome(case): + return r.evaluate_ret( + "round5", F(7), lambda: r.apply_ret_year(case, PARAMS) + ) + + +def _assert_refusal(case, reason): + outcome = _outcome(case) + assert not outcome.supported + assert outcome.unsupported.reason is reason + counts = r.count_ret_outcomes([outcome]) + assert (counts.rows, counts.weight, counts.unsupported_weight) == (1, 7, 7) + assert (g.count_family_outcomes([outcome]).rows) == 1 + + +def _assert_invalid(case): + rows = [] + with pytest.raises(g.InvalidFamilyInput): + rows.append(_outcome(case)) + counts = r.count_ret_outcomes(rows) + assert (counts.rows, counts.weight) == (0, 0) + + +def _unsettled(fact, held): + """The held condition's scope on the record built by ``_case``.""" + return ( + held is RC.ADMINISTRATIVE_FINALITY + or held is BC.RATE_PROTECTED_BY_FINALITY + and fact in ("F4", "F5", "F6") + or held is RC.DIB_AFTER_REDUCED_RIB + and fact == "F2" + or held is RC.WORKERS_COMPENSATION_OFFSET + and fact in ("F2", "F3") + ) + + +def _reason(held): + if isinstance(held, RC): + return g._RECORD_CONDITION_REASONS[held][0] + if isinstance(held, BC): + return g._BENEFICIARY_CONDITION_REASONS[held][0] + return r.RETUnsupportedReason.FISCAL_YEAR + + +@pytest.mark.parametrize("fact", FACTS) +@pytest.mark.parametrize("money", [0, 4]) +@pytest.mark.parametrize( + "held", + [None, RC.ADMINISTRATIVE_FINALITY, RC.NON_AIME_FORMULA_PIA, "fiscal_year"], +) +def test_each_fact_contradiction_is_classified_by_its_declared_condition( + fact, money, held +): + case = _case(fact, money, held=held, contradiction=True) + if _unsettled(fact, held): + _assert_refusal(case, _reason(held)) + else: + _assert_invalid(case) + + +@pytest.mark.parametrize( + "held,gross", + [(RC.DIB_AFTER_REDUCED_RIB, 800), (RC.WORKERS_COMPENSATION_OFFSET, 600)], +) +def test_lawful_dib_gross_changes_remain_counted_refusals(held, gross): + case = _case("F2", 1000, held=held) + case = replace( + case, + beneficiaries=( + replace( + case.beneficiaries[0], gross_rates=(F(gross),) + (F(0),) * 11 + ), + ), + ) + _assert_refusal(case, _reason(held)) + + +@pytest.mark.parametrize("fact", ["F3", "F4", "F6"]) +@pytest.mark.parametrize("money", [0, 4]) +@pytest.mark.parametrize( + "held", + [ + RC.ADMINISTRATIVE_FINALITY, + RC.NON_AIME_FORMULA_PIA, + BC.ENTITLED_ON_ANOTHER_RECORD, + "fiscal_year", + ], +) +def test_review_counterexamples_follow_finality_ruling(fact, money, held): + case = _case(fact, money, held=held, contradiction=True) + if held is RC.ADMINISTRATIVE_FINALITY: + _assert_refusal(case, UR.ADMINISTRATIVE_FINALITY) + else: + _assert_invalid(case) + + +@pytest.mark.parametrize("fact", ["F4", "F5", "F6"]) +def test_beneficiary_finality_protects_its_own_unsettled_fact(fact): + _assert_refusal( + _case(fact, held=BC.RATE_PROTECTED_BY_FINALITY, contradiction=True), + UR.ADMINISTRATIVE_FINALITY, + ) + + +@pytest.mark.parametrize("fact", ["F1", "F3"]) +def test_one_beneficiary_finality_does_not_protect_the_nh(fact): + _assert_invalid( + _case(fact, held=BC.RATE_PROTECTED_BY_FINALITY, contradiction=True) + ) + + +def test_first_administrative_finality_example_keeps_nh_rate(): + case = _case("F4", 750, held=RC.ADMINISTRATIVE_FINALITY) + context = case.family_months[1] + case = replace( + case, + beneficiaries=( + replace( + case.beneficiaries[0], + gross_rates=(F(1000),) + (F(0),) * 11, + original_rates=(F(1000),) * 12, + ), + replace( + case.beneficiaries[1], + gross_rates=(F("375.50"),) + (F(0),) * 11, + original_rates=(F("375.50"),) * 12, + ), + ), + family_months={ + 1: replace( + context, + state=replace(context.state, family_maximum=F("1312.50")), + ) + }, + ) + _assert_refusal(case, UR.ADMINISTRATIVE_FINALITY) + + +def test_second_administrative_finality_example_keeps_two_protected_rates(): + state = g.RecordState( + g.FamilyKind.RETIREMENT, + F(750), + F("1312.50"), + worker=g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, F(750)), + conditions={RC.ADMINISTRATIVE_FINALITY}, + ) + members = ( + g.Beneficiary( + "old", g.Role.CHILD, conditions={BC.RATE_PROTECTED_BY_FINALITY} + ), + g.Beneficiary("new", g.Role.CHILD), + ) + case = r.RecordYear( + 2024, + "nh", + beneficiaries=( + _person("nh", T.RIB, 1000, 1000, 1), + _person("old", T.CHILD, 375, 500, 1), + _person("new", T.CHILD, F("281.20"), 375, 1), + ), + family_months={ + 1: r.RETFamilyMonth( + state, members, ssa_params(), {"old": "h", "new": "h"} + ) + }, + family_maximum_binding_months={1}, + ) + _assert_refusal(case, UR.ADMINISTRATIVE_FINALITY) + + +def test_finality_examples_are_verbatim_and_the_capture_hash_matches(): + source_id = "poms_rs_00615_754" + entry = next( + row for row in manifest()["sources"] if row["id"] == source_id + ) + assert ( + hashlib.sha256((SOURCES / entry["file"]).read_bytes()).hexdigest() + == entry["sha256"] + ) + text = source_text(source_id) + quotes = ( + "the correct PIA is really $750.00 with a maximum of $1,312.50.", + "the rate to the NH is protected by administrative finality and cannot be changed.", + "to show the PIA and maximum used to arrive at those rates.", + "The rates payable will then be $1,000.00 to the NH and $375.50 to the new child.", + "The total payable to the family will then be $1,375.50", + "the rates to the NH and the first child are protected by administrative finality and must be based on the protected PIA and maximum.", + "$1,750 minus $1,000 is $750 divided by 2 or $375.00.", + "We divide that by the number of children (2) and get $281.20 as the correct rate for the new child.", + "$1,000.00 to the NH, $375.00 to the first child and $281.20 to the new child.", + "The total payable to the family will then be $1,656.20", + ) + for quote in quotes: + assert quote in text + # These are the published declarations, preserved as refusals; the + # capture's $375.50 is not silently replaced by half of $750. + assert F(1000) + F("375.50") == F("1375.50") + assert F(1000) + F(375) + F("281.20") == F("1656.20") + + +def test_fact_table_explicitly_covers_all_conditions_and_held_g_reasons(): + table = g._PREFLIGHT_FACT_UNSETTLERS + assert set(table) == set(RC) | set(BC) | set(UR) + assert all( + type(facts) is frozenset and facts <= set(FACTS) + for facts in table.values() + ) + for held in (*RECORD_HOLDS, *BENEFICIARY_HOLDS): + expected = ( + frozenset({"F4"}) + if held is BC.WIDOW_DRC_SAVINGS_CLAUSE + else frozenset(fact for fact in FACTS if _unsettled(fact, held)) + ) + assert table[held] == expected + + +def test_spouse_sequence_condition_does_not_unsettle_other_own_eligibility(): + _assert_invalid( + _case( + "F6", + held=BC.DIB_BETWEEN_SPOUSE_BENEFIT_AND_RIB, + contradiction=True, + ) + ) + + +@settings(max_examples=90, deadline=None) +@given( + fact=st.sampled_from(FACTS), + held=st.sampled_from((*RECORD_HOLDS, *BENEFICIARY_HOLDS, "fiscal_year")), + money=st.integers(0, 30).map(lambda n: n * 4), + month=st.integers(1, 12), +) +@example(fact="F2", held=RC.DIB_AFTER_REDUCED_RIB, money=4, month=12) +@example(fact="F3", held=RC.WORKERS_COMPENSATION_OFFSET, money=4, month=1) +@example(fact="F4", held=BC.RATE_PROTECTED_BY_FINALITY, money=0, month=6) +@example(fact="F1", held=RC.NON_AIME_FORMULA_PIA, money=4, month=1) +@example(fact="F4", held=BC.WIDOW_DRC_SAVINGS_CLAUSE, money=4, month=12) +@example( + fact="F6", + held=BC.DIB_BETWEEN_SPOUSE_BENEFIT_AND_RIB, + money=4, + month=1, +) +def test_held_against_unheld_fact_classification(fact, held, money, month): + _assert_invalid(_case(fact, money, month=month, contradiction=True)) + held_case = _case(fact, money, month=month, held=held, contradiction=True) + if _unsettled(fact, held): + _assert_refusal(held_case, _reason(held)) + else: + _assert_invalid(held_case) + + +@settings(max_examples=70, deadline=None) +@given( + fact=st.sampled_from(FACTS), + held=st.sampled_from( + (None, *RECORD_HOLDS, *BENEFICIARY_HOLDS, "fiscal_year") + ), + money=st.integers(0, 30).map(lambda n: n * 4), + month=st.integers(1, 12), +) +def test_matching_declarations_never_raise_input_errors( + fact, held, money, month +): + outcome = _outcome(_case(fact, money, month=month, held=held)) + counts = r.count_ret_outcomes([outcome]) + assert (counts.rows, counts.weight) == (1, 7) + assert outcome.supported == (held is None) + if held is not None: + assert outcome.unsupported.reason is _reason(held) + + +@pytest.mark.parametrize("fact", FACTS) +@pytest.mark.parametrize("money", [0, 4]) +@pytest.mark.parametrize("contradiction", [False, True]) +def test_wep_declaration_alone_changes_none_of_the_six_facts( + fact, money, contradiction +): + case = _case(fact, money, contradiction=contradiction) + context = case.family_months[1] + state = replace( + context.state, conditions={RC.WINDFALL_ELIMINATION_PROVISION} + ) + case = replace(case, family_months={1: replace(context, state=state)}) + if contradiction: + _assert_invalid(case) + return + outcome = _outcome(case) + assert outcome.supported + assert r.count_ret_outcomes([outcome]).supported_weight == 7 + + +@pytest.mark.parametrize("money", [0, 4]) +def test_worker_not_entitled_declares_an_ieds_record_without_nh_rate(money): + state = g.RecordState( + g.FamilyKind.RETIREMENT, + F(money), + F(3 * money, 2), + conditions={RC.WORKER_NOT_ENTITLED}, + ) + member = g.Beneficiary( + "a", + g.Role.DIVORCED_SPOUSE, + child_in_care=False, + first_entitlement_child_in_care=False, + ) + case = r.RecordYear( + 2024, + "nh", + beneficiaries=( + replace(_person("nh", T.RIB, 0, money, 1), entitled_months=()), + _person("a", T.DIVORCED_SPOUSE, F(money, 2), F(money, 2), 1), + ), + family_months={ + 1: r.RETFamilyMonth(state, (member,), ssa_params(), {"a": "h"}) + }, + ) + outcome = _outcome(case) + assert outcome.supported + assert r.count_ret_outcomes([outcome]).supported_weight == 7 + + +@pytest.mark.parametrize("fact", ["F4", "F5"]) +@pytest.mark.parametrize("money", [0, 4]) +@pytest.mark.parametrize("wep", [False, True]) +def test_ieds_does_not_mask_settled_auxiliary_facts(fact, money, wep): + state = g.RecordState( + g.FamilyKind.RETIREMENT, + F(money), + F(3 * money, 2), + conditions={RC.WORKER_NOT_ENTITLED} + | ({RC.WINDFALL_ELIMINATION_PROVISION} if wep else set()), + ) + own = ( + g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, F(money, 2)) + if fact == "F5" + else None + ) + member = g.Beneficiary( + "a", + g.Role.DIVORCED_SPOUSE, + own_benefit=own, + own_benefit_first=True if own else None, + child_in_care=False, + first_entitlement_child_in_care=False, + ) + original = F(money, 2) + (F(1, 10) if fact == "F4" else 0) + case = r.RecordYear( + 2023, + "nh", + beneficiaries=( + replace(_person("nh", T.RIB, 0, money, 1), entitled_months=()), + _person( + "a", T.DIVORCED_SPOUSE, 0 if own else F(money, 2), original, 1 + ), + ), + family_months={ + 1: r.RETFamilyMonth(state, (member,), ssa_params(), {"a": "h"}) + }, + ) + _assert_invalid(case) + + +def test_implicit_widow_history_remains_unsettled_behind_explicit_hold(): + case = _case("F6", held=BC.ENTITLED_ON_ANOTHER_RECORD, contradiction=True) + context = case.family_months[1] + member = replace(context.beneficiaries[0], birth_year=1920) + case = replace( + case, family_months={1: replace(context, beneficiaries=(member,))} + ) + _assert_refusal(case, UR.COMBINED_FAMILY_MAXIMUM) + + +@settings(max_examples=60, deadline=None) +@given( + fact=st.sampled_from(FACTS), + held=st.sampled_from( + (None, *RECORD_HOLDS, *BENEFICIARY_HOLDS, "fiscal_year") + ), + money=st.integers(0, 15).map(lambda n: n * 4), + month=st.integers(1, 12), +) +def test_preflight_changes_no_valid_outcome_or_refusal( + fact, held, money, month +): + case = _case(fact, money, month=month, held=held) + actual = _outcome(case) + with pytest.MonkeyPatch.context() as patch: + patch.setattr(r, "_check_settled_family_facts", lambda record: None) + without = _outcome(case) + assert actual.supported == without.supported + if actual.supported: + assert actual.ledger == without.ledger + else: + assert actual.unsupported.reason is without.unsupported.reason + assert actual.unsupported.detail == without.unsupported.detail + assert r.count_ret_outcomes([actual]) == r.count_ret_outcomes([without]) + + +def test_historical_rib_gross_rule_refusal_leaves_original_reason(): + case = _case("F3", contradiction=True) + context = case.family_months[1] + state = replace( + context.state, + worker=g.OwnBenefit( + g.OwnBenefitKind.OLD_AGE, F(4), reduction_months=1, birth_year=1915 + ), + ) + case = replace(case, family_months={1: replace(context, state=state)}) + _assert_refusal(case, UR.OWN_RIB_HISTORY_BEFORE_1978) + + +def test_two_declared_conditions_preserve_finality_protection(): + case = _case("F1", held=RC.NON_AIME_FORMULA_PIA, contradiction=True) + context = case.family_months[1] + state = replace( + context.state, + conditions={RC.NON_AIME_FORMULA_PIA, RC.ADMINISTRATIVE_FINALITY}, + ) + _assert_refusal( + replace(case, family_months={1: replace(context, state=state)}), + UR.ADMINISTRATIVE_FINALITY, + ) + + +@pytest.mark.parametrize("contradiction_in_unprotected_month", [False, True]) +def test_finality_is_resolved_for_each_month( + contradiction_in_unprotected_month, +): + first = _case("F1", held=RC.ADMINISTRATIVE_FINALITY, contradiction=True) + second = _case( + "F1", month=2, contradiction=contradiction_in_unprotected_month + ) + rates = list(first.beneficiaries[0].original_rates) + rates[1] = second.beneficiaries[0].original_rates[1] + person = replace( + first.beneficiaries[0], + entitled_months={1, 2}, + gross_rates=(F(4), F(4)) + (F(0),) * 10, + original_rates=tuple(rates), + ) + case = replace( + first, + beneficiaries=(person,), + family_months={**first.family_months, **second.family_months}, + ) + if contradiction_in_unprotected_month: + _assert_invalid(case) + else: + _assert_refusal(case, UR.ADMINISTRATIVE_FINALITY) + + +def test_protected_auxiliary_does_not_protect_another_auxiliary(): + case = _case("F4", held=BC.RATE_PROTECTED_BY_FINALITY, contradiction=True) + context = case.family_months[1] + other = g.Beneficiary("other", g.Role.CHILD) + state = replace(context.state, family_maximum=F(8)) + case = replace( + case, + beneficiaries=case.beneficiaries + + (_person("other", T.CHILD, 2, F("2.10"), 1),), + family_months={ + 1: r.RETFamilyMonth( + state, + context.beneficiaries + (other,), + context.params, + {"a": "h", "other": "h"}, + ) + }, + ) + _assert_invalid(case) + + +@pytest.mark.parametrize( + "fact,helper", + [ + ("F3", "_own_monthly_benefit_validated"), + ("F4", "_original_benefit_validated"), + ], +) +def test_canonical_input_error_is_never_caught_as_a_coverage_refusal( + monkeypatch, fact, helper +): + case = _case(fact, held=RC.NON_AIME_FORMULA_PIA) + + def invalid_rule(*args, **kwargs): + raise g.InvalidFamilyInput("canonical fact rule rejected the input") + + monkeypatch.setattr(g, helper, invalid_rule) + with pytest.raises( + g.InvalidFamilyInput, match="canonical fact rule rejected" + ): + _outcome(case) + + +@pytest.mark.parametrize( + "role,kind", + [(g.Role.WIDOW, T.WIDOW), (g.Role.MOTHER_FATHER, T.MOTHER_FATHER)], +) +@pytest.mark.parametrize( + "held", [None, RC.NON_AIME_FORMULA_PIA, RC.ADMINISTRATIVE_FINALITY] +) +def test_other_own_entitlement_uses_real_reduced_monthly_benefit( + role, kind, held +): + state = g.RecordState( + g.FamilyKind.SURVIVOR, F(20), F(40), widow_drc_savings_clause=False + ) + member = g.Beneficiary( + "a", + role, + own_benefit=g.OwnBenefit( + g.OwnBenefitKind.OLD_AGE, + F(20 if role is g.Role.WIDOW else 19), + reduction_months=48, + birth_year=1950, + ), + birth_year=1950, + child_in_care=False if role is g.Role.WIDOW else None, + ) + baseline = g.family_benefits( + state, + (member,), + payment_month=g.YearMonth(2024, 1), + params=ssa_params(), + standalone=True, + ) + row = baseline.by_id()["a"] + assert row.entitled + assert row.own_benefit == (15 if role is g.Role.WIDOW else F("14.20")) + state = replace(state, conditions={held} if held else ()) + case = r.RecordYear( + 2024, + "nh", + r.RecordKind.DECEASED, + (_person("a", kind, row.auxiliary_payable, row.original_benefit, 1),), + family_months={ + 1: r.RETFamilyMonth(state, (member,), ssa_params(), {"a": "h"}) + }, + ) + outcome = _outcome(case) + assert r.count_ret_outcomes([outcome]).weight == 7 + assert outcome.supported == (held is None) + if held: + assert outcome.unsupported.reason is _reason(held) + + +@pytest.mark.parametrize("household", [False, True]) +@pytest.mark.parametrize( + "protection", [RC.ADMINISTRATIVE_FINALITY, BC.RATE_PROTECTED_BY_FINALITY] +) +@pytest.mark.parametrize( + "payable,reserved", + [(F(375), F(0)), (F(400), F(0)), (F(200), F(200)), (F(0), F(400))], +) +def test_protected_deduction_rate_is_not_bounded_by_correct_pia_ob( + household, protection, payable, reserved +): + state = g.RecordState( + g.FamilyKind.RETIREMENT, + F(750), + F("1312.50"), + worker=g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, F(750)), + conditions={protection} if isinstance(protection, RC) else (), + ) + member = g.Beneficiary( + "c", + g.Role.CHILD, + conditions={protection} if isinstance(protection, BC) else (), + ) + deductions = { + "c": g.BenefitDeduction(g.DeductionReason.OWN_EARNINGS_TEST, payable) + } + kwargs = dict( + payment_month=g.YearMonth(2024, 1), + params=ssa_params(), + deductions=deductions, + households={"c": "h"}, + worker_deductions={"c": reserved}, + ) + + def compute(): + if household: + return g.household_benefits_after_deductions( + {"record": g.HouseholdRecord("nh", state, (member,))}, **kwargs + ) + return g.family_benefits_after_deductions( + state, (member,), standalone=True, **kwargs + ) + + outcome = g.evaluate_family("protected-deduction", 7, compute) + assert outcome.unsupported.reason is UR.ADMINISTRATIVE_FINALITY + counts = g.count_family_outcomes([outcome]) + assert (counts.rows, counts.weight, counts.unsupported_weight) == (1, 7, 7) + + +@pytest.mark.parametrize("household", [False, True]) +def test_disqualified_widow_does_not_unsettle_a_child_original_benefit( + household, +): + state = g.RecordState( + g.FamilyKind.SURVIVOR, F(4), F(6), eligibility_year=2020 + ) + members = ( + g.Beneficiary( + "w", + g.Role.WIDOW, + birth_year=1950, + original_benefit_basis=F(8), + own_benefit=g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, F(8)), + child_in_care=False, + ), + g.Beneficiary("c", g.Role.CHILD), + ) + baseline = g.family_benefits( + state, + members, + payment_month=g.YearMonth(2024, 1), + params=ssa_params(), + standalone=True, + ) + assert not baseline.by_id()["w"].entitled + assert baseline.by_id()["c"].original_benefit == 3 + kwargs = dict( + payment_month=g.YearMonth(2024, 1), + params=ssa_params(), + deductions={ + "c": g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST, F("3.10") + ) + }, + households={"w": "h", "c": "h"}, + ) + + def compute(): + if household: + return g.household_benefits_after_deductions( + {"record": g.HouseholdRecord("nh", state, members)}, **kwargs + ) + return g.family_benefits_after_deductions( + state, members, standalone=True, **kwargs + ) + + outcomes = [] + with pytest.raises(g.InvalidFamilyInput): + outcomes.append(g.evaluate_family("settled-child", 7, compute)) + counts = g.count_family_outcomes(outcomes) + assert (counts.rows, counts.weight) == (0, 0) + + +@pytest.mark.parametrize( + "path", ["ret", "deduction", "deduction_disqualified_widow"] +) +def test_unrelated_refused_child_does_not_invent_widow_protection(path): + state = g.RecordState( + g.FamilyKind.SURVIVOR, F(4), F(8), eligibility_year=2024 + ) + members = ( + g.Beneficiary( + "a", + g.Role.CHILD, + own_benefit=g.OwnBenefit( + g.OwnBenefitKind.DISABILITY, F(1), reduction_months=1 + ), + ), + g.Beneficiary("b", g.Role.CHILD), + ) + if path == "deduction_disqualified_widow": + members += ( + g.Beneficiary( + "w", + g.Role.WIDOW, + birth_year=1950, + original_benefit_basis=F(5), + own_benefit=g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, F(5)), + child_in_care=False, + ), + ) + if path == "ret": + case = r.RecordYear( + 2024, + "nh", + r.RecordKind.DECEASED, + ( + _person("a", T.CHILD, 0, 3, 1), + _person("b", T.CHILD, 3, F("3.10"), 1), + ), + family_months={ + 1: r.RETFamilyMonth( + state, members, ssa_params(), {"a": "h", "b": "h"} + ) + }, + ) + _assert_invalid(case) + return + + def compute(): + return g.family_benefits_after_deductions( + state, + members, + payment_month=g.YearMonth(2024, 1), + params=ssa_params(), + standalone=True, + households={member.beneficiary_id: "h" for member in members}, + deductions={ + "b": g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST, F("3.10") + ) + }, + ) + + outcomes = [] + with pytest.raises(g.InvalidFamilyInput): + outcomes.append(g.evaluate_family("no-widow", 7, compute)) + counts = g.count_family_outcomes(outcomes) + assert (counts.rows, counts.weight) == (0, 0) + + +@pytest.mark.parametrize( + "held", [None, RC.NON_AIME_FORMULA_PIA, RC.ADMINISTRATIVE_FINALITY] +) +def test_widow_own_cohort_alone_matches_the_resolved_cohort_control(held): + state = g.RecordState( + g.FamilyKind.SURVIVOR, + F(4), + F(8), + widow_drc_savings_clause=False, + conditions={held} if held else (), + ) + member = g.Beneficiary( + "w", + g.Role.WIDOW, + own_benefit=g.OwnBenefit( + g.OwnBenefitKind.OLD_AGE, F(1), birth_year=1950 + ), + child_in_care=False, + ) + case = r.RecordYear( + 2024, + "nh", + r.RecordKind.DECEASED, + (_person("w", T.WIDOW, 3, 4, 1),), + family_months={ + 1: r.RETFamilyMonth(state, (member,), ssa_params(), {"w": "h"}) + }, + ) + outcome = _outcome(case) + context = case.family_months[1] + control = _outcome( + replace( + case, + family_months={ + 1: replace( + context, beneficiaries=(replace(member, birth_year=1950),) + ) + }, + ) + ) + assert outcome.supported == control.supported == (held is None) + assert r.count_ret_outcomes([outcome]).weight == 7 + if held: + assert ( + outcome.unsupported.reason + is control.unsupported.reason + is _reason(held) + ) + else: + assert outcome.ledger == control.ledger + + +def test_auxiliary_cohort_supplies_own_rib_historical_refusal(): + state = g.RecordState( + g.FamilyKind.SURVIVOR, F(4), F(8), widow_drc_savings_clause=False + ) + member = g.Beneficiary( + "a", + g.Role.MOTHER_FATHER, + birth_year=1915, + own_benefit=g.OwnBenefit( + g.OwnBenefitKind.OLD_AGE, F(4), reduction_months=1 + ), + ) + case = r.RecordYear( + 2024, + "nh", + r.RecordKind.DECEASED, + (_person("a", T.MOTHER_FATHER, 0, 3, 1),), + family_months={ + 1: r.RETFamilyMonth(state, (member,), ssa_params(), {"a": "h"}) + }, + ) + _assert_refusal(case, UR.OWN_RIB_HISTORY_BEFORE_1978) + + +_FACT_TABLE_QUOTES = ( + ( + "tests/data/track_b/ret_ledger_sources/poms_rs_02501_110.html", + "their original benefit is equal to 100% of the PIA", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_101.html", + "The MBA is equal to the PIA reduced by 5/9 of 1%", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_754.html", + "the rate to the NH is protected by administrative finality and cannot be changed", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_754.html", + "the PIA and maximum used to arrive at those rates", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_754.html", + "the protected PIA and maximum", + ), + ( + "tests/data/track_b/gross_benefit_sources/ssa_act_202_215_excerpts.txt", + "such disability insurance benefit for each month shall be reduced by the amount such old-age insurance benefit would be reduced", + ), + ( + "tests/data/track_b/gross_benefit_sources/ssa_act_202_215_excerpts.txt", + "after any reduction under sections 203(a) and 224", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_gn_02603_050.html", + "Workers’ compensation (WC) or public disability benefit (PDB) offset amount", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_736.html", + "To establish a family maximum for a DIB Guarantee PIA", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_740.html", + "The PIA is an AIME, OS, Special Minimum or Frozen Minimum PIA.", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_740.html", + "determining the total amount of the family maximum benefit", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00202_100.html", + "the NH is eligible but has not filed for benefits", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00202_100.html", + "is subject to the number holder’s (NH) WEP PIA although the NH is not yet entitled", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_754.html", + "which rates are protected by administrative finality", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_712.html", + "beneficiaries who were entitled for the month of 5/78", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_712.html", + "the child is protected by the savings clause and the child's rate will remain at $300", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_770.html", + "Maximums from all SSNs that the child is entitled on may be combined on the SSN where payment is actually made.", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_684.html", + "The deemed or putative spouse and all other beneficiaries on the record are reduced for the maximum.", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_684.html", + "the legal spouse is paid outside the family maximum", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_684.html", + "the legal spouse will receive the OB", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_gn_02608_100.html", + "a reduction of spouse's benefits due to the receipt of a federal, state, or local government pension", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_gn_02608_100.html", + "proven his or her rights to them for a given period", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_260.html", + "Reduce the spouse's reduced benefit further by the amount of the RIB reduction.", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_005.html", + "all cases involving single entitlement to actuarially reduced benefits prior to 1/78", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_692.html", + "Before 01/02/17", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_692.html", + "1/12%", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_101.html", + "Round the result down to the next dime for benefits after 5/82 and up to the next dime for benefits prior to 6/82.", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_740.html", + "The NH was ever entitled to DIB before July 1980", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00209_001.html", + "equal to or exceeding the amount of the parent's original benefit (One parent = 82 1/2%; Two parents = 75%)", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00209_015.html", + "Benefit rate equals 75% of the worker's PIA for each month both are entitled.", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_310.html", + "Determine the WIB OB", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_020.html", + "First benefit calculated independently", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_315.html", + "if all eligibility requirements are met", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_766.html", + "after reduction for the maximum", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_768.html", + "Beneficiaries will still be limited by the original benefit amount.", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_340.html", + "receiving a reduced widow(er) benefit", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_340.html", + "The benefit amount is raised for all months the child is in care.", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00630_400.html", + "Any person's benefit may not exceed the original benefit (OB)", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00630_400.html", + "the new PIA in a life case", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_320.html", + "deductions", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_754.html", + "the correct PIA is really $750.00", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_754.html", + "cannot be changed", + ), +) + + +def test_fact_table_source_quotations_and_capture_hashes(): + root = Path(__file__).resolve().parents[1] + manifests = {} + for relative, quote in _FACT_TABLE_QUOTES: + capture = root / relative + if capture.parent not in manifests: + manifests[capture.parent] = json.loads( + (capture.parent / "manifest.json").read_text() + )["sources"] + entry = next( + row + for row in manifests[capture.parent] + if row["file"] == capture.name + ) + raw = capture.read_bytes() + assert hashlib.sha256(raw).hexdigest() == entry["sha256"] + text = raw.decode() + if capture.suffix == ".html": + text = re.sub(r"<[^>]+>", " ", text) + text = re.sub(r"\s+", " ", html.unescape(text)) + assert quote in text + + +@pytest.mark.parametrize("path", ["ret", "deduction"]) +@pytest.mark.parametrize("basis", [F(5), None]) +@pytest.mark.parametrize("history", [None, False]) +def test_protected_widow_cannot_be_excluded_from_unknown_drc_history( + path, basis, history +): + state = g.RecordState( + g.FamilyKind.SURVIVOR, + F(4), + F(8), + eligibility_year=2024, + widow_drc_savings_clause=history, + ) + members = ( + g.Beneficiary( + "w", + g.Role.WIDOW, + birth_year=1950, + original_benefit_basis=basis, + own_benefit=g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, F(5)), + child_in_care=False, + conditions={BC.RATE_PROTECTED_BY_FINALITY}, + ), + g.Beneficiary("c", g.Role.CHILD), + ) + if path == "ret": + case = r.RecordYear( + 2024, + "nh", + r.RecordKind.DECEASED, + ( + _person("w", T.WIDOW, 0, 5, 1), + _person("c", T.CHILD, 3, F("3.10"), 1), + ), + family_months={ + 1: r.RETFamilyMonth( + state, members, ssa_params(), {"w": "h", "c": "h"} + ) + }, + ) + if history is False: + _assert_invalid(case) + else: + _assert_refusal(case, UR.ADMINISTRATIVE_FINALITY) + return + + def compute(): + return g.family_benefits_after_deductions( + state, + members, + payment_month=g.YearMonth(2024, 1), + params=ssa_params(), + standalone=True, + deductions={ + "c": g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST, F("3.10") + ) + }, + households={"w": "h", "c": "h"}, + ) + + if history is False: + rows = [] + with pytest.raises(g.InvalidFamilyInput): + rows.append(g.evaluate_family("settled-history", 7, compute)) + counts = g.count_family_outcomes(rows) + assert (counts.rows, counts.weight) == (0, 0) + return + outcome = g.evaluate_family( + "protected-widow-history", + 7, + compute, + ) + assert outcome.unsupported.reason is UR.ADMINISTRATIVE_FINALITY + counts = g.count_family_outcomes([outcome]) + assert (counts.rows, counts.weight, counts.unsupported_weight) == (1, 7, 7) + + +@pytest.mark.parametrize( + "held", [None, RC.NON_AIME_FORMULA_PIA, RC.ADMINISTRATIVE_FINALITY] +) +def test_missing_both_widow_cohorts_remains_canonical_input_error(held): + case = _case("F6", held=held, contradiction=True) + context = case.family_months[1] + member = replace(context.beneficiaries[0], birth_year=None) + case = replace( + case, family_months={1: replace(context, beneficiaries=(member,))} + ) + rows = [] + with pytest.raises(g.InvalidFamilyInput, match="needs birth_year"): + rows.append(_outcome(case)) + counts = r.count_ret_outcomes(rows) + assert (counts.rows, counts.weight) == (0, 0) + + +@pytest.mark.parametrize("cohort", [1920, 1928]) +@pytest.mark.parametrize("money", [0, 4]) +@pytest.mark.parametrize("held", [None, BC.ENTITLED_ON_ANOTHER_RECORD]) +def test_aged_widow_sequence_refusal_only_unsettles_possible_carryover( + cohort, money, held +): + case = _case("F6", money, held=held, contradiction=True) + context = case.family_months[1] + member = replace(context.beneficiaries[0], birth_year=cohort) + case = replace( + case, family_months={1: replace(context, beneficiaries=(member,))} + ) + if cohort < 1928 and money > 0: + _assert_refusal( + case, + ( + UR.COMBINED_FAMILY_MAXIMUM + if held + else UR.DUAL_ENTITLEMENT_SEQUENCE + ), + ) + else: + _assert_invalid(case) + + +@pytest.mark.parametrize("money", [0, 4]) +@pytest.mark.parametrize( + "held", + [ + None, + RC.NON_AIME_FORMULA_PIA, + RC.ADMINISTRATIVE_FINALITY, + BC.ENTITLED_ON_ANOTHER_RECORD, + ], +) +def test_modern_disabled_widow_own_rib_eligibility_is_settled(money, held): + own = g.OwnBenefit( + g.OwnBenefitKind.OLD_AGE, + F(money), + reduction_months=12, + birth_year=1950, + ) + own_mba = g.own_monthly_benefit(own, ssa_params())[1] + assert own_mba == (F("3.70") if money else 0) + state = g.RecordState( + g.FamilyKind.SURVIVOR, + own_mba, + 2 * own_mba, + widow_drc_savings_clause=False, + conditions={held} if isinstance(held, RC) else (), + ) + member = g.Beneficiary( + "w", + g.Role.DISABLED_WIDOW, + birth_year=1950, + own_benefit=own, + child_in_care=False, + conditions={held} if isinstance(held, BC) else (), + ) + case = r.RecordYear( + 2015, + "nh", + r.RecordKind.DECEASED, + (replace(_person("w", T.DWB, 0, own_mba, 6), fra_month=None),), + family_months={ + 6: r.RETFamilyMonth(state, (member,), ssa_params(), {"w": "h"}) + }, + ) + if held is RC.ADMINISTRATIVE_FINALITY: + _assert_refusal(case, UR.ADMINISTRATIVE_FINALITY) + else: + _assert_invalid(case) + + +def test_eligible_disabled_widow_retains_own_sequence_refusal(): + own = g.OwnBenefit( + g.OwnBenefitKind.OLD_AGE, + F(4), + reduction_months=12, + birth_year=1950, + ) + state = g.RecordState( + g.FamilyKind.SURVIVOR, + F(4), + F(8), + widow_drc_savings_clause=False, + ) + member = g.Beneficiary( + "w", + g.Role.DISABLED_WIDOW, + birth_year=1950, + own_benefit=own, + child_in_care=False, + ) + case = r.RecordYear( + 2015, + "nh", + r.RecordKind.DECEASED, + (replace(_person("w", T.DWB, 0, 4, 6), fra_month=None),), + family_months={ + 6: r.RETFamilyMonth(state, (member,), ssa_params(), {"w": "h"}) + }, + ) + _assert_refusal(case, UR.DUAL_ENTITLEMENT_SEQUENCE) + + +_FACT_TABLE_QUOTES += ( + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_005.html", + "Eliminated the carry-over reduction in RIB or DIB due to WIB before age 62.", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_005.html", + "This applies to RIB for workers born 1/2/28 or later", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_010.html", + "RIB After Reduced WIB (D then A) with date of birth of 1/2/1928 or later Reduce the RIB in the usual manner without regard to the WIB", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_010.html", + "RIB After Reduced WIB (D then A) with date of birth before 1/2/1928 If there was prior entitlement to a reduced WIB in any month before the month of attainment of age 62 reduce the RIB", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_315.html", + "When an eligible person elects to switch from WIB to DWB or DWB to WIB the PIA and the reduction factors remain the same.", + ), +) + + +@pytest.mark.parametrize("year", [1973, 2024]) +@pytest.mark.parametrize("household", [False, True]) +@pytest.mark.parametrize("event", ["payable", "reservation"]) +def test_legacy_widow_later_payment_gross_retains_eligibility_refusal( + year, household, event +): + _legacy_widow_gross_refusal(year, household, event, deferred=False) + + +@pytest.mark.parametrize("household", [False, True]) +@pytest.mark.parametrize("event", ["payable", "reservation"]) +@pytest.mark.parametrize( + "reason", + [UR.ELIGIBILITY_BEFORE_1983, UR.DI_ENTITLEMENT_BEFORE_JULY_1980], +) +def test_deferred_legacy_eligibility_gross_retains_its_original_refusal( + household, event, reason +): + _legacy_widow_gross_refusal( + 2024, household, event, deferred=True, reason=reason + ) + + +def _legacy_widow_gross_refusal( + year, household, event, *, deferred, reason=UR.ELIGIBILITY_BEFORE_1983 +): + state = g.RecordState( + g.FamilyKind.SURVIVOR, + F(4), + F(8), + eligibility_year=None if deferred else 1972, + deferred_refusal=(reason, "legacy eligibility") if deferred else None, + widow_drc_savings_clause=False, + ) + members = ( + g.Beneficiary("w", g.Role.WIDOW, birth_year=1910, child_in_care=False), + ) + kwargs = dict( + payment_month=g.YearMonth(year, 1), + params=ssa_params(), + deductions=( + { + "w": g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST, F("4.10") + ) + } + if event == "payable" + else {} + ), + worker_deductions={"w": F("4.10")} if event == "reservation" else {}, + households={"w": "h"}, + ) + + def compute(): + if household: + return g.household_benefits_after_deductions( + {"record": g.HouseholdRecord("nh", state, members)}, **kwargs + ) + return g.family_benefits_after_deductions( + state, members, standalone=True, **kwargs + ) + + outcome = g.evaluate_family("legacy-widow-gross", 7, compute) + assert outcome.unsupported.reason is reason + counts = g.count_family_outcomes([outcome]) + assert (counts.rows, counts.weight, counts.unsupported_weight) == (1, 7, 7) + + +@pytest.mark.parametrize("household", [False, True]) +@pytest.mark.parametrize("event", ["payable", "reservation"]) +def test_old_first_dib_history_does_not_unsettle_current_child_upper_bound( + household, event +): + state = g.RecordState( + g.FamilyKind.DISABILITY, + F(4), + F(8), + eligibility_year=2024, + first_dib_entitlement=g.YearMonth(1979, 1), + ) + members = (g.Beneficiary("c", g.Role.CHILD),) + kwargs = dict( + payment_month=g.YearMonth(2024, 1), + params=ssa_params(), + deductions=( + { + "c": g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST, F("2.10") + ) + } + if event == "payable" + else {} + ), + worker_deductions={"c": F("2.10")} if event == "reservation" else {}, + households={"c": "h"}, + ) + + def compute(): + if household: + return g.household_benefits_after_deductions( + {"record": g.HouseholdRecord("nh", state, members)}, **kwargs + ) + return g.family_benefits_after_deductions( + state, members, standalone=True, **kwargs + ) + + _assert_no_family_row(compute) + + +_FACT_TABLE_QUOTES += ( + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_010.html", + "Sole Surviving Widow(er) $84.50 reduced for months of entitlement, if any, prior to age 62 or, if higher, the WIB computed without regard to this sole survivor's provision", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_010.html", + "The sole survivor's rate was eliminated when NH died after 1981 and was not eligible for RIB or DIB", + ), +) + + +def _historical_child_uncertainty_case(year, *, scale=0, month=1): + pia = F(2 * scale + 1, 10) + current_ob = g.original_benefit(g.Role.CHILD, g.FamilyKind.RETIREMENT, pia) + declared = current_ob + F(1, 10) + state = g.RecordState( + g.FamilyKind.RETIREMENT, + pia, + 2 * pia, + worker=g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, pia, birth_year=1910), + eligibility_year=1972, + ) + member = g.Beneficiary("c", g.Role.CHILD) + return r.RecordYear( + year, + "nh", + beneficiaries=( + _person("nh", T.RIB, pia, pia, month), + replace( + _person("c", T.CHILD, declared, declared, month), + fra_month=None, + ), + ), + family_months={ + month: r.RETFamilyMonth(state, (member,), ssa_params(), {"c": "h"}) + }, + ) + + +@pytest.mark.parametrize("year", [1981, 1983]) +def test_child_ob_uncertainty_is_limited_to_pre1983_payment_months(year): + case = _historical_child_uncertainty_case(year) + if year < 1983: + _assert_refusal(case, UR.ELIGIBILITY_BEFORE_1983) + else: + _assert_invalid(case) + + +@settings(max_examples=40, deadline=None) +@given(scale=st.integers(0, 10), month=st.integers(1, 12)) +@example(scale=0, month=1) +@example(scale=10, month=12) +def test_child_ob_uncertainty_preserves_old_refusals_for_odd_dime_pias( + scale, month +): + _assert_refusal( + _historical_child_uncertainty_case(1981, scale=scale, month=month), + UR.ELIGIBILITY_BEFORE_1983, + ) + _assert_invalid( + _historical_child_uncertainty_case(1983, scale=scale, month=month) + ) + + +def _historical_widow_gross_uncertainty_computation( + household, + event, + *, + scale=1, + month=1, + year=1972, + amount=None, + finality=False, +): + state = g.RecordState( + g.FamilyKind.SURVIVOR, + F(4 * scale), + F(8 * scale), + eligibility_year=None if finality else 1972, + widow_drc_savings_clause=False, + conditions={RC.ADMINISTRATIVE_FINALITY} if finality else (), + ) + members = ( + g.Beneficiary("w", g.Role.WIDOW, birth_year=1910, child_in_care=False), + ) + if amount is None: + amount = F(4 * scale) + F(1, 10) + kwargs = dict( + payment_month=g.YearMonth(year, month), + params=ssa_params(), + deductions=( + { + "w": g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST, amount + ) + } + if event == "payable" + else {} + ), + worker_deductions={"w": amount} if event == "reservation" else {}, + households={"w": "h"}, + ) + + def compute(): + if household: + return g.household_benefits_after_deductions( + {"record": g.HouseholdRecord("nh", state, members)}, **kwargs + ) + return g.family_benefits_after_deductions( + state, members, standalone=True, **kwargs + ) + + return compute + + +@pytest.mark.parametrize("household", [False, True]) +@pytest.mark.parametrize("event", ["payable", "reservation"]) +@pytest.mark.parametrize("zero", [False, True]) +def test_historical_widow_gross_uncertainty_retains_original_refusal( + household, event, zero +): + compute = _historical_widow_gross_uncertainty_computation( + household, event, amount=F(0) if zero else None + ) + outcome = g.evaluate_family("zero-historical-widow", 7, compute) + assert outcome.unsupported.reason is UR.ELIGIBILITY_BEFORE_1983 + counts = g.count_family_outcomes([outcome]) + assert (counts.rows, counts.weight, counts.unsupported_weight) == (1, 7, 7) + + +@pytest.mark.parametrize("household", [False, True]) +@pytest.mark.parametrize("event", ["payable", "reservation"]) +def test_historical_widow_finality_keeps_its_original_refusal( + household, event +): + outcome = g.evaluate_family( + "protected-historical-widow", + 7, + _historical_widow_gross_uncertainty_computation( + household, event, finality=True + ), + ) + assert outcome.unsupported.reason is UR.ADMINISTRATIVE_FINALITY + counts = g.count_family_outcomes([outcome]) + assert (counts.rows, counts.weight, counts.unsupported_weight) == (1, 7, 7) + + +@settings(max_examples=40, deadline=None) +@given( + year=st.sampled_from((1972, 1973, 2024)), + scale=st.integers(1, 10), + month=st.integers(1, 12), + household=st.booleans(), + event=st.sampled_from(("payable", "reservation")), +) +@example(year=1972, scale=1, month=1, household=False, event="payable") +@example(year=1973, scale=1, month=1, household=False, event="payable") +@example(year=2024, scale=10, month=12, household=True, event="reservation") +def test_historical_widow_gross_uncertainty_preserves_refusals_across_months( + year, scale, month, household, event +): + outcome = g.evaluate_family( + "historical-widow-uncertainty", + 7, + _historical_widow_gross_uncertainty_computation( + household, event, scale=scale, month=month, year=year + ), + ) + assert outcome.unsupported.reason is UR.ELIGIBILITY_BEFORE_1983 + counts = g.count_family_outcomes([outcome]) + assert (counts.rows, counts.weight, counts.unsupported_weight) == (1, 7, 7) + + +def _parent_upper_bound_computation( + household, + event, + *, + scale=1, + month=1, + deferred=True, + finality=False, + amount=None, +): + state = g.RecordState( + g.FamilyKind.SURVIVOR, + F(4 * scale), + F(8 * scale), + widow_drc_savings_clause=False, + deferred_refusal=(UR.PARENT_BENEFIT, "count") if deferred else None, + conditions={RC.ADMINISTRATIVE_FINALITY} if finality else (), + ) + members = tuple( + g.Beneficiary( + key, + g.Role.PARENT, + own_benefit=g.OwnBenefit( + g.OwnBenefitKind.OLD_AGE, + F(31 * scale, 10), + birth_year=1950, + ), + birth_year=1950, + ) + for key in ("p", "q") + ) + if amount is None: + amount = F(33 * scale, 10) + F(1, 10) + kwargs = dict( + payment_month=g.YearMonth(2024, month), + params=ssa_params(), + deductions=( + { + "p": g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST, amount + ) + } + if event == "payable" + else {} + ), + worker_deductions={"p": amount} if event == "reservation" else {}, + households={"p": "h", "q": "h"}, + ) + + def compute(): + if household: + return g.household_benefits_after_deductions( + {"record": g.HouseholdRecord("nh", state, members)}, **kwargs + ) + return g.family_benefits_after_deductions( + state, members, standalone=True, **kwargs + ) + + return compute + + +def _assert_no_family_row(compute): + outcomes = [] + with pytest.raises(g.InvalidFamilyInput): + outcomes.append(g.evaluate_family("parent-bound", 7, compute)) + counts = g.count_family_outcomes(outcomes) + assert (counts.rows, counts.weight) == (0, 0) + + +@pytest.mark.parametrize("household", [False, True]) +@pytest.mark.parametrize("event", ["payable", "reservation"]) +@pytest.mark.parametrize("deferred", [False, True]) +def test_parent_count_uncertainty_keeps_the_one_parent_upper_bound( + household, event, deferred +): + _assert_no_family_row( + _parent_upper_bound_computation(household, event, deferred=deferred) + ) + + +@pytest.mark.parametrize("household", [False, True]) +@pytest.mark.parametrize("deferred", [False, True]) +def test_zero_parent_deduction_retains_parent_count_refusal( + household, deferred +): + outcome = g.evaluate_family( + "zero-parent", + 7, + _parent_upper_bound_computation( + household, "payable", deferred=deferred, amount=F(0) + ), + ) + assert outcome.unsupported.reason is UR.PARENT_BENEFIT + counts = g.count_family_outcomes([outcome]) + assert (counts.rows, counts.weight, counts.unsupported_weight) == (1, 7, 7) + + +@pytest.mark.parametrize("household", [False, True]) +@pytest.mark.parametrize("event", ["payable", "reservation"]) +def test_finality_can_unsettle_the_parent_upper_bound(household, event): + outcome = g.evaluate_family( + "protected-parent", + 7, + _parent_upper_bound_computation(household, event, finality=True), + ) + assert outcome.unsupported.reason is UR.ADMINISTRATIVE_FINALITY + counts = g.count_family_outcomes([outcome]) + assert (counts.rows, counts.weight, counts.unsupported_weight) == (1, 7, 7) + + +@settings(max_examples=40, deadline=None) +@given( + scale=st.integers(1, 10), + month=st.integers(1, 12), + household=st.booleans(), + event=st.sampled_from(("payable", "reservation")), +) +@example(scale=1, month=1, household=False, event="payable") +@example(scale=10, month=12, household=True, event="reservation") +def test_parent_upper_bound_holds_across_scales_months_and_deferred_holds( + scale, month, household, event +): + for deferred in (False, True): + _assert_no_family_row( + _parent_upper_bound_computation( + household, + event, + scale=scale, + month=month, + deferred=deferred, + ) + ) + + +@pytest.mark.parametrize("money", [0, 4]) +@pytest.mark.parametrize("contradiction", [False, True]) +def test_widow_drc_condition_on_a_living_child_keeps_ob_settled( + money, contradiction +): + case = _case( + "F4", + money, + held=BC.WIDOW_DRC_SAVINGS_CLAUSE, + contradiction=contradiction, + ) + if contradiction: + _assert_invalid(case) + else: + _assert_refusal(case, UR.WIDOW_DRC_SAVINGS_CLAUSE) + + +def test_survivor_widow_drc_protection_keeps_its_original_refusal(): + case = _case("F6", held=BC.WIDOW_DRC_SAVINGS_CLAUSE) + context = case.family_months[1] + member = replace(context.beneficiaries[0], birth_year=1910) + state = replace(context.state, widow_drc_savings_clause=None) + person = replace(case.beneficiaries[0], original_rates=(F("4.10"),) * 12) + case = replace( + case, + beneficiaries=(person,), + family_months={ + 1: replace(context, state=state, beneficiaries=(member,)) + }, + ) + _assert_refusal(case, UR.WIDOW_DRC_SAVINGS_CLAUSE) + + +@pytest.mark.parametrize( + "fact,reason", + [ + ("F4", UR.PARENT_BENEFIT), + ("F3", UR.OWN_RIB_HISTORY_BEFORE_1978), + ("F6", UR.OWN_RIB_HISTORY_BEFORE_1978), + ("F3", UR.DELAYED_CREDITS_BEFORE_1917), + ("F6", UR.DELAYED_CREDITS_BEFORE_1917), + ("F3", UR.PAYMENT_MONTH_BEFORE_1983), + ("F6", UR.PAYMENT_MONTH_BEFORE_1983), + ("F4", UR.WIDOW_DRC_SAVINGS_CLAUSE), + ("F4", UR.WIDOW_DRC_SAVINGS_CLAUSE_HISTORY_UNKNOWN), + ], +) +@pytest.mark.parametrize("money", [0, 4]) +@pytest.mark.parametrize("contradiction", [False, True]) +def test_deferred_reason_unsettles_only_the_fact_within_its_scope( + fact, reason, money, contradiction +): + case = _case(fact, money, contradiction=contradiction) + context = case.family_months[1] + state = context.state + if fact == "F3": + state = replace( + state, + worker=replace(state.worker, birth_year=1950), + worker_birth_year=1950, + ) + state = replace(state, deferred_refusal=(reason, "declared deferred hold")) + case = replace(case, family_months={1: replace(context, state=state)}) + if contradiction: + _assert_invalid(case) + else: + _assert_refusal(case, reason) + + +@pytest.mark.parametrize("year", [1972, 1973]) +def test_historical_widow_original_benefit_uses_the_payment_period(year): + state = g.RecordState( + g.FamilyKind.SURVIVOR, + F(4), + F(8), + eligibility_year=1972, + widow_drc_savings_clause=False, + ) + member = g.Beneficiary( + "w", g.Role.WIDOW, birth_year=1910, child_in_care=False + ) + case = r.RecordYear( + year, + "nh", + r.RecordKind.DECEASED, + ( + replace( + _person("w", T.WIDOW, F("3.30"), F("3.30"), 1), + fra_month=None, + ), + ), + family_months={ + 1: r.RETFamilyMonth(state, (member,), ssa_params(), {"w": "h"}) + }, + ) + if year == 1972: + _assert_refusal(case, UR.ELIGIBILITY_BEFORE_1983) + else: + _assert_invalid(case) + + +_FACT_TABLE_QUOTES += ( + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_005.html", + "Raised the unreduced benefit amount for widow(er)s to 82 1/2% at age 62. This benefit was not subject to reduction for age.", + ), + ( + "tests/data/track_b/gross_benefit_sources/poms_rs_00615_005.html", + "5. 1972 Amendments Effective 1/73 • Provided for reduced widower's benefits at age 60. • Changed age for unreduced widow(er)'s benefits to 65. • Changed WIB to 100% of the deceased worker's PIA unless the DNH was entitled to a reduced RIB.", + ), +) diff --git a/tests/tier_counts.json b/tests/tier_counts.json index 0e47318ad..2980955eb 100644 --- a/tests/tier_counts.json +++ b/tests/tier_counts.json @@ -1,7 +1,7 @@ { "schema_version": 1, "counts": { - "unit": 20495, + "unit": 20804, "artifact": 4271, "integration_psid": 1471, "reproduction_legacy": 520, From 3212f8231e4029539ebe8258a280217f7cdbbe3a Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 1 Nov 2026 01:46:55 -0500 Subject: [PATCH 11/17] Track B R2: keep the direction a hold leaves settled Sol's fifth review of a135519f found three mediums, and all three reproduced. Each fact table treated a fact as wholly open or wholly settled, where the sources settle one direction of it. - RS 00615.712 protects a widow's adjusted cash and leaves a child's original rate alone, so a child's original above its OB now raises under a declared clause and under unknown history. - 20 CFR 404.411(c)(2) keeps a prior reduced WIB's carryover before cohort 1928 and reaches someone with no current WIB, so an NH's own RIB below its ordinary rate keeps dual_entitlement_sequence and its weight. Cohort 1928 stays settled. - A hold that can only lower an NH rate keeps that rate as a cap, so a DIB above its PIA raises. Only administrative finality lifts a cap. The same class reaches a DIB after a reduced WIB, which Sol's probe showed outside its verdict. A DIB below the PIA now keeps its row under dual_entitlement_sequence in every cohort, because the schema omits the onset that scopes 404.411(b)(2). The pre-1978 reasons open it before cohort 1928 only. Protected cash stays a named refusal, because the capture states no cap. No money moves. The conformance report regenerates byte-identically, and the cross-head comparison keeps 240 R2 and 240 R3 results. Invariants: under a reduction-only hold, an NH rate above its ordinary rate raises and one at or below it keeps its row. Every rate the carryover can reach stays a counted refusal, with or without the preflight. A nonwidow's OB stays settled under widow DRC protection. Co-Authored-By: Claude Opus 5.5 --- docs/design/track_b_g2_r2b_mutations.json | 2213 ++++++++++++++++- docs/design/track_b_g2_r2b_verification.json | 81 +- docs/design/track_b_r2_ret_ledger.md | 108 +- .../track_b/gross_benefits.py | 101 +- src/populace_dynamics/track_b/ret_ledger.py | 19 +- tests/README-tiers.md | 4 +- tests/test_track_b_ret_ledger_fix_round_4.py | 13 +- tests/test_track_b_ret_ledger_fix_round_5.py | 16 +- tests/test_track_b_ret_ledger_fix_round_6.py | 672 +++++ tests/tier_counts.json | 2 +- 10 files changed, 3174 insertions(+), 55 deletions(-) create mode 100644 tests/test_track_b_ret_ledger_fix_round_6.py diff --git a/docs/design/track_b_g2_r2b_mutations.json b/docs/design/track_b_g2_r2b_mutations.json index 3d90c73c3..4a7867f47 100644 --- a/docs/design/track_b_g2_r2b_mutations.json +++ b/docs/design/track_b_g2_r2b_mutations.json @@ -2,12 +2,12 @@ "schema_version": 1, "verification_class": "statutory_conformance", "admitted_scope": "Mutation sensitivity of statutory rules on invented and captured worked cases only; no population, behavioral or forecast claim.", - "confirmed_mutation_count": 80, + "confirmed_mutation_count": 118, "counts_by_layer": { "g_deductions": 18, - "g_preflight": 21, + "g_preflight": 52, "g_savings": 12, - "r2": 28, + "r2": 35, "shared_provenance": 1 }, "environment_contract": { @@ -4401,6 +4401,2207 @@ } }, "layer": "g_preflight" + }, + { + "id": "round6-cap_lifts_equality", + "round": 6, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " upper_bound\n and hold in _NH_REDUCTION_ONLY_HOLDS\n", + "after": " hold in _NH_REDUCTION_ONLY_HOLDS\n" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_published_rule_carryover_keeps_its_refusal[400-300-359.10]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_published_rule_carryover_keeps_its_refusal[1.20-.50-1.00]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_carryover_ends_at_cohort_1928[1926-False-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_carryover_ends_at_cohort_1928[1926-False-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_carryover_ends_at_cohort_1928[1927-False-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_carryover_ends_at_cohort_1928[1927-False-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_an_unknown_cohort_cannot_rule_out_the_carryover", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_an_unknown_cohort_cannot_rule_out_a_pre_1978_history[UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_an_unknown_cohort_cannot_rule_out_a_pre_1978_history[UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_workers_compensation_caps_a_rib_at_its_canonical_rate" + ], + "failed_test_count": 43, + "log": { + "path": "scratch/review/round6-mutations/cap_lifts_equality.log", + "sha256": "085ff0968f25343a4101a2177ba2c3066f194645bcfa7b690abed64d7812d47d", + "failure_summary": "43 failed, 181 passed in 3.53s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round6-cap_never_settled", + "round": 6, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " upper_bound\n and hold in _NH_REDUCTION_ONLY_HOLDS\n", + "after": " False\n and hold in _NH_REDUCTION_ONLY_HOLDS\n" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_an_unknown_cohort_cannot_rule_out_the_carryover", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_an_unknown_cohort_cannot_rule_out_a_pre_1978_history[UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_an_unknown_cohort_cannot_rule_out_a_pre_1978_history[UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_rib_above_the_canonical_rate_stays_an_input_error[0.10-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_rib_above_the_canonical_rate_stays_an_input_error[0.10-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_rib_above_the_canonical_rate_stays_an_input_error[1.00-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_rib_above_the_canonical_rate_stays_an_input_error[1.00-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_workers_compensation_caps_a_rib_at_its_canonical_rate", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions0-None]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions1-None]" + ], + "failed_test_count": 39, + "log": { + "path": "scratch/review/round6-mutations/cap_never_settled.log", + "sha256": "cdf7486a40c0ae0153549d350e788c2aa2f2827ba6f74340d95c86ea078285db", + "failure_summary": "39 failed, 185 passed in 1.10s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round6-cap_scope_f2_only", + "round": 6, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " and hold in _NH_REDUCTION_ONLY_HOLDS\n and fact in (\"F2\", \"F3\")\n", + "after": " and hold in _NH_REDUCTION_ONLY_HOLDS\n and fact == \"F2\"\n" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_an_unknown_cohort_cannot_rule_out_the_carryover", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_rib_above_the_canonical_rate_stays_an_input_error[0.10-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_rib_above_the_canonical_rate_stays_an_input_error[0.10-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_rib_above_the_canonical_rate_stays_an_input_error[1.00-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_rib_above_the_canonical_rate_stays_an_input_error[1.00-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_workers_compensation_caps_a_rib_at_its_canonical_rate", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_only_finality_lifts_an_nh_rate_cap[rib-workers_compensation_offset]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_only_finality_lifts_an_nh_rate_cap[rib-dual_entitlement_sequence]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_only_finality_lifts_an_nh_rate_cap[rib-reduced_benefit_history_before_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_every_carryover_rate_keeps_its_row" + ], + "failed_test_count": 10, + "log": { + "path": "scratch/review/round6-mutations/cap_scope_f2_only.log", + "sha256": "f395859eb7456257a58687c9f14ea73195b2f368a8c194bff55766a985199f80", + "failure_summary": "10 failed, 214 passed in 2.05s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round6-cap_scope_f3_only", + "round": 6, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " and hold in _NH_REDUCTION_ONLY_HOLDS\n and fact in (\"F2\", \"F3\")\n", + "after": " and hold in _NH_REDUCTION_ONLY_HOLDS\n and fact == \"F3\"\n" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_an_unknown_cohort_cannot_rule_out_a_pre_1978_history[UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_an_unknown_cohort_cannot_rule_out_a_pre_1978_history[UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions0-None]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions1-None]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions2-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions3-UnsupportedReason.WORKERS_COMPENSATION_OFFSET]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions4-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions5-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions6-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[4-conditions0-None]" + ], + "failed_test_count": 29, + "log": { + "path": "scratch/review/round6-mutations/cap_scope_f3_only.log", + "sha256": "554edd539a4a082fea101b2a36efca4fb4476592a52b37a6fd4fb218be1da39a", + "failure_summary": "29 failed, 195 passed in 1.80s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round6-carryover_any_kind", + "round": 6, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " own is not None\n and own.kind is OwnBenefitKind.OLD_AGE\n and own.pia > 0\n and (\n birth_year is None", + "after": " own is not None\n and own.pia > 0\n and (\n birth_year is None" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_the_carryover_reaches_only_an_old_age_benefit[OwnBenefitKind.DISABILITY-True]" + ], + "failed_test_count": 1, + "log": { + "path": "scratch/review/round6-mutations/carryover_any_kind.log", + "sha256": "4f2752c5a56c1da752b9990cab08d269114e3d9a9023d05c79bb53f598b0559a", + "failure_summary": "1 failed, 223 passed in 2.57s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round6-carryover_cohort_1927", + "round": 6, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "_FIRST_OWN_RIB_WITHOUT_WIB_CARRYOVER_BIRTH_YEAR = 1928", + "after": "_FIRST_OWN_RIB_WITHOUT_WIB_CARRYOVER_BIRTH_YEAR = 1927" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_published_rule_carryover_keeps_its_refusal[400-300-359.10]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_published_rule_carryover_keeps_its_refusal[1.20-.50-1.00]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_carryover_ends_at_cohort_1928[1927-False-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_carryover_ends_at_cohort_1928[1927-False-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_the_carryover_reaches_only_an_old_age_benefit[OwnBenefitKind.OLD_AGE-False]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_each_reason_classifies_a_lower_rib[dual_entitlement_sequence]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_each_reason_classifies_a_lower_rib[reduced_benefit_history_before_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_every_carryover_rate_keeps_its_row" + ], + "failed_test_count": 8, + "log": { + "path": "scratch/review/round6-mutations/carryover_cohort_1927.log", + "sha256": "1743b7efd5b69f92e4c3b546025a3ed3960b817abf233f04f78212cce5390507", + "failure_summary": "8 failed, 216 passed in 3.50s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round6-carryover_cohort_1929", + "round": 6, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "_FIRST_OWN_RIB_WITHOUT_WIB_CARRYOVER_BIRTH_YEAR = 1928", + "after": "_FIRST_OWN_RIB_WITHOUT_WIB_CARRYOVER_BIRTH_YEAR = 1929" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_carryover_ends_at_cohort_1928[1928-True-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_carryover_ends_at_cohort_1928[1928-True-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]" + ], + "failed_test_count": 2, + "log": { + "path": "scratch/review/round6-mutations/carryover_cohort_1929.log", + "sha256": "46086cf4738d8a758f09e59c452cd5ac09cfe4855e8bba5b998a92603b50e16c", + "failure_summary": "2 failed, 222 passed in 2.73s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round6-carryover_unknown_cohort_settled", + "round": 6, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " birth_year is None\n or birth_year < _FIRST_OWN_RIB", + "after": " birth_year is not None\n and birth_year < _FIRST_OWN_RIB" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_an_unknown_cohort_cannot_rule_out_the_carryover" + ], + "failed_test_count": 1, + "log": { + "path": "scratch/review/round6-mutations/carryover_unknown_cohort_settled.log", + "sha256": "946f7329025e5aa17b9544a62e5b38179e699cd7fdefe29b1ac1d770d4006daa", + "failure_summary": "1 failed, 223 passed in 2.96s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round6-carryover_unscoped", + "round": 6, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " return _wib_carryover_possible(state.worker, state.worker_birth_year)\n", + "after": " return True\n" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_carryover_ends_at_cohort_1928[1928-True-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_carryover_ends_at_cohort_1928[1928-True-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_carryover_ends_at_cohort_1928[1929-True-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_carryover_ends_at_cohort_1928[1929-True-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_zero_pia_leaves_no_rate_for_the_carryover_to_lower" + ], + "failed_test_count": 5, + "log": { + "path": "scratch/review/round6-mutations/carryover_unscoped.log", + "sha256": "13c94ccbc9e8893573f379b1757446aa923bb5d32bd65812c3ab8347b98a613a", + "failure_summary": "5 failed, 219 passed in 3.10s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round6-carryover_zero_pia", + "round": 6, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " and own.kind is OwnBenefitKind.OLD_AGE\n and own.pia > 0\n and (\n birth_year is None", + "after": " and own.kind is OwnBenefitKind.OLD_AGE\n and (\n birth_year is None" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_zero_pia_leaves_no_rate_for_the_carryover_to_lower" + ], + "failed_test_count": 1, + "log": { + "path": "scratch/review/round6-mutations/carryover_zero_pia.log", + "sha256": "c900ef3d6845e7db6871381321456cb37b2fd22f92b42973a5ffcc7f59234a46", + "failure_summary": "1 failed, 223 passed in 2.50s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round6-closure_drops_upper_bound", + "round": 6, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": [ + { + "before": " params=context.params,\n upper_bound=upper_bound,\n", + "after": " params=context.params,\n" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_rib_above_the_canonical_rate_stays_an_input_error[0.10-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_rib_above_the_canonical_rate_stays_an_input_error[0.10-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_rib_above_the_canonical_rate_stays_an_input_error[1.00-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_rib_above_the_canonical_rate_stays_an_input_error[1.00-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_workers_compensation_caps_a_rib_at_its_canonical_rate", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions0-None]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions1-None]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions2-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions3-UnsupportedReason.WORKERS_COMPENSATION_OFFSET]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions4-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]" + ], + "failed_test_count": 36, + "log": { + "path": "scratch/review/round6-mutations/closure_drops_upper_bound.log", + "sha256": "697b55f7313402650984184ea603af0b268c1e64c06fc8b9ebc5c38ff6682556", + "failure_summary": "36 failed, 188 passed in 1.16s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "r2" + }, + { + "id": "round6-dib_cap_inclusive", + "round": 6, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": [ + { + "before": " and declared > state.pia\n", + "after": " and declared >= state.pia\n" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions0-None]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions1-None]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions2-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions3-UnsupportedReason.WORKERS_COMPENSATION_OFFSET]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions4-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions5-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions6-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[4-conditions0-None]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[4-conditions1-None]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[4-conditions2-UnsupportedReason.DIB_AFTER_REDUCED_RIB]" + ], + "failed_test_count": 22, + "log": { + "path": "scratch/review/round6-mutations/dib_cap_inclusive.log", + "sha256": "c93fbf65ca0d1dc38ce1673d51375f76edc4d91f0d1d2037d4ef77ba16ddd57a", + "failure_summary": "22 failed, 202 passed in 4.72s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "r2" + }, + { + "id": "round6-dib_no_cap", + "round": 6, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": [ + { + "before": " if (settled(\"F2\") and declared != state.pia) or (\n settled(\"F2\", upper_bound=True)\n and declared > state.pia\n ):", + "after": " if settled(\"F2\") and declared != state.pia:" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions0-None]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions1-None]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions2-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions3-UnsupportedReason.WORKERS_COMPENSATION_OFFSET]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions4-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions5-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions6-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[4-conditions0-None]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[4-conditions1-None]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[4-conditions2-UnsupportedReason.DIB_AFTER_REDUCED_RIB]" + ], + "failed_test_count": 27, + "log": { + "path": "scratch/review/round6-mutations/dib_no_cap.log", + "sha256": "27dfd952c77b12127ebf00a0279ce7cc4c06184799fddafa43d39aca24e1c857", + "failure_summary": "27 failed, 197 passed in 1.77s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "r2" + }, + { + "id": "round6-drc_settles_cap", + "round": 6, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " return state.kind is FamilyKind.SURVIVOR and (\n upper_bound or beneficiary.role in _WIDOW_ROLES\n )\n", + "after": " return state.kind is FamilyKind.SURVIVOR and (\n beneficiary.role in _WIDOW_ROLES\n )\n" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_deduction_cap_stays_open_under_widow_drc_protection" + ], + "failed_test_count": 1, + "log": { + "path": "scratch/review/round6-mutations/drc_settles_cap.log", + "sha256": "35b1cd1098ac0b33a5c9b19103385636925be2101a69b548372189c9292a8370", + "failure_summary": "1 failed, 223 passed in 2.94s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round6-drc_settles_widow", + "round": 6, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " return state.kind is FamilyKind.SURVIVOR and (\n upper_bound or beneficiary.role in _WIDOW_ROLES\n )\n", + "after": " return state.kind is FamilyKind.SURVIVOR and upper_bound\n" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_widow_drc_rate_stays_unsettled_for_the_widow_herself" + ], + "failed_test_count": 1, + "log": { + "path": "scratch/review/round6-mutations/drc_settles_widow.log", + "sha256": "c271933d6a5aae3ae51a6c68b0882dc882c6bec38696acb64132a45df6fd5213", + "failure_summary": "1 failed, 223 passed in 3.08s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round6-drc_unsettles_child", + "round": 6, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " return state.kind is FamilyKind.SURVIVOR and (\n upper_bound or beneficiary.role in _WIDOW_ROLES\n )\n", + "after": " return state.kind is FamilyKind.SURVIVOR\n" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_child_original_stays_settled_under_widow_drc_protection[100-300.10-True]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_child_original_stays_settled_under_widow_drc_protection[100-300.10-None]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_child_original_stays_settled_under_widow_drc_protection[1-3.10-True]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_child_original_stays_settled_under_widow_drc_protection[1-3.10-None]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_child_condition_alone_leaves_the_child_original_settled", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_deduction_cap_stays_open_under_widow_drc_protection", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_every_child_original_mismatch_errors_under_widow_drc" + ], + "failed_test_count": 7, + "log": { + "path": "scratch/review/round6-mutations/drc_unsettles_child.log", + "sha256": "f00b860da7e8906a534534b46858d900966e3c90bb7bcc809de7ebcdc4788a38", + "failure_summary": "7 failed, 217 passed in 5.47s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round6-dual_drop_f2", + "round": 6, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE: frozenset({\"F2\", \"F3\", \"F6\"})", + "after": "UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE: frozenset({\"F3\", \"F6\"})" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions4-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[4-conditions4-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[400-conditions4-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_each_reason_classifies_a_lower_dib[dual_entitlement_sequence]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_every_dib_at_or_below_the_cap_keeps_its_row" + ], + "failed_test_count": 5, + "log": { + "path": "scratch/review/round6-mutations/dual_drop_f2.log", + "sha256": "a5bbf75f764169ccedee0d88c56438e6c2c0a6582d575e8eeeec704c20749064", + "failure_summary": "5 failed, 219 passed in 2.52s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round6-dual_drop_f3", + "round": 6, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE: frozenset({\"F2\", \"F3\", \"F6\"})", + "after": "UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE: frozenset({\"F2\", \"F6\"})" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_published_rule_carryover_keeps_its_refusal[400-300-359.10]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_published_rule_carryover_keeps_its_refusal[1.20-.50-1.00]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_carryover_ends_at_cohort_1928[1926-False-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_carryover_ends_at_cohort_1928[1927-False-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_an_unknown_cohort_cannot_rule_out_the_carryover", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_each_reason_classifies_a_lower_rib[dual_entitlement_sequence]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_every_carryover_rate_keeps_its_row" + ], + "failed_test_count": 7, + "log": { + "path": "scratch/review/round6-mutations/dual_drop_f3.log", + "sha256": "fb7d16586797d5572c4200cc578292459bbc5c8619f27e420387c9e7f242d499", + "failure_summary": "7 failed, 217 passed in 4.26s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round6-f3_scope_skips_dual", + "round": 6, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " if fact == \"F3\" and hold in (\n UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE,\n UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978,\n ):", + "after": " if fact == \"F3\" and hold in (\n UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978,\n ):" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_carryover_ends_at_cohort_1928[1928-True-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_carryover_ends_at_cohort_1928[1929-True-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_zero_pia_leaves_no_rate_for_the_carryover_to_lower" + ], + "failed_test_count": 3, + "log": { + "path": "scratch/review/round6-mutations/f3_scope_skips_dual.log", + "sha256": "13d63f833dc67c7b6bd846e7b0c8861d7f29d141e985d294da62b069cc06c890", + "failure_summary": "3 failed, 221 passed in 2.98s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round6-f3_scope_skips_reduced", + "round": 6, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " if fact == \"F3\" and hold in (\n UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE,\n UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978,\n ):", + "after": " if fact == \"F3\" and hold in (\n UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE,\n ):" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_carryover_ends_at_cohort_1928[1928-True-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_carryover_ends_at_cohort_1928[1929-True-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]" + ], + "failed_test_count": 2, + "log": { + "path": "scratch/review/round6-mutations/f3_scope_skips_reduced.log", + "sha256": "3257e89568e4a44510127f0a83f2cdf6166c3db93d5ebaea19e92e07863605f4", + "failure_summary": "2 failed, 222 passed in 3.25s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round6-only_drop_dual", + "round": 6, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE,\n UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978,\n UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978,\n }\n)\n", + "after": " UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978,\n UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978,\n }\n)\n" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_an_unknown_cohort_cannot_rule_out_the_carryover", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_rib_above_the_canonical_rate_stays_an_input_error[0.10-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_rib_above_the_canonical_rate_stays_an_input_error[1.00-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions4-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[4-conditions4-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[400-conditions4-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_only_finality_lifts_an_nh_rate_cap[dib-dual_entitlement_sequence]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_only_finality_lifts_an_nh_rate_cap[rib-dual_entitlement_sequence]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_every_dib_at_or_below_the_cap_keeps_its_row", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_every_carryover_rate_keeps_its_row" + ], + "failed_test_count": 10, + "log": { + "path": "scratch/review/round6-mutations/only_drop_dual.log", + "sha256": "b6ee09e0a93088a3a364a7d448f2fef573698a42ab0f3339621a16bf80e3724c", + "failure_summary": "10 failed, 214 passed in 1.48s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round6-only_drop_own", + "round": 6, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE,\n UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978,\n UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978,\n }\n)\n", + "after": " UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE,\n UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978,\n }\n)\n" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_an_unknown_cohort_cannot_rule_out_a_pre_1978_history[UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions5-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[4-conditions5-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[400-conditions5-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_only_finality_lifts_an_nh_rate_cap[dib-own_rib_history_before_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_every_dib_at_or_below_the_cap_keeps_its_row" + ], + "failed_test_count": 6, + "log": { + "path": "scratch/review/round6-mutations/only_drop_own.log", + "sha256": "0e619a6dbaba6f053e17cc3b40c22e5642bde1d26e719ea538a0b46b97a879b6", + "failure_summary": "6 failed, 218 passed in 14.20s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round6-only_drop_rc_dib", + "round": 6, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " RecordCondition.DIB_AFTER_REDUCED_RIB,\n RecordCondition.WORKERS_COMPENSATION_OFFSET,\n UnsupportedReason.DIB_AFTER_REDUCED_RIB,", + "after": " RecordCondition.WORKERS_COMPENSATION_OFFSET,\n UnsupportedReason.DIB_AFTER_REDUCED_RIB," + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions0-None]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[4-conditions0-None]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[400-conditions0-None]" + ], + "failed_test_count": 3, + "log": { + "path": "scratch/review/round6-mutations/only_drop_rc_dib.log", + "sha256": "a0a802e5ef379564b908065c003c23a118e5199d40b9e1a07821f43dc87659f3", + "failure_summary": "3 failed, 221 passed in 2.68s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round6-only_drop_rc_wc", + "round": 6, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " RecordCondition.DIB_AFTER_REDUCED_RIB,\n RecordCondition.WORKERS_COMPENSATION_OFFSET,\n UnsupportedReason.DIB_AFTER_REDUCED_RIB,", + "after": " RecordCondition.DIB_AFTER_REDUCED_RIB,\n UnsupportedReason.DIB_AFTER_REDUCED_RIB," + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_workers_compensation_caps_a_rib_at_its_canonical_rate", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions1-None]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[4-conditions1-None]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[400-conditions1-None]" + ], + "failed_test_count": 4, + "log": { + "path": "scratch/review/round6-mutations/only_drop_rc_wc.log", + "sha256": "06cd4bd91fc856f08ee9d2c6f403eb791f94531d5e82aa2881cea59fdffe924a", + "failure_summary": "4 failed, 220 passed in 2.79s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round6-only_drop_reduced", + "round": 6, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE,\n UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978,\n UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978,\n }\n)\n", + "after": " UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE,\n UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978,\n }\n)\n" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_an_unknown_cohort_cannot_rule_out_a_pre_1978_history[UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_rib_above_the_canonical_rate_stays_an_input_error[0.10-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_rib_above_the_canonical_rate_stays_an_input_error[1.00-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions6-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[4-conditions6-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[400-conditions6-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_only_finality_lifts_an_nh_rate_cap[dib-reduced_benefit_history_before_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_only_finality_lifts_an_nh_rate_cap[rib-reduced_benefit_history_before_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_every_dib_at_or_below_the_cap_keeps_its_row", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_every_carryover_rate_keeps_its_row" + ], + "failed_test_count": 10, + "log": { + "path": "scratch/review/round6-mutations/only_drop_reduced.log", + "sha256": "d3cf4c96506e86869b3587725a3f4f2d5099bfe92e2b94966c03dec65adb268b", + "failure_summary": "10 failed, 214 passed in 22.15s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round6-only_drop_ur_dib", + "round": 6, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " UnsupportedReason.DIB_AFTER_REDUCED_RIB,\n UnsupportedReason.WORKERS_COMPENSATION_OFFSET,\n UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE,", + "after": " UnsupportedReason.WORKERS_COMPENSATION_OFFSET,\n UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE," + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions2-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[4-conditions2-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[400-conditions2-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_only_finality_lifts_an_nh_rate_cap[dib-dib_after_reduced_rib]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_every_dib_at_or_below_the_cap_keeps_its_row" + ], + "failed_test_count": 5, + "log": { + "path": "scratch/review/round6-mutations/only_drop_ur_dib.log", + "sha256": "30643bf93258094a29710f7bdfaec18526775eff7b300c8ba2e9679c59c9a02a", + "failure_summary": "5 failed, 219 passed in 13.44s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round6-only_drop_ur_wc", + "round": 6, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " UnsupportedReason.DIB_AFTER_REDUCED_RIB,\n UnsupportedReason.WORKERS_COMPENSATION_OFFSET,\n UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE,", + "after": " UnsupportedReason.DIB_AFTER_REDUCED_RIB,\n UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE," + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions3-UnsupportedReason.WORKERS_COMPENSATION_OFFSET]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[4-conditions3-UnsupportedReason.WORKERS_COMPENSATION_OFFSET]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[400-conditions3-UnsupportedReason.WORKERS_COMPENSATION_OFFSET]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_only_finality_lifts_an_nh_rate_cap[dib-workers_compensation_offset]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_only_finality_lifts_an_nh_rate_cap[rib-workers_compensation_offset]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_every_dib_at_or_below_the_cap_keeps_its_row" + ], + "failed_test_count": 6, + "log": { + "path": "scratch/review/round6-mutations/only_drop_ur_wc.log", + "sha256": "e83adc2929eccb79d1a2114ad336b559beca1c65e58a631a0ddcbd5ad7c076f9", + "failure_summary": "6 failed, 218 passed in 14.80s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round6-own_history_drop_f2", + "round": 6, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978: frozenset(\n {\"F2\", \"F3\", \"F6\"}\n )", + "after": "UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978: frozenset(\n {\"F3\", \"F6\"}\n )" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_an_unknown_cohort_cannot_rule_out_a_pre_1978_history[UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions5-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[4-conditions5-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[400-conditions5-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_pre_1978_history_reaches_only_cohorts_old_enough_for_it[1927-False-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_each_reason_classifies_a_lower_dib[own_rib_history_before_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_every_dib_at_or_below_the_cap_keeps_its_row" + ], + "failed_test_count": 7, + "log": { + "path": "scratch/review/round6-mutations/own_history_drop_f2.log", + "sha256": "aa3d8489455666939d568349964e4e5bd3ace6b5235bb78af15bbb4e74e4d4dd", + "failure_summary": "7 failed, 217 passed in 5.83s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round6-pre1978_cohort_1927", + "round": 6, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "_FIRST_COHORT_WITHOUT_PRE_1978_REDUCTION = 1928", + "after": "_FIRST_COHORT_WITHOUT_PRE_1978_REDUCTION = 1927" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions5-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions6-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[4-conditions5-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[4-conditions6-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[400-conditions5-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[400-conditions6-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_pre_1978_history_reaches_only_cohorts_old_enough_for_it[1927-False-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_pre_1978_history_reaches_only_cohorts_old_enough_for_it[1927-False-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_each_reason_classifies_a_lower_dib[own_rib_history_before_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_each_reason_classifies_a_lower_dib[reduced_benefit_history_before_1978]" + ], + "failed_test_count": 11, + "log": { + "path": "scratch/review/round6-mutations/pre1978_cohort_1927.log", + "sha256": "da766acd2a5f419a3506bcf52c3940d643023a128c453400bd212b3fdb9b0e6e", + "failure_summary": "11 failed, 213 passed in 3.53s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round6-pre1978_cohort_1929", + "round": 6, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "_FIRST_COHORT_WITHOUT_PRE_1978_REDUCTION = 1928", + "after": "_FIRST_COHORT_WITHOUT_PRE_1978_REDUCTION = 1929" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_pre_1978_history_reaches_only_cohorts_old_enough_for_it[1928-True-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_pre_1978_history_reaches_only_cohorts_old_enough_for_it[1928-True-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]" + ], + "failed_test_count": 2, + "log": { + "path": "scratch/review/round6-mutations/pre1978_cohort_1929.log", + "sha256": "a2c02c16b02d4c2679fc4c96ec2136744a496df61fc6ed95403a372d71b7bd5e", + "failure_summary": "2 failed, 222 passed in 2.60s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round6-pre1978_unknown_cohort_settled", + "round": 6, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " cohort is None or cohort < _FIRST_COHORT_WITHOUT_PRE_1978_REDUCTION", + "after": " cohort is not None\n and cohort < _FIRST_COHORT_WITHOUT_PRE_1978_REDUCTION" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_an_unknown_cohort_cannot_rule_out_a_pre_1978_history[UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_an_unknown_cohort_cannot_rule_out_a_pre_1978_history[UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]" + ], + "failed_test_count": 2, + "log": { + "path": "scratch/review/round6-mutations/pre1978_unknown_cohort_settled.log", + "sha256": "9d89da52425f6e2b8912987fe14ea978afbecf09b59ad1f86f17b2f6044c38cf", + "failure_summary": "2 failed, 222 passed in 2.63s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round6-pre1978_unscoped", + "round": 6, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " cohort = state.worker_birth_year\n return (\n cohort is None or cohort < _FIRST_COHORT_WITHOUT_PRE_1978_REDUCTION\n )\n", + "after": " return True\n" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_pre_1978_history_reaches_only_cohorts_old_enough_for_it[1928-True-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_pre_1978_history_reaches_only_cohorts_old_enough_for_it[1928-True-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_pre_1978_history_reaches_only_cohorts_old_enough_for_it[1960-True-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_pre_1978_history_reaches_only_cohorts_old_enough_for_it[1960-True-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]" + ], + "failed_test_count": 4, + "log": { + "path": "scratch/review/round6-mutations/pre1978_unscoped.log", + "sha256": "771a624078a9ad60c78306fb9c17fa4be48f0c0a718cce5c1ace49469e1c16eb", + "failure_summary": "4 failed, 220 passed in 3.02s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round6-reduced_history_drop_f2", + "round": 6, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978: frozenset(\n {\"F2\", \"F3\"}\n )", + "after": "UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978: frozenset(\n {\"F3\"}\n )" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_an_unknown_cohort_cannot_rule_out_a_pre_1978_history[UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[0.10-conditions6-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[4-conditions6-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_a_reducing_hold_bounds_a_dib_at_its_pia[400-conditions6-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_pre_1978_history_reaches_only_cohorts_old_enough_for_it[1927-False-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_each_reason_classifies_a_lower_dib[reduced_benefit_history_before_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_every_dib_at_or_below_the_cap_keeps_its_row" + ], + "failed_test_count": 7, + "log": { + "path": "scratch/review/round6-mutations/reduced_history_drop_f2.log", + "sha256": "782b574a51118e633d98f6bdda038a50efd59dad372e79da12860589f46ebe26", + "failure_summary": "7 failed, 217 passed in 4.03s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round6-reduced_history_drop_f3", + "round": 6, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978: frozenset(\n {\"F2\", \"F3\"}\n )", + "after": "UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978: frozenset(\n {\"F2\"}\n )" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_carryover_ends_at_cohort_1928[1926-False-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_carryover_ends_at_cohort_1928[1927-False-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_each_reason_classifies_a_lower_rib[reduced_benefit_history_before_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_every_carryover_rate_keeps_its_row" + ], + "failed_test_count": 4, + "log": { + "path": "scratch/review/round6-mutations/reduced_history_drop_f3.log", + "sha256": "3f196f1033e43730fed5ec764a1dcc777a2ec2e94493e05e517c1a24cf073ccd", + "failure_summary": "4 failed, 220 passed in 6.25s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round6-rib_cap_inclusive", + "round": 6, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": [ + { + "before": " if declared > gross or (\n", + "after": " if declared >= gross or (\n" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_rib_at_the_canonical_rate_keeps_its_refusal[UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_rib_at_the_canonical_rate_keeps_its_refusal[UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_every_carryover_rate_keeps_its_row" + ], + "failed_test_count": 3, + "log": { + "path": "scratch/review/round6-mutations/rib_cap_inclusive.log", + "sha256": "90878ec82c2c5bc6329ec9392d7a42328c060ced4af1c909c5d38eed0fe17a44", + "failure_summary": "3 failed, 221 passed in 1.87s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "r2" + }, + { + "id": "round6-rib_gate_exact", + "round": 6, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": [ + { + "before": " elif settled(\"F3\", upper_bound=True):\n", + "after": " elif settled(\"F3\"):\n" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_rib_above_the_canonical_rate_stays_an_input_error[0.10-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_rib_above_the_canonical_rate_stays_an_input_error[0.10-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_rib_above_the_canonical_rate_stays_an_input_error[1.00-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_rib_above_the_canonical_rate_stays_an_input_error[1.00-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_workers_compensation_caps_a_rib_at_its_canonical_rate", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_only_finality_lifts_an_nh_rate_cap[rib-workers_compensation_offset]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_only_finality_lifts_an_nh_rate_cap[rib-dual_entitlement_sequence]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_only_finality_lifts_an_nh_rate_cap[rib-reduced_benefit_history_before_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_every_carryover_rate_keeps_its_row" + ], + "failed_test_count": 9, + "log": { + "path": "scratch/review/round6-mutations/rib_gate_exact.log", + "sha256": "9e4a0a2e53a15bfb385ed028247a0c57533a6e0f812a14dbb8c605a12edd2698", + "failure_summary": "9 failed, 215 passed in 1.81s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "r2" + }, + { + "id": "round6-rib_no_cap", + "round": 6, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": [ + { + "before": " if declared > gross or (\n settled(\"F3\") and declared != gross\n ):", + "after": " if settled(\"F3\") and declared != gross:" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_rib_above_the_canonical_rate_stays_an_input_error[0.10-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_rib_above_the_canonical_rate_stays_an_input_error[0.10-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_rib_above_the_canonical_rate_stays_an_input_error[1.00-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_rib_above_the_canonical_rate_stays_an_input_error[1.00-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_workers_compensation_caps_a_rib_at_its_canonical_rate", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_only_finality_lifts_an_nh_rate_cap[rib-workers_compensation_offset]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_only_finality_lifts_an_nh_rate_cap[rib-dual_entitlement_sequence]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_only_finality_lifts_an_nh_rate_cap[rib-reduced_benefit_history_before_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_every_carryover_rate_keeps_its_row" + ], + "failed_test_count": 9, + "log": { + "path": "scratch/review/round6-mutations/rib_no_cap.log", + "sha256": "32aaad22cf546689e07bb6632433148172875544d51f6fa7673d62096fba674f", + "failure_summary": "9 failed, 215 passed in 1.99s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "r2" + }, + { + "id": "round6-rib_no_equality", + "round": 6, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": [ + { + "before": " if declared > gross or (\n settled(\"F3\") and declared != gross\n ):", + "after": " if declared > gross:" + } + ], + "command": [ + "python", + "scratch/review/run_round6_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_6.py" + ], + "outer_command": [ + "python", + "scratch/review/round6_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round6", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round6", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_6.py::test_carryover_ends_at_cohort_1928[1928-True-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_carryover_ends_at_cohort_1928[1928-True-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_carryover_ends_at_cohort_1928[1929-True-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_carryover_ends_at_cohort_1928[1929-True-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_each_reason_classifies_a_lower_rib[eligibility_before_1983]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_each_reason_classifies_a_lower_rib[payment_month_before_1983]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_each_reason_classifies_a_lower_rib[di_entitlement_before_july_1980]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_each_reason_classifies_a_lower_rib[combined_family_maximum]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_each_reason_classifies_a_lower_rib[deemed_or_putative_spouse]", + "tests/test_track_b_ret_ledger_fix_round_6.py::test_each_reason_classifies_a_lower_rib[parent_benefit]" + ], + "failed_test_count": 38, + "log": { + "path": "scratch/review/round6-mutations/rib_no_equality.log", + "sha256": "dbd9605c30d1e23029a2bd1d246526f6688dd723ad42fe12588f3c87fc76302f", + "failure_summary": "38 failed, 186 passed in 2.45s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "r2" } ], "restoration_verification_snapshot": { @@ -4450,5 +6651,11 @@ "round_5_restoration_snapshot": { "src/populace_dynamics/track_b/gross_benefits.py": "d51f5d77c7aa7cf6004392e27187ce89523151fef12148088565226f7444fb64", "src/populace_dynamics/track_b/ret_ledger.py": "2aa5eff5e4f88f4a7dd3104c7aafeac60f6460faa132a53f8834ce0b0ef72587" + }, + "round_6_head": "a135519fbfb2a3ebf9fd9c052a4619cdcedff2ca", + "round_6_note": "38 fresh one-line semantic mutations failed named tests in tests/test_track_b_ret_ledger_fix_round_6.py on the final test bytes. A first pass left two survivors, each a test gap, and the module gained a test for each before this run. The session ran these in copied source trees, and production sources stayed unchanged. Earlier records remain historical.", + "round_6_restoration_snapshot": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" } } diff --git a/docs/design/track_b_g2_r2b_verification.json b/docs/design/track_b_g2_r2b_verification.json index 813fe0b54..55ff328f4 100644 --- a/docs/design/track_b_g2_r2b_verification.json +++ b/docs/design/track_b_g2_r2b_verification.json @@ -12998,5 +12998,84 @@ "ledger": "docs/design/track_b_g2_r2b_mutations.json" } }, - "round_5_current_evidence_note": "Fresh reviewed-head failing-first, named module gates, cross-head diagnostic and isolated mutation evidence is under round_5. Earlier heads, counts and commands remain historical. No tier-policy or birth-evidence local run and no whole-suite collection." + "round_5_current_evidence_note": "Fresh reviewed-head failing-first, named module gates, cross-head diagnostic and isolated mutation evidence is under round_5. Earlier heads, counts and commands remain historical. No tier-policy or birth-evidence local run and no whole-suite collection.", + "round_6": { + "reviewed_head": "a135519fbfb2a3ebf9fd9c052a4619cdcedff2ca", + "workspace": "/Users/maxghenis/PolicyEngine/_clones/mdyn-trackb-g2-20261023", + "verification_class": "statutory_conformance", + "admitted_scope": "Invented declarations and captured published examples only; no population, behavioral or forecast claim.", + "fixed_by": "the session, because every Codex lane was held", + "named_test_gate": { + "selection": "tests/test_track_b_*.py", + "result": "13874 passed, 7 skipped in 838.63s (0:13:58)", + "environment": "both data roots set to a nonexistent path" + }, + "failing_first": { + "reviewed_head": "a135519fbfb2a3ebf9fd9c052a4619cdcedff2ca", + "module": "tests/test_track_b_ret_ledger_fix_round_6.py", + "result": "50 failed, 174 passed in 6.29s" + }, + "cross_head": { + "r2_stable_rows": 240, + "r3_stable_rows": 240, + "identical_declared_output_bytes": true, + "stable_sha256": "799fc9e23a902ac1ca0c2563579ceb094d0dbcd631a912305c40062cf21a5f55" + }, + "conformance_report_sha256": "17d144575b38bb85080d8cbed28fad470ec93fd6eb6803b48729bb26a78b3d45", + "conformance_report_byte_identical": true, + "tier_policy": "Left to CI; no local whole-suite collection.", + "final_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + }, + "final_test_sha256": { + "tests/test_track_b_ret_ledger_fix_round_4.py": "02c5c86b64070f9e7350868f8d94dcc9233bedc32cbcae32b3264f9ae570d1bb", + "tests/test_track_b_ret_ledger_fix_round_5.py": "c86ef045d797e31d6db09ef11bc7fbfbcf7c1fa54d32f04e7b6b42e8b813c9cd", + "tests/test_track_b_ret_ledger_fix_round_6.py": "4979b4ae4fc434f540fed293ad1fc44cf0508aaaffa95e7ed3ec00e3c4c9fd6c" + }, + "mutations": { + "count": 38, + "ids": [ + "round6-cap_lifts_equality", + "round6-cap_never_settled", + "round6-cap_scope_f2_only", + "round6-cap_scope_f3_only", + "round6-carryover_any_kind", + "round6-carryover_cohort_1927", + "round6-carryover_cohort_1929", + "round6-carryover_unknown_cohort_settled", + "round6-carryover_unscoped", + "round6-carryover_zero_pia", + "round6-closure_drops_upper_bound", + "round6-dib_cap_inclusive", + "round6-dib_no_cap", + "round6-drc_settles_cap", + "round6-drc_settles_widow", + "round6-drc_unsettles_child", + "round6-dual_drop_f2", + "round6-dual_drop_f3", + "round6-f3_scope_skips_dual", + "round6-f3_scope_skips_reduced", + "round6-only_drop_dual", + "round6-only_drop_own", + "round6-only_drop_rc_dib", + "round6-only_drop_rc_wc", + "round6-only_drop_reduced", + "round6-only_drop_ur_dib", + "round6-only_drop_ur_wc", + "round6-own_history_drop_f2", + "round6-pre1978_cohort_1927", + "round6-pre1978_cohort_1929", + "round6-pre1978_unknown_cohort_settled", + "round6-pre1978_unscoped", + "round6-reduced_history_drop_f2", + "round6-reduced_history_drop_f3", + "round6-rib_cap_inclusive", + "round6-rib_gate_exact", + "round6-rib_no_cap", + "round6-rib_no_equality" + ] + } + }, + "round_6_current_evidence_note": "Fresh reviewed-head failing-first, named module gates, cross-head diagnostic and copied-tree mutation evidence sits under round_6. Earlier heads, counts and commands remain historical." } diff --git a/docs/design/track_b_r2_ret_ledger.md b/docs/design/track_b_r2_ret_ledger.md index 590bbbbec..a66baae50 100644 --- a/docs/design/track_b_r2_ret_ledger.md +++ b/docs/design/track_b_r2_ret_ledger.md @@ -2105,14 +2105,14 @@ and auxiliary gross remain comparisons against a completed G result. | Declared condition | Facts unsettled | Captured quotation and inference | | --- | --- | --- | | `ADMINISTRATIVE_FINALITY` | F1–F6 for the record | RS 00615.754A.3 says "the rate to the NH is protected by administrative finality and cannot be changed" and requires recording "the PIA and maximum used to arrive at those rates". The second example protects both NH and child on "the protected PIA and maximum". The declared correct PIA need not be the protected-rate basis. | -| `DIB_AFTER_REDUCED_RIB` | F2 | Captured Act 202(q)(2): "such disability insurance benefit for each month shall be reduced by the amount such old-age insurance benefit would be reduced". This changes the DIB payable rather than its original PIA share. | -| `WORKERS_COMPENSATION_OFFSET` | F2, F3 | Captured Act 215(g) places rounding "after any reduction under sections 203(a) and 224". GN 02603.050C separately lists the "Workers’ compensation (WC) or public disability benefit (PDB) offset amount" after defining OB. The ordinary own-benefit amount cannot establish the offset amount. | +| `DIB_AFTER_REDUCED_RIB` | F2 below the PIA | Captured Act 202(q)(2): "such disability insurance benefit for each month shall be reduced by the amount such old-age insurance benefit would be reduced". This changes the DIB payable rather than its original PIA share. It can only lower the rate, so the PIA stays the cap (round 6). | +| `WORKERS_COMPENSATION_OFFSET` | F2 and F3 below the ordinary rate | Captured Act 215(g) places rounding "after any reduction under sections 203(a) and 224". GN 02603.050C separately lists the "Workers’ compensation (WC) or public disability benefit (PDB) offset amount" after defining OB. The ordinary own-benefit amount cannot establish the offset amount. 20 CFR 404.408(c)(1) says the total "is reduced monthly (but not below zero)", so the ordinary rate stays the cap (round 6). | | `DIB_GUARANTEE_PIA` | None | RS 00615.736B.2 begins "To establish a family maximum for a DIB Guarantee PIA". G is supplied the applicable PIA; the refused calculation is its maximum. | | `NON_AIME_FORMULA_PIA` | None | RS 00615.740B.1 says "The PIA is an AIME, OS, Special Minimum or Frozen Minimum PIA." The page concerns "determining the total amount of the family maximum benefit"; it does not replace the declared applicable PIA. | | `WORKER_NOT_ENTITLED` | None | RS 00202.100 says "the NH is eligible but has not filed for benefits". This changes the declared NH entitlement and permitted roster; those identities are checked separately before money. | | `WINDFALL_ELIMINATION_PROVISION` | None | RS 00202.100 says an IEDS "is subject to the number holder’s (NH) WEP PIA although the NH is not yet entitled". The supplied applicable PIA remains the OB basis; unsupported pre-repeal IEDS processing keeps its refusal. | | `RATE_PROTECTED_BY_FINALITY` | F4–F6 for that beneficiary | RS 00615.754A.3 directs SSA to document "which rates are protected by administrative finality". Protection is specific to the beneficiary declared with this condition; the NH and other auxiliary facts remain subject to their own settlement checks. | -| `WIDOW_DRC_SAVINGS_CLAUSE` | F4 for that survivor | RS 00615.712 protects "beneficiaries who were entitled for the month of 5/78"; its example says "the child is protected by the savings clause and the child's rate will remain at $300". The protected rate basis is not silently reconstructed. | +| `WIDOW_DRC_SAVINGS_CLAUSE` | F4 for a widow(er) on that survivor record, and the OB cap on deductions for anyone on it | RS 00615.712 protects "beneficiaries who were entitled for the month of 5/78"; its example says "the child is protected by the savings clause and the child's rate will remain at $300". Its Step 2 says "The child's original rate is $300", on a PIA that stays $400, so the clause leaves a nonwidow's OB settled (round 6). The widow's rate is $400 or, with DRCs, $410. The capture states no cap on protected cash, so that bound stays open. | | `ENTITLED_ON_ANOTHER_RECORD` | None | RS 00615.770: "Maximums from all SSNs that the child is entitled on may be combined on the SSN where payment is actually made." This changes the maximum allocation rather than the role's OB or own-PIA eligibility test. | | `DEEMED_OR_PUTATIVE_SPOUSE` | None | RS 00615.684: "The deemed or putative spouse and all other beneficiaries on the record are reduced for the maximum." Its original spouse rate and raw own-PIA test remain the same quantities. | | `LEGAL_SPOUSE_WITH_DEEMED_SPOUSE` | None | RS 00615.684: "the legal spouse is paid outside the family maximum" and "the legal spouse will receive the OB" when DMAX applies. This changes maximum membership. | @@ -2137,17 +2137,17 @@ member separately. | Held refusal or origin | Facts whose comparison can be unsettled | Captured basis | | --- | --- | --- | -| `_refuse_own_benefit`: reduced own DIB; historical own RIB; pre-1917 delayed credits | The affected own MBA used for F3 or F6; F2 for the NH reduced-DIB reason | Act 202(q)(2) expressly reduces DIB. RS 00615.005C.2 requires the money-history method in "all cases involving single entitlement to actuarially reduced benefits prior to 1/78". RS 00615.692D gives "Before 01/02/17" a "1/12%" monthly credit. The canonical helper refuses rather than fabricating an MBA. | +| `_refuse_own_benefit`: reduced own DIB; historical own RIB; pre-1917 delayed credits | The affected own MBA used for F3 or F6; F2 below the PIA for the NH reduced-DIB reason and, before cohort 1928, for the own-RIB history reason | Act 202(q)(2) expressly reduces DIB. RS 00615.005C.2 requires the money-history method in "all cases involving single entitlement to actuarially reduced benefits prior to 1/78". RS 00615.692D gives "Before 01/02/17" a "1/12%" monthly credit. The canonical helper refuses rather than fabricating an MBA. | | `PAYMENT_MONTH_BEFORE_1983` | Historical own MBA used for F3/F6; nonwidow auxiliary OB in actual pre-1983 months; survivor widow OB before January 1973 | RS 00615.101 says "Round the result down to the next dime for benefits after 5/82 and up to the next dime for benefits prior to 6/82." The captures do not establish unchanged modern dime-floored nonwidow OB throughout G's refused historical interval. RS 00615.005A.2 says "Raised the unreduced benefit amount for widow(er)s to 82 1/2% at age 62." Its A.5 says "Changed WIB to 100% of the deceased worker's PIA" effective January 1973. Actual payment dates determine which exact facts remain unsettled; a deferred payment reason cannot manufacture an earlier date. | | `ELIGIBILITY_BEFORE_1983`, `DI_ENTITLEMENT_BEFORE_JULY_1980` | None | RS 00615.736 gives the historical maximum procedure; RS 00615.740B.2 says DMAX does not apply when "The NH was ever entitled to DIB before July 1980". These maximum histories do not replace role OB or current own-benefit facts. | | `PARENT_BENEFIT` | F4/F6 when parent count refuses | RS 00209.001 excludes own RIB "equal to or exceeding the amount of the parent's original benefit (One parent = 82 1/2%; Two parents = 75%)". RS 00209.015 states "Benefit rate equals 75% of the worker's PIA for each month both are entitled." An unresolved entitled-parent count leaves both threshold and OB unsettled. | | `DISABLED_WIDOW_UNDER_60` | No additional fact beyond a separately refusing own MBA | RS 00615.310C first says "Determine the WIB OB", then separately determines and subtracts reductions. The historical extra reduction changes gross, not F4's OB. | -| `DUAL_ENTITLEMENT_SEQUENCE` | F6 only where historical carryover can change own RIB | RS 00615.005A.8 says "Eliminated the carry-over reduction in RIB or DIB due to WIB before age 62" and applies the RIB change to workers born January 2, 1928 or later. RS 00615.010 preserves the earlier rule: "If there was prior entitlement to a reduced WIB in any month before the month of attainment of age 62 reduce the RIB per RS 00615.160 and RS 00615.170." The schema omits that history. Modern WIB/DWB election instead requires "if all eligibility requirements are met" and preserves "the PIA and the reduction factors remain the same" (RS 00615.315). It does not waive F6. A nonnegative own RIB cannot be less than a zero deemed-death PIA. The spouse raw own-PIA test stays F5. | -| `REDUCED_BENEFIT_HISTORY_BEFORE_1978` | No additional fact beyond a separately refusing own MBA | RS 00615.005C.2 requires historical money reductions. That does not change the original benefit determined before reduction. | +| `DUAL_ENTITLEMENT_SEQUENCE` | F2 below the PIA; F3 below the ordinary rate and F6, each only where historical carryover can change own RIB | 20 CFR 404.411(b) reduces a DIB after a reduced RIB and, for "all individuals born before January 2, 1928" or a disability before 1990, after a WIB. The schema omits the onset, so F2 stays open in every cohort. 404.411(c)(2) reduces an old-age benefit "by the larger of the following" for a person born before January 2, 1928, even one who met every WIB condition "except that the old-age benefit equals or exceeds the primary insurance amount", so no current WIB or auxiliary record needs to appear. Both only lower a rate, so the ordinary rate stays the cap (round 6). RS 00615.005A.8 says "Eliminated the carry-over reduction in RIB or DIB due to WIB before age 62" and applies the RIB change to workers born January 2, 1928 or later. RS 00615.010 preserves the earlier rule: "If there was prior entitlement to a reduced WIB in any month before the month of attainment of age 62 reduce the RIB per RS 00615.160 and RS 00615.170." The schema omits that history. Modern WIB/DWB election instead requires "if all eligibility requirements are met" and preserves "the PIA and the reduction factors remain the same" (RS 00615.315). It does not waive F6. A nonnegative own RIB cannot be less than a zero deemed-death PIA. The spouse raw own-PIA test stays F5. | +| `REDUCED_BENEFIT_HISTORY_BEFORE_1978` | F2 below the PIA and, within the carryover scope above, F3 below the ordinary rate; each only before cohort 1928 | RS 00615.005C.2 requires historical money reductions. That does not change the original benefit determined before reduction, but the 404.411 rules above carry such a reduction into a later DIB or RIB. RS 00615.005A.7 gives age 50 as the earliest reduced disabled widow(er), so cohort 1928 reached no reduced benefit before 1978 (round 6). | | `INDEPENDENT_DIVORCED_SPOUSE` | None | RS 00202.100 identifies the unfiled NH and requires the applicable WEP PIA; the declared PIA and eligibility facts are still the inputs. | | `COMBINED_FAMILY_MAXIMUM`, `MULTIPLE_AUXILIARY_RECORDS`, `DEEMED_SPOUSE`, `NON_AIME_FORMULA_PIA`, `DIB_GUARANTEE_PIA`, `GOVERNMENT_PENSION_OFFSET` | None | The condition table's captured maximum-membership, maximum-formula and payable-offset rules apply equally when the reason is deferred. | | `PARISI_AMBIGUOUS`, `PARISI_BEFORE_OCTOBER_1999` | None | RS 00615.768E says the change affects benefits "after reduction for the maximum" and "Beneficiaries will still be limited by the original benefit amount." | -| `WIDOW_DRC_SAVINGS_CLAUSE`, `WIDOW_DRC_SAVINGS_CLAUSE_HISTORY_UNKNOWN` | F4 for the potentially protected survivor | RS 00615.712's protection is specific to May 1978 survivors and can preserve a different original rate basis. Unknown history does not establish absence of that protection. | +| `WIDOW_DRC_SAVINGS_CLAUSE`, `WIDOW_DRC_SAVINGS_CLAUSE_HISTORY_UNKNOWN` | F4 for a widow(er), and the OB cap on deductions for anyone on the survivor record | RS 00615.712's protection is specific to May 1978 survivors. It preserves cash, not a different original rate: the child's OB stays 75% of the PIA. Only a widow(er)'s OB carries DRCs. Unknown history does not establish absence of that protection, so a widow(er)'s OB and protected cash stay open. | | `WIDOW_CHILD_IN_CARE_UNKNOWN`, `DIVORCED_SPOUSE_CHILD_IN_CARE_UNKNOWN`, `DIVORCED_SPOUSE_CARE_HISTORY` | None | RS 00615.340 begins with a person already "receiving a reduced widow(er) benefit" and says "The benefit amount is raised for all months the child is in care." RS 00615.201 changes age reduction/conversion when care ends. These change gross or reduction history after OB and entitlement. | | `SAVINGS_CLAUSE`, `SAVINGS_CLAUSE_HISTORY_UNKNOWN`, `SAVINGS_CLAUSE_MEMBERSHIP_CHANGE`, `SAVINGS_CLAUSE_RATE_PROCEDURE` | None for F1–F6 | RS 00630.400 says "Any person's benefit may not exceed the original benefit (OB)" and adds "the new PIA in a life case" to the savings maximum. The refusal concerns carried allocation/rate procedure rather than the ordinary OB, NH own benefit or raw own-benefit entitlement. | | `PRISONER_SUSPENSION`, `DRUG_ADDICTION_SUSPENSION`, `FOREIGN_WORK_DEDUCTION`, `PENALTY_DEDUCTION`, `MARITIME_DEDUCTION`, `ELECTION_CERTIFICATE_SUSPENSION` | None | GN 02603.040 calls these "deductions" and suspensions. GN 02603.050B first applies the maximum, then deductions, then redistribution. They do not alter the pre-reduction facts F1–F6. | @@ -2285,7 +2285,7 @@ examples and Hypothesis properties: | Canonically matching zero and positive declarations never raise a preflight input error under any condition | Hypothesis `test_matching_declarations_never_raise_input_errors` | | Valid outcomes and refusal reasons equal the path with preflight removed, exactly | Hypothesis `test_preflight_changes_no_valid_outcome_or_refusal` | | Deferred reason labels do not unsettle unrelated canonical facts, roles, record kinds or actual payment dates | `test_deferred_reason_unsettles_only_the_fact_within_its_scope` | -| Widow DRC protection applies to survivors; its beneficiary flag leaves a living child's OB settled | `test_widow_drc_condition_on_a_living_child_keeps_ob_settled`; `test_survivor_widow_drc_protection_keeps_its_original_refusal`; explicit Hypothesis example in `test_held_against_unheld_fact_classification` | +| Widow DRC protection applies to survivors; its beneficiary flag leaves a living child's OB settled; round 6 settles every nonwidow's OB | `test_widow_drc_condition_on_a_living_child_keeps_ob_settled`; `test_survivor_widow_drc_protection_keeps_its_original_refusal`; explicit Hypothesis example in `test_held_against_unheld_fact_classification` | | A pre-1973 widow's 82.5% OB preserves the historical refusal; the same declaration contradicts the 100% OB from January 1973 | `test_historical_widow_original_benefit_uses_the_payment_period` | | Protection remains local to its declared beneficiary, month and condition union | `test_beneficiary_finality_protects_its_own_unsettled_fact`; `test_one_beneficiary_finality_does_not_protect_the_nh`; `test_protected_auxiliary_does_not_protect_another_auxiliary`; `test_finality_is_resolved_for_each_month`; `test_two_declared_conditions_preserve_finality_protection` | | A shared reason does not broaden an explicit condition or hide a later implicit sequence refusal | `test_spouse_sequence_condition_does_not_unsettle_other_own_eligibility`; `test_implicit_widow_history_remains_unsettled_behind_explicit_hold` | @@ -2306,14 +2306,96 @@ examples and Hypothesis properties: Protected eligibility can affect another survivor indirectly: an ordinary own-RIB disqualification cannot exclude a finality-protected widow from possible May 1978 DRC protection. A protected OB likewise cannot establish -absence of a larger protected basis. Unknown history therefore retains the -original finality refusal. An explicit `widow_drc_savings_clause=False` -settles that absence and leaves the other child's F4 checked. This is a -dependency through independently unknown history, not a record-wide -finality exemption (RS 00615.712 and .754A.3). +absence of a larger protected basis. Unknown history therefore keeps the +child's OB cap on a deduction open and retains the original finality +refusal there. An explicit `widow_drc_savings_clause=False` settles that +absence and applies the cap. The child's own OB stays checked in both +cases since round 6. This is a dependency through independently unknown +history, not a record-wide finality exemption (RS 00615.712 and .754A.3). Maximum binding and auxiliary gross comparisons remain after successful G. Public validation still runs once; no monetary rule is reimplemented. The exact first-failure evidence, deliberate mutations and adversarial cases are recorded in `scratch/review/fix-round-5-report.md` and the existing machine-readable verification and mutation records. + +## PR 563 round 6: rates a hold can lower + +GPT-6.1 Sol reviewed `a135519f` and asked for changes, with three medium +findings. All three reproduced. Each came from a table that treated a fact +as wholly open or wholly settled, when the sources settle one direction of +it. Two kept a row that should raise, and one dropped a row that should stay. + +### What changed + +**A widow's DRC clause doesn't reach a child's original rate.** Round 5 +read RS 00615.712 as preserving a different original rate basis. The +capture says otherwise: "The child's original rate is $300", and "The MBR +will show a PIA of $400.00". The clause protects the adjusted cash. So a +$3.10 original against OB $3.00 now raises under `True` and under unknown +history, as it does under `False`. A widow(er) stays open: the same page +gives her $400 and, with DRCs, $410. No other survivor's OB carries DRCs. + +**A prior reduced WIB can lower an NH's own RIB.** 20 CFR 404.411(c)(2) +keeps the carryover for a person born before January 2, 1928, and reaches +someone never entitled to a current WIB because "the old-age benefit +equals or exceeds the primary insurance amount". Round 5 opened this for +another person's own RIB (F6) and missed the NH's (F3). So PIA $400, +deceased PIA $300, first WIB at 60 and RIB at 64 gives $359.10 against an +ordinary $373.30. That declaration raised and lost its row. It now keeps +`dual_entitlement_sequence` with weight 7. Cohort 1928 stays settled: +404.411(c)(1) says "There is no further reduction." + +**A reducing hold keeps its cap.** Round 5 skipped the exact DIB comparison +under a prior reduced RIB or workers' compensation, which also skipped the +direction those sources settle. A DIB of $4.10 on PIA $4 counted as a +refusal. It now raises. Every NH reduction-only hold, listed in +`_NH_REDUCTION_ONLY_HOLDS`, leaves equality open below the rate and keeps +the rate as a cap. Administrative finality alone lifts a cap, because it +can protect a rate built on another PIA. + +**The same class, beyond the findings.** Sol's exploratory probe of a DIB +after a reduced WIB (404.411(b)) didn't enter its verdict. The session +tested it and found the same lost row: $398.10 on PIA $400 raised under +`dual_entitlement_sequence`. F2 now stays open below the PIA for that +reason in every cohort, because the schema omits the disability onset +that scopes 404.411(b)(2). `OWN_RIB_HISTORY_BEFORE_1978` and +`REDUCED_BENEFIT_HISTORY_BEFORE_1978` open it too, before cohort 1928 only: +a later cohort reached age 50 after 1977. + +### What stayed + +- **Protected cash stays a refusal.** A child paid $300.10 on OB $300, and + a deduction above that OB, keep the named refusal. The capture states no + cap on protected cash, and the direction rule keeps a row the rule can't + show is invalid. A stricter proof could drop these rows, and no amount + moves either way. +- **No money moved.** This round changes classification only. +- **Sol's three new `needs_max` items are these fixes.** Sol called each + one source-settled, so none reaches Max. + +### New executed invariants + +| Invariant | Executing tests in `test_track_b_ret_ledger_fix_round_6.py` | +| --- | --- | +| A nonwidow's OB stays settled under widow DRC protection or unknown history, at every scale | `test_child_original_stays_settled_under_widow_drc_protection`; `test_a_child_condition_alone_leaves_the_child_original_settled`; Hypothesis `test_every_child_original_mismatch_errors_under_widow_drc` | +| The published child rate keeps its refusal, row and weight, unchanged by the preflight | `test_published_child_rate_keeps_its_widow_drc_refusal` | +| A widow(er)'s OB and protected cash stay open | `test_a_widow_drc_rate_stays_unsettled_for_the_widow_herself`; `test_protected_cash_above_the_original_stays_a_named_refusal`; `test_deduction_cap_stays_open_under_widow_drc_protection` | +| Every rate 404.411(c)(2)(ii) can reach stays a counted refusal, and the preflight changes nothing about it | `test_published_rule_carryover_keeps_its_refusal`; Hypothesis `test_every_carryover_rate_keeps_its_row` | +| The carryover ends at cohort 1928, reaches only an old-age benefit, and an unknown cohort can't rule it out | `test_carryover_ends_at_cohort_1928`; `test_the_carryover_reaches_only_an_old_age_benefit`; `test_an_unknown_cohort_cannot_rule_out_the_carryover`; `test_a_zero_pia_leaves_no_rate_for_the_carryover_to_lower` | +| Each NH rate has a cap: a declaration above it raises, and one at or below it keeps its row | `test_a_reducing_hold_bounds_a_dib_at_its_pia`; `test_rib_above_the_canonical_rate_stays_an_input_error`; `test_rib_at_the_canonical_rate_keeps_its_refusal`; `test_workers_compensation_caps_a_rib_at_its_canonical_rate`; Hypothesis `test_every_dib_at_or_below_the_cap_keeps_its_row` | +| Only finality lifts a cap | `test_finality_still_protects_a_rate_above_the_cap`; `test_finality_still_protects_a_rib_above_the_cap`; `test_only_finality_lifts_an_nh_rate_cap` | +| Every G refusal reason classifies a lower DIB and a lower RIB against a written-out expectation | `test_each_reason_classifies_a_lower_dib`; `test_each_reason_classifies_a_lower_rib` | +| Pre-1978 reasons reach only cohorts old enough for a reduced benefit by then | `test_pre_1978_history_reaches_only_cohorts_old_enough_for_it`; `test_an_unknown_cohort_cannot_rule_out_a_pre_1978_history` | +| Each quotation above sits in its capture | `test_the_captures_carry_each_quoted_rule` | + +Two existing assertions moved, and each now states both sides: +`test_protected_widow_cannot_be_excluded_from_unknown_drc_history` asserts +the input error and the finality refusal on the matching child, and +`_expect_fact_classification` in `test_track_b_ret_ledger_fix_round_4.py` +keeps an input error for a DIB above the PIA under workers' compensation. + +Thirty-eight fresh mutations, each in a copied source tree, failed named +tests in the round 6 module. A first pass left two survivors, both test +gaps, and each gained a test before the final run. Against `a135519f`, 50 +of that module's 224 tests fail. diff --git a/src/populace_dynamics/track_b/gross_benefits.py b/src/populace_dynamics/track_b/gross_benefits.py index d7f7a7483..7d600ff14 100644 --- a/src/populace_dynamics/track_b/gross_benefits.py +++ b/src/populace_dynamics/track_b/gross_benefits.py @@ -426,6 +426,9 @@ # RS 00615.005A.8/.010: RIB no longer carries a prior reduced WIB's # reduction for SSA cohorts beginning January 2, 1928. _FIRST_OWN_RIB_WITHOUT_WIB_CARRYOVER_BIRTH_YEAR = 1928 +# This cohort reached 50 after 1977, so no benefit reached it reduced by then +# (RS 00615.005A.7 gives age 50 as the earliest reduced disabled widow(er)). +_FIRST_COHORT_WITHOUT_PRE_1978_REDUCTION = 1928 # --------------------------------------------------------------------------- @@ -1755,7 +1758,7 @@ class BeneficiaryCondition(Enum): UnsupportedReason.ADMINISTRATIVE_FINALITY: frozenset( {"F1", "F2", "F3", "F4", "F5", "F6"} ), - UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE: frozenset({"F6"}), + UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE: frozenset({"F2", "F3", "F6"}), UnsupportedReason.PARISI_AMBIGUOUS: frozenset(), UnsupportedReason.PARISI_BEFORE_OCTOBER_1999: frozenset(), UnsupportedReason.INDEPENDENT_DIVORCED_SPOUSE: frozenset(), @@ -1773,8 +1776,12 @@ class BeneficiaryCondition(Enum): UnsupportedReason.DIVORCED_SPOUSE_CHILD_IN_CARE_UNKNOWN: frozenset(), UnsupportedReason.DIVORCED_SPOUSE_CARE_HISTORY: frozenset(), UnsupportedReason.DELAYED_CREDITS_BEFORE_1917: frozenset({"F3", "F6"}), - UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978: frozenset({"F3", "F6"}), - UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978: frozenset(), + UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978: frozenset( + {"F2", "F3", "F6"} + ), + UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978: frozenset( + {"F2", "F3"} + ), UnsupportedReason.PRISONER_SUSPENSION: frozenset(), UnsupportedReason.DRUG_ADDICTION_SUSPENSION: frozenset(), UnsupportedReason.FOREIGN_WORK_DEDUCTION: frozenset(), @@ -1784,6 +1791,19 @@ class BeneficiaryCondition(Enum): UnsupportedReason.DEDUCTION_AGE_WORK_INTERACTION: frozenset(), UnsupportedReason.SOLE_FULL_DEDUCTION_ZERO_DUAL_COMPOSITION: frozenset(), } +# These holds can only lower an NH rate (402(q)(2), 224; 20 CFR 404.408(c)(1), +# 404.411(b)-(c)), so the rate an unheld record would pay stays its cap. +_NH_REDUCTION_ONLY_HOLDS = frozenset( + { + RecordCondition.DIB_AFTER_REDUCED_RIB, + RecordCondition.WORKERS_COMPENSATION_OFFSET, + UnsupportedReason.DIB_AFTER_REDUCED_RIB, + UnsupportedReason.WORKERS_COMPENSATION_OFFSET, + UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE, + UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978, + UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978, + } +) def _declared_fact_holds(state, beneficiary=None): @@ -1795,6 +1815,23 @@ def _declared_fact_holds(state, beneficiary=None): return holds +def _wib_carryover_possible(own, birth_year): + """Whether a prior reduced WIB could lower this own RIB. + + RS 00615.005A.8 ends the carryover for workers born 1/2/28 or later, and + 20 CFR 404.411(c)(2) keeps it before then, even with no current WIB. + """ + return ( + own is not None + and own.kind is OwnBenefitKind.OLD_AGE + and own.pia > 0 + and ( + birth_year is None + or birth_year < _FIRST_OWN_RIB_WITHOUT_WIB_CARRYOVER_BIRTH_YEAR + ) + ) + + def _hold_unsettles_fact( hold, fact, @@ -1804,10 +1841,31 @@ def _hold_unsettles_fact( payment_month, beneficiaries, params, - original_benefit_upper_bound=False, + upper_bound=False, ): if fact not in _PREFLIGHT_FACT_UNSETTLERS[hold]: return False + if ( + upper_bound + and hold in _NH_REDUCTION_ONLY_HOLDS + and fact in ("F2", "F3") + ): + return False + # 404.411(b) reduces a DIB after a reduced RIB in any cohort and after a + # WIB under (b)(2). The schema omits the onset that scopes (b)(2). + if fact == "F2" and hold in ( + UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978, + UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978, + ): + cohort = state.worker_birth_year + return ( + cohort is None or cohort < _FIRST_COHORT_WITHOUT_PRE_1978_REDUCTION + ) + if fact == "F3" and hold in ( + UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE, + UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978, + ): + return _wib_carryover_possible(state.worker, state.worker_birth_year) if hold in ( UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978, UnsupportedReason.DELAYED_CREDITS_BEFORE_1917, @@ -1825,7 +1883,7 @@ def _hold_unsettles_fact( return False # RS 00209.001/.015: count changes 82.5% to 75%, so uncertainty # about exact OB cannot invalidate the one-parent upper bound. - if original_benefit_upper_bound: + if upper_bound: return False try: _entitled_parent_count(state, beneficiaries, params) @@ -1871,26 +1929,24 @@ def _hold_unsettles_fact( UnsupportedReason.WIDOW_DRC_SAVINGS_CLAUSE_HISTORY_UNKNOWN, ): # RS 00615.712 protects survivors; a deferred reason cannot - # change a living record's original benefits. - return state.kind is FamilyKind.SURVIVOR + # change a living record's original benefits. DRCs enter only a + # widow(er)'s OB: "The child's original rate is $300" on the same + # PIA, and the clause protects the child's adjusted cash. + return state.kind is FamilyKind.SURVIVOR and ( + upper_bound or beneficiary.role in _WIDOW_ROLES + ) if hold is UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE and fact == "F6": if beneficiary is None: return True - own = beneficiary.own_benefit # RS 00615.005A.8/.010 can change the own RIB before cohort 1928. # Modern DWB election still requires eligibility and keeps the # PIA/RFs unchanged (RS 00615.315). A nonnegative RIB cannot be # less than a zero deemed-death PIA (402(e)(1)(D)). return ( beneficiary.role in _WIDOW_ROLES - and own is not None - and own.kind is OwnBenefitKind.OLD_AGE - and own.pia > 0 and (beneficiary.original_benefit_basis or state.pia) > 0 - and ( - beneficiary.birth_year is None - or beneficiary.birth_year - < _FIRST_OWN_RIB_WITHOUT_WIB_CARRYOVER_BIRTH_YEAR + and _wib_carryover_possible( + beneficiary.own_benefit, beneficiary.birth_year ) ) return True @@ -1904,7 +1960,7 @@ def _fact_is_settled( payment_month=None, beneficiaries=(), params=None, - original_benefit_upper_bound=False, + upper_bound=False, ): """Whether ordinary G can establish this fact before a coverage hold. @@ -1912,8 +1968,8 @@ def _fact_is_settled( implicit coverage holds apply only to that person. Inspect every declared condition even when another condition would refuse first. Canonical money helpers may still refuse a fact that passes this test. - The upper-bound request permits the conservative one-parent bound - without asserting that the exact parent OB or count is settled. + An upper-bound request asks only for a cap: the one-parent OB without + an exact parent count, or an NH rate a reduction-only hold can lower. """ if beneficiary is not None: beneficiary = _with_effective_cohort(beneficiary) @@ -1927,7 +1983,7 @@ def _fact_is_settled( payment_month=payment_month, beneficiaries=beneficiaries, params=params, - original_benefit_upper_bound=original_benefit_upper_bound, + upper_bound=upper_bound, ) for hold in holds ): @@ -1984,7 +2040,7 @@ def _fact_is_settled( payment_month=payment_month, beneficiaries=beneficiaries, params=params, - original_benefit_upper_bound=original_benefit_upper_bound, + upper_bound=upper_bound, ) for hold in holds ) @@ -4329,7 +4385,8 @@ def _check_deduction_amount_bounds( Ordinary OB bounds gross only when the declared conditions settle that upper bound (GN 02603.050A). Administrative finality can protect a rate based on another PIA (RS 00615.754A.3); the historical - sole-survivor alternative can also exceed ordinary OB (RS 00615.010). + sole-survivor alternative can also exceed ordinary OB (RS 00615.010), + and RS 00615.712 states no cap on protected cash. For a parent, the one-parent OB is the conservative upper bound until a supported computation resolves entitlement/count. Own-work events need strictly positive withholding after NH reserves; @@ -4343,7 +4400,7 @@ def _check_deduction_amount_bounds( beneficiaries=beneficiaries, params=params, payment_month=payment_month, - original_benefit_upper_bound=True, + upper_bound=True, ) or _historical_widow_gross_bound_unsettled( state, member, payment_month ): diff --git a/src/populace_dynamics/track_b/ret_ledger.py b/src/populace_dynamics/track_b/ret_ledger.py index 11c27608c..7632ebe32 100644 --- a/src/populace_dynamics/track_b/ret_ledger.py +++ b/src/populace_dynamics/track_b/ret_ledger.py @@ -1151,7 +1151,9 @@ def _check_settled_family_facts(record: RecordYear) -> None: Entitlement to the NH benefit is an identity between declarations. Money and own-benefit eligibility use G's canonical rules and its condition table. A rule's coverage refusal leaves that fact unsettled; - an input error always propagates. Whole-family allocations stay after G. + an input error always propagates. A hold that can only reduce an NH + rate leaves equality open and keeps its cap. Whole-family allocations + stay after G. """ people = {b.beneficiary_id: b for b in record.beneficiaries} # These identities hold even under protected monetary rates. @@ -1172,6 +1174,7 @@ def settled( fact, member=None, *, + upper_bound=False, state=state, payment_month=payment_month, context=context, @@ -1183,6 +1186,7 @@ def settled( payment_month=payment_month, beneficiaries=context.beneficiaries, params=context.params, + upper_bound=upper_bound, ) if record.kind is not RecordKind.DECEASED: @@ -1192,15 +1196,16 @@ def settled( raise InvalidFamilyInput( "G context does not match RET rates" ) + declared = nh.gross_rates[month - 1] if record.kind is RecordKind.DISABILITY: - if ( - settled("F2") - and nh.gross_rates[month - 1] != state.pia + if (settled("F2") and declared != state.pia) or ( + settled("F2", upper_bound=True) + and declared > state.pia ): raise InvalidFamilyInput( "G context does not match RET rates" ) - elif settled("F3"): + elif settled("F3", upper_bound=True): try: gross = g._own_monthly_benefit_validated( state.worker, context.params @@ -1208,7 +1213,9 @@ def settled( except FamilyConfigurationUnsupported: pass else: - if nh.gross_rates[month - 1] != gross: + if declared > gross or ( + settled("F3") and declared != gross + ): raise InvalidFamilyInput( "G context does not match RET rates" ) diff --git a/tests/README-tiers.md b/tests/README-tiers.md index f71dfc565..d85e08e30 100644 --- a/tests/README-tiers.md +++ b/tests/README-tiers.md @@ -39,9 +39,9 @@ pytest --collect-only -q -m oracle_policyengine | tail -1 | Tier | Tests at HEAD | |---|---:| -| `unit` | 20,804 | +| `unit` | 21,028 | | `artifact` | 4,271 | | `integration_psid` | 1,471 | | `reproduction_legacy` | 520 | | `oracle_policyengine` | 308 | -| **Total** | **27,374** | +| **Total** | **27,598** | diff --git a/tests/test_track_b_ret_ledger_fix_round_4.py b/tests/test_track_b_ret_ledger_fix_round_4.py index 8ba1d5a02..fd268b3a9 100644 --- a/tests/test_track_b_ret_ledger_fix_round_4.py +++ b/tests/test_track_b_ret_ledger_fix_round_4.py @@ -602,10 +602,16 @@ def _spouse_entitlement_case( ) -def _expect_fact_classification(call, fact, held, message): - """Round 5: a protected fact retains its precise counted refusal.""" +def _expect_fact_classification(call, fact, held, message, above=False): + """Round 5: a protected fact retains its precise counted refusal. + + Round 6: workers' compensation can only lower a rate, so a DIB above + the PIA stays an input error. + """ unsettled = held is g.RecordCondition.ADMINISTRATIVE_FINALITY or ( - held is g.RecordCondition.WORKERS_COMPENSATION_OFFSET and fact == "F2" + held is g.RecordCondition.WORKERS_COMPENSATION_OFFSET + and fact == "F2" + and not above ) if not unsettled: _expect_no_row(call, message) @@ -944,6 +950,7 @@ def test_no_held_coverage_condition_masks_direct_nh_rate_contradiction( ("F1" if kind == "original" else "F2"), condition, "G context does not match RET rates", + above=direction > 0, ) diff --git a/tests/test_track_b_ret_ledger_fix_round_5.py b/tests/test_track_b_ret_ledger_fix_round_5.py index 895d2036c..d0984c0cc 100644 --- a/tests/test_track_b_ret_ledger_fix_round_5.py +++ b/tests/test_track_b_ret_ledger_fix_round_5.py @@ -1195,10 +1195,18 @@ def test_protected_widow_cannot_be_excluded_from_unknown_drc_history( ) }, ) - if history is False: - _assert_invalid(case) - else: - _assert_refusal(case, UR.ADMINISTRATIVE_FINALITY) + # Round 6: DRC history can't change a child's OB (RS 00615.712). + _assert_invalid(case) + _assert_refusal( + replace( + case, + beneficiaries=( + case.beneficiaries[0], + _person("c", T.CHILD, 3, 3, 1), + ), + ), + UR.ADMINISTRATIVE_FINALITY, + ) return def compute(): diff --git a/tests/test_track_b_ret_ledger_fix_round_6.py b/tests/test_track_b_ret_ledger_fix_round_6.py new file mode 100644 index 000000000..f053826a6 --- /dev/null +++ b/tests/test_track_b_ret_ledger_fix_round_6.py @@ -0,0 +1,672 @@ +"""Round 6: rates a hold can lower and original rates it cannot. + +Every record is invented or copied from a captured SSA example. Nothing here +admits a population, behavioral or forecast claim. +""" + +from __future__ import annotations + +import html +import re +from dataclasses import replace +from fractions import Fraction as F +from pathlib import Path + +import pytest +from hypothesis import example, given, settings +from hypothesis import strategies as st + +from populace_dynamics.track_b import gross_benefits as g +from populace_dynamics.track_b import ret_ledger as r +from populace_dynamics.track_b.ret_grace import BenefitType as T +from populace_dynamics.track_b.ret_params import load_ret_parameters +from tests.track_b_gross_benefit_support import source_text, ssa_params + +PARAMS = load_ret_parameters() +RC = g.RecordCondition +BC = g.BeneficiaryCondition +UR = g.UnsupportedReason +ARF_SOURCES = Path(__file__).parent / "data/track_b/arf_recompute_sources" +LOWERING_REASONS = ( + UR.DUAL_ENTITLEMENT_SEQUENCE, + UR.OWN_RIB_HISTORY_BEFORE_1978, + UR.REDUCED_BENEFIT_HISTORY_BEFORE_1978, + UR.DIB_AFTER_REDUCED_RIB, + UR.WORKERS_COMPENSATION_OFFSET, +) +HISTORY_REASONS = ( + UR.DUAL_ENTITLEMENT_SEQUENCE, + UR.REDUCED_BENEFIT_HISTORY_BEFORE_1978, +) +PRE_1978_REASONS = ( + UR.OWN_RIB_HISTORY_BEFORE_1978, + UR.REDUCED_BENEFIT_HISTORY_BEFORE_1978, +) +# Written out, not read from G's table: an edit to the table must fail here. +DIB_UNSETTLING_REASONS = frozenset( + {*LOWERING_REASONS, UR.ADMINISTRATIVE_FINALITY} +) +RIB_UNSETTLING_REASONS = frozenset( + { + *HISTORY_REASONS, + UR.WORKERS_COMPENSATION_OFFSET, + UR.ADMINISTRATIVE_FINALITY, + } +) + + +def _outcome(case): + return r.evaluate_ret( + "round6", F(7), lambda: r.apply_ret_year(case, PARAMS) + ) + + +def _assert_refusal(case, reason): + outcome = _outcome(case) + assert not outcome.supported + assert outcome.unsupported.reason is reason + counts = r.count_ret_outcomes([outcome]) + assert (counts.rows, counts.weight, counts.unsupported_weight) == (1, 7, 7) + + +def _assert_invalid(case): + rows = [] + with pytest.raises(g.InvalidFamilyInput): + rows.append(_outcome(case)) + counts = r.count_ret_outcomes(rows) + assert (counts.rows, counts.weight) == (0, 0) + + +def _assert_preflight_neutral(case): + actual = _outcome(case) + with pytest.MonkeyPatch.context() as patch: + patch.setattr(r, "_check_settled_family_facts", lambda record: None) + without = _outcome(case) + assert actual.supported == without.supported + assert not actual.supported + assert actual.unsupported.reason is without.unsupported.reason + assert actual.unsupported.detail == without.unsupported.detail + assert r.count_ret_outcomes([actual]) == r.count_ret_outcomes([without]) + + +def _published_widow_drc(flag, child_original, *, scale=100, child_gross=None): + """RS 00615.712B: PIA $400, maximum $700, widow $410 with DRCs.""" + pia, maximum = F(4 * scale), F(7 * scale) + basis = pia + F(1, 10) * (scale // 10 or 1) + state = g.RecordState( + g.FamilyKind.SURVIVOR, + pia, + maximum, + eligibility_year=1999, + widow_drc_savings_clause=flag, + ) + members = ( + g.Beneficiary( + "w", + g.Role.WIDOW, + birth_year=1934, + child_in_care=False, + original_benefit_basis=basis, + ), + g.Beneficiary("c", g.Role.CHILD), + ) + return r.RecordYear( + 2000, + "nh", + r.RecordKind.DECEASED, + ( + r.RETBeneficiary( + "w", + (T.WIDOW,) * 12, + {1}, + (pia,) + (F(0),) * 11, + (basis,) * 12, + fra_month=0, + ), + r.RETBeneficiary( + "c", + (T.CDB,) * 12, + {1}, + (F(3 * scale) if child_gross is None else child_gross,) + + (F(0),) * 11, + (child_original,) * 12, + fra_month=0, + ), + ), + family_months={ + 1: r.RETFamilyMonth( + state, members, ssa_params(), {"w": "h", "c": "h"} + ) + }, + family_maximum_binding_months={1}, + ) + + +def _rib_record(pia, gross, *, birth=1927, reason=None, conditions=()): + state = g.RecordState( + g.FamilyKind.RETIREMENT, + pia, + g.floor_dime(pia * F(3, 2)), + worker=g.OwnBenefit( + g.OwnBenefitKind.OLD_AGE, + pia, + reduction_months=12, + birth_year=birth, + ), + eligibility_year=birth + 62, + conditions=conditions, + deferred_refusal=( + None if reason is None else (reason, "invented declared history") + ), + ) + return r.RecordYear( + 2000, + "nh", + r.RecordKind.RETIREMENT, + ( + r.RETBeneficiary( + "nh", + (T.RIB,) * 12, + {1}, + (gross,) + (F(0),) * 11, + (pia,) * 12, + fra_month=0, + ), + ), + family_months={1: r.RETFamilyMonth(state, (), ssa_params(), {})}, + ) + + +def _dib_record(pia, gross, *, reason=None, conditions=(), birth=None): + if birth is None: + birth = 1927 if reason in PRE_1978_REASONS else 1960 + year = 1985 if birth < 1960 else 2024 + state = g.RecordState( + g.FamilyKind.DISABILITY, + pia, + g.floor_dime(pia * F(3, 2)), + worker_birth_year=birth, + eligibility_year=year - 1, + first_dib_entitlement=g.YearMonth(year - 1, 1), + conditions=conditions, + deferred_refusal=( + None if reason is None else (reason, "invented declared history") + ), + ) + return r.RecordYear( + year, + "nh", + r.RecordKind.DISABILITY, + ( + r.RETBeneficiary( + "nh", + (T.DIB,) * 12, + {1}, + (gross,) + (F(0),) * 11, + (pia,) * 12, + fra_month=None, + ), + ), + family_months={1: r.RETFamilyMonth(state, (), ssa_params(), {})}, + ) + + +def _carryover_rib(pia, prior_widow_pia): + """Exact 404.411(c)(2)(ii) rate: WIB at 60, own RIB at 64, cohort 1927.""" + return g.floor_dime( + pia + - prior_widow_pia * 24 * F(19, 4000) + - (pia - prior_widow_pia) * F(12, 180) + ) + + +def _ordinary_rib(pia): + return g.floor_dime(pia * F(168, 180)) + + +def test_the_captures_carry_each_quoted_rule(): + drc = source_text("poms_rs_00615_712") + for quote in ( + "In 3/00 the original rates would be $400 for the widow and $300 " + "for the child.", + "The child's original rate is $300.", + "the child is protected by the savings clause and the child's rate " + "will remain at $300.", + "The MBR will show a PIA of $400.00", + ): + assert quote in drc + assert ( + "Eliminated the additional reduction for the period between age 50 " + "and age 60." in source_text("poms_rs_00615_005") + ) + raw = (ARF_SOURCES / "ecfr_20cfr_404_411.xml").read_text() + text = re.sub(r"\s+", " ", html.unescape(re.sub("<[^>]+>", " ", raw))) + for quote in ( + "Individual born before January 2, 1928.", + "except that the old-age benefit equals or exceeds the primary " + "insurance amount on which the widow's or widower's benefit would " + "be based.", + "the old-age benefit is reduced by the larger of the following", + "Individual born after January 1, 1928. The old-age benefit is " + "reduced in accordance with § 404.410(a). There is no further " + "reduction.", + "the disability benefit is reduced by the amount by which the " + "old-age benefit would be reduced", + ): + assert quote in text + + +@pytest.mark.parametrize("flag", [True, None]) +@pytest.mark.parametrize("scale,original", [(100, "300.10"), (1, "3.10")]) +def test_child_original_stays_settled_under_widow_drc_protection( + flag, scale, original +): + _assert_invalid(_published_widow_drc(flag, F(original), scale=scale)) + + +@pytest.mark.parametrize( + "flag,reason", + [ + (True, UR.WIDOW_DRC_SAVINGS_CLAUSE), + (None, UR.WIDOW_DRC_SAVINGS_CLAUSE_HISTORY_UNKNOWN), + ], +) +def test_published_child_rate_keeps_its_widow_drc_refusal(flag, reason): + case = _published_widow_drc(flag, F(300)) + _assert_refusal(case, reason) + _assert_preflight_neutral(case) + + +def test_a_child_condition_alone_leaves_the_child_original_settled(): + case = _published_widow_drc(False, F("300.10")) + context = case.family_months[1] + widow, child = context.beneficiaries + case = replace( + case, + family_months={ + 1: replace( + context, + beneficiaries=( + widow, + replace(child, conditions={BC.WIDOW_DRC_SAVINGS_CLAUSE}), + ), + ) + }, + ) + _assert_invalid(case) + + +def test_a_widow_drc_rate_stays_unsettled_for_the_widow_herself(): + """.712's widow has two original rates: $400, and $410 with DRCs.""" + case = _published_widow_drc(True, F(300)) + context = case.family_months[1] + widow, child = context.beneficiaries + unstated = replace( + case, + family_months={ + 1: replace( + context, + beneficiaries=( + replace(widow, original_benefit_basis=None), + child, + ), + ) + }, + ) + _assert_refusal(unstated, UR.WIDOW_DRC_SAVINGS_CLAUSE) + unknown = _published_widow_drc(None, F(300)) + person = unknown.beneficiaries[0] + _assert_refusal( + replace( + unknown, + beneficiaries=( + replace(person, original_rates=(F(400),) * 12), + unknown.beneficiaries[1], + ), + ), + UR.WIDOW_DRC_SAVINGS_CLAUSE_HISTORY_UNKNOWN, + ) + + +@pytest.mark.parametrize( + "flag,reason", + [ + (True, UR.WIDOW_DRC_SAVINGS_CLAUSE), + (None, UR.WIDOW_DRC_SAVINGS_CLAUSE_HISTORY_UNKNOWN), + ], +) +def test_protected_cash_above_the_original_stays_a_named_refusal(flag, reason): + """The capture states no cap on protected cash, so the row stays.""" + _assert_refusal( + _published_widow_drc(flag, F(300), child_gross=F("300.10")), + reason, + ) + + +def test_deduction_cap_stays_open_under_widow_drc_protection(): + state = g.RecordState( + g.FamilyKind.SURVIVOR, + F(400), + F(700), + eligibility_year=1999, + widow_drc_savings_clause=True, + ) + child = g.Beneficiary("c", g.Role.CHILD) + outcome = g.evaluate_family( + "protected-cap", + F(7), + lambda: g.family_benefits_after_deductions( + state, + (child,), + payment_month=g.YearMonth(2000, 1), + params=ssa_params(), + deductions={ + "c": g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST, F("300.10") + ) + }, + households={"c": "h"}, + standalone=True, + ), + ) + assert not outcome.supported + assert outcome.unsupported.reason is UR.WIDOW_DRC_SAVINGS_CLAUSE + assert not g._fact_is_settled( + "F4", state, child, params=ssa_params(), upper_bound=True + ) + assert g._fact_is_settled("F4", state, child, params=ssa_params()) + + +@pytest.mark.parametrize( + "pia,prior,declared", + [ + ("400", "300", "359.10"), + ("1.20", ".50", "1.00"), + ], +) +def test_published_rule_carryover_keeps_its_refusal(pia, prior, declared): + pia, prior, declared = F(pia), F(prior), F(declared) + assert _carryover_rib(pia, prior) == declared < _ordinary_rib(pia) + # The own RIB exceeds the deceased PIA even in whole dollars, so no + # current WIB or omitted auxiliary record explains the lower rate. + assert declared // 1 >= prior + case = _rib_record(pia, declared, reason=UR.DUAL_ENTITLEMENT_SEQUENCE) + _assert_refusal(case, UR.DUAL_ENTITLEMENT_SEQUENCE) + _assert_preflight_neutral(case) + + +@pytest.mark.parametrize("reason", HISTORY_REASONS) +@pytest.mark.parametrize( + "birth,settled", [(1926, False), (1927, False), (1928, True), (1929, True)] +) +def test_carryover_ends_at_cohort_1928(reason, birth, settled): + case = _rib_record(F("1.20"), F(1), birth=birth, reason=reason) + if settled: + _assert_invalid(case) + else: + _assert_refusal(case, reason) + + +def test_an_unknown_cohort_cannot_rule_out_the_carryover(): + state = g.RecordState( + g.FamilyKind.RETIREMENT, + F("1.20"), + F("1.80"), + worker=g.OwnBenefit( + g.OwnBenefitKind.OLD_AGE, F("1.20"), reduction_months=12 + ), + deferred_refusal=(UR.DUAL_ENTITLEMENT_SEQUENCE, "invented history"), + ) + assert not g._fact_is_settled("F3", state, params=ssa_params()) + assert g._fact_is_settled( + "F3", state, params=ssa_params(), upper_bound=True + ) + + +@pytest.mark.parametrize("reason", PRE_1978_REASONS) +def test_an_unknown_cohort_cannot_rule_out_a_pre_1978_history(reason): + state = g.RecordState( + g.FamilyKind.DISABILITY, + F(4), + F(6), + deferred_refusal=(reason, "invented history"), + ) + assert not g._fact_is_settled("F2", state, params=ssa_params()) + assert g._fact_is_settled( + "F2", state, params=ssa_params(), upper_bound=True + ) + + +@pytest.mark.parametrize( + "kind,settled", + [(g.OwnBenefitKind.OLD_AGE, False), (g.OwnBenefitKind.DISABILITY, True)], +) +def test_the_carryover_reaches_only_an_old_age_benefit(kind, settled): + state = g.RecordState( + g.FamilyKind.SURVIVOR, + F(4), + F(8), + eligibility_year=1989, + widow_drc_savings_clause=False, + deferred_refusal=(UR.DUAL_ENTITLEMENT_SEQUENCE, "invented history"), + ) + widow = g.Beneficiary( + "w", + g.Role.WIDOW, + birth_year=1927, + child_in_care=False, + own_benefit=g.OwnBenefit(kind, F(5)), + ) + assert ( + g._fact_is_settled( + "F6", + state, + widow, + payment_month=g.YearMonth(2000, 1), + beneficiaries=(widow,), + params=ssa_params(), + ) + is settled + ) + + +def test_a_zero_pia_leaves_no_rate_for_the_carryover_to_lower(): + state = g.RecordState( + g.FamilyKind.RETIREMENT, + F(0), + F(0), + worker=g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, F(0), birth_year=1927), + deferred_refusal=(UR.DUAL_ENTITLEMENT_SEQUENCE, "invented history"), + ) + assert g._fact_is_settled("F3", state, params=ssa_params()) + + +@pytest.mark.parametrize("reason", HISTORY_REASONS) +@pytest.mark.parametrize("gap", ["0.10", "1.00"]) +def test_rib_above_the_canonical_rate_stays_an_input_error(reason, gap): + pia = F(400) + _assert_invalid( + _rib_record(pia, _ordinary_rib(pia) + F(gap), reason=reason) + ) + + +@pytest.mark.parametrize("reason", HISTORY_REASONS) +def test_rib_at_the_canonical_rate_keeps_its_refusal(reason): + pia = F(400) + _assert_refusal( + _rib_record(pia, _ordinary_rib(pia), reason=reason), reason + ) + + +def test_workers_compensation_caps_a_rib_at_its_canonical_rate(): + pia = F(400) + conditions = {RC.WORKERS_COMPENSATION_OFFSET} + ordinary = _ordinary_rib(pia) + _assert_invalid( + _rib_record(pia, ordinary + F(1, 10), conditions=conditions) + ) + _assert_refusal( + _rib_record(pia, ordinary - F(1), conditions=conditions), + UR.WORKERS_COMPENSATION_OFFSET, + ) + + +@pytest.mark.parametrize( + "conditions,reason", + [ + ({RC.DIB_AFTER_REDUCED_RIB}, None), + ({RC.WORKERS_COMPENSATION_OFFSET}, None), + ((), UR.DIB_AFTER_REDUCED_RIB), + ((), UR.WORKERS_COMPENSATION_OFFSET), + ((), UR.DUAL_ENTITLEMENT_SEQUENCE), + ((), UR.OWN_RIB_HISTORY_BEFORE_1978), + ((), UR.REDUCED_BENEFIT_HISTORY_BEFORE_1978), + ], +) +@pytest.mark.parametrize("pia", ["0.10", "4", "400"]) +def test_a_reducing_hold_bounds_a_dib_at_its_pia(conditions, reason, pia): + pia = F(pia) + named = ( + reason + if reason is not None + else g._RECORD_CONDITION_REASONS[next(iter(conditions))][0] + ) + above = _dib_record( + pia, pia + F(1, 10), conditions=conditions, reason=reason + ) + below = _dib_record( + pia, pia - F(1, 10), conditions=conditions, reason=reason + ) + _assert_invalid(above) + _assert_refusal(below, named) + _assert_preflight_neutral(below) + _assert_refusal( + _dib_record(pia, pia, conditions=conditions, reason=reason), named + ) + + +@pytest.mark.parametrize("reason", LOWERING_REASONS) +def test_finality_still_protects_a_rate_above_the_cap(reason): + pia = F(4) + _assert_refusal( + _dib_record( + pia, + pia + F(1, 10), + conditions={RC.ADMINISTRATIVE_FINALITY}, + reason=reason, + ), + UR.ADMINISTRATIVE_FINALITY, + ) + + +@pytest.mark.parametrize("reason", HISTORY_REASONS) +def test_finality_still_protects_a_rib_above_the_cap(reason): + pia = F(400) + _assert_refusal( + _rib_record( + pia, + _ordinary_rib(pia) + F(1, 10), + reason=reason, + conditions={RC.ADMINISTRATIVE_FINALITY}, + ), + UR.ADMINISTRATIVE_FINALITY, + ) + + +@pytest.mark.parametrize("reason", PRE_1978_REASONS) +@pytest.mark.parametrize( + "birth,settled", [(1927, False), (1928, True), (1960, True)] +) +def test_pre_1978_history_reaches_only_cohorts_old_enough_for_it( + reason, birth, settled +): + pia = F(400) + case = _dib_record(pia, pia - F(1), reason=reason, birth=birth) + if settled: + _assert_invalid(case) + else: + _assert_refusal(case, reason) + + +@pytest.mark.parametrize("reason", list(UR), ids=lambda reason: reason.value) +def test_each_reason_classifies_a_lower_dib(reason): + pia = F(400) + case = _dib_record(pia, pia - F(1), reason=reason) + if reason in DIB_UNSETTLING_REASONS: + _assert_refusal(case, reason) + else: + _assert_invalid(case) + + +@pytest.mark.parametrize("reason", list(UR), ids=lambda reason: reason.value) +def test_each_reason_classifies_a_lower_rib(reason): + pia = F(400) + case = _rib_record(pia, _ordinary_rib(pia) - F(1), reason=reason) + if reason in RIB_UNSETTLING_REASONS: + _assert_refusal(case, reason) + else: + _assert_invalid(case) + + +@pytest.mark.parametrize("reason", list(UR), ids=lambda reason: reason.value) +@pytest.mark.parametrize("kind", ["dib", "rib"]) +def test_only_finality_lifts_an_nh_rate_cap(reason, kind): + pia = F(400) + case = ( + _dib_record(pia, pia + F(1, 10), reason=reason) + if kind == "dib" + else _rib_record(pia, _ordinary_rib(pia) + F(1, 10), reason=reason) + ) + if reason is UR.ADMINISTRATIVE_FINALITY: + _assert_refusal(case, reason) + else: + _assert_invalid(case) + + +@settings(max_examples=80, deadline=None) +@given( + pia=st.integers(1, 9_000).map(lambda n: F(n, 10)), + reason=st.sampled_from(LOWERING_REASONS), + gap=st.integers(0, 40).map(lambda n: F(n, 10)), +) +@example(pia=F(1, 10), reason=UR.DUAL_ENTITLEMENT_SEQUENCE, gap=F(1, 10)) +def test_every_dib_at_or_below_the_cap_keeps_its_row(pia, reason, gap): + """Valid rates stay rows with the preflight's own reason; the rest error.""" + below = max(F(0), pia - gap) + case = _dib_record(pia, below, reason=reason) + _assert_refusal(case, reason) + _assert_preflight_neutral(case) + _assert_invalid(_dib_record(pia, pia + gap + F(1, 10), reason=reason)) + + +@settings(max_examples=80, deadline=None) +@given( + pia=st.integers(10, 9_000).map(lambda n: F(n, 10)), + share=st.integers(1, 9), + reason=st.sampled_from(HISTORY_REASONS), +) +@example(pia=F("1.20"), share=4, reason=UR.DUAL_ENTITLEMENT_SEQUENCE) +def test_every_carryover_rate_keeps_its_row(pia, share, reason): + """Each rate 404.411(c)(2)(ii) can reach stays a counted refusal.""" + prior = g.floor_dime(pia * F(share, 10)) + lawful = _carryover_rib(pia, prior) + ordinary = _ordinary_rib(pia) + assert lawful <= ordinary + case = _rib_record(pia, lawful, reason=reason) + _assert_refusal(case, reason) + _assert_preflight_neutral(case) + _assert_invalid(_rib_record(pia, ordinary + F(1, 10), reason=reason)) + + +@settings(max_examples=60, deadline=None) +@given( + scale=st.integers(1, 40), + gap=st.integers(1, 9).map(lambda n: F(n, 10)), + flag=st.sampled_from((True, None)), +) +def test_every_child_original_mismatch_errors_under_widow_drc( + scale, gap, flag +): + _assert_invalid( + _published_widow_drc(flag, F(3 * scale) + gap, scale=scale) + ) diff --git a/tests/tier_counts.json b/tests/tier_counts.json index 2980955eb..c14a7e38b 100644 --- a/tests/tier_counts.json +++ b/tests/tier_counts.json @@ -1,7 +1,7 @@ { "schema_version": 1, "counts": { - "unit": 20804, + "unit": 21028, "artifact": 4271, "integration_psid": 1471, "reproduction_legacy": 520, From fbe491d4c3ea3077702616eee79a742da124eefd Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 1 Nov 2026 07:25:13 -0500 Subject: [PATCH 12/17] Track B R2: read each hold's reach before comparing a rate Sol's sixth review of 3212f823 found three mediums, and all three reproduced. Two lost a lawful row by comparing a rate with an amount the declaration had already put in doubt. One kept a row no filling can make lawful. - A declared pre-1978 history reaches past an omitted cohort, because RS 00615.005C.2's money reduction can exceed today's fraction. PIA $333.30 at RF 8 pays $318.50 on all sixteen rounding paths from the captured COLAs, against $318.40 today. That rate now keeps its row, and only for an old-age benefit with a PIA and a remaining reduction, in a cohort before 1916 or none. - Every test of an actual own RIB shares the 404.411(c)(2) carryover, so a mother's $359.10 against an ordinary $373.30 keeps its row beside a $360 threshold. - No reduced benefit starts before age 50, so a cohort below that age has one lawful DIB rate. A DIB below the PIA now raises under every hold that works through a prior reduced benefit. Workers' compensation and finality need no such benefit and keep young rows. The same classes reach F6 under a declared history, and REDUCED_BENEFIT_HISTORY_BEFORE_1978 now opens F6 in the carryover scope. The age floor uses 50 for DIB_AFTER_REDUCED_RIB too, because the schema has no separate declaration for a DIB after a reduced WIB. That row stays a named refusal from 50 through 61. No money moves. The conformance report regenerates byte-identically, and the cross-head comparison keeps 240 R2 and 240 R3 results. Invariants: under a declared history, every rate in its scope keeps its row, and past that scope a reduction-only hold keeps the cap. F6 opens under a carryover hold for exactly the roles that read an actual own RIB. Before January of cohort + 50, a DIB equals its PIA or raises. Co-Authored-By: Claude Opus 5.5 --- docs/design/track_b_g2_r2b_mutations.json | 2446 ++++++++++++++++- docs/design/track_b_g2_r2b_verification.json | 86 +- docs/design/track_b_r2_ret_ledger.md | 113 +- .../track_b/gross_benefits.py | 102 +- tests/README-tiers.md | 4 +- tests/test_track_b_ret_ledger_fix_round_6.py | 1 + tests/test_track_b_ret_ledger_fix_round_7.py | 900 ++++++ tests/tier_counts.json | 2 +- 8 files changed, 3631 insertions(+), 23 deletions(-) create mode 100644 tests/test_track_b_ret_ledger_fix_round_7.py diff --git a/docs/design/track_b_g2_r2b_mutations.json b/docs/design/track_b_g2_r2b_mutations.json index 4a7867f47..1869c8c44 100644 --- a/docs/design/track_b_g2_r2b_mutations.json +++ b/docs/design/track_b_g2_r2b_mutations.json @@ -2,10 +2,10 @@ "schema_version": 1, "verification_class": "statutory_conformance", "admitted_scope": "Mutation sensitivity of statutory rules on invented and captured worked cases only; no population, behavioral or forecast claim.", - "confirmed_mutation_count": 118, + "confirmed_mutation_count": 160, "counts_by_layer": { "g_deductions": 18, - "g_preflight": 52, + "g_preflight": 94, "g_savings": 12, "r2": 35, "shared_provenance": 1 @@ -6602,6 +6602,2442 @@ } }, "layer": "r2" + }, + { + "id": "round7-age_floor_49", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "_EARLIEST_REDUCED_BENEFIT_AGE = 50", + "after": "_EARLIEST_REDUCED_BENEFIT_AGE = 49" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_cohort_too_young_for_any_reduced_benefit_has_one_dib_rate", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_before_age_50_a_dib_below_the_pia_raises[1975-conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_before_age_50_a_dib_below_the_pia_raises[1975-conditions1-UnsupportedReason.DIB_AFTER_REDUCED_RIB-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_before_age_50_a_dib_below_the_pia_raises[1975-conditions2-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50[1974-2023-12-False-conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50[1974-2023-12-False-conditions1-UnsupportedReason.DIB_AFTER_REDUCED_RIB-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50[1974-2023-12-False-conditions2-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_pre_1978_hold_needs_both_the_cohort_and_the_age[1927-1976-12-True-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_pre_1978_hold_needs_both_the_cohort_and_the_age[1927-1976-12-True-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_f2_matches_a_table_written_from_the_sources" + ], + "failed_test_count": 11, + "log": { + "path": "scratch/review/round7-mutations/age_floor_49.log", + "sha256": "cd7ade27e7daeed35a340f1b232af43633a8dd2e375b02183478343709e5153f", + "failure_summary": "11 failed, 147 passed in 3.94s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-age_floor_51", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "_EARLIEST_REDUCED_BENEFIT_AGE = 50", + "after": "_EARLIEST_REDUCED_BENEFIT_AGE = 51" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50[1974-2024-1-True-conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50[1974-2024-1-True-conditions1-UnsupportedReason.DIB_AFTER_REDUCED_RIB-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50[1974-2024-1-True-conditions2-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50[1973-2023-12-True-conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50[1973-2023-12-True-conditions1-UnsupportedReason.DIB_AFTER_REDUCED_RIB-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50[1973-2023-12-True-conditions2-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_pre_1978_hold_needs_both_the_cohort_and_the_age[1927-1977-1-False-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_pre_1978_hold_needs_both_the_cohort_and_the_age[1927-1977-1-False-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_pre_1978_hold_needs_both_the_cohort_and_the_age[1926-1976-12-False-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_pre_1978_hold_needs_both_the_cohort_and_the_age[1926-1976-12-False-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]" + ], + "failed_test_count": 11, + "log": { + "path": "scratch/review/round7-mutations/age_floor_51.log", + "sha256": "0417e504eeb717aa12fcdd57d548b5229f7e10f68a1fe9556d9809958653a1b3", + "failure_summary": "11 failed, 147 passed in 1.90s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-age_floor_62", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "_EARLIEST_REDUCED_BENEFIT_AGE = 50", + "after": "_EARLIEST_REDUCED_BENEFIT_AGE = 62" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50[1974-2024-1-True-conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50[1974-2024-1-True-conditions1-UnsupportedReason.DIB_AFTER_REDUCED_RIB-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50[1974-2024-1-True-conditions2-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50[1973-2023-12-True-conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50[1973-2023-12-True-conditions1-UnsupportedReason.DIB_AFTER_REDUCED_RIB-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50[1973-2023-12-True-conditions2-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_pre_1978_hold_needs_both_the_cohort_and_the_age[1927-1977-1-False-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_pre_1978_hold_needs_both_the_cohort_and_the_age[1927-1977-1-False-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_pre_1978_hold_needs_both_the_cohort_and_the_age[1926-1976-12-False-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_pre_1978_hold_needs_both_the_cohort_and_the_age[1926-1976-12-False-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]" + ], + "failed_test_count": 11, + "log": { + "path": "scratch/review/round7-mutations/age_floor_62.log", + "sha256": "622cfe1540034ec0c29b3e42d329f6288fcf9659f57f3e37cb26a71aa5e8d064", + "failure_summary": "11 failed, 147 passed in 1.81s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-early_f3_only", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " if fact in (\"F3\", \"F6\") and hold in _PRE_1978_HISTORY_HOLDS:\n", + "after": " if fact == \"F3\" and hold in _PRE_1978_HISTORY_HOLDS:\n" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_mothers_own_rib_opens_only_in_each_holds_scope[UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978-None-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_deemed_pia_keeps_a_history_open_on_a_zero_record_pia", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_f6_matches_a_table_written_from_the_sources" + ], + "failed_test_count": 3, + "log": { + "path": "scratch/review/round7-mutations/early_f3_only.log", + "sha256": "c1f9a1c1d99176984a786a7d4a37f065bfb90bb962fd883e63f96d39247ec5cf", + "failure_summary": "3 failed, 155 passed in 1.73s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-early_f6_only", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " if fact in (\"F3\", \"F6\") and hold in _PRE_1978_HISTORY_HOLDS:\n", + "after": " if fact == \"F6\" and hold in _PRE_1978_HISTORY_HOLDS:\n" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_declared_history_keeps_a_rate_above_todays_formula[333.30-318.50-8-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_declared_history_keeps_a_rate_above_todays_formula[333.30-318.50-8-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_declared_history_keeps_a_rate_above_todays_formula[1000-988.90-2-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_declared_history_keeps_a_rate_above_todays_formula[1000-988.90-2-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_history_reaching_rib_keeps_either_direction[-1.00-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978-None]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_history_reaching_rib_keeps_either_direction[-0.10-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978-None]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_history_reaching_rib_keeps_either_direction[0.10-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978-None]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_history_reaching_rib_keeps_either_direction[0.10-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-None]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_history_reaching_rib_keeps_either_direction[1.00-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978-None]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_history_reaching_rib_keeps_either_direction[1.00-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-None]" + ], + "failed_test_count": 11, + "log": { + "path": "scratch/review/round7-mutations/early_f6_only.log", + "sha256": "a796b7684bbaf48f006186d58f391073158027f07c1914ba5adef3bb37038c3c", + "failure_summary": "11 failed, 147 passed in 1.53s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-early_only_cap", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " if tested_pia > 0 and _historical_own_rib_possible(own, cohort):\n return True\n", + "after": " if upper_bound and tested_pia > 0 and _historical_own_rib_possible(own, cohort):\n return True\n" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_mothers_own_rib_opens_only_in_each_holds_scope[UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978-None-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_deemed_pia_keeps_a_history_open_on_a_zero_record_pia", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_f6_matches_a_table_written_from_the_sources" + ], + "failed_test_count": 3, + "log": { + "path": "scratch/review/round7-mutations/early_only_cap.log", + "sha256": "f17c9baa1728a07ace7db675f5bf178d2ed5294b4f18a9402c6600068beb7c4c", + "failure_summary": "3 failed, 155 passed in 1.94s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-early_skips_cap", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " if tested_pia > 0 and _historical_own_rib_possible(own, cohort):\n return True\n", + "after": " if not upper_bound and tested_pia > 0 and _historical_own_rib_possible(own, cohort):\n return True\n" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_declared_history_keeps_a_rate_above_todays_formula[333.30-318.50-8-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_declared_history_keeps_a_rate_above_todays_formula[333.30-318.50-8-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_declared_history_keeps_a_rate_above_todays_formula[1000-988.90-2-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_declared_history_keeps_a_rate_above_todays_formula[1000-988.90-2-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_history_reaching_rib_keeps_either_direction[0.10-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978-None]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_history_reaching_rib_keeps_either_direction[0.10-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-None]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_history_reaching_rib_keeps_either_direction[1.00-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978-None]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_history_reaching_rib_keeps_either_direction[1.00-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-None]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_history_keeps_every_rate_in_its_scope" + ], + "failed_test_count": 9, + "log": { + "path": "scratch/review/round7-mutations/early_skips_cap.log", + "sha256": "a9cbbc39eb52d1fd562a67e84af727184cdb72ad85aebac8c4a9620a42979e01", + "failure_summary": "9 failed, 149 passed in 1.55s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-early_tested_pia_ignores_basis", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " else (\n beneficiary.own_benefit,\n beneficiary.birth_year,\n beneficiary.original_benefit_basis or state.pia,\n )\n", + "after": " else (\n beneficiary.own_benefit,\n beneficiary.birth_year,\n state.pia,\n )\n" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_deemed_pia_keeps_a_history_open_on_a_zero_record_pia" + ], + "failed_test_count": 1, + "log": { + "path": "scratch/review/round7-mutations/early_tested_pia_ignores_basis.log", + "sha256": "b361ce7d0b468331ec57f58440b8646b0186195aa28d3b4a81f1dfebfc727f8b", + "failure_summary": "1 failed, 157 passed in 2.10s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-early_worker_cohort_for_beneficiary", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " else (\n beneficiary.own_benefit,\n beneficiary.birth_year,\n beneficiary.original_benefit_basis or state.pia,\n )\n", + "after": " else (\n beneficiary.own_benefit,\n state.worker_birth_year,\n beneficiary.original_benefit_basis or state.pia,\n )\n" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_mothers_own_rib_opens_only_in_each_holds_scope[UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-1928-None]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_mothers_own_rib_opens_only_in_each_holds_scope[UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978-1916-None]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_mothers_own_rib_opens_only_in_each_holds_scope[UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978-1927-None]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_f6_matches_a_table_written_from_the_sources" + ], + "failed_test_count": 4, + "log": { + "path": "scratch/review/round7-mutations/early_worker_cohort_for_beneficiary.log", + "sha256": "ea5854dd62f99b672a38933e48f9af9c29373c563d3db607f1ee38c498c876ed", + "failure_summary": "4 failed, 154 passed in 1.91s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-early_worker_own_for_beneficiary", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " else (\n beneficiary.own_benefit,\n beneficiary.birth_year,\n beneficiary.original_benefit_basis or state.pia,\n )\n", + "after": " else (\n state.worker,\n beneficiary.birth_year,\n beneficiary.original_benefit_basis or state.pia,\n )\n" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_mothers_own_rib_opens_only_in_each_holds_scope[UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978-None-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_deemed_pia_keeps_a_history_open_on_a_zero_record_pia", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_f6_matches_a_table_written_from_the_sources" + ], + "failed_test_count": 3, + "log": { + "path": "scratch/review/round7-mutations/early_worker_own_for_beneficiary.log", + "sha256": "808eb0ac26756964c6ccdd41e7bcf14c586c798a9374381b9e7cd584aeb08415", + "failure_summary": "3 failed, 155 passed in 1.83s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-early_zero_pia", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " if tested_pia > 0 and _historical_own_rib_possible(own, cohort):\n return True\n", + "after": " if _historical_own_rib_possible(own, cohort):\n return True\n" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_zero_pia_fails_every_rib_on_every_filling[UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_zero_pia_fails_every_rib_on_every_filling[UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_f6_matches_a_table_written_from_the_sources" + ], + "failed_test_count": 3, + "log": { + "path": "scratch/review/round7-mutations/early_zero_pia.log", + "sha256": "5cd548dfefcf4c541993dfc6dabfa608c99d048732bd8e64302dbafd1b41b693", + "failure_summary": "3 failed, 155 passed in 1.89s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-f6_drop_dual", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " if fact == \"F6\" and hold in (\n UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE,\n UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978,\n ):\n", + "after": " if fact == \"F6\" and hold in (\n UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978,\n ):\n" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_mothers_own_rib_opens_only_in_each_holds_scope[UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-1928-None]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_zero_pia_fails_every_rib_on_every_filling[UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_every_actual_rib_test_shares_the_carryover[1928-True-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-Role.WIDOW]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_every_actual_rib_test_shares_the_carryover[1928-True-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-Role.SURVIVING_DIVORCED_SPOUSE]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_every_actual_rib_test_shares_the_carryover[1928-True-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-Role.DISABLED_WIDOW]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_every_actual_rib_test_shares_the_carryover[1928-True-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-Role.MOTHER_FATHER]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_every_actual_rib_test_shares_the_carryover[1928-True-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-Role.PARENT]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_every_actual_rib_test_shares_the_carryover[1928-True-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-Role.WIDOW]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_every_actual_rib_test_shares_the_carryover[1928-True-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-Role.SURVIVING_DIVORCED_SPOUSE]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_every_actual_rib_test_shares_the_carryover[1928-True-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-Role.DISABLED_WIDOW]" + ], + "failed_test_count": 16, + "log": { + "path": "scratch/review/round7-mutations/f6_drop_dual.log", + "sha256": "55d9660f31c436c470268a57face2f6413f996ba320bb8cb93bfcc031c0d7a9d", + "failure_summary": "16 failed, 142 passed in 2.46s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-f6_drop_reduced", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " if fact == \"F6\" and hold in (\n UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE,\n UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978,\n ):\n", + "after": " if fact == \"F6\" and hold in (\n UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE,\n ):\n" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_mothers_own_rib_opens_only_in_each_holds_scope[UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-1928-None]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_zero_pia_fails_every_rib_on_every_filling[UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_every_actual_rib_test_shares_the_carryover[1928-True-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-Role.WIDOW]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_every_actual_rib_test_shares_the_carryover[1928-True-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-Role.SURVIVING_DIVORCED_SPOUSE]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_every_actual_rib_test_shares_the_carryover[1928-True-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-Role.DISABLED_WIDOW]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_every_actual_rib_test_shares_the_carryover[1928-True-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-Role.MOTHER_FATHER]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_every_actual_rib_test_shares_the_carryover[1928-True-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-Role.PARENT]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_role_with_no_rib_amount_test_stays_settled[UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-Role.CHILD]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_role_with_no_rib_amount_test_stays_settled[UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-Role.SPOUSE]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_role_with_no_rib_amount_test_stays_settled[UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-Role.DIVORCED_SPOUSE]" + ], + "failed_test_count": 15, + "log": { + "path": "scratch/review/round7-mutations/f6_drop_reduced.log", + "sha256": "aaabb05ce026080a4537e2d5d12993fa04c49471167ef074f960e2e0bcde25c6", + "failure_summary": "15 failed, 143 passed in 2.39s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-floor_for_every_hold", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " if (\n fact == \"F2\"\n and hold in _PRIOR_REDUCED_BENEFIT_HOLDS\n and not _prior_reduced_benefit_possible(\n state.worker_birth_year, payment_month\n )\n ):\n return False\n", + "after": " if (\n fact == \"F2\"\n and not _prior_reduced_benefit_possible(\n state.worker_birth_year, payment_month\n )\n ):\n return False\n" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_hold_no_age_limits_keeps_a_young_row[1975-conditions0-None-UnsupportedReason.WORKERS_COMPENSATION_OFFSET]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_hold_no_age_limits_keeps_a_young_row[1975-conditions1-UnsupportedReason.WORKERS_COMPENSATION_OFFSET-UnsupportedReason.WORKERS_COMPENSATION_OFFSET]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_hold_no_age_limits_keeps_a_young_row[1975-conditions2-None-UnsupportedReason.ADMINISTRATIVE_FINALITY]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_hold_no_age_limits_keeps_a_young_row[1975-conditions3-UnsupportedReason.ADMINISTRATIVE_FINALITY-UnsupportedReason.ADMINISTRATIVE_FINALITY]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_hold_no_age_limits_keeps_a_young_row[2000-conditions0-None-UnsupportedReason.WORKERS_COMPENSATION_OFFSET]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_hold_no_age_limits_keeps_a_young_row[2000-conditions1-UnsupportedReason.WORKERS_COMPENSATION_OFFSET-UnsupportedReason.WORKERS_COMPENSATION_OFFSET]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_hold_no_age_limits_keeps_a_young_row[2000-conditions2-None-UnsupportedReason.ADMINISTRATIVE_FINALITY]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_hold_no_age_limits_keeps_a_young_row[2000-conditions3-UnsupportedReason.ADMINISTRATIVE_FINALITY-UnsupportedReason.ADMINISTRATIVE_FINALITY]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_an_independent_hold_survives_a_young_dual_declaration[conditions0-UnsupportedReason.WORKERS_COMPENSATION_OFFSET]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_an_independent_hold_survives_a_young_dual_declaration[conditions1-UnsupportedReason.ADMINISTRATIVE_FINALITY]" + ], + "failed_test_count": 11, + "log": { + "path": "scratch/review/round7-mutations/floor_for_every_hold.log", + "sha256": "1db00ba45a8265a2ddcb0dd9d8e0bfde845fc46deac118819d98d85691c26948", + "failure_summary": "11 failed, 147 passed in 2.30s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-floor_reads_the_month_as_a_year", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " birth_year is None\n or payment_month is None\n or payment_month.year >= birth_year + _EARLIEST_REDUCED_BENEFIT_AGE\n", + "after": " birth_year is None\n or payment_month is None\n or payment_month.year + payment_month.month - 1 >= birth_year + _EARLIEST_REDUCED_BENEFIT_AGE\n" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50[1974-2023-12-False-conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50[1974-2023-12-False-conditions1-UnsupportedReason.DIB_AFTER_REDUCED_RIB-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50[1974-2023-12-False-conditions2-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_pre_1978_hold_needs_both_the_cohort_and_the_age[1927-1976-12-True-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_pre_1978_hold_needs_both_the_cohort_and_the_age[1927-1976-12-True-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_f2_matches_a_table_written_from_the_sources" + ], + "failed_test_count": 6, + "log": { + "path": "scratch/review/round7-mutations/floor_reads_the_month_as_a_year.log", + "sha256": "fcc192bdaace3f24d83a8c3ac9ec64aeba9dfb410a4339efae83f56644785e68", + "failure_summary": "6 failed, 152 passed in 1.92s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-floor_removed", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " if (\n fact == \"F2\"\n and hold in _PRIOR_REDUCED_BENEFIT_HOLDS\n and not _prior_reduced_benefit_possible(\n state.worker_birth_year, payment_month\n )\n ):\n return False\n", + "after": "" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_cohort_too_young_for_any_reduced_benefit_has_one_dib_rate", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_before_age_50_a_dib_below_the_pia_raises[1975-conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_before_age_50_a_dib_below_the_pia_raises[1975-conditions1-UnsupportedReason.DIB_AFTER_REDUCED_RIB-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_before_age_50_a_dib_below_the_pia_raises[1975-conditions2-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_before_age_50_a_dib_below_the_pia_raises[1980-conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_before_age_50_a_dib_below_the_pia_raises[1980-conditions1-UnsupportedReason.DIB_AFTER_REDUCED_RIB-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_before_age_50_a_dib_below_the_pia_raises[1980-conditions2-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_before_age_50_a_dib_below_the_pia_raises[2000-conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_before_age_50_a_dib_below_the_pia_raises[2000-conditions1-UnsupportedReason.DIB_AFTER_REDUCED_RIB-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_before_age_50_a_dib_below_the_pia_raises[2000-conditions2-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]" + ], + "failed_test_count": 17, + "log": { + "path": "scratch/review/round7-mutations/floor_removed.log", + "sha256": "5704eb0badaa1a792c7bea0c024c0bb2043ff7a28d7f39dfc078e7b438bfe160", + "failure_summary": "17 failed, 141 passed in 4.89s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-floor_strict", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " birth_year is None\n or payment_month is None\n or payment_month.year >= birth_year + _EARLIEST_REDUCED_BENEFIT_AGE\n", + "after": " birth_year is None\n or payment_month is None\n or payment_month.year > birth_year + _EARLIEST_REDUCED_BENEFIT_AGE\n" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50[1974-2024-1-True-conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50[1974-2024-1-True-conditions1-UnsupportedReason.DIB_AFTER_REDUCED_RIB-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50[1974-2024-1-True-conditions2-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50[1973-2023-12-True-conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50[1973-2023-12-True-conditions1-UnsupportedReason.DIB_AFTER_REDUCED_RIB-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50[1973-2023-12-True-conditions2-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_pre_1978_hold_needs_both_the_cohort_and_the_age[1927-1977-1-False-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_pre_1978_hold_needs_both_the_cohort_and_the_age[1927-1977-1-False-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_pre_1978_hold_needs_both_the_cohort_and_the_age[1926-1976-12-False-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_pre_1978_hold_needs_both_the_cohort_and_the_age[1926-1976-12-False-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]" + ], + "failed_test_count": 11, + "log": { + "path": "scratch/review/round7-mutations/floor_strict.log", + "sha256": "59689386d22239689c695befe6ac6f0bf7ad71907b40d22ea50ad966ff607915", + "failure_summary": "11 failed, 147 passed in 1.73s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-floor_unknown_cohort_settled", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " birth_year is None\n or payment_month is None\n or payment_month.year >= birth_year + _EARLIEST_REDUCED_BENEFIT_AGE\n", + "after": " payment_month is None\n or payment_month.year >= birth_year + _EARLIEST_REDUCED_BENEFIT_AGE\n" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_history_leaves_a_dib_cap_alone[None-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_history_leaves_a_dib_cap_alone[None-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50[None-2024-1-True-conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50[None-2024-1-True-conditions1-UnsupportedReason.DIB_AFTER_REDUCED_RIB-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50[None-2024-1-True-conditions2-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_needs_a_cohort_and_a_month" + ], + "failed_test_count": 6, + "log": { + "path": "scratch/review/round7-mutations/floor_unknown_cohort_settled.log", + "sha256": "7a60544ed349b8aaa520bd4b50e74e585a5dfcfa4fc74a20523eec6e107b8460", + "failure_summary": "6 failed, 152 passed in 1.98s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-floor_unknown_month_settled", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " birth_year is None\n or payment_month is None\n or payment_month.year >= birth_year + _EARLIEST_REDUCED_BENEFIT_AGE\n", + "after": " birth_year is None\n or (payment_month is not None and False)\n or payment_month.year >= birth_year + _EARLIEST_REDUCED_BENEFIT_AGE\n" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_needs_a_cohort_and_a_month" + ], + "failed_test_count": 1, + "log": { + "path": "scratch/review/round7-mutations/floor_unknown_month_settled.log", + "sha256": "f78ae07179b72814b5cd7a6d86e926b3a96adf40a3c684d9dd756a69df400973", + "failure_summary": "1 failed, 157 passed in 1.89s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-history_any_cohort", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " and own.kind is OwnBenefitKind.OLD_AGE\n and own.pia > 0\n and own.reduction_months > 0\n and (\n birth_year is None\n or birth_year < _FIRST_COHORT_WITHOUT_PRE_1978_OWN_RIB\n )\n", + "after": " and own.kind is OwnBenefitKind.OLD_AGE\n and own.pia > 0\n and own.reduction_months > 0\n and (\n birth_year is None\n or True\n )\n" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_cohort_past_1915_keeps_todays_formula_as_a_cap[1916-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_cohort_past_1915_keeps_todays_formula_as_a_cap[1916-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_cohort_past_1915_keeps_todays_formula_as_a_cap[1920-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_cohort_past_1915_keeps_todays_formula_as_a_cap[1920-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_cohort_past_1915_keeps_todays_formula_as_a_cap[1927-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_cohort_past_1915_keeps_todays_formula_as_a_cap[1927-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_cohort_past_1915_keeps_exact_own_history[1916]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_cohort_past_1915_keeps_exact_own_history[1927]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_past_1915_every_reduction_only_hold_keeps_the_cap", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_mothers_own_rib_opens_only_in_each_holds_scope[UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-1928-None]" + ], + "failed_test_count": 13, + "log": { + "path": "scratch/review/round7-mutations/history_any_cohort.log", + "sha256": "f43ed34ed09c32bf2ffff6099ef8cff31a996859519aff9a1218ea50d4b436f8", + "failure_summary": "13 failed, 145 passed in 5.17s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-history_any_kind", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " and own.kind is OwnBenefitKind.OLD_AGE\n and own.pia > 0\n and own.reduction_months > 0\n and (\n birth_year is None\n or birth_year < _FIRST_COHORT_WITHOUT_PRE_1978_OWN_RIB\n )\n", + "after": " and own.pia > 0\n and own.reduction_months > 0\n and (\n birth_year is None\n or birth_year < _FIRST_COHORT_WITHOUT_PRE_1978_OWN_RIB\n )\n" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_reduced_dib_opens_no_money_history" + ], + "failed_test_count": 1, + "log": { + "path": "scratch/review/round7-mutations/history_any_kind.log", + "sha256": "42b8c804ec4f2b197c5828586573a0d6a3a05d481033f4ced018fdb5803c5b11", + "failure_summary": "1 failed, 157 passed in 1.91s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-history_no_reduction", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " and own.kind is OwnBenefitKind.OLD_AGE\n and own.pia > 0\n and own.reduction_months > 0\n and (\n birth_year is None\n or birth_year < _FIRST_COHORT_WITHOUT_PRE_1978_OWN_RIB\n )\n", + "after": " and own.kind is OwnBenefitKind.OLD_AGE\n and own.pia > 0\n and (\n birth_year is None\n or birth_year < _FIRST_COHORT_WITHOUT_PRE_1978_OWN_RIB\n )\n" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_no_remaining_reduction_needs_no_money_history[UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_no_remaining_reduction_needs_no_money_history[UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_f6_matches_a_table_written_from_the_sources" + ], + "failed_test_count": 3, + "log": { + "path": "scratch/review/round7-mutations/history_no_reduction.log", + "sha256": "148c9ec0a784cc6bc0b5d0ff5cdb23281e86dd0d363b35d12e5802e5dc4ca15c", + "failure_summary": "3 failed, 155 passed in 1.92s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-history_unknown_cohort_settled", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " and own.kind is OwnBenefitKind.OLD_AGE\n and own.pia > 0\n and own.reduction_months > 0\n and (\n birth_year is None\n or birth_year < _FIRST_COHORT_WITHOUT_PRE_1978_OWN_RIB\n )\n", + "after": " and own.kind is OwnBenefitKind.OLD_AGE\n and own.pia > 0\n and own.reduction_months > 0\n and (\n birth_year is not None\n and birth_year < _FIRST_COHORT_WITHOUT_PRE_1978_OWN_RIB\n )\n" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_declared_history_keeps_a_rate_above_todays_formula[333.30-318.50-8-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_declared_history_keeps_a_rate_above_todays_formula[333.30-318.50-8-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_declared_history_keeps_a_rate_above_todays_formula[1000-988.90-2-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_declared_history_keeps_a_rate_above_todays_formula[1000-988.90-2-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_history_reaching_rib_keeps_either_direction[-1.00-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978-None]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_history_reaching_rib_keeps_either_direction[-0.10-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978-None]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_history_reaching_rib_keeps_either_direction[0.10-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978-None]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_history_reaching_rib_keeps_either_direction[0.10-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-None]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_history_reaching_rib_keeps_either_direction[1.00-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978-None]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_history_reaching_rib_keeps_either_direction[1.00-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-None]" + ], + "failed_test_count": 14, + "log": { + "path": "scratch/review/round7-mutations/history_unknown_cohort_settled.log", + "sha256": "1d5662e0c7034b2c4de16ee6cb43d812b5d3f3f61ae612bb7a8d1af7baf1755a", + "failure_summary": "14 failed, 144 passed in 1.43s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-history_zero_pia", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " and own.kind is OwnBenefitKind.OLD_AGE\n and own.pia > 0\n and own.reduction_months > 0\n and (\n birth_year is None\n or birth_year < _FIRST_COHORT_WITHOUT_PRE_1978_OWN_RIB\n )\n", + "after": " and own.kind is OwnBenefitKind.OLD_AGE\n and own.reduction_months > 0\n and (\n birth_year is None\n or birth_year < _FIRST_COHORT_WITHOUT_PRE_1978_OWN_RIB\n )\n" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_zero_own_pia_leaves_no_money_history[UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_zero_own_pia_leaves_no_money_history[UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]" + ], + "failed_test_count": 2, + "log": { + "path": "scratch/review/round7-mutations/history_zero_pia.log", + "sha256": "404d8b2bcfa02d8b5d92ed7bf255e99d2b0981395eb0e6d43384da31725f310b", + "failure_summary": "2 failed, 156 passed in 2.07s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-own_rib_cohort_1915", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "_FIRST_COHORT_WITHOUT_PRE_1978_OWN_RIB = 1916", + "after": "_FIRST_COHORT_WITHOUT_PRE_1978_OWN_RIB = 1915" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_history_reaching_rib_keeps_either_direction[-1.00-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978-1915]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_history_reaching_rib_keeps_either_direction[-0.10-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978-1915]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_history_reaching_rib_keeps_either_direction[0.10-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978-1915]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_history_reaching_rib_keeps_either_direction[0.10-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-1915]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_history_reaching_rib_keeps_either_direction[1.00-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978-1915]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_history_reaching_rib_keeps_either_direction[1.00-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-1915]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_history_keeps_every_rate_in_its_scope", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_mothers_own_rib_opens_only_in_each_holds_scope[UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978-1915-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]" + ], + "failed_test_count": 8, + "log": { + "path": "scratch/review/round7-mutations/own_rib_cohort_1915.log", + "sha256": "9e48e827fd88cfda6f2793355030bcff86fcf3e125b5751915ddfc416d6df9e5", + "failure_summary": "8 failed, 150 passed in 5.01s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-own_rib_cohort_1917", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "_FIRST_COHORT_WITHOUT_PRE_1978_OWN_RIB = 1916", + "after": "_FIRST_COHORT_WITHOUT_PRE_1978_OWN_RIB = 1917" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_cohort_past_1915_keeps_todays_formula_as_a_cap[1916-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_cohort_past_1915_keeps_todays_formula_as_a_cap[1916-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_cohort_past_1915_keeps_exact_own_history[1916]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_past_1915_every_reduction_only_hold_keeps_the_cap", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_mothers_own_rib_opens_only_in_each_holds_scope[UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978-1916-None]" + ], + "failed_test_count": 5, + "log": { + "path": "scratch/review/round7-mutations/own_rib_cohort_1917.log", + "sha256": "aaa81e34fd01ea53f87dd1b8d04b56366a39ad26dbbf0684d8565b3044c8a274", + "failure_summary": "5 failed, 153 passed in 5.00s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-pre1978_drop_own", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "_PRE_1978_HISTORY_HOLDS = frozenset(\n {\n UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978,\n UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978,\n }\n)\n", + "after": "_PRE_1978_HISTORY_HOLDS = frozenset(\n {UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978}\n)\n" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_declared_history_keeps_a_rate_above_todays_formula[333.30-318.50-8-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_declared_history_keeps_a_rate_above_todays_formula[1000-988.90-2-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_history_reaching_rib_keeps_either_direction[-1.00-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978-None]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_history_reaching_rib_keeps_either_direction[-0.10-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978-None]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_history_reaching_rib_keeps_either_direction[0.10-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978-None]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_history_reaching_rib_keeps_either_direction[1.00-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978-None]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_history_keeps_every_rate_in_its_scope", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_mothers_own_rib_opens_only_in_each_holds_scope[UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978-None-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_deemed_pia_keeps_a_history_open_on_a_zero_record_pia", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_f6_matches_a_table_written_from_the_sources" + ], + "failed_test_count": 13, + "log": { + "path": "scratch/review/round7-mutations/pre1978_drop_own.log", + "sha256": "72fcdc84fcd14071fe9b8b7471108918ac9f2572d32ed18449ba8bc7865ef9ec", + "failure_summary": "13 failed, 145 passed in 1.53s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-pre1978_drop_reduced", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "_PRE_1978_HISTORY_HOLDS = frozenset(\n {\n UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978,\n UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978,\n }\n)\n", + "after": "_PRE_1978_HISTORY_HOLDS = frozenset(\n {UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978}\n)\n" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_declared_history_keeps_a_rate_above_todays_formula[333.30-318.50-8-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_declared_history_keeps_a_rate_above_todays_formula[1000-988.90-2-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_history_reaching_rib_keeps_either_direction[0.10-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-None]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_history_reaching_rib_keeps_either_direction[1.00-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-None]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_history_keeps_every_rate_in_its_scope", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_f6_matches_a_table_written_from_the_sources", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_pre_1978_hold_needs_both_the_cohort_and_the_age[1927-1976-12-True-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_pre_1978_hold_needs_both_the_cohort_and_the_age[1928-1990-1-True-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_f2_matches_a_table_written_from_the_sources" + ], + "failed_test_count": 9, + "log": { + "path": "scratch/review/round7-mutations/pre1978_drop_reduced.log", + "sha256": "15d02a28f1cca5b288fb6b19df92deb413e78cac920e5d29bef397661c6b778e", + "failure_summary": "9 failed, 149 passed in 4.83s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-prior_adds_finality_reason", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "_PRIOR_REDUCED_BENEFIT_HOLDS = _PRE_1978_HISTORY_HOLDS | {\n RecordCondition.DIB_AFTER_REDUCED_RIB,\n UnsupportedReason.DIB_AFTER_REDUCED_RIB,\n UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE,\n}\n", + "after": "_PRIOR_REDUCED_BENEFIT_HOLDS = _PRE_1978_HISTORY_HOLDS | {\n RecordCondition.DIB_AFTER_REDUCED_RIB,\n UnsupportedReason.ADMINISTRATIVE_FINALITY,\n UnsupportedReason.DIB_AFTER_REDUCED_RIB,\n UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE,\n}\n" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_hold_no_age_limits_keeps_a_young_row[1975-conditions3-UnsupportedReason.ADMINISTRATIVE_FINALITY-UnsupportedReason.ADMINISTRATIVE_FINALITY]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_hold_no_age_limits_keeps_a_young_row[2000-conditions3-UnsupportedReason.ADMINISTRATIVE_FINALITY-UnsupportedReason.ADMINISTRATIVE_FINALITY]" + ], + "failed_test_count": 2, + "log": { + "path": "scratch/review/round7-mutations/prior_adds_finality_reason.log", + "sha256": "547f08e9013d4653294d3392447033f9e8455d33437658cbab4f0e8cb9707147", + "failure_summary": "2 failed, 156 passed in 2.12s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-prior_adds_finality_record", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "_PRIOR_REDUCED_BENEFIT_HOLDS = _PRE_1978_HISTORY_HOLDS | {\n RecordCondition.DIB_AFTER_REDUCED_RIB,\n UnsupportedReason.DIB_AFTER_REDUCED_RIB,\n UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE,\n}\n", + "after": "_PRIOR_REDUCED_BENEFIT_HOLDS = _PRE_1978_HISTORY_HOLDS | {\n RecordCondition.DIB_AFTER_REDUCED_RIB,\n RecordCondition.ADMINISTRATIVE_FINALITY,\n UnsupportedReason.DIB_AFTER_REDUCED_RIB,\n UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE,\n}\n" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_hold_no_age_limits_keeps_a_young_row[1975-conditions2-None-UnsupportedReason.ADMINISTRATIVE_FINALITY]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_hold_no_age_limits_keeps_a_young_row[2000-conditions2-None-UnsupportedReason.ADMINISTRATIVE_FINALITY]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_an_independent_hold_survives_a_young_dual_declaration[conditions1-UnsupportedReason.ADMINISTRATIVE_FINALITY]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_f2_matches_a_table_written_from_the_sources" + ], + "failed_test_count": 4, + "log": { + "path": "scratch/review/round7-mutations/prior_adds_finality_record.log", + "sha256": "387be4e6eafd8c80fc8e457fca353f95103bbb28412b0c153db5bb60a3c29fbe", + "failure_summary": "4 failed, 154 passed in 2.36s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-prior_adds_wc_reason", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "_PRIOR_REDUCED_BENEFIT_HOLDS = _PRE_1978_HISTORY_HOLDS | {\n RecordCondition.DIB_AFTER_REDUCED_RIB,\n UnsupportedReason.DIB_AFTER_REDUCED_RIB,\n UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE,\n}\n", + "after": "_PRIOR_REDUCED_BENEFIT_HOLDS = _PRE_1978_HISTORY_HOLDS | {\n RecordCondition.DIB_AFTER_REDUCED_RIB,\n UnsupportedReason.WORKERS_COMPENSATION_OFFSET,\n UnsupportedReason.DIB_AFTER_REDUCED_RIB,\n UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE,\n}\n" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_hold_no_age_limits_keeps_a_young_row[1975-conditions1-UnsupportedReason.WORKERS_COMPENSATION_OFFSET-UnsupportedReason.WORKERS_COMPENSATION_OFFSET]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_hold_no_age_limits_keeps_a_young_row[2000-conditions1-UnsupportedReason.WORKERS_COMPENSATION_OFFSET-UnsupportedReason.WORKERS_COMPENSATION_OFFSET]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_f2_matches_a_table_written_from_the_sources" + ], + "failed_test_count": 3, + "log": { + "path": "scratch/review/round7-mutations/prior_adds_wc_reason.log", + "sha256": "34aeb404fd0df8c717e409a74c142a68bc0ef0f7a2655df0ce1b8d015accede5", + "failure_summary": "3 failed, 155 passed in 2.14s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-prior_adds_wc_record", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "_PRIOR_REDUCED_BENEFIT_HOLDS = _PRE_1978_HISTORY_HOLDS | {\n RecordCondition.DIB_AFTER_REDUCED_RIB,\n UnsupportedReason.DIB_AFTER_REDUCED_RIB,\n UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE,\n}\n", + "after": "_PRIOR_REDUCED_BENEFIT_HOLDS = _PRE_1978_HISTORY_HOLDS | {\n RecordCondition.DIB_AFTER_REDUCED_RIB,\n RecordCondition.WORKERS_COMPENSATION_OFFSET,\n UnsupportedReason.DIB_AFTER_REDUCED_RIB,\n UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE,\n}\n" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_hold_no_age_limits_keeps_a_young_row[1975-conditions0-None-UnsupportedReason.WORKERS_COMPENSATION_OFFSET]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_hold_no_age_limits_keeps_a_young_row[2000-conditions0-None-UnsupportedReason.WORKERS_COMPENSATION_OFFSET]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_an_independent_hold_survives_a_young_dual_declaration[conditions0-UnsupportedReason.WORKERS_COMPENSATION_OFFSET]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_f2_matches_a_table_written_from_the_sources" + ], + "failed_test_count": 4, + "log": { + "path": "scratch/review/round7-mutations/prior_adds_wc_record.log", + "sha256": "606b7500b3af4463cd9a88983573c625903a6527f5716abc851684448369112a", + "failure_summary": "4 failed, 154 passed in 2.01s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-prior_drop_dual", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "_PRIOR_REDUCED_BENEFIT_HOLDS = _PRE_1978_HISTORY_HOLDS | {\n RecordCondition.DIB_AFTER_REDUCED_RIB,\n UnsupportedReason.DIB_AFTER_REDUCED_RIB,\n UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE,\n}\n", + "after": "_PRIOR_REDUCED_BENEFIT_HOLDS = _PRE_1978_HISTORY_HOLDS | {\n RecordCondition.DIB_AFTER_REDUCED_RIB,\n UnsupportedReason.DIB_AFTER_REDUCED_RIB,\n}\n" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_cohort_too_young_for_any_reduced_benefit_has_one_dib_rate", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_before_age_50_a_dib_below_the_pia_raises[1975-conditions2-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_before_age_50_a_dib_below_the_pia_raises[1980-conditions2-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_before_age_50_a_dib_below_the_pia_raises[2000-conditions2-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50[1974-2023-12-False-conditions2-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_f2_matches_a_table_written_from_the_sources", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_young_dib_rate_equals_its_pia_or_raises" + ], + "failed_test_count": 7, + "log": { + "path": "scratch/review/round7-mutations/prior_drop_dual.log", + "sha256": "5c112a645905c28ce05a282abf4b16bb437cd9830bb6204e1afc8c70a8016cc4", + "failure_summary": "7 failed, 151 passed in 4.55s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-prior_drop_pre1978", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "_PRIOR_REDUCED_BENEFIT_HOLDS = _PRE_1978_HISTORY_HOLDS | {\n RecordCondition.DIB_AFTER_REDUCED_RIB,\n UnsupportedReason.DIB_AFTER_REDUCED_RIB,\n UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE,\n}\n", + "after": "_PRIOR_REDUCED_BENEFIT_HOLDS = frozenset({\n RecordCondition.DIB_AFTER_REDUCED_RIB,\n UnsupportedReason.DIB_AFTER_REDUCED_RIB,\n UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE,\n})\n" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_pre_1978_hold_needs_both_the_cohort_and_the_age[1927-1976-12-True-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_pre_1978_hold_needs_both_the_cohort_and_the_age[1927-1976-12-True-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]" + ], + "failed_test_count": 2, + "log": { + "path": "scratch/review/round7-mutations/prior_drop_pre1978.log", + "sha256": "8327a89fe702445d1abd978ab2d81f9119ae9603727aef2d602f9f00e1dc3aaa", + "failure_summary": "2 failed, 156 passed in 1.87s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-prior_drop_rc_dib", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "_PRIOR_REDUCED_BENEFIT_HOLDS = _PRE_1978_HISTORY_HOLDS | {\n RecordCondition.DIB_AFTER_REDUCED_RIB,\n UnsupportedReason.DIB_AFTER_REDUCED_RIB,\n UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE,\n}\n", + "after": "_PRIOR_REDUCED_BENEFIT_HOLDS = _PRE_1978_HISTORY_HOLDS | {\n UnsupportedReason.DIB_AFTER_REDUCED_RIB,\n UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE,\n}\n" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_before_age_50_a_dib_below_the_pia_raises[1975-conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_before_age_50_a_dib_below_the_pia_raises[1980-conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_before_age_50_a_dib_below_the_pia_raises[2000-conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50[1974-2023-12-False-conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_f2_matches_a_table_written_from_the_sources", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_young_dib_rate_equals_its_pia_or_raises" + ], + "failed_test_count": 6, + "log": { + "path": "scratch/review/round7-mutations/prior_drop_rc_dib.log", + "sha256": "363173ed0a4b6d114a8b29489131a0cccdf2d7a3ea7c6ed46612aa76ae32ef99", + "failure_summary": "6 failed, 152 passed in 4.77s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-prior_drop_ur_dib", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "_PRIOR_REDUCED_BENEFIT_HOLDS = _PRE_1978_HISTORY_HOLDS | {\n RecordCondition.DIB_AFTER_REDUCED_RIB,\n UnsupportedReason.DIB_AFTER_REDUCED_RIB,\n UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE,\n}\n", + "after": "_PRIOR_REDUCED_BENEFIT_HOLDS = _PRE_1978_HISTORY_HOLDS | {\n RecordCondition.DIB_AFTER_REDUCED_RIB,\n UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE,\n}\n" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_before_age_50_a_dib_below_the_pia_raises[1975-conditions1-UnsupportedReason.DIB_AFTER_REDUCED_RIB-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_before_age_50_a_dib_below_the_pia_raises[1980-conditions1-UnsupportedReason.DIB_AFTER_REDUCED_RIB-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_before_age_50_a_dib_below_the_pia_raises[2000-conditions1-UnsupportedReason.DIB_AFTER_REDUCED_RIB-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50[1974-2023-12-False-conditions1-UnsupportedReason.DIB_AFTER_REDUCED_RIB-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_f2_matches_a_table_written_from_the_sources", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_young_dib_rate_equals_its_pia_or_raises" + ], + "failed_test_count": 6, + "log": { + "path": "scratch/review/round7-mutations/prior_drop_ur_dib.log", + "sha256": "5fcc08eab0ef0b8d2f3312bb707a50a37861d503c59684875eb3c40707e776ae", + "failure_summary": "6 failed, 152 passed in 4.59s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-reduced_history_drop_f6", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978: frozenset(\n {\"F2\", \"F3\", \"F6\"}\n", + "after": "UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978: frozenset(\n {\"F2\", \"F3\"}\n" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_mothers_own_rib_opens_only_in_each_holds_scope[UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-None-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_mothers_own_rib_opens_only_in_each_holds_scope[UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-1919-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_mothers_own_rib_opens_only_in_each_holds_scope[UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-1927-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_every_actual_rib_test_shares_the_carryover[1920-False-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-Role.MOTHER_FATHER]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_every_actual_rib_test_shares_the_carryover[1920-False-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-Role.PARENT]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_f6_matches_a_table_written_from_the_sources" + ], + "failed_test_count": 6, + "log": { + "path": "scratch/review/round7-mutations/reduced_history_drop_f6.log", + "sha256": "7581e21ded9dc450ccc5e657234c11af95b212588be6d8b05015609b190cc893", + "failure_summary": "6 failed, 152 passed in 2.07s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-roles_add_child", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "_OWN_RIB_AMOUNT_TEST_ROLES = _WIDOW_ROLES | {Role.MOTHER_FATHER, Role.PARENT}", + "after": "_OWN_RIB_AMOUNT_TEST_ROLES = _WIDOW_ROLES | {Role.MOTHER_FATHER, Role.PARENT, Role.CHILD}" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_role_with_no_rib_amount_test_stays_settled[UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-Role.CHILD]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_role_with_no_rib_amount_test_stays_settled[UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-Role.CHILD]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_f6_matches_a_table_written_from_the_sources" + ], + "failed_test_count": 3, + "log": { + "path": "scratch/review/round7-mutations/roles_add_child.log", + "sha256": "60707c24bc84f4b0a95769c1f7b7766c0f255808f6eac9c19f1eb2f15bf2d9b3", + "failure_summary": "3 failed, 155 passed in 1.95s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-roles_add_spouse", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "_OWN_RIB_AMOUNT_TEST_ROLES = _WIDOW_ROLES | {Role.MOTHER_FATHER, Role.PARENT}", + "after": "_OWN_RIB_AMOUNT_TEST_ROLES = _WIDOW_ROLES | {Role.MOTHER_FATHER, Role.PARENT, Role.SPOUSE}" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_role_with_no_rib_amount_test_stays_settled[UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-Role.SPOUSE]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_role_with_no_rib_amount_test_stays_settled[UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-Role.SPOUSE]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_f6_matches_a_table_written_from_the_sources" + ], + "failed_test_count": 3, + "log": { + "path": "scratch/review/round7-mutations/roles_add_spouse.log", + "sha256": "f97264012fe8b53cd71b76b090efdcee72c151e07e27c5c90570521b74743630", + "failure_summary": "3 failed, 155 passed in 2.17s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-roles_drop_mother", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "_OWN_RIB_AMOUNT_TEST_ROLES = _WIDOW_ROLES | {Role.MOTHER_FATHER, Role.PARENT}", + "after": "_OWN_RIB_AMOUNT_TEST_ROLES = _WIDOW_ROLES | {Role.PARENT}" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_mothers_carried_rib_passes_where_the_ordinary_one_fails[480-400-300-359.10-373.30-360]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_mothers_carried_rib_passes_where_the_ordinary_one_fails[1.20-1-0.80-0.80-0.90-0.90]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_pre_fra_mother_keeps_the_historical_year_row", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_mothers_own_rib_opens_only_in_each_holds_scope[UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-None-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_mothers_own_rib_opens_only_in_each_holds_scope[UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-1919-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_mothers_own_rib_opens_only_in_each_holds_scope[UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-1927-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_mothers_own_rib_opens_only_in_each_holds_scope[UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-1919-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_mothers_own_rib_opens_only_in_each_holds_scope[UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-1927-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_every_actual_rib_test_shares_the_carryover[1920-False-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-Role.MOTHER_FATHER]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_every_actual_rib_test_shares_the_carryover[1920-False-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-Role.MOTHER_FATHER]" + ], + "failed_test_count": 11, + "log": { + "path": "scratch/review/round7-mutations/roles_drop_mother.log", + "sha256": "e37bcb40b80e103b592ee6445f77b6fa2968907bba59d5821695015392fb81f4", + "failure_summary": "11 failed, 147 passed in 2.03s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-roles_drop_parent", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "_OWN_RIB_AMOUNT_TEST_ROLES = _WIDOW_ROLES | {Role.MOTHER_FATHER, Role.PARENT}", + "after": "_OWN_RIB_AMOUNT_TEST_ROLES = _WIDOW_ROLES | {Role.MOTHER_FATHER}" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_every_actual_rib_test_shares_the_carryover[1920-False-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-Role.PARENT]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_every_actual_rib_test_shares_the_carryover[1920-False-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-Role.PARENT]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_f6_matches_a_table_written_from_the_sources" + ], + "failed_test_count": 3, + "log": { + "path": "scratch/review/round7-mutations/roles_drop_parent.log", + "sha256": "86216f5b50c4a8112bd8dd67f4523c25535db9107317922a39ee8e8fa192b00e", + "failure_summary": "3 failed, 155 passed in 1.99s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" + }, + { + "id": "round7-roles_drop_widows", + "round": 7, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "_OWN_RIB_AMOUNT_TEST_ROLES = _WIDOW_ROLES | {Role.MOTHER_FATHER, Role.PARENT}", + "after": "_OWN_RIB_AMOUNT_TEST_ROLES = frozenset({Role.MOTHER_FATHER, Role.PARENT})" + } + ], + "command": [ + "python", + "scratch/review/run_round7_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round7_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round7", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round7", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_7.py::test_every_actual_rib_test_shares_the_carryover[1920-False-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-Role.WIDOW]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_every_actual_rib_test_shares_the_carryover[1920-False-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-Role.SURVIVING_DIVORCED_SPOUSE]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_every_actual_rib_test_shares_the_carryover[1920-False-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-Role.DISABLED_WIDOW]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_every_actual_rib_test_shares_the_carryover[1920-False-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-Role.WIDOW]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_every_actual_rib_test_shares_the_carryover[1920-False-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-Role.SURVIVING_DIVORCED_SPOUSE]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_every_actual_rib_test_shares_the_carryover[1920-False-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978-Role.DISABLED_WIDOW]" + ], + "failed_test_count": 6, + "log": { + "path": "scratch/review/round7-mutations/roles_drop_widows.log", + "sha256": "0bd2e973e96bf441050c4f1d72b9127b47bfe880773f1a5af3e9c4f94cb6f5ec", + "failure_summary": "6 failed, 152 passed in 2.05s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + } + }, + "layer": "g_preflight" } ], "restoration_verification_snapshot": { @@ -6657,5 +9093,11 @@ "round_6_restoration_snapshot": { "src/populace_dynamics/track_b/gross_benefits.py": "2584e41931506885ba34f43b147731f2f5adfb25bc84df6fc17bd134b9564f3d", "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + }, + "round_7_head": "3212f8231e4029539ebe8258a280217f7cdbbe3a", + "round_7_note": "42 fresh one-line semantic mutations failed named tests in tests/test_track_b_ret_ledger_fix_round_7.py on the final test bytes. A first pass killed 39 of 43. One survivor proved a redundant month comparison, so the code now compares years and that mutation is gone, and each of the other three was a test gap that gained a test before this run. The session ran these in copied source trees, and production sources stayed unchanged. Earlier records remain historical.", + "round_7_restoration_snapshot": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" } } diff --git a/docs/design/track_b_g2_r2b_verification.json b/docs/design/track_b_g2_r2b_verification.json index 55ff328f4..010118c5b 100644 --- a/docs/design/track_b_g2_r2b_verification.json +++ b/docs/design/track_b_g2_r2b_verification.json @@ -13077,5 +13077,89 @@ ] } }, - "round_6_current_evidence_note": "Fresh reviewed-head failing-first, named module gates, cross-head diagnostic and copied-tree mutation evidence sits under round_6. Earlier heads, counts and commands remain historical." + "round_6_current_evidence_note": "Fresh reviewed-head failing-first, named module gates, cross-head diagnostic and copied-tree mutation evidence sits under round_6. Earlier heads, counts and commands remain historical.", + "round_7": { + "reviewed_head": "3212f8231e4029539ebe8258a280217f7cdbbe3a", + "workspace": "/Users/maxghenis/PolicyEngine/_clones/mdyn-trackb-g2-20261023", + "verification_class": "statutory_conformance", + "admitted_scope": "Invented declarations and captured published examples only; no population, behavioral or forecast claim.", + "fixed_by": "the session, because Fleet ops asked for one job at a time and a review held the slot", + "named_test_gate": { + "selection": "tests/test_track_b_*.py", + "result": "14032 passed, 7 skipped in 750.31s (0:12:30)", + "environment": "both data roots set to a nonexistent path" + }, + "failing_first": { + "reviewed_head": "3212f8231e4029539ebe8258a280217f7cdbbe3a", + "module": "tests/test_track_b_ret_ledger_fix_round_7.py", + "result": "44 failed, 114 passed in 5.00s" + }, + "cross_head": { + "r2_stable_rows": 240, + "r3_stable_rows": 240, + "identical_declared_output_bytes": true, + "stable_sha256": "799fc9e23a902ac1ca0c2563579ceb094d0dbcd631a912305c40062cf21a5f55" + }, + "conformance_report_sha256": "17d144575b38bb85080d8cbed28fad470ec93fd6eb6803b48729bb26a78b3d45", + "conformance_report_byte_identical": true, + "tier_policy": "Left to CI; no local whole-suite collection.", + "final_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", + "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + }, + "final_test_sha256": { + "tests/test_track_b_ret_ledger_fix_round_4.py": "02c5c86b64070f9e7350868f8d94dcc9233bedc32cbcae32b3264f9ae570d1bb", + "tests/test_track_b_ret_ledger_fix_round_5.py": "c86ef045d797e31d6db09ef11bc7fbfbcf7c1fa54d32f04e7b6b42e8b813c9cd", + "tests/test_track_b_ret_ledger_fix_round_6.py": "afb00d6ed4b1fdfba114b830e25a7488168b96d68bb77d30cf56640c2b088aa1", + "tests/test_track_b_ret_ledger_fix_round_7.py": "ca905c8940d3b7ee32c2894b11a9fb0f11f393d6fdf80f43afa9768d4aeed829" + }, + "mutations": { + "count": 42, + "ids": [ + "round7-age_floor_49", + "round7-age_floor_51", + "round7-age_floor_62", + "round7-early_f3_only", + "round7-early_f6_only", + "round7-early_only_cap", + "round7-early_skips_cap", + "round7-early_tested_pia_ignores_basis", + "round7-early_worker_cohort_for_beneficiary", + "round7-early_worker_own_for_beneficiary", + "round7-early_zero_pia", + "round7-f6_drop_dual", + "round7-f6_drop_reduced", + "round7-floor_for_every_hold", + "round7-floor_reads_the_month_as_a_year", + "round7-floor_removed", + "round7-floor_strict", + "round7-floor_unknown_cohort_settled", + "round7-floor_unknown_month_settled", + "round7-history_any_cohort", + "round7-history_any_kind", + "round7-history_no_reduction", + "round7-history_unknown_cohort_settled", + "round7-history_zero_pia", + "round7-own_rib_cohort_1915", + "round7-own_rib_cohort_1917", + "round7-pre1978_drop_own", + "round7-pre1978_drop_reduced", + "round7-prior_adds_finality_reason", + "round7-prior_adds_finality_record", + "round7-prior_adds_wc_reason", + "round7-prior_adds_wc_record", + "round7-prior_drop_dual", + "round7-prior_drop_pre1978", + "round7-prior_drop_rc_dib", + "round7-prior_drop_ur_dib", + "round7-reduced_history_drop_f6", + "round7-roles_add_child", + "round7-roles_add_spouse", + "round7-roles_drop_mother", + "round7-roles_drop_parent", + "round7-roles_drop_widows" + ] + } + }, + "round_7_current_evidence_note": "Fresh reviewed-head failing-first, named module gates, cross-head diagnostic and copied-tree mutation evidence sits under round_7. Earlier heads, counts and commands remain historical." } diff --git a/docs/design/track_b_r2_ret_ledger.md b/docs/design/track_b_r2_ret_ledger.md index a66baae50..62c926c24 100644 --- a/docs/design/track_b_r2_ret_ledger.md +++ b/docs/design/track_b_r2_ret_ledger.md @@ -2142,8 +2142,8 @@ member separately. | `ELIGIBILITY_BEFORE_1983`, `DI_ENTITLEMENT_BEFORE_JULY_1980` | None | RS 00615.736 gives the historical maximum procedure; RS 00615.740B.2 says DMAX does not apply when "The NH was ever entitled to DIB before July 1980". These maximum histories do not replace role OB or current own-benefit facts. | | `PARENT_BENEFIT` | F4/F6 when parent count refuses | RS 00209.001 excludes own RIB "equal to or exceeding the amount of the parent's original benefit (One parent = 82 1/2%; Two parents = 75%)". RS 00209.015 states "Benefit rate equals 75% of the worker's PIA for each month both are entitled." An unresolved entitled-parent count leaves both threshold and OB unsettled. | | `DISABLED_WIDOW_UNDER_60` | No additional fact beyond a separately refusing own MBA | RS 00615.310C first says "Determine the WIB OB", then separately determines and subtracts reductions. The historical extra reduction changes gross, not F4's OB. | -| `DUAL_ENTITLEMENT_SEQUENCE` | F2 below the PIA; F3 below the ordinary rate and F6, each only where historical carryover can change own RIB | 20 CFR 404.411(b) reduces a DIB after a reduced RIB and, for "all individuals born before January 2, 1928" or a disability before 1990, after a WIB. The schema omits the onset, so F2 stays open in every cohort. 404.411(c)(2) reduces an old-age benefit "by the larger of the following" for a person born before January 2, 1928, even one who met every WIB condition "except that the old-age benefit equals or exceeds the primary insurance amount", so no current WIB or auxiliary record needs to appear. Both only lower a rate, so the ordinary rate stays the cap (round 6). RS 00615.005A.8 says "Eliminated the carry-over reduction in RIB or DIB due to WIB before age 62" and applies the RIB change to workers born January 2, 1928 or later. RS 00615.010 preserves the earlier rule: "If there was prior entitlement to a reduced WIB in any month before the month of attainment of age 62 reduce the RIB per RS 00615.160 and RS 00615.170." The schema omits that history. Modern WIB/DWB election instead requires "if all eligibility requirements are met" and preserves "the PIA and the reduction factors remain the same" (RS 00615.315). It does not waive F6. A nonnegative own RIB cannot be less than a zero deemed-death PIA. The spouse raw own-PIA test stays F5. | -| `REDUCED_BENEFIT_HISTORY_BEFORE_1978` | F2 below the PIA and, within the carryover scope above, F3 below the ordinary rate; each only before cohort 1928 | RS 00615.005C.2 requires historical money reductions. That does not change the original benefit determined before reduction, but the 404.411 rules above carry such a reduction into a later DIB or RIB. RS 00615.005A.7 gives age 50 as the earliest reduced disabled widow(er), so cohort 1928 reached no reduced benefit before 1978 (round 6). | +| `DUAL_ENTITLEMENT_SEQUENCE` | F2 below the PIA from the January a cohort can turn 50; F3 below the ordinary rate and F6, each only where historical carryover can change own RIB | 20 CFR 404.411(b) reduces a DIB after a reduced RIB and, for "all individuals born before January 2, 1928" or a disability before 1990, after a WIB. The schema omits the onset, so only age limits F2: no cohort reaches a reduced benefit before 50 (round 7). 404.411(c)(2) reduces an old-age benefit "by the larger of the following" for a person born before January 2, 1928, even one who met every WIB condition "except that the old-age benefit equals or exceeds the primary insurance amount", so no current WIB or auxiliary record needs to appear. Both only lower a rate, so the ordinary rate stays the cap (round 6). RS 00615.005A.8 says "Eliminated the carry-over reduction in RIB or DIB due to WIB before age 62" and applies the RIB change to workers born January 2, 1928 or later. RS 00615.010 preserves the earlier rule: "If there was prior entitlement to a reduced WIB in any month before the month of attainment of age 62 reduce the RIB per RS 00615.160 and RS 00615.170." The schema omits that history. Modern WIB/DWB election instead requires "if all eligibility requirements are met" and preserves "the PIA and the reduction factors remain the same" (RS 00615.315). It does not waive F6, which covers every test of an actual own RIB: widow(er), mother or father, and parent (round 7). A nonnegative own RIB cannot be less than a zero deemed-death PIA. The spouse raw own-PIA test stays F5. | +| `REDUCED_BENEFIT_HISTORY_BEFORE_1978` | F2 below the PIA and, within the carryover scope above, F3 below the ordinary rate and F6; each only before cohort 1928. Before cohort 1916, or with no cohort, F3 and F6 in both directions | RS 00615.005C.2 requires historical money reductions. That does not change the original benefit determined before reduction, but the 404.411 rules above carry such a reduction into a later DIB or RIB. RS 00615.005A.7 gives age 50 as the earliest reduced disabled widow(er), so cohort 1928 reached no reduced benefit before 1978 (round 6). A declared money history can exceed today's fraction, so it lifts the F3 cap where it can reach an own RIB, and F6 follows the same amount (round 7). | | `INDEPENDENT_DIVORCED_SPOUSE` | None | RS 00202.100 identifies the unfiled NH and requires the applicable WEP PIA; the declared PIA and eligibility facts are still the inputs. | | `COMBINED_FAMILY_MAXIMUM`, `MULTIPLE_AUXILIARY_RECORDS`, `DEEMED_SPOUSE`, `NON_AIME_FORMULA_PIA`, `DIB_GUARANTEE_PIA`, `GOVERNMENT_PENSION_OFFSET` | None | The condition table's captured maximum-membership, maximum-formula and payable-offset rules apply equally when the reason is deferred. | | `PARISI_AMBIGUOUS`, `PARISI_BEFORE_OCTOBER_1999` | None | RS 00615.768E says the change affects benefits "after reduction for the maximum" and "Beneficiaries will still be limited by the original benefit amount." | @@ -2351,15 +2351,17 @@ under a prior reduced RIB or workers' compensation, which also skipped the direction those sources settle. A DIB of $4.10 on PIA $4 counted as a refusal. It now raises. Every NH reduction-only hold, listed in `_NH_REDUCTION_ONLY_HOLDS`, leaves equality open below the rate and keeps -the rate as a cap. Administrative finality alone lifts a cap, because it -can protect a rate built on another PIA. +the rate as a cap. Administrative finality lifts a cap, because it can +protect a rate built on another PIA. Round 7 corrects this paragraph's +first statement that finality alone does so: a declared pre-1978 money +history also lifts an own RIB's cap. **The same class, beyond the findings.** Sol's exploratory probe of a DIB after a reduced WIB (404.411(b)) didn't enter its verdict. The session tested it and found the same lost row: $398.10 on PIA $400 raised under `dual_entitlement_sequence`. F2 now stays open below the PIA for that -reason in every cohort, because the schema omits the disability onset -that scopes 404.411(b)(2). `OWN_RIB_HISTORY_BEFORE_1978` and +reason, because the schema omits the disability onset that scopes +404.411(b)(2). Round 7 limits this to months a cohort can reach age 50. `OWN_RIB_HISTORY_BEFORE_1978` and `REDUCED_BENEFIT_HISTORY_BEFORE_1978` open it too, before cohort 1928 only: a later cohort reached age 50 after 1977. @@ -2384,7 +2386,7 @@ a later cohort reached age 50 after 1977. | Every rate 404.411(c)(2)(ii) can reach stays a counted refusal, and the preflight changes nothing about it | `test_published_rule_carryover_keeps_its_refusal`; Hypothesis `test_every_carryover_rate_keeps_its_row` | | The carryover ends at cohort 1928, reaches only an old-age benefit, and an unknown cohort can't rule it out | `test_carryover_ends_at_cohort_1928`; `test_the_carryover_reaches_only_an_old_age_benefit`; `test_an_unknown_cohort_cannot_rule_out_the_carryover`; `test_a_zero_pia_leaves_no_rate_for_the_carryover_to_lower` | | Each NH rate has a cap: a declaration above it raises, and one at or below it keeps its row | `test_a_reducing_hold_bounds_a_dib_at_its_pia`; `test_rib_above_the_canonical_rate_stays_an_input_error`; `test_rib_at_the_canonical_rate_keeps_its_refusal`; `test_workers_compensation_caps_a_rib_at_its_canonical_rate`; Hypothesis `test_every_dib_at_or_below_the_cap_keeps_its_row` | -| Only finality lifts a cap | `test_finality_still_protects_a_rate_above_the_cap`; `test_finality_still_protects_a_rib_above_the_cap`; `test_only_finality_lifts_an_nh_rate_cap` | +| Outside round 7's history scope, only finality lifts a cap | `test_finality_still_protects_a_rate_above_the_cap`; `test_finality_still_protects_a_rib_above_the_cap`; `test_only_finality_lifts_an_nh_rate_cap` | | Every G refusal reason classifies a lower DIB and a lower RIB against a written-out expectation | `test_each_reason_classifies_a_lower_dib`; `test_each_reason_classifies_a_lower_rib` | | Pre-1978 reasons reach only cohorts old enough for a reduced benefit by then | `test_pre_1978_history_reaches_only_cohorts_old_enough_for_it`; `test_an_unknown_cohort_cannot_rule_out_a_pre_1978_history` | | Each quotation above sits in its capture | `test_the_captures_carry_each_quoted_rule` | @@ -2399,3 +2401,100 @@ Thirty-eight fresh mutations, each in a copied source tree, failed named tests in the round 6 module. A first pass left two survivors, both test gaps, and each gained a test before the final run. Against `a135519f`, 50 of that module's 224 tests fail. + + +## PR 563 round 7: what a declared history reaches and what age rules out + +GPT-6.1 Sol reviewed `3212f823` and asked for changes, with three medium +findings. All three reproduced, and each one's reading matches its capture. +Two lost a lawful row by comparing a rate with an amount the declaration had +already put in doubt. One kept a row that no filling can make lawful. + +### What changed + +**A declared history reaches past an omitted cohort.** An omitted cohort +keeps the current formula, and that stays the rule for an undated input. A +declared `OWN_RIB_HISTORY_BEFORE_1978` or +`REDUCED_BENEFIT_HISTORY_BEFORE_1978` says more: RS 00615.005C.2's money +reduction set the amount, and that reduction can exceed today's fraction. +Take PIA $123.40 at RF 8 in December 1977, every captured COLA through 1999, +and an upward January 2000 recomputation to PIA $333.30. All sixteen rounding +paths give $318.50, and today's formula gives $318.40. That declaration +raised and lost its row. It now keeps its reason with weight 7, in both +directions. The sources set the scope in `_historical_own_rib_possible`: an +old-age benefit, a positive PIA, a remaining reduction, and a cohort before +1916 or none. Cohort 1916 attains 62 no earlier than January 1978, so it +keeps today's formula as its cap. A DIB keeps its PIA as its cap, because +this history reaches a DIB only through a 404.411(b) reduction. F6 reads the +same amount, so it follows the same rule. + +**Every test of an actual own RIB shares the carryover.** Act 202(g)(1)(C) +compares a mother's or father's actual own RIB with three-quarters of the +PIA, and RS 00209.001 compares a parent's with the parent's OB. Round 6 opened +the 404.411(c)(2) carryover for widow(er)s alone, though that rule doesn't +depend on the benefit a person claims now. So a mother with own PIA $400, a +prior WIB on PIA $300 and a threshold of $360 carries $359.10 against an +ordinary $373.30. That declaration raised and lost its row. It now keeps +`dual_entitlement_sequence` with weight 7, in a pre-FRA year too. +`_OWN_RIB_AMOUNT_TEST_ROLES` lists the roles. A spouse's test reads the raw +own PIA (F5), which no history changes, and a child's has no amount test. +`REDUCED_BENEFIT_HISTORY_BEFORE_1978` now opens F6 in the same scope, because +it carries through the same rule that already opened F3. + +**Age rules out a prior reduced benefit.** RS 00615.010 says "DIB is not +reduced unless there was prior entitlement to reduced RIB (or WIB prior to +1/90)." RS 00615.005 starts those benefits at 62 and, for a disabled +widow(er), at 50. A cohort attains 50 no earlier than January of its birth +year plus 50. So a DIB of $404.90 on PIA $405 for cohort 1975 in 2024 has no +lawful filling under `dual_entitlement_sequence`. It now raises before +`evaluate_ret` and leaves no row. A rate at the PIA keeps its named refusal, +and the PIA stays the cap. + +`_PRIOR_REDUCED_BENEFIT_HOLDS` lists the holds that open F2 through a prior +reduced benefit. A workers' compensation offset and administrative finality +need no such benefit, so each keeps a young row, even beside a dual +declaration. Before writing this check, the session read each hold that opens +F2, as the preflight rule requires, and no other hold can lawfully lower a +young DIB. + +**The floor takes the earliest age on any route.** `DIB_AFTER_REDUCED_RIB` +names a RIB, which starts at 62. The schema offers no separate declaration +for a DIB after a reduced WIB under 404.411(b)(2), though, so this round +applies age 50 to that hold too. From 50 through 61 the row stays a named +refusal. The direction rule decides this: the rule can't show that a caller +meant a RIB alone, and a loose refusal moves no money. + +### What stayed + +- **An undated input with no history hold keeps today's formula.** A + carryover or workers' compensation offset can only lower an own RIB: + 404.411(c)(2) reduces it "by the larger of the following". So + `dual_entitlement_sequence` keeps the cap with no cohort. +- **G still takes entitlement as declared.** An RIB below age 62 computes + with no hold, as it did before this round, because G computes payment and + not entitlement. Under a carryover hold such a rate keeps a named refusal. + An entitlement-age check would reach every record, so it sits outside this + fix. +- **Round 6's generator stays.** `_dib_record` there defaults to cohort 1960 + in 2024, age 64, which sits above the floor. Round 7's generators sweep + both sides. +- **No money moved.** This round changes classification only. +- **Sol's `needs_max` items need no new call.** Each one keeps a standing + ruling or resolves inside these fixes. + +### New executed invariants + +| Invariant | Executing tests in `test_track_b_ret_ledger_fix_round_7.py` | +| --- | --- | +| Money history lands above today's formula on every rounding path, from the captured COLAs | `test_money_history_lands_above_todays_formula_on_every_path` | +| A declared history keeps every rate in its scope, in both directions, and the preflight changes nothing about it | `test_declared_history_keeps_a_rate_above_todays_formula`; `test_a_history_reaching_rib_keeps_either_direction`; Hypothesis `test_history_keeps_every_rate_in_its_scope` | +| Past that scope the cap holds: cohort 1916 on, no remaining reduction, no declared history, and every DIB | `test_a_cohort_past_1915_keeps_todays_formula_as_a_cap`; `test_a_cohort_past_1915_keeps_exact_own_history`; `test_no_remaining_reduction_needs_no_money_history`; `test_only_a_declared_history_reaches_past_an_omitted_cohort`; `test_history_leaves_a_dib_cap_alone`; Hypothesis `test_past_1915_every_reduction_only_hold_keeps_the_cap` | +| A mother's carried rate keeps its row where the ordinary rate fails her test, in a pre-FRA year too | `test_a_mothers_carried_rib_passes_where_the_ordinary_one_fails`; `test_a_pre_fra_mother_keeps_the_historical_year_row`; `test_a_mothers_own_rib_opens_only_in_each_holds_scope` | +| Every actual-RIB test shares the carryover, and no other role or a DIB does | `test_every_actual_rib_test_shares_the_carryover`; `test_a_role_with_no_rib_amount_test_stays_settled`; `test_a_disability_own_benefit_faces_no_rib_amount_test`; Hypothesis `test_f6_matches_a_table_written_from_the_sources` | +| A zero PIA fails every RIB on every filling, a deemed PIA counts as the tested PIA, and a money history needs an old-age benefit with a PIA | `test_a_zero_pia_fails_every_rib_on_every_filling`; `test_a_deemed_pia_keeps_a_history_open_on_a_zero_record_pia`; `test_a_reduced_dib_opens_no_money_history`; `test_a_zero_own_pia_leaves_no_money_history` | +| Before a cohort can reach 50, a DIB rate equals its PIA or raises and leaves no row | `test_a_cohort_too_young_for_any_reduced_benefit_has_one_dib_rate`; `test_before_age_50_a_dib_below_the_pia_raises`; Hypothesis `test_a_young_dib_rate_equals_its_pia_or_raises` | +| The floor opens in January of the year a cohort turns 50, and needs a cohort and a month | `test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50`; `test_the_floor_needs_a_cohort_and_a_month`; `test_a_pre_1978_hold_needs_both_the_cohort_and_the_age` | +| No age limits a hold that needs no prior reduced benefit | `test_a_hold_no_age_limits_keeps_a_young_row`; `test_an_independent_hold_survives_a_young_dual_declaration`; Hypothesis `test_f2_matches_a_table_written_from_the_sources` | +| Each quotation above sits in its capture | `test_the_captures_carry_each_quoted_rule` | + +Forty-two fresh mutations each fail a named test on the final test bytes, and 44 of the module's 158 tests fail against `3212f823`. A first pass killed 39 of 43. One survivor showed that a month comparison added nothing, so the rule now compares years and that mutation went away. The other three exposed test gaps, and each gained a test before this run. diff --git a/src/populace_dynamics/track_b/gross_benefits.py b/src/populace_dynamics/track_b/gross_benefits.py index 7d600ff14..6558e2ee0 100644 --- a/src/populace_dynamics/track_b/gross_benefits.py +++ b/src/populace_dynamics/track_b/gross_benefits.py @@ -429,6 +429,11 @@ # This cohort reached 50 after 1977, so no benefit reached it reduced by then # (RS 00615.005A.7 gives age 50 as the earliest reduced disabled widow(er)). _FIRST_COHORT_WITHOUT_PRE_1978_REDUCTION = 1928 +# RS 00615.005A.4 starts reduced disabled widow(er)'s benefits at age 50. RIB +# and spouse's benefits start at 62 (A.1, A.2) and aged WIB at 60 (A.3). +_EARLIEST_REDUCED_BENEFIT_AGE = 50 +# This cohort attains 62 no earlier than January 1978 (RS 00615.005C.2). +_FIRST_COHORT_WITHOUT_PRE_1978_OWN_RIB = 1916 # --------------------------------------------------------------------------- @@ -1384,7 +1389,7 @@ def _refuse_historical_own_rib( pia > 0 and reduction_months > 0 and birth_year is not None - and birth_year < 1916 + and birth_year < _FIRST_COHORT_WITHOUT_PRE_1978_OWN_RIB ): raise _computed( FamilyConfigurationUnsupported, @@ -1780,7 +1785,7 @@ class BeneficiaryCondition(Enum): {"F2", "F3", "F6"} ), UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978: frozenset( - {"F2", "F3"} + {"F2", "F3", "F6"} ), UnsupportedReason.PRISONER_SUSPENSION: frozenset(), UnsupportedReason.DRUG_ADDICTION_SUSPENSION: frozenset(), @@ -1792,7 +1797,9 @@ class BeneficiaryCondition(Enum): UnsupportedReason.SOLE_FULL_DEDUCTION_ZERO_DUAL_COMPOSITION: frozenset(), } # These holds can only lower an NH rate (402(q)(2), 224; 20 CFR 404.408(c)(1), -# 404.411(b)-(c)), so the rate an unheld record would pay stays its cap. +# 404.411(b)-(c)), so the rate an unheld record would pay stays its cap. Pre-1978 +# money history is the exception for an own RIB, which it can raise above +# today's formula (_historical_own_rib_possible). _NH_REDUCTION_ONLY_HOLDS = frozenset( { RecordCondition.DIB_AFTER_REDUCED_RIB, @@ -1804,6 +1811,22 @@ class BeneficiaryCondition(Enum): UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978, } ) +_PRE_1978_HISTORY_HOLDS = frozenset( + { + UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978, + UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978, + } +) +# Each opens F2 only through a prior reduced benefit. A workers' compensation +# offset and administrative finality don't, so no age limits them. +_PRIOR_REDUCED_BENEFIT_HOLDS = _PRE_1978_HISTORY_HOLDS | { + RecordCondition.DIB_AFTER_REDUCED_RIB, + UnsupportedReason.DIB_AFTER_REDUCED_RIB, + UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE, +} +# _is_entitled compares these roles' actual own RIB. A spouse's test reads the +# raw own PIA (F5), which no reduction history changes. +_OWN_RIB_AMOUNT_TEST_ROLES = _WIDOW_ROLES | {Role.MOTHER_FATHER, Role.PARENT} def _declared_fact_holds(state, beneficiary=None): @@ -1832,6 +1855,42 @@ def _wib_carryover_possible(own, birth_year): ) +def _historical_own_rib_possible(own, birth_year): + """Whether pre-1978 money history could set this own RIB. + + RS 00615.005C.2's money reduction can exceed today's fraction. Undated + inputs stay in the current-formula domain, so only a declared history + hold reaches an omitted cohort. A zero PIA or no remaining reduction + needs no historical reduction amount (_refuse_historical_own_rib). + """ + return ( + own is not None + and own.kind is OwnBenefitKind.OLD_AGE + and own.pia > 0 + and own.reduction_months > 0 + and ( + birth_year is None + or birth_year < _FIRST_COHORT_WITHOUT_PRE_1978_OWN_RIB + ) + ) + + +def _prior_reduced_benefit_possible(birth_year, payment_month): + """Whether any reduced benefit could precede this payment month. + + RS 00615.010 says "DIB is not reduced unless there was prior entitlement + to reduced RIB (or WIB prior to 1/90)." RS 00615.005A.1-A.4 start those + benefits no earlier than age 50, and an SSA cohort attains an age no + earlier than January of that year. The schema doesn't say which route a + hold took, so every hold shares the earliest age of any route. + """ + return ( + birth_year is None + or payment_month is None + or payment_month.year >= birth_year + _EARLIEST_REDUCED_BENEFIT_AGE + ) + + def _hold_unsettles_fact( hold, fact, @@ -1845,18 +1904,38 @@ def _hold_unsettles_fact( ): if fact not in _PREFLIGHT_FACT_UNSETTLERS[hold]: return False + if fact in ("F3", "F6") and hold in _PRE_1978_HISTORY_HOLDS: + own, cohort, tested_pia = ( + (state.worker, state.worker_birth_year, state.pia) + if beneficiary is None + else ( + beneficiary.own_benefit, + beneficiary.birth_year, + beneficiary.original_benefit_basis or state.pia, + ) + ) + # A declared history reaches past the undated current formula, in + # either direction. A zero PIA fails every RIB on every filling. + if tested_pia > 0 and _historical_own_rib_possible(own, cohort): + return True if ( upper_bound and hold in _NH_REDUCTION_ONLY_HOLDS and fact in ("F2", "F3") ): return False - # 404.411(b) reduces a DIB after a reduced RIB in any cohort and after a - # WIB under (b)(2). The schema omits the onset that scopes (b)(2). - if fact == "F2" and hold in ( - UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978, - UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978, + # 404.411(b) reduces a DIB after a reduced RIB and after a WIB under + # (b)(2). The schema omits the onset that scopes (b)(2), so only age and + # the pre-1978 cohort limit a hold that works through either benefit. + if ( + fact == "F2" + and hold in _PRIOR_REDUCED_BENEFIT_HOLDS + and not _prior_reduced_benefit_possible( + state.worker_birth_year, payment_month + ) ): + return False + if fact == "F2" and hold in _PRE_1978_HISTORY_HOLDS: cohort = state.worker_birth_year return ( cohort is None or cohort < _FIRST_COHORT_WITHOUT_PRE_1978_REDUCTION @@ -1935,7 +2014,10 @@ def _hold_unsettles_fact( return state.kind is FamilyKind.SURVIVOR and ( upper_bound or beneficiary.role in _WIDOW_ROLES ) - if hold is UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE and fact == "F6": + if fact == "F6" and hold in ( + UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE, + UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978, + ): if beneficiary is None: return True # RS 00615.005A.8/.010 can change the own RIB before cohort 1928. @@ -1943,7 +2025,7 @@ def _hold_unsettles_fact( # PIA/RFs unchanged (RS 00615.315). A nonnegative RIB cannot be # less than a zero deemed-death PIA (402(e)(1)(D)). return ( - beneficiary.role in _WIDOW_ROLES + beneficiary.role in _OWN_RIB_AMOUNT_TEST_ROLES and (beneficiary.original_benefit_basis or state.pia) > 0 and _wib_carryover_possible( beneficiary.own_benefit, beneficiary.birth_year diff --git a/tests/README-tiers.md b/tests/README-tiers.md index d85e08e30..f0ed6c644 100644 --- a/tests/README-tiers.md +++ b/tests/README-tiers.md @@ -39,9 +39,9 @@ pytest --collect-only -q -m oracle_policyengine | tail -1 | Tier | Tests at HEAD | |---|---:| -| `unit` | 21,028 | +| `unit` | 21,186 | | `artifact` | 4,271 | | `integration_psid` | 1,471 | | `reproduction_legacy` | 520 | | `oracle_policyengine` | 308 | -| **Total** | **27,598** | +| **Total** | **27,756** | diff --git a/tests/test_track_b_ret_ledger_fix_round_6.py b/tests/test_track_b_ret_ledger_fix_round_6.py index f053826a6..d3456371c 100644 --- a/tests/test_track_b_ret_ledger_fix_round_6.py +++ b/tests/test_track_b_ret_ledger_fix_round_6.py @@ -611,6 +611,7 @@ def test_each_reason_classifies_a_lower_rib(reason): @pytest.mark.parametrize("reason", list(UR), ids=lambda reason: reason.value) @pytest.mark.parametrize("kind", ["dib", "rib"]) def test_only_finality_lifts_an_nh_rate_cap(reason, kind): + # Cohort 1927 sits past the money-history scope that round 7 opens. pia = F(400) case = ( _dib_record(pia, pia + F(1, 10), reason=reason) diff --git a/tests/test_track_b_ret_ledger_fix_round_7.py b/tests/test_track_b_ret_ledger_fix_round_7.py new file mode 100644 index 000000000..50b1b8825 --- /dev/null +++ b/tests/test_track_b_ret_ledger_fix_round_7.py @@ -0,0 +1,900 @@ +"""Round 7: what a declared history reaches, and what age rules out. + +Every record is invented or built from a captured SSA rule. Nothing here +admits a population, behavioral or forecast claim. +""" + +from __future__ import annotations + +import html +import re +from fractions import Fraction as F +from pathlib import Path + +import pytest +from hypothesis import example, given, settings +from hypothesis import strategies as st + +from populace_dynamics.track_b import gross_benefits as g +from populace_dynamics.track_b import ret_ledger as r +from populace_dynamics.track_b.ret_grace import BenefitType as T +from populace_dynamics.track_b.ret_params import load_ret_parameters +from tests.track_b_gross_benefit_support import source_text, ssa_params + +PARAMS = load_ret_parameters() +RC = g.RecordCondition +UR = g.UnsupportedReason +ARF_SOURCES = Path(__file__).parent / "data/track_b/arf_recompute_sources" +RET_SOURCES = Path(__file__).parent / "data/track_b/ret_sources" +OWN_HISTORY = UR.OWN_RIB_HISTORY_BEFORE_1978 +REDUCED_HISTORY = UR.REDUCED_BENEFIT_HISTORY_BEFORE_1978 +DUAL = UR.DUAL_ENTITLEMENT_SEQUENCE +PRE_1978_REASONS = (OWN_HISTORY, REDUCED_HISTORY) +CARRYOVER_REASONS = (DUAL, REDUCED_HISTORY) +# Written out, not read from G: an edit to G's sets must fail here. +AMOUNT_TEST_ROLES = ( + g.Role.WIDOW, + g.Role.SURVIVING_DIVORCED_SPOUSE, + g.Role.DISABLED_WIDOW, + g.Role.MOTHER_FATHER, + g.Role.PARENT, +) +SPOUSE_ROLES = (g.Role.SPOUSE, g.Role.DIVORCED_SPOUSE) +# (conditions, deferred reason, the refusal it names) +PRIOR_REDUCED_HOLDS = ( + ({RC.DIB_AFTER_REDUCED_RIB}, None, UR.DIB_AFTER_REDUCED_RIB), + ((), UR.DIB_AFTER_REDUCED_RIB, UR.DIB_AFTER_REDUCED_RIB), + ((), DUAL, DUAL), +) +# None of these holds needs a prior reduced benefit. +AGE_FREE_HOLDS = ( + ({RC.WORKERS_COMPENSATION_OFFSET}, None, UR.WORKERS_COMPENSATION_OFFSET), + ((), UR.WORKERS_COMPENSATION_OFFSET, UR.WORKERS_COMPENSATION_OFFSET), + ({RC.ADMINISTRATIVE_FINALITY}, None, UR.ADMINISTRATIVE_FINALITY), + ((), UR.ADMINISTRATIVE_FINALITY, UR.ADMINISTRATIVE_FINALITY), +) + + +def _outcome(case): + return r.evaluate_ret( + "round7", F(7), lambda: r.apply_ret_year(case, PARAMS) + ) + + +def _assert_refusal(case, reason): + outcome = _outcome(case) + assert not outcome.supported + assert outcome.unsupported.reason is reason + counts = r.count_ret_outcomes([outcome]) + assert (counts.rows, counts.weight, counts.unsupported_weight) == (1, 7, 7) + + +def _assert_invalid(case, match="G context does not match RET rates"): + rows = [] + with pytest.raises(g.InvalidFamilyInput, match=match): + rows.append(_outcome(case)) + counts = r.count_ret_outcomes(rows) + assert (counts.rows, counts.weight) == (0, 0) + + +def _assert_preflight_neutral(case): + actual = _outcome(case) + with pytest.MonkeyPatch.context() as patch: + patch.setattr(r, "_check_settled_family_facts", lambda record: None) + without = _outcome(case) + assert not actual.supported and not without.supported + assert actual.unsupported.reason is without.unsupported.reason + assert actual.unsupported.detail == without.unsupported.detail + assert r.count_ret_outcomes([actual]) == r.count_ret_outcomes([without]) + + +def _deferred(reason): + return None if reason is None else (reason, "invented declared history") + + +def _rib_record( + pia, gross, *, reason=None, cohort=None, months=8, conditions=() +): + state = g.RecordState( + g.FamilyKind.RETIREMENT, + pia, + g.floor_dime(pia * F(3, 2)), + worker=g.OwnBenefit( + g.OwnBenefitKind.OLD_AGE, + pia, + reduction_months=months, + birth_year=cohort, + ), + worker_birth_year=cohort, + conditions=conditions, + deferred_refusal=_deferred(reason), + ) + return r.RecordYear( + 2000, + "nh", + r.RecordKind.RETIREMENT, + ( + r.RETBeneficiary( + "nh", + (T.RIB,) * 12, + {1}, + (gross,) + (F(0),) * 11, + (pia,) * 12, + fra_month=0, + ), + ), + family_months={1: r.RETFamilyMonth(state, (), ssa_params(), {})}, + ) + + +def _ordinary(pia, months=8): + return g.floor_dime(pia * F(180 - months, 180)) + + +def _dib_record( + pia, + gross, + *, + birth=1975, + year=2024, + month=1, + conditions=(), + reason=None, + maximum=None, + first=None, +): + state = g.RecordState( + g.FamilyKind.DISABILITY, + pia, + g.floor_dime(pia * F(3, 2)) if maximum is None else maximum, + worker_birth_year=birth, + eligibility_year=year - 1 if first is None else first.year, + first_dib_entitlement=( + g.YearMonth(year - 1, 1) if first is None else first + ), + conditions=conditions, + deferred_refusal=_deferred(reason), + ) + return r.RecordYear( + year, + "nh", + r.RecordKind.DISABILITY, + ( + r.RETBeneficiary( + "nh", + (T.DIB,) * 12, + {month}, + tuple(gross if m == month else F(0) for m in range(1, 13)), + (pia,) * 12, + fra_month=None, + ), + ), + family_months={month: r.RETFamilyMonth(state, (), ssa_params(), {})}, + ) + + +def _mother_record( + reason=DUAL, + *, + cohort=1919, + pia=F(480), + own=F(400), + months=12, + gross=F("0.90"), + year=2000, + eligibility=1990, + maximum=None, +): + state = g.RecordState( + g.FamilyKind.SURVIVOR, + pia, + g.floor_dime(pia * F(3, 2)) if maximum is None else maximum, + eligibility_year=eligibility, + widow_drc_savings_clause=False, + deferred_refusal=_deferred(reason), + ) + members = ( + g.Beneficiary( + "m", + g.Role.MOTHER_FATHER, + birth_year=cohort, + own_benefit=g.OwnBenefit( + g.OwnBenefitKind.OLD_AGE, + own, + reduction_months=months, + birth_year=cohort, + ), + ), + g.Beneficiary("c", g.Role.CHILD), + ) + original = g.floor_dime(pia * F(3, 4)) + fra_month = 0 if year == 2000 else None + return r.RecordYear( + year, + "nh", + r.RecordKind.DECEASED, + ( + r.RETBeneficiary( + "m", + (T.MOTHER_FATHER,) * 12, + {1}, + (gross,) + (F(0),) * 11, + (original,) * 12, + fra_month=fra_month, + ), + r.RETBeneficiary( + "c", + (T.CDB,) * 12, + {1}, + (original,) + (F(0),) * 11, + (original,) * 12, + fra_month=fra_month, + ), + ), + family_months={ + 1: r.RETFamilyMonth( + state, members, ssa_params(), {"m": "h", "c": "h"} + ) + }, + ) + + +def _f2_settled(birth, year, month, *, conditions=(), reason=None): + state = g.RecordState( + g.FamilyKind.DISABILITY, + F(400), + F(600), + worker_birth_year=birth, + eligibility_year=year - 1, + first_dib_entitlement=g.YearMonth(year - 1, 1), + conditions=conditions, + deferred_refusal=_deferred(reason), + ) + return g._fact_is_settled( + "F2", + state, + payment_month=g.YearMonth(year, month), + params=ssa_params(), + ) + + +def _f6_settled( + role, reason, cohort, *, pia=F(480), months=12, kind=None, own_pia=F(400) +): + state = g.RecordState( + g.FamilyKind.SURVIVOR, + pia, + g.floor_dime(pia * F(3, 2)), + eligibility_year=1990, + widow_drc_savings_clause=False, + deferred_refusal=_deferred(reason), + ) + member = g.Beneficiary( + "m", + role, + birth_year=cohort, + own_benefit=g.OwnBenefit( + g.OwnBenefitKind.OLD_AGE if kind is None else kind, + own_pia, + reduction_months=months, + birth_year=cohort, + ), + own_benefit_first=True if role in SPOUSE_ROLES else None, + ) + return g._fact_is_settled( + "F6", + state, + member, + payment_month=g.YearMonth(2000, 1), + beneficiaries=(member,), + params=ssa_params(), + ) + + +def _carried_rib(own, prior_pia): + """404.411(c)(2)(ii): first WIB at 60, own RIB at 64, cohort 1927.""" + return g.floor_dime( + own - prior_pia * 24 * F(19, 4000) - (own - prior_pia) * F(12, 180) + ) + + +def _money_history_rates(start_pia, months, final_pia): + """Every dime path of RS 00615.005C.2's money reduction, as gross rates. + + The rate starts in December 1977 and takes each captured COLA through + 1999. Before June 1982 the MBA rounds up (RS 00615.101), so the money + reduction rounds down, and each of the four PIA dimes can fall either + way. From June 1982 the reduction rounds up. A January 2000 recomputation + then applies the current money ratio to the new PIA. + """ + raw = (RET_SOURCES / "ssa_cola_history.html").read_text() + rows = re.findall( + r"]*>(19[789]\d)(.*?)\s*]*>([\d.]+)", + raw, + re.S, + ) + colas = {int(year): int(F(rate) * 10) for year, _, rate in rows} + rates = set() + for path in range(16): + pia = int(start_pia * 10) + reduction = pia * months // 180 + for year in range(1978, 2000): + raised = pia * (1000 + colas[year]) + upward = year < 1982 and path >> (year - 1978) & 1 + new_pia = (raised + 999) // 1000 if upward else raised // 1000 + scaled = new_pia * reduction + reduction = ( + scaled // pia if year < 1982 else (scaled + pia - 1) // pia + ) + pia = new_pia + final = int(final_pia * 10) + assert final > pia + rates.add(F(final - (final * reduction + pia - 1) // pia, 10)) + return rates + + +def test_the_captures_carry_each_quoted_rule(): + assert ( + "DIB is not reduced unless there was prior entitlement to reduced " + "RIB (or WIB prior to 1/90)." in source_text("poms_rs_00615_010") + ) + reduced = source_text("poms_rs_00615_005") + for quote in ( + "Provided for reduced disabled widow's benefits at ages 50-59", + "Provided for the payment of reduced retirement, reduced spouse's " + "and unreduced widow's benefits to women at age 62.", + "Provided for reduced widow's benefits beginning at age 60.", + ): + assert quote in reduced + raw = (ARF_SOURCES / "ecfr_20cfr_404_411.xml").read_text() + text = re.sub(r"\s+", " ", html.unescape(re.sub("<[^>]+>", " ", raw))) + for quote in ( + "the old-age benefit is reduced by the larger of the following", + "A person's disability benefit is reduced following entitlement to " + "an old-age or widow's or widower's benefit", + ): + assert quote in text + + +@pytest.mark.parametrize( + "start,months,final,rate,ordinary", + [ + ("123.40", 8, "333.30", "318.50", "318.40"), + ("251.30", 2, "1000", "988.90", "988.80"), + ], +) +def test_money_history_lands_above_todays_formula_on_every_path( + start, months, final, rate, ordinary +): + assert _money_history_rates(F(start), months, F(final)) == {F(rate)} + assert _ordinary(F(final), months) == F(ordinary) + + +@pytest.mark.parametrize("reason", PRE_1978_REASONS) +@pytest.mark.parametrize( + "pia,gross,months", + [("333.30", "318.50", 8), ("1000", "988.90", 2)], +) +def test_declared_history_keeps_a_rate_above_todays_formula( + reason, pia, gross, months +): + case = _rib_record(F(pia), F(gross), reason=reason, months=months) + _assert_refusal(case, reason) + _assert_preflight_neutral(case) + + +@pytest.mark.parametrize("cohort", [None, 1913, 1915]) +@pytest.mark.parametrize("reason", PRE_1978_REASONS) +@pytest.mark.parametrize("gap", ["-1.00", "-0.10", "0", "0.10", "1.00"]) +def test_a_history_reaching_rib_keeps_either_direction(reason, cohort, gap): + pia = F("333.30") + gross = _ordinary(pia) + F(gap) + _assert_refusal( + _rib_record(pia, gross, reason=reason, cohort=cohort), reason + ) + + +@pytest.mark.parametrize("reason", PRE_1978_REASONS) +@pytest.mark.parametrize("cohort", [1916, 1920, 1927]) +def test_a_cohort_past_1915_keeps_todays_formula_as_a_cap(reason, cohort): + pia = F("333.30") + _assert_invalid( + _rib_record( + pia, _ordinary(pia) + F(1, 10), reason=reason, cohort=cohort + ) + ) + + +@pytest.mark.parametrize("cohort", [1916, 1927]) +def test_a_cohort_past_1915_keeps_exact_own_history(cohort): + pia = F("333.30") + _assert_invalid( + _rib_record( + pia, _ordinary(pia) - F(1, 10), reason=OWN_HISTORY, cohort=cohort + ) + ) + _assert_refusal( + _rib_record( + pia, + _ordinary(pia) - F(1, 10), + reason=REDUCED_HISTORY, + cohort=cohort, + ), + REDUCED_HISTORY, + ) + + +@pytest.mark.parametrize("reason", PRE_1978_REASONS) +def test_no_remaining_reduction_needs_no_money_history(reason): + pia = F("333.30") + _assert_invalid(_rib_record(pia, pia + F(1, 10), reason=reason, months=0)) + + +@pytest.mark.parametrize( + "conditions,reason", + [ + ((), None), + ((), DUAL), + ((), UR.WORKERS_COMPENSATION_OFFSET), + ({RC.WORKERS_COMPENSATION_OFFSET}, None), + ], +) +def test_only_a_declared_history_reaches_past_an_omitted_cohort( + conditions, reason +): + pia = F("333.30") + _assert_invalid( + _rib_record( + pia, + _ordinary(pia) + F(1, 10), + conditions=conditions, + reason=reason, + ) + ) + + +@pytest.mark.parametrize("reason", PRE_1978_REASONS) +def test_finality_still_lifts_the_cap_past_the_history_scope(reason): + pia = F("333.30") + _assert_refusal( + _rib_record( + pia, + _ordinary(pia) + F(1, 10), + conditions={RC.ADMINISTRATIVE_FINALITY}, + reason=reason, + cohort=1920, + ), + UR.ADMINISTRATIVE_FINALITY, + ) + + +@pytest.mark.parametrize("reason", PRE_1978_REASONS) +@pytest.mark.parametrize("birth", [None, 1927]) +def test_history_leaves_a_dib_cap_alone(reason, birth): + _assert_invalid( + _dib_record( + F(1000), F("1000.10"), birth=birth, year=1985, reason=reason + ) + ) + + +@given( + pia=st.integers(10, 30_000).map(lambda n: F(n, 10)), + months=st.integers(1, 36), + cohort=st.sampled_from((None, 1900, 1913, 1915)), + reason=st.sampled_from(PRE_1978_REASONS), + gap=st.integers(-40, 40).map(lambda n: F(n, 10)), +) +@example( + pia=F("333.30"), months=8, cohort=None, reason=OWN_HISTORY, gap=F(1, 10) +) +@settings(max_examples=150, deadline=None) +def test_history_keeps_every_rate_in_its_scope( + pia, months, cohort, reason, gap +): + gross = max(F(0), _ordinary(pia, months) + gap) + _assert_refusal( + _rib_record(pia, gross, reason=reason, cohort=cohort, months=months), + reason, + ) + + +@given( + pia=st.integers(10, 30_000).map(lambda n: F(n, 10)), + months=st.integers(0, 36), + cohort=st.integers(1916, 1927), + reason=st.sampled_from(PRE_1978_REASONS + (DUAL,)), + gap=st.integers(1, 40).map(lambda n: F(n, 10)), +) +@settings(max_examples=150, deadline=None) +def test_past_1915_every_reduction_only_hold_keeps_the_cap( + pia, months, cohort, reason, gap +): + _assert_invalid( + _rib_record( + pia, + _ordinary(pia, months) + gap, + reason=reason, + cohort=cohort, + months=months, + ) + ) + + +@pytest.mark.parametrize( + "pia,own,prior,carried,ordinary,original", + [ + ("480", "400", "300", "359.10", "373.30", "360"), + ("1.20", "1", "0.80", "0.80", "0.90", "0.90"), + ], +) +def test_a_mothers_carried_rib_passes_where_the_ordinary_one_fails( + pia, own, prior, carried, ordinary, original +): + pia, own, prior = F(pia), F(own), F(prior) + assert _carried_rib(own, prior) == F(carried) < F(original) + assert _ordinary(own, 12) == F(ordinary) >= F(original) + assert g.floor_dime(pia * F(3, 4)) == F(original) + case = _mother_record(pia=pia, own=own, gross=F(original) - F(carried)) + _assert_refusal(case, DUAL) + _assert_preflight_neutral(case) + + +def test_a_pre_fra_mother_keeps_the_historical_year_row(): + case = _mother_record( + cohort=1919, + year=1983, + eligibility=1983, + maximum=g.retirement_survivor_family_maximum( + F(480), 1983, ssa_params() + ), + ) + _assert_refusal(case, DUAL) + _assert_preflight_neutral(case) + + +@pytest.mark.parametrize( + "reason,cohort,kept", + [ + (DUAL, None, DUAL), + (DUAL, 1919, DUAL), + (DUAL, 1927, DUAL), + (DUAL, 1928, None), + (REDUCED_HISTORY, None, REDUCED_HISTORY), + (REDUCED_HISTORY, 1919, REDUCED_HISTORY), + (REDUCED_HISTORY, 1927, REDUCED_HISTORY), + (REDUCED_HISTORY, 1928, None), + (OWN_HISTORY, None, OWN_HISTORY), + (OWN_HISTORY, 1915, OWN_HISTORY), + (OWN_HISTORY, 1916, None), + (OWN_HISTORY, 1927, None), + ], +) +def test_a_mothers_own_rib_opens_only_in_each_holds_scope( + reason, cohort, kept +): + case = _mother_record(reason, cohort=cohort) + if kept is None: + _assert_invalid(case, "auxiliary entitlement facts differ") + else: + _assert_refusal(case, kept) + + +@pytest.mark.parametrize("reason", (DUAL, REDUCED_HISTORY, OWN_HISTORY)) +def test_a_zero_pia_fails_every_rib_on_every_filling(reason): + _assert_invalid( + _mother_record(reason, cohort=None, pia=F(0), gross=F(0)), + "auxiliary entitlement facts differ", + ) + + +@pytest.mark.parametrize("role", AMOUNT_TEST_ROLES) +@pytest.mark.parametrize("reason", CARRYOVER_REASONS) +@pytest.mark.parametrize("cohort,settled", [(1920, False), (1928, True)]) +def test_every_actual_rib_test_shares_the_carryover( + role, reason, cohort, settled +): + assert _f6_settled(role, reason, cohort, months=0) is settled + + +@pytest.mark.parametrize( + "role", (g.Role.CHILD, g.Role.SPOUSE, g.Role.DIVORCED_SPOUSE) +) +@pytest.mark.parametrize("reason", CARRYOVER_REASONS) +def test_a_role_with_no_rib_amount_test_stays_settled(role, reason): + assert _f6_settled(role, reason, 1920, months=0) is True + + +@pytest.mark.parametrize("role", (g.Role.MOTHER_FATHER, g.Role.PARENT)) +@pytest.mark.parametrize("reason", CARRYOVER_REASONS) +def test_a_disability_own_benefit_faces_no_rib_amount_test(role, reason): + assert ( + _f6_settled( + role, reason, 1920, months=0, kind=g.OwnBenefitKind.DISABILITY + ) + is True + ) + + +def test_a_reduced_dib_opens_no_money_history(): + assert ( + _f6_settled( + g.Role.MOTHER_FATHER, + REDUCED_HISTORY, + 1913, + kind=g.OwnBenefitKind.DISABILITY, + ) + is True + ) + + +@pytest.mark.parametrize("reason", PRE_1978_REASONS) +def test_a_zero_own_pia_leaves_no_money_history(reason): + assert ( + _f6_settled(g.Role.MOTHER_FATHER, reason, None, own_pia=F(0)) is True + ) + + +def test_a_deemed_pia_keeps_a_history_open_on_a_zero_record_pia(): + state = g.RecordState( + g.FamilyKind.SURVIVOR, + F(0), + F(0), + eligibility_year=1990, + widow_drc_savings_clause=False, + deferred_refusal=_deferred(OWN_HISTORY), + ) + member = g.Beneficiary( + "w", + g.Role.DISABLED_WIDOW, + original_benefit_basis=F(100), + own_benefit=g.OwnBenefit( + g.OwnBenefitKind.OLD_AGE, F(400), reduction_months=12 + ), + ) + assert g._hold_unsettles_fact( + OWN_HISTORY, + "F6", + state, + member, + payment_month=g.YearMonth(2000, 1), + beneficiaries=(member,), + params=ssa_params(), + ) + + +@given( + role=st.sampled_from( + (g.Role.MOTHER_FATHER, g.Role.PARENT, g.Role.CHILD, g.Role.SPOUSE) + ), + reason=st.sampled_from(CARRYOVER_REASONS + (OWN_HISTORY,)), + cohort=st.one_of(st.none(), st.integers(1905, 1935)), + months=st.integers(0, 24), + pia=st.sampled_from((F(0), F("0.10"), F(480))), +) +@example( + role=g.Role.MOTHER_FATHER, + reason=OWN_HISTORY, + cohort=None, + months=1, + pia=F(480), +) +@settings(max_examples=250, deadline=None) +def test_f6_matches_a_table_written_from_the_sources( + role, reason, cohort, months, pia +): + money_history = ( + reason in PRE_1978_REASONS + and months > 0 + and (cohort is None or cohort < 1916) + ) + carryover = ( + reason in CARRYOVER_REASONS + and role in (g.Role.MOTHER_FATHER, g.Role.PARENT) + and (cohort is None or cohort < 1928) + ) + # A known cohort refuses its own history whatever the record declares. + implicit_history = months > 0 and cohort is not None and cohort < 1916 + expected_open = implicit_history or ( + pia > 0 and (money_history or carryover) + ) + settled = _f6_settled(role, reason, cohort, months=months, pia=pia) + assert settled is not expected_open + + +def test_a_cohort_too_young_for_any_reduced_benefit_has_one_dib_rate(): + case = _dib_record( + F(405), + F("404.90"), + birth=1975, + year=2024, + reason=DUAL, + maximum=F(405), + first=g.YearMonth(2024, 1), + ) + _assert_invalid(case) + + +@pytest.mark.parametrize("conditions,reason,named", PRIOR_REDUCED_HOLDS) +@pytest.mark.parametrize("birth", [1975, 1980, 2000]) +def test_before_age_50_a_dib_below_the_pia_raises( + conditions, reason, named, birth +): + pia = F(405) + _assert_invalid( + _dib_record( + pia, + pia - F(1, 10), + birth=birth, + conditions=conditions, + reason=reason, + ) + ) + _assert_invalid( + _dib_record( + pia, + pia + F(1, 10), + birth=birth, + conditions=conditions, + reason=reason, + ) + ) + _assert_refusal( + _dib_record( + pia, pia, birth=birth, conditions=conditions, reason=reason + ), + named, + ) + + +@pytest.mark.parametrize("conditions,reason,named", PRIOR_REDUCED_HOLDS) +@pytest.mark.parametrize( + "birth,year,month,keeps", + [ + (1974, 2023, 12, False), + (1974, 2024, 1, True), + (1973, 2023, 12, True), + (1960, 2024, 1, True), + (None, 2024, 1, True), + ], +) +def test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50( + conditions, reason, named, birth, year, month, keeps +): + pia = F(405) + case = _dib_record( + pia, + pia - F(1, 10), + birth=birth, + year=year, + month=month, + conditions=conditions, + reason=reason, + ) + if keeps: + _assert_refusal(case, named) + _assert_preflight_neutral(case) + else: + _assert_invalid(case) + + +@pytest.mark.parametrize("conditions,reason,named", AGE_FREE_HOLDS) +@pytest.mark.parametrize("birth", [1975, 2000]) +def test_a_hold_no_age_limits_keeps_a_young_row( + conditions, reason, named, birth +): + pia = F(405) + case = _dib_record( + pia, + pia - F(1, 10), + birth=birth, + conditions=conditions, + reason=reason, + ) + _assert_refusal(case, named) + _assert_preflight_neutral(case) + + +@pytest.mark.parametrize( + "conditions,named", + [ + ({RC.WORKERS_COMPENSATION_OFFSET}, UR.WORKERS_COMPENSATION_OFFSET), + ({RC.ADMINISTRATIVE_FINALITY}, UR.ADMINISTRATIVE_FINALITY), + ], +) +def test_an_independent_hold_survives_a_young_dual_declaration( + conditions, named +): + pia = F(405) + case = _dib_record(pia, pia - F(1, 10), conditions=conditions, reason=DUAL) + _assert_refusal(case, named) + + +def test_the_floor_needs_a_cohort_and_a_month(): + assert not _f2_settled(None, 2024, 1, reason=DUAL) + state = g.RecordState( + g.FamilyKind.DISABILITY, + F(400), + F(600), + worker_birth_year=1990, + eligibility_year=2020, + first_dib_entitlement=g.YearMonth(2020, 1), + deferred_refusal=_deferred(DUAL), + ) + assert not g._fact_is_settled("F2", state, params=ssa_params()) + + +@pytest.mark.parametrize("reason", PRE_1978_REASONS) +@pytest.mark.parametrize( + "birth,year,month,settled", + [ + (1927, 1976, 12, True), + (1927, 1977, 1, False), + (1926, 1976, 12, False), + (1928, 1990, 1, True), + ], +) +def test_a_pre_1978_hold_needs_both_the_cohort_and_the_age( + reason, birth, year, month, settled +): + assert _f2_settled(birth, year, month, reason=reason) is settled + + +@given( + birth=st.integers(1900, 2005), + year=st.integers(1984, 2030), + month=st.integers(1, 12), + hold=st.sampled_from( + ( + RC.DIB_AFTER_REDUCED_RIB, + UR.DIB_AFTER_REDUCED_RIB, + DUAL, + OWN_HISTORY, + REDUCED_HISTORY, + RC.WORKERS_COMPENSATION_OFFSET, + UR.WORKERS_COMPENSATION_OFFSET, + RC.ADMINISTRATIVE_FINALITY, + ) + ), +) +@example(birth=1974, year=2023, month=12, hold=DUAL) +@example(birth=1974, year=2024, month=1, hold=DUAL) +@settings(max_examples=250, deadline=None) +def test_f2_matches_a_table_written_from_the_sources(birth, year, month, hold): + if hold in ( + RC.WORKERS_COMPENSATION_OFFSET, + UR.WORKERS_COMPENSATION_OFFSET, + RC.ADMINISTRATIVE_FINALITY, + ): + expected_open = True + else: + expected_open = year >= birth + 50 + if hold in PRE_1978_REASONS: + expected_open = expected_open and birth < 1928 + conditions, reason = ({hold}, None) if isinstance(hold, RC) else ((), hold) + settled = _f2_settled( + birth, year, month, conditions=conditions, reason=reason + ) + assert settled is not expected_open + + +@given( + pia=st.integers(2, 30_000).map(lambda n: F(n, 10)), + gap=st.integers(0, 40).map(lambda n: F(n, 10)), + birth=st.integers(1975, 2003), + hold=st.sampled_from(PRIOR_REDUCED_HOLDS), +) +@settings(max_examples=120, deadline=None) +def test_a_young_dib_rate_equals_its_pia_or_raises(pia, gap, birth, hold): + conditions, reason, named = hold + case = _dib_record( + pia, + max(F(0), pia - gap), + birth=birth, + conditions=conditions, + reason=reason, + ) + if gap == 0: + _assert_refusal(case, named) + else: + _assert_invalid(case) diff --git a/tests/tier_counts.json b/tests/tier_counts.json index c14a7e38b..aa07d4b42 100644 --- a/tests/tier_counts.json +++ b/tests/tier_counts.json @@ -1,7 +1,7 @@ { "schema_version": 1, "counts": { - "unit": 21028, + "unit": 21186, "artifact": 4271, "integration_psid": 1471, "reproduction_legacy": 520, From aa86a4da87dde6664d5475a197632ca685579e1e Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 1 Nov 2026 11:52:38 -0500 Subject: [PATCH 13/17] Track B R2: rule out rates no filling can reach Sol's seventh review of fbe491d4 found three mediums and a nit, and all three mediums reproduced. Each kept a counted row for a declaration no filling can make lawful. - History leaves a RIB at or below its PIA. RS 00615.005C.2 subtracts a money reduction from the new PIA, so with no delayed credits a rate above the PIA has no lawful filling. Round 7 dropped that cap with the exact rate. The check also reaches a known cohort before 1916 with no declaration. Finality, positive delayed credits and months before 1983 keep their rows. - A zero threshold fails every RIB, known cohort or not. The preflight tests a RIB it can't compute at zero, the lowest RIB there is, so a test that fails there fails on every filling. A positive threshold passes at zero and keeps its row, and a deemed PIA counts. - A reduced DIB needs a month before it. RS 00615.010 counts only months before the first DIB month, and RS 00615.005 dates each route: RIB from 11/56 at 62, WIB from 9/65 at 60, disabled WIB from 2/68 at 50, and the reduced DIB itself from 9/65. So January of cohort + 50 has one lawful DIB rate, and so do February 1958, 1966 and 1968 for the cohorts Sol named. The floor reads the payment month, because first_dib_entitlement holds the first-ever DIB month and RS 00615.010 counts from the most recent period. Every hold shares the earliest route, and a modern cohort keeps the WIB route because the schema omits the onset that ends it. No money moves. The conformance report regenerates byte-identically, and the cross-head comparison keeps 240 R2 and 240 R3 results. Invariants: with no delayed credits, no history admits a RIB above its PIA. A zero threshold fails every RIB on every filling, and only a zero threshold does. A route opens the month after its own first month, and before any route opens a DIB equals its PIA or raises. Co-Authored-By: Claude Opus 5.5 --- docs/design/track_b_g2_r2b_mutations.json | 2316 ++++++++++++++++- docs/design/track_b_g2_r2b_verification.json | 84 +- docs/design/track_b_r2_ret_ledger.md | 126 +- .../track_b/gross_benefits.py | 75 +- src/populace_dynamics/track_b/ret_ledger.py | 67 +- tests/README-tiers.md | 4 +- tests/test_track_b_ret_ledger_fix_round_6.py | 4 +- tests/test_track_b_ret_ledger_fix_round_7.py | 55 +- tests/test_track_b_ret_ledger_fix_round_8.py | 505 ++++ tests/tier_counts.json | 2 +- 10 files changed, 3163 insertions(+), 75 deletions(-) create mode 100644 tests/test_track_b_ret_ledger_fix_round_8.py diff --git a/docs/design/track_b_g2_r2b_mutations.json b/docs/design/track_b_g2_r2b_mutations.json index 1869c8c44..b017499f7 100644 --- a/docs/design/track_b_g2_r2b_mutations.json +++ b/docs/design/track_b_g2_r2b_mutations.json @@ -2,12 +2,12 @@ "schema_version": 1, "verification_class": "statutory_conformance", "admitted_scope": "Mutation sensitivity of statutory rules on invented and captured worked cases only; no population, behavioral or forecast claim.", - "confirmed_mutation_count": 160, + "confirmed_mutation_count": 199, "counts_by_layer": { "g_deductions": 18, - "g_preflight": 94, + "g_preflight": 126, "g_savings": 12, - "r2": 35, + "r2": 42, "shared_provenance": 1 }, "environment_contract": { @@ -9038,6 +9038,2310 @@ } }, "layer": "g_preflight" + }, + { + "id": "round8-cap_also_at_the_pia", + "round": 8, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": [ + { + "before": " if (\n declared > state.pia\n and state.worker.delayed_credit_months == 0\n and settled(\"F3\", pia_cap=True)\n ):\n", + "after": " if (\n declared >= state.pia\n and state.worker.delayed_credit_months == 0\n and settled(\"F3\", pia_cap=True)\n ):\n" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_rate_at_the_pia_keeps_its_history_row[None-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_rate_at_the_pia_keeps_its_history_row[None-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_rate_at_the_pia_keeps_its_history_row[1915-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_rate_at_the_pia_keeps_its_history_row[1915-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_known_cohort_keeps_the_pia_cap_with_no_declaration[1900]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_known_cohort_keeps_the_pia_cap_with_no_declaration[1915]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_history_keeps_every_rate_in_its_scope" + ], + "failed_test_count": 7, + "log": { + "path": "scratch/review/round8-mutations/cap_also_at_the_pia.log", + "sha256": "11f7396ffa5571c0bf036bfef2db671863a09f54df47dbe17231f7de400fc4d6", + "failure_summary": "7 failed, 312 passed in 3.67s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "r2" + }, + { + "id": "round8-cap_ignores_credits", + "round": 8, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": [ + { + "before": " if (\n declared > state.pia\n and state.worker.delayed_credit_months == 0\n and settled(\"F3\", pia_cap=True)\n ):\n", + "after": " if (\n declared > state.pia\n and settled(\"F3\", pia_cap=True)\n ):\n" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_delayed_credits_can_lift_a_history_rib_past_its_pia[UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_delayed_credits_can_lift_a_history_rib_past_its_pia[UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]" + ], + "failed_test_count": 2, + "log": { + "path": "scratch/review/round8-mutations/cap_ignores_credits.log", + "sha256": "5965cb9c0c856c459dc474d61057c4d50c323589314918807822439a67b91369", + "failure_summary": "2 failed, 317 passed in 4.02s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "r2" + }, + { + "id": "round8-cap_ignores_every_hold", + "round": 8, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": [ + { + "before": " if (\n declared > state.pia\n and state.worker.delayed_credit_months == 0\n and settled(\"F3\", pia_cap=True)\n ):\n", + "after": " if (\n declared > state.pia\n and state.worker.delayed_credit_months == 0\n ):\n" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_finality_can_lift_a_rib_past_its_pia[None-None]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_finality_can_lift_a_rib_past_its_pia[None-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_finality_can_lift_a_rib_past_its_pia[None-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_finality_can_lift_a_rib_past_its_pia[1915-None]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_finality_can_lift_a_rib_past_its_pia[1915-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_finality_can_lift_a_rib_past_its_pia[1915-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_deferred_finality_can_lift_a_rib_past_its_pia[None]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_deferred_finality_can_lift_a_rib_past_its_pia[1915]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_month_before_1983_leaves_the_rate_unsettled_past_the_pia" + ], + "failed_test_count": 9, + "log": { + "path": "scratch/review/round8-mutations/cap_ignores_every_hold.log", + "sha256": "8e142c8e0d53004d99f67c261ecc7ac5e858530db0b62dd7f93d3c2650ba12dd", + "failure_summary": "9 failed, 310 passed in 4.04s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "r2" + }, + { + "id": "round8-cap_removed", + "round": 8, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": [ + { + "before": " if (\n declared > state.pia\n and state.worker.delayed_credit_months == 0\n and settled(\"F3\", pia_cap=True)\n ):\n", + "after": " if (\n False\n and state.worker.delayed_credit_months == 0\n and settled(\"F3\", pia_cap=True)\n ):\n" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-None-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-None-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-1900-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-1900-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-1915-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-1915-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[1000-1000.10-2-None-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[1000-1000.10-2-None-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[1000-1000.10-2-1900-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[1000-1000.10-2-1900-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]" + ], + "failed_test_count": 25, + "log": { + "path": "scratch/review/round8-mutations/cap_removed.log", + "sha256": "bf78e6693f5a7345b593e39b15bc726cbc19932d34e88e2dda33477aacc88ab9", + "failure_summary": "25 failed, 294 passed in 3.82s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "r2" + }, + { + "id": "round8-cap_uses_the_ordinary_upper_bound", + "round": 8, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": [ + { + "before": " if (\n declared > state.pia\n and state.worker.delayed_credit_months == 0\n and settled(\"F3\", pia_cap=True)\n ):\n", + "after": " if (\n declared > state.pia\n and state.worker.delayed_credit_months == 0\n and settled(\"F3\", upper_bound=True)\n ):\n" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-None-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-None-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-1900-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-1900-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-1915-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-1915-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[1000-1000.10-2-None-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[1000-1000.10-2-None-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[1000-1000.10-2-1900-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[1000-1000.10-2-1900-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]" + ], + "failed_test_count": 20, + "log": { + "path": "scratch/review/round8-mutations/cap_uses_the_ordinary_upper_bound.log", + "sha256": "0d9b27543bec0b71b42ded8113b2699551add086f1c92f1830f3d41593e8a9bd", + "failure_summary": "20 failed, 299 passed in 3.77s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "r2" + }, + { + "id": "round8-disabled_route_age_49", + "round": 8, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " ((1968, 2), 50),\n", + "after": " ((1968, 2), 49),\n" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1974-2024-1-False]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_the_floor_matches_month_counts_written_from_the_sources", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_modern_january_of_cohort_plus_50_has_one_dib_rate[pia0-gross0-conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_modern_january_of_cohort_plus_50_has_one_dib_rate[pia0-gross0-conditions1-UnsupportedReason.DIB_AFTER_REDUCED_RIB-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_modern_january_of_cohort_plus_50_has_one_dib_rate[pia0-gross0-conditions2-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_modern_january_of_cohort_plus_50_has_one_dib_rate[pia1-gross1-conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_modern_january_of_cohort_plus_50_has_one_dib_rate[pia1-gross1-conditions1-UnsupportedReason.DIB_AFTER_REDUCED_RIB-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_modern_january_of_cohort_plus_50_has_one_dib_rate[pia1-gross1-conditions2-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_the_month_after_a_cohort_turns_50[1974-2023-12-False-conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_the_month_after_a_cohort_turns_50[1974-2023-12-False-conditions1-UnsupportedReason.DIB_AFTER_REDUCED_RIB-UnsupportedReason.DIB_AFTER_REDUCED_RIB]" + ], + "failed_test_count": 24, + "log": { + "path": "scratch/review/round8-mutations/disabled_route_age_49.log", + "sha256": "d6f782565d16f8588fa3c9b186222741619f385b566a1bd62e1eb2b45f256f9f", + "failure_summary": "24 failed, 295 passed in 3.88s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "g_preflight" + }, + { + "id": "round8-disabled_route_age_51", + "round": 8, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " ((1968, 2), 50),\n", + "after": " ((1968, 2), 51),\n" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1918-1968-3-True]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1974-2024-2-True]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_modern_january_of_cohort_plus_50_has_one_dib_rate[pia0-gross0-conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_modern_january_of_cohort_plus_50_has_one_dib_rate[pia0-gross0-conditions1-UnsupportedReason.DIB_AFTER_REDUCED_RIB-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_modern_january_of_cohort_plus_50_has_one_dib_rate[pia0-gross0-conditions2-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_modern_january_of_cohort_plus_50_has_one_dib_rate[pia1-gross1-conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_modern_january_of_cohort_plus_50_has_one_dib_rate[pia1-gross1-conditions1-UnsupportedReason.DIB_AFTER_REDUCED_RIB-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_modern_january_of_cohort_plus_50_has_one_dib_rate[pia1-gross1-conditions2-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_historical_route_keeps_its_row_once_it_opens[conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_historical_route_keeps_its_row_once_it_opens[conditions1-UnsupportedReason.DIB_AFTER_REDUCED_RIB-UnsupportedReason.DIB_AFTER_REDUCED_RIB]" + ], + "failed_test_count": 25, + "log": { + "path": "scratch/review/round8-mutations/disabled_route_age_51.log", + "sha256": "91b1d24b285752de4f0707a7e4478b6e2361b10adc73e5963373384cfe48f5b3", + "failure_summary": "25 failed, 294 passed in 3.94s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "g_preflight" + }, + { + "id": "round8-disabled_route_month_early", + "round": 8, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " ((1968, 2), 50),\n", + "after": " ((1968, 1), 50),\n" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1918-1968-2-False]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1910-1968-2-False]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_before_a_route_exists_a_dib_rate_equals_its_pia_or_raises[pia0-gross0-1918-1968-conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_before_a_route_exists_a_dib_rate_equals_its_pia_or_raises[pia0-gross0-1918-1968-conditions1-UnsupportedReason.DIB_AFTER_REDUCED_RIB-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_before_a_route_exists_a_dib_rate_equals_its_pia_or_raises[pia0-gross0-1918-1968-conditions2-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_before_a_route_exists_a_dib_rate_equals_its_pia_or_raises[pia1-gross1-1918-1968-conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_before_a_route_exists_a_dib_rate_equals_its_pia_or_raises[pia1-gross1-1918-1968-conditions1-UnsupportedReason.DIB_AFTER_REDUCED_RIB-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_before_a_route_exists_a_dib_rate_equals_its_pia_or_raises[pia1-gross1-1918-1968-conditions2-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_pre_1978_hold_shares_the_first_route[UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_pre_1978_hold_shares_the_first_route[UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]" + ], + "failed_test_count": 10, + "log": { + "path": "scratch/review/round8-mutations/disabled_route_month_early.log", + "sha256": "f280de4203a67a6ab38ea9850cbe30ba48e8eb7e601965ea9b56ff22abf2b25a", + "failure_summary": "10 failed, 309 passed in 4.41s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "g_preflight" + }, + { + "id": "round8-disabled_route_month_late", + "round": 8, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " ((1968, 2), 50),\n", + "after": " ((1968, 3), 50),\n" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1918-1968-3-True]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1910-1968-3-True]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_historical_route_keeps_its_row_once_it_opens[conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_historical_route_keeps_its_row_once_it_opens[conditions1-UnsupportedReason.DIB_AFTER_REDUCED_RIB-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_historical_route_keeps_its_row_once_it_opens[conditions2-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]" + ], + "failed_test_count": 5, + "log": { + "path": "scratch/review/round8-mutations/disabled_route_month_late.log", + "sha256": "19fc0e3370fc3fcfbb8c7db6f2cb6eb8a0ffe1982ae5836f18da6e7ab9bf757e", + "failure_summary": "5 failed, 314 passed in 4.14s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "g_preflight" + }, + { + "id": "round8-disabled_route_removed", + "round": 8, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " ((1968, 2), 50),\n", + "after": "" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1918-1968-3-True]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1910-1968-3-True]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1974-2024-2-True]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_the_floor_matches_month_counts_written_from_the_sources", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_modern_january_of_cohort_plus_50_has_one_dib_rate[pia0-gross0-conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_modern_january_of_cohort_plus_50_has_one_dib_rate[pia0-gross0-conditions1-UnsupportedReason.DIB_AFTER_REDUCED_RIB-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_modern_january_of_cohort_plus_50_has_one_dib_rate[pia0-gross0-conditions2-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_modern_january_of_cohort_plus_50_has_one_dib_rate[pia1-gross1-conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_modern_january_of_cohort_plus_50_has_one_dib_rate[pia1-gross1-conditions1-UnsupportedReason.DIB_AFTER_REDUCED_RIB-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_modern_january_of_cohort_plus_50_has_one_dib_rate[pia1-gross1-conditions2-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]" + ], + "failed_test_count": 27, + "log": { + "path": "scratch/review/round8-mutations/disabled_route_removed.log", + "sha256": "7ce634149205612a1b652de0df7802a94e1df9a061224d6ee2ef51367d22a20e", + "failure_summary": "27 failed, 292 passed in 4.09s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "g_preflight" + }, + { + "id": "round8-effective_date_removed", + "round": 8, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " if month < _FIRST_REDUCED_DIB_MONTH:\n return False\n", + "after": "" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1900-1965-8-False]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[None-1965-8-False]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_the_floor_matches_month_counts_written_from_the_sources" + ], + "failed_test_count": 3, + "log": { + "path": "scratch/review/round8-mutations/effective_date_removed.log", + "sha256": "18a3c2efe129b13d6207fc1810afaf21df7d46441edb1f1b27b7a2cb4e94e306", + "failure_summary": "3 failed, 316 passed in 4.17s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "g_preflight" + }, + { + "id": "round8-every_route_must_precede", + "round": 8, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " return birth_year is None or any(\n max(first_month, (birth_year + age, 1)) < month\n for first_month, age in _PRIOR_REDUCED_BENEFIT_ROUTES\n )\n", + "after": " return birth_year is None or all(\n max(first_month, (birth_year + age, 1)) < month\n for first_month, age in _PRIOR_REDUCED_BENEFIT_ROUTES\n )\n" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1903-1965-9-True]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1904-1965-10-True]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1905-1965-10-True]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1907-1967-2-True]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1908-1968-2-True]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1918-1968-3-True]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1910-1968-3-True]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1974-2024-2-True]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_the_floor_matches_month_counts_written_from_the_sources", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_modern_january_of_cohort_plus_50_has_one_dib_rate[pia0-gross0-conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]" + ], + "failed_test_count": 32, + "log": { + "path": "scratch/review/round8-mutations/every_route_must_precede.log", + "sha256": "f6175f94eb0d4528585623b6fab2184bc4f351fa2a285f886295c418e93e0d31", + "failure_summary": "32 failed, 287 passed in 3.76s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "g_preflight" + }, + { + "id": "round8-first_pass_drops_pia_cap", + "round": 8, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " if any(\n _hold_unsettles_fact(\n hold,\n fact,\n state,\n beneficiary,\n payment_month=payment_month,\n beneficiaries=beneficiaries,\n params=params,\n upper_bound=upper_bound,\n pia_cap=pia_cap,\n )\n", + "after": " if any(\n _hold_unsettles_fact(\n hold,\n fact,\n state,\n beneficiary,\n payment_month=payment_month,\n beneficiaries=beneficiaries,\n params=params,\n upper_bound=upper_bound,\n )\n" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-None-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-None-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-1900-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-1900-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-1915-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-1915-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[1000-1000.10-2-None-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[1000-1000.10-2-None-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[1000-1000.10-2-1900-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[1000-1000.10-2-1900-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]" + ], + "failed_test_count": 23, + "log": { + "path": "scratch/review/round8-mutations/first_pass_drops_pia_cap.log", + "sha256": "6e0d6d9ff28bcfbaea3fb8a937c5b6c2aebcebe7f194e48d1f3c8199f0e3ef71", + "failure_summary": "23 failed, 296 passed in 3.46s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "g_preflight" + }, + { + "id": "round8-last_pass_drops_pia_cap", + "round": 8, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " return not any(\n _hold_unsettles_fact(\n hold,\n fact,\n state,\n beneficiary,\n payment_month=payment_month,\n beneficiaries=beneficiaries,\n params=params,\n upper_bound=upper_bound,\n pia_cap=pia_cap,\n )\n", + "after": " return not any(\n _hold_unsettles_fact(\n hold,\n fact,\n state,\n beneficiary,\n payment_month=payment_month,\n beneficiaries=beneficiaries,\n params=params,\n upper_bound=upper_bound,\n )\n" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-None-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-None-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-1900-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-1900-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-1915-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-1915-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[1000-1000.10-2-None-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[1000-1000.10-2-None-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[1000-1000.10-2-1900-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[1000-1000.10-2-1900-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]" + ], + "failed_test_count": 23, + "log": { + "path": "scratch/review/round8-mutations/last_pass_drops_pia_cap.log", + "sha256": "f8939743c1e7645e93df891d3df5cd3f008115e78a05c998818da495b4a54345", + "failure_summary": "23 failed, 296 passed in 3.36s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "g_preflight" + }, + { + "id": "round8-pia_cap_drops_delayed_hold", + "round": 8, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "_PIA_CAP_KEEPING_HOLDS = _NH_REDUCTION_ONLY_HOLDS | {\n UnsupportedReason.DELAYED_CREDITS_BEFORE_1917,\n}\n", + "after": "_PIA_CAP_KEEPING_HOLDS = _NH_REDUCTION_ONLY_HOLDS\n" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_no_other_hold_lifts_a_known_cohort_past_the_pia[conditions3-UnsupportedReason.DELAYED_CREDITS_BEFORE_1917]" + ], + "failed_test_count": 1, + "log": { + "path": "scratch/review/round8-mutations/pia_cap_drops_delayed_hold.log", + "sha256": "07378f187f961a191212ecb8a3567fdf581d499599a45174f9df912244bfeb93", + "failure_summary": "1 failed, 318 passed in 4.25s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "g_preflight" + }, + { + "id": "round8-pia_cap_for_every_hold", + "round": 8, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " if pia_cap and hold in _PIA_CAP_KEEPING_HOLDS:\n return False\n", + "after": " if pia_cap:\n return False\n" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_finality_can_lift_a_rib_past_its_pia[None-None]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_finality_can_lift_a_rib_past_its_pia[None-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_finality_can_lift_a_rib_past_its_pia[None-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_finality_can_lift_a_rib_past_its_pia[1915-None]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_finality_can_lift_a_rib_past_its_pia[1915-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_finality_can_lift_a_rib_past_its_pia[1915-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_deferred_finality_can_lift_a_rib_past_its_pia[None]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_deferred_finality_can_lift_a_rib_past_its_pia[1915]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_month_before_1983_leaves_the_rate_unsettled_past_the_pia" + ], + "failed_test_count": 9, + "log": { + "path": "scratch/review/round8-mutations/pia_cap_for_every_hold.log", + "sha256": "5fdc5422920f0954d2c6b89414a5dd9b31b6279156f8c527ea771e77d587fe30", + "failure_summary": "9 failed, 310 passed in 4.63s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "g_preflight" + }, + { + "id": "round8-pia_cap_only_delayed_hold", + "round": 8, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "_PIA_CAP_KEEPING_HOLDS = _NH_REDUCTION_ONLY_HOLDS | {\n UnsupportedReason.DELAYED_CREDITS_BEFORE_1917,\n}\n", + "after": "_PIA_CAP_KEEPING_HOLDS = frozenset(\n {UnsupportedReason.DELAYED_CREDITS_BEFORE_1917}\n)\n" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-None-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-None-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-1900-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-1900-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-1915-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-1915-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[1000-1000.10-2-None-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[1000-1000.10-2-None-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[1000-1000.10-2-1900-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[1000-1000.10-2-1900-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]" + ], + "failed_test_count": 22, + "log": { + "path": "scratch/review/round8-mutations/pia_cap_only_delayed_hold.log", + "sha256": "14198deced1720e352ea02eb228476be8634fd5330270582c3134e4e7a5da565", + "failure_summary": "22 failed, 297 passed in 3.64s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "g_preflight" + }, + { + "id": "round8-pia_cap_removed", + "round": 8, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " if pia_cap and hold in _PIA_CAP_KEEPING_HOLDS:\n return False\n", + "after": "" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-None-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-None-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-1900-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-1900-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-1915-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[333.30-333.40-8-1915-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[1000-1000.10-2-None-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[1000-1000.10-2-None-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[1000-1000.10-2-1900-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_history_leaves_a_rib_at_or_below_its_pia[1000-1000.10-2-1900-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]" + ], + "failed_test_count": 23, + "log": { + "path": "scratch/review/round8-mutations/pia_cap_removed.log", + "sha256": "08ed53da63c47b34cb4682e328f5f2fe078995c7845ea9ab4d6524ecbb902f18", + "failure_summary": "23 failed, 296 passed in 3.85s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "g_preflight" + }, + { + "id": "round8-reduced_dib_month_early", + "round": 8, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "_FIRST_REDUCED_DIB_MONTH = (1965, 9)", + "after": "_FIRST_REDUCED_DIB_MONTH = (1965, 8)" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1900-1965-8-False]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[None-1965-8-False]" + ], + "failed_test_count": 2, + "log": { + "path": "scratch/review/round8-mutations/reduced_dib_month_early.log", + "sha256": "554edc83ef2d61d50b9b0a5ef51430b8018b52d159eb22024c54fb2786db238e", + "failure_summary": "2 failed, 317 passed in 4.31s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "g_preflight" + }, + { + "id": "round8-reduced_dib_month_late", + "round": 8, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": "_FIRST_REDUCED_DIB_MONTH = (1965, 9)", + "after": "_FIRST_REDUCED_DIB_MONTH = (1965, 10)" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1903-1965-9-True]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[None-1965-9-True]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_the_floor_matches_month_counts_written_from_the_sources" + ], + "failed_test_count": 3, + "log": { + "path": "scratch/review/round8-mutations/reduced_dib_month_late.log", + "sha256": "50448b6502515a1326adbf589e28516d67d63faae257c24244da7eb8b0e47f1e", + "failure_summary": "3 failed, 316 passed in 4.25s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "g_preflight" + }, + { + "id": "round8-rib_route_age_61", + "round": 8, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " ((1956, 11), 62),\n", + "after": " ((1956, 11), 61),\n" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1904-1965-9-False]" + ], + "failed_test_count": 1, + "log": { + "path": "scratch/review/round8-mutations/rib_route_age_61.log", + "sha256": "eb25412ce103beb7e2a162d3f0ce35da438ffc2e7651e7a73e13c3b8393f7372", + "failure_summary": "1 failed, 318 passed in 4.14s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "g_preflight" + }, + { + "id": "round8-rib_route_age_63", + "round": 8, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " ((1956, 11), 62),\n", + "after": " ((1956, 11), 63),\n" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1903-1965-9-True]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_the_floor_matches_month_counts_written_from_the_sources" + ], + "failed_test_count": 2, + "log": { + "path": "scratch/review/round8-mutations/rib_route_age_63.log", + "sha256": "424d0b363515c807ef4b99df2d0ef428255e4b135dee81f127a9fabf9976af21", + "failure_summary": "2 failed, 317 passed in 3.86s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "g_preflight" + }, + { + "id": "round8-rib_route_removed", + "round": 8, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " ((1956, 11), 62),\n", + "after": "" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1903-1965-9-True]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_the_floor_matches_month_counts_written_from_the_sources" + ], + "failed_test_count": 2, + "log": { + "path": "scratch/review/round8-mutations/rib_route_removed.log", + "sha256": "6eedd6bcd66d70387622668f12bb5eed3a49f2413defb1520d8c5d007ff5b131", + "failure_summary": "2 failed, 317 passed in 3.71s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "g_preflight" + }, + { + "id": "round8-rib_route_starts_with_the_dib", + "round": 8, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " ((1956, 11), 62),\n", + "after": " ((1965, 9), 62),\n" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1903-1965-9-True]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_the_floor_matches_month_counts_written_from_the_sources" + ], + "failed_test_count": 2, + "log": { + "path": "scratch/review/round8-mutations/rib_route_starts_with_the_dib.log", + "sha256": "bd3bc0fbbf62fc1b47be6a002954897e1a4096442a3e7c8b015f16ae8dcc3645", + "failure_summary": "2 failed, 317 passed in 3.76s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "g_preflight" + }, + { + "id": "round8-route_ignores_age", + "round": 8, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " return birth_year is None or any(\n max(first_month, (birth_year + age, 1)) < month\n for first_month, age in _PRIOR_REDUCED_BENEFIT_ROUTES\n )\n", + "after": " return birth_year is None or any(\n first_month < month\n for first_month, age in _PRIOR_REDUCED_BENEFIT_ROUTES\n )\n" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1904-1965-9-False]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1907-1967-1-False]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1908-1968-1-False]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1916-1966-2-False]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1918-1968-2-False]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1910-1968-2-False]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1974-2024-1-False]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_the_floor_matches_month_counts_written_from_the_sources", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_modern_january_of_cohort_plus_50_has_one_dib_rate[pia0-gross0-conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_modern_january_of_cohort_plus_50_has_one_dib_rate[pia0-gross0-conditions1-UnsupportedReason.DIB_AFTER_REDUCED_RIB-UnsupportedReason.DIB_AFTER_REDUCED_RIB]" + ], + "failed_test_count": 55, + "log": { + "path": "scratch/review/round8-mutations/route_ignores_age.log", + "sha256": "5853e87ed51a0ad82d63a79cca7670bdd96a5000b70bb8b074b4e3527fa34588", + "failure_summary": "55 failed, 264 passed in 6.87s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "g_preflight" + }, + { + "id": "round8-route_ignores_its_first_month", + "round": 8, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " return birth_year is None or any(\n max(first_month, (birth_year + age, 1)) < month\n for first_month, age in _PRIOR_REDUCED_BENEFIT_ROUTES\n )\n", + "after": " return birth_year is None or any(\n (birth_year + age, 1) < month\n for first_month, age in _PRIOR_REDUCED_BENEFIT_ROUTES\n )\n" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1904-1965-9-False]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1907-1967-1-False]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1908-1968-1-False]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1916-1966-2-False]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1918-1968-2-False]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1910-1968-2-False]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_before_a_route_exists_a_dib_rate_equals_its_pia_or_raises[pia0-gross0-1916-1966-conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_before_a_route_exists_a_dib_rate_equals_its_pia_or_raises[pia0-gross0-1916-1966-conditions1-UnsupportedReason.DIB_AFTER_REDUCED_RIB-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_before_a_route_exists_a_dib_rate_equals_its_pia_or_raises[pia0-gross0-1916-1966-conditions2-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_before_a_route_exists_a_dib_rate_equals_its_pia_or_raises[pia0-gross0-1918-1968-conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]" + ], + "failed_test_count": 20, + "log": { + "path": "scratch/review/round8-mutations/route_ignores_its_first_month.log", + "sha256": "8766ecbb9bfb0394bc4f686b18807f7d289cab580dcd487e8a7abbd82f747c7d", + "failure_summary": "20 failed, 299 passed in 4.27s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "g_preflight" + }, + { + "id": "round8-route_month_may_equal_the_dib", + "round": 8, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " return birth_year is None or any(\n max(first_month, (birth_year + age, 1)) < month\n for first_month, age in _PRIOR_REDUCED_BENEFIT_ROUTES\n )\n", + "after": " return birth_year is None or any(\n max(first_month, (birth_year + age, 1)) <= month\n for first_month, age in _PRIOR_REDUCED_BENEFIT_ROUTES\n )\n" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1904-1965-9-False]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1907-1967-1-False]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1908-1968-1-False]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1918-1968-2-False]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1910-1968-2-False]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1974-2024-1-False]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_the_floor_matches_month_counts_written_from_the_sources", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_modern_january_of_cohort_plus_50_has_one_dib_rate[pia0-gross0-conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_modern_january_of_cohort_plus_50_has_one_dib_rate[pia0-gross0-conditions1-UnsupportedReason.DIB_AFTER_REDUCED_RIB-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_modern_january_of_cohort_plus_50_has_one_dib_rate[pia0-gross0-conditions2-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]" + ], + "failed_test_count": 32, + "log": { + "path": "scratch/review/round8-mutations/route_month_may_equal_the_dib.log", + "sha256": "f65a95d7baca530eed1c8fb0a33a67e5dc1cb36d4666d6a8731a4b6997f96b8c", + "failure_summary": "32 failed, 287 passed in 3.81s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "g_preflight" + }, + { + "id": "round8-tested_pia_ignores_basis", + "round": 8, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " if beneficiary is None:\n return state.pia\n return beneficiary.original_benefit_basis or state.pia\n", + "after": " if beneficiary is None:\n return state.pia\n return state.pia\n" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_deemed_pia_keeps_a_known_cohorts_history_open", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_a_deemed_pia_keeps_a_history_open_on_a_zero_record_pia" + ], + "failed_test_count": 2, + "log": { + "path": "scratch/review/round8-mutations/tested_pia_ignores_basis.log", + "sha256": "6969f9f9c169ef5ad037d357142a342fbdc2431cb06e4cc7b11bd45120efe464", + "failure_summary": "2 failed, 317 passed in 3.61s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "g_preflight" + }, + { + "id": "round8-unknown_cohort_closes_the_route", + "round": 8, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " return birth_year is None or any(\n max(first_month, (birth_year + age, 1)) < month\n for first_month, age in _PRIOR_REDUCED_BENEFIT_ROUTES\n )\n", + "after": " return birth_year is not None and any(\n max(first_month, (birth_year + age, 1)) < month\n for first_month, age in _PRIOR_REDUCED_BENEFIT_ROUTES\n )\n" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[None-1965-9-True]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[None-2024-1-True]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_the_floor_matches_month_counts_written_from_the_sources", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_the_month_after_a_cohort_turns_50[None-2024-1-True-conditions0-None-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_the_month_after_a_cohort_turns_50[None-2024-1-True-conditions1-UnsupportedReason.DIB_AFTER_REDUCED_RIB-UnsupportedReason.DIB_AFTER_REDUCED_RIB]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_opens_the_month_after_a_cohort_turns_50[None-2024-1-True-conditions2-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_needs_a_cohort_and_a_month" + ], + "failed_test_count": 7, + "log": { + "path": "scratch/review/round8-mutations/unknown_cohort_closes_the_route.log", + "sha256": "ecdb5bd3499ffdb82a1d64f598030a3cdd4e09090ba031475f8e927c348aa834", + "failure_summary": "7 failed, 312 passed in 4.04s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "g_preflight" + }, + { + "id": "round8-unknown_month_closes_the_route", + "round": 8, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " if payment_month is None:\n return True\n month = (payment_month.year", + "after": " if payment_month is None:\n return False\n month = (payment_month.year" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_an_unknown_month_leaves_every_route_open", + "tests/test_track_b_ret_ledger_fix_round_7.py::test_the_floor_needs_a_cohort_and_a_month" + ], + "failed_test_count": 2, + "log": { + "path": "scratch/review/round8-mutations/unknown_month_closes_the_route.log", + "sha256": "f41e3f2704b6bef56fcb6502984be6267dd21cddf0c1a0612a123b54ba4d7e5c", + "failure_summary": "2 failed, 317 passed in 4.61s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "g_preflight" + }, + { + "id": "round8-unknown_rib_passes_the_test", + "round": 8, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": [ + { + "before": " own_mba = Fraction(0)\n", + "after": " own_mba = None\n continue\n" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_zero_pia_fails_a_known_cohorts_rib[0.10-1-1900-None]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_zero_pia_fails_a_known_cohorts_rib[0.10-1-1900-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_zero_pia_fails_a_known_cohorts_rib[0.10-1-1900-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_zero_pia_fails_a_known_cohorts_rib[0.10-1-1900-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_zero_pia_fails_a_known_cohorts_rib[0.10-1-1915-None]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_zero_pia_fails_a_known_cohorts_rib[0.10-1-1915-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_zero_pia_fails_a_known_cohorts_rib[0.10-1-1915-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_zero_pia_fails_a_known_cohorts_rib[0.10-1-1915-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_zero_pia_fails_a_known_cohorts_rib[400-12-1900-None]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_zero_pia_fails_a_known_cohorts_rib[400-12-1900-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]" + ], + "failed_test_count": 19, + "log": { + "path": "scratch/review/round8-mutations/unknown_rib_passes_the_test.log", + "sha256": "4f3e7487f673ab1ab0a5ba42c24bf6978739a4b703276611bf6e71a6b2e918be", + "failure_summary": "19 failed, 300 passed in 3.84s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "r2" + }, + { + "id": "round8-unknown_rib_takes_its_pia", + "round": 8, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": [ + { + "before": " own_mba = Fraction(0)\n", + "after": " own_mba = auxiliary.own_benefit.pia\n" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_early_credits_keep_their_row_on_a_positive_threshold[0.10]" + ], + "failed_test_count": 1, + "log": { + "path": "scratch/review/round8-mutations/unknown_rib_takes_its_pia.log", + "sha256": "35ac96f45de9e924f67a6c6d3c89e73c19dc8b3678bc0ee1b826019777075527", + "failure_summary": "1 failed, 318 passed in 4.34s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "r2" + }, + { + "id": "round8-widow_route_age_59", + "round": 8, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " ((1965, 9), 60),\n", + "after": " ((1965, 9), 59),\n" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1907-1967-1-False]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1908-1968-1-False]" + ], + "failed_test_count": 2, + "log": { + "path": "scratch/review/round8-mutations/widow_route_age_59.log", + "sha256": "5c47bc7ae8dc9c2c3c64568fcbed03b9c7f5285305ad643293b79bf39c90401b", + "failure_summary": "2 failed, 317 passed in 4.35s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "g_preflight" + }, + { + "id": "round8-widow_route_age_61", + "round": 8, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " ((1965, 9), 60),\n", + "after": " ((1965, 9), 61),\n" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1905-1965-10-True]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1907-1967-2-True]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1908-1968-2-True]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_the_floor_matches_month_counts_written_from_the_sources" + ], + "failed_test_count": 4, + "log": { + "path": "scratch/review/round8-mutations/widow_route_age_61.log", + "sha256": "150eba5e0ffcf5c3a8bae774cb752cf361334c3f5f4e30fa5ef42d74a45d0b29", + "failure_summary": "4 failed, 315 passed in 4.40s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "g_preflight" + }, + { + "id": "round8-widow_route_month_early", + "round": 8, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " ((1965, 9), 60),\n", + "after": " ((1965, 8), 60),\n" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1904-1965-9-False]" + ], + "failed_test_count": 1, + "log": { + "path": "scratch/review/round8-mutations/widow_route_month_early.log", + "sha256": "e866194e063815d60e25714d241683c62e89beb355f1c5fa74922c4393691ffb", + "failure_summary": "1 failed, 318 passed in 4.02s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "g_preflight" + }, + { + "id": "round8-widow_route_month_late", + "round": 8, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " ((1965, 9), 60),\n", + "after": " ((1965, 10), 60),\n" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1904-1965-10-True]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1905-1965-10-True]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_the_floor_matches_month_counts_written_from_the_sources" + ], + "failed_test_count": 3, + "log": { + "path": "scratch/review/round8-mutations/widow_route_month_late.log", + "sha256": "281b9c600fe6b8c12918c38c8fdc90a4fa180617268c737669669e79171b35c6", + "failure_summary": "3 failed, 316 passed in 3.94s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "g_preflight" + }, + { + "id": "round8-widow_route_removed", + "round": 8, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " ((1965, 9), 60),\n", + "after": "" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1904-1965-10-True]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1905-1965-10-True]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1907-1967-2-True]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_each_route_dates_the_first_reduced_dib[1908-1968-2-True]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_the_floor_matches_month_counts_written_from_the_sources" + ], + "failed_test_count": 5, + "log": { + "path": "scratch/review/round8-mutations/widow_route_removed.log", + "sha256": "b5e198ef69e2fbedc7a14ef01780ea2eb16ce0176339436d7e17728b2cac8127", + "failure_summary": "5 failed, 314 passed in 4.43s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "g_preflight" + }, + { + "id": "round8-zero_threshold_reaches_positive_pia", + "round": 8, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " if fact == \"F6\" and tested_pia == 0:\n return False\n", + "after": " if fact == \"F6\" and tested_pia <= Fraction(1, 10):\n return False\n" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_only_a_zero_threshold_settles_a_rib_with_early_credits[Role.MOTHER_FATHER]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_only_a_zero_threshold_settles_a_rib_with_early_credits[Role.PARENT]" + ], + "failed_test_count": 2, + "log": { + "path": "scratch/review/round8-mutations/zero_threshold_reaches_positive_pia.log", + "sha256": "7716c0364c269b952f34169424ce56f8eb46bc78daf767c42e5e97706715bc8e", + "failure_summary": "2 failed, 317 passed in 3.83s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "g_preflight" + }, + { + "id": "round8-zero_threshold_removed", + "round": 8, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " if fact == \"F6\" and tested_pia == 0:\n return False\n", + "after": "" + } + ], + "command": [ + "python", + "scratch/review/run_round8_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_8.py", + "tests/test_track_b_ret_ledger_fix_round_7.py" + ], + "outer_command": [ + "python", + "scratch/review/round8_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round8", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round8", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_zero_pia_fails_a_known_cohorts_rib[0.10-1-1900-None]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_zero_pia_fails_a_known_cohorts_rib[0.10-1-1900-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_zero_pia_fails_a_known_cohorts_rib[0.10-1-1900-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_zero_pia_fails_a_known_cohorts_rib[0.10-1-1900-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_zero_pia_fails_a_known_cohorts_rib[0.10-1-1915-None]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_zero_pia_fails_a_known_cohorts_rib[0.10-1-1915-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_zero_pia_fails_a_known_cohorts_rib[0.10-1-1915-UnsupportedReason.REDUCED_BENEFIT_HISTORY_BEFORE_1978]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_zero_pia_fails_a_known_cohorts_rib[0.10-1-1915-UnsupportedReason.DUAL_ENTITLEMENT_SEQUENCE]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_zero_pia_fails_a_known_cohorts_rib[400-12-1900-None]", + "tests/test_track_b_ret_ledger_fix_round_8.py::test_a_zero_pia_fails_a_known_cohorts_rib[400-12-1900-UnsupportedReason.OWN_RIB_HISTORY_BEFORE_1978]" + ], + "failed_test_count": 34, + "log": { + "path": "scratch/review/round8-mutations/zero_threshold_removed.log", + "sha256": "cb6e0d2ae932784a84488068fe8899769613ba2a66b67f8cc10cf9a720ee986c", + "failure_summary": "34 failed, 285 passed in 3.41s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + } + }, + "layer": "g_preflight" } ], "restoration_verification_snapshot": { @@ -9099,5 +11403,11 @@ "round_7_restoration_snapshot": { "src/populace_dynamics/track_b/gross_benefits.py": "cfa04745d7fd52591115a046dabda8ac5a793ec7f529766eaecc4e2bd0c4044e", "src/populace_dynamics/track_b/ret_ledger.py": "9d1dd9caf88ff8d843c8196a4f672ba2d247328132ab16aa326918b2df2df645" + }, + "round_8_head": "fbe491d4c3ea3077702616eee79a742da124eefd", + "round_8_note": "39 fresh one-line semantic mutations failed named tests in tests/test_track_b_ret_ledger_fix_round_8.py and tests/test_track_b_ret_ledger_fix_round_7.py on the final test bytes. A first pass killed 38 of 39. The survivor let a positive threshold settle F6 under an early delayed-credit hold, which changes the fact and no outcome, and it gained a test before this run. The session ran these in copied source trees, and production sources stayed unchanged. Earlier records remain historical.", + "round_8_restoration_snapshot": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" } } diff --git a/docs/design/track_b_g2_r2b_verification.json b/docs/design/track_b_g2_r2b_verification.json index 010118c5b..8842a238c 100644 --- a/docs/design/track_b_g2_r2b_verification.json +++ b/docs/design/track_b_g2_r2b_verification.json @@ -13161,5 +13161,87 @@ ] } }, - "round_7_current_evidence_note": "Fresh reviewed-head failing-first, named module gates, cross-head diagnostic and copied-tree mutation evidence sits under round_7. Earlier heads, counts and commands remain historical." + "round_7_current_evidence_note": "Fresh reviewed-head failing-first, named module gates, cross-head diagnostic and copied-tree mutation evidence sits under round_7. Earlier heads, counts and commands remain historical.", + "round_8": { + "reviewed_head": "fbe491d4c3ea3077702616eee79a742da124eefd", + "workspace": "/Users/maxghenis/PolicyEngine/_clones/mdyn-trackb-g2-20261023", + "verification_class": "statutory_conformance", + "admitted_scope": "Invented declarations and captured published examples only; no population, behavioral or forecast claim.", + "fixed_by": "the session, because Fleet ops asked for one job at a time and a review held the slot", + "named_test_gate": { + "selection": "tests/test_track_b_*.py", + "result": "14193 passed, 7 skipped in 979.17s (0:16:19)", + "environment": "both data roots set to a nonexistent path" + }, + "failing_first": { + "reviewed_head": "fbe491d4c3ea3077702616eee79a742da124eefd", + "module": "tests/test_track_b_ret_ledger_fix_round_8.py", + "result": "96 failed, 52 passed in 0.77s" + }, + "cross_head": { + "r2_stable_rows": 240, + "r3_stable_rows": 240, + "identical_declared_output_bytes": true, + "stable_sha256": "799fc9e23a902ac1ca0c2563579ceb094d0dbcd631a912305c40062cf21a5f55" + }, + "conformance_report_sha256": "17d144575b38bb85080d8cbed28fad470ec93fd6eb6803b48729bb26a78b3d45", + "conformance_report_byte_identical": true, + "tier_policy": "Left to CI; no local whole-suite collection.", + "final_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", + "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + }, + "final_test_sha256": { + "tests/test_track_b_ret_ledger_fix_round_4.py": "02c5c86b64070f9e7350868f8d94dcc9233bedc32cbcae32b3264f9ae570d1bb", + "tests/test_track_b_ret_ledger_fix_round_5.py": "c86ef045d797e31d6db09ef11bc7fbfbcf7c1fa54d32f04e7b6b42e8b813c9cd", + "tests/test_track_b_ret_ledger_fix_round_6.py": "8ec899e262d6e242f67f860e1722f465882573bbcb481b8459f2ff13946f92b0", + "tests/test_track_b_ret_ledger_fix_round_7.py": "6f8f1cdc4f90e594759225870e1ec36a905fa1cd6eea7d142747ac13bec066c4", + "tests/test_track_b_ret_ledger_fix_round_8.py": "f6702f15e22000379a5e1bd45c3d15bd9766c71b7e9965266574458bfdfd8f23" + }, + "mutations": { + "count": 39, + "ids": [ + "round8-cap_also_at_the_pia", + "round8-cap_ignores_credits", + "round8-cap_ignores_every_hold", + "round8-cap_removed", + "round8-cap_uses_the_ordinary_upper_bound", + "round8-disabled_route_age_49", + "round8-disabled_route_age_51", + "round8-disabled_route_month_early", + "round8-disabled_route_month_late", + "round8-disabled_route_removed", + "round8-effective_date_removed", + "round8-every_route_must_precede", + "round8-first_pass_drops_pia_cap", + "round8-last_pass_drops_pia_cap", + "round8-pia_cap_drops_delayed_hold", + "round8-pia_cap_for_every_hold", + "round8-pia_cap_only_delayed_hold", + "round8-pia_cap_removed", + "round8-reduced_dib_month_early", + "round8-reduced_dib_month_late", + "round8-rib_route_age_61", + "round8-rib_route_age_63", + "round8-rib_route_removed", + "round8-rib_route_starts_with_the_dib", + "round8-route_ignores_age", + "round8-route_ignores_its_first_month", + "round8-route_month_may_equal_the_dib", + "round8-tested_pia_ignores_basis", + "round8-unknown_cohort_closes_the_route", + "round8-unknown_month_closes_the_route", + "round8-unknown_rib_passes_the_test", + "round8-unknown_rib_takes_its_pia", + "round8-widow_route_age_59", + "round8-widow_route_age_61", + "round8-widow_route_month_early", + "round8-widow_route_month_late", + "round8-widow_route_removed", + "round8-zero_threshold_reaches_positive_pia", + "round8-zero_threshold_removed" + ] + } + }, + "round_8_current_evidence_note": "Fresh reviewed-head failing-first, named module gates, cross-head diagnostic and copied-tree mutation evidence sits under round_8. Earlier heads, counts and commands remain historical." } diff --git a/docs/design/track_b_r2_ret_ledger.md b/docs/design/track_b_r2_ret_ledger.md index 62c926c24..afe43805a 100644 --- a/docs/design/track_b_r2_ret_ledger.md +++ b/docs/design/track_b_r2_ret_ledger.md @@ -2137,13 +2137,13 @@ member separately. | Held refusal or origin | Facts whose comparison can be unsettled | Captured basis | | --- | --- | --- | -| `_refuse_own_benefit`: reduced own DIB; historical own RIB; pre-1917 delayed credits | The affected own MBA used for F3 or F6; F2 below the PIA for the NH reduced-DIB reason and, before cohort 1928, for the own-RIB history reason | Act 202(q)(2) expressly reduces DIB. RS 00615.005C.2 requires the money-history method in "all cases involving single entitlement to actuarially reduced benefits prior to 1/78". RS 00615.692D gives "Before 01/02/17" a "1/12%" monthly credit. The canonical helper refuses rather than fabricating an MBA. | +| `_refuse_own_benefit`: reduced own DIB; historical own RIB; pre-1917 delayed credits | The affected own MBA used for F3 or F6; F2 below the PIA for the NH reduced-DIB reason and, before cohort 1928, for the own-RIB history reason | Act 202(q)(2) expressly reduces DIB. RS 00615.005C.2 requires the money-history method in "all cases involving single entitlement to actuarially reduced benefits prior to 1/78". RS 00615.692D gives "Before 01/02/17" a "1/12%" monthly credit. The canonical helper refuses rather than fabricating an MBA, so a zero tested PIA settles F6 without one, and the PIA still caps a RIB with no delayed credits (round 8). | | `PAYMENT_MONTH_BEFORE_1983` | Historical own MBA used for F3/F6; nonwidow auxiliary OB in actual pre-1983 months; survivor widow OB before January 1973 | RS 00615.101 says "Round the result down to the next dime for benefits after 5/82 and up to the next dime for benefits prior to 6/82." The captures do not establish unchanged modern dime-floored nonwidow OB throughout G's refused historical interval. RS 00615.005A.2 says "Raised the unreduced benefit amount for widow(er)s to 82 1/2% at age 62." Its A.5 says "Changed WIB to 100% of the deceased worker's PIA" effective January 1973. Actual payment dates determine which exact facts remain unsettled; a deferred payment reason cannot manufacture an earlier date. | | `ELIGIBILITY_BEFORE_1983`, `DI_ENTITLEMENT_BEFORE_JULY_1980` | None | RS 00615.736 gives the historical maximum procedure; RS 00615.740B.2 says DMAX does not apply when "The NH was ever entitled to DIB before July 1980". These maximum histories do not replace role OB or current own-benefit facts. | | `PARENT_BENEFIT` | F4/F6 when parent count refuses | RS 00209.001 excludes own RIB "equal to or exceeding the amount of the parent's original benefit (One parent = 82 1/2%; Two parents = 75%)". RS 00209.015 states "Benefit rate equals 75% of the worker's PIA for each month both are entitled." An unresolved entitled-parent count leaves both threshold and OB unsettled. | | `DISABLED_WIDOW_UNDER_60` | No additional fact beyond a separately refusing own MBA | RS 00615.310C first says "Determine the WIB OB", then separately determines and subtracts reductions. The historical extra reduction changes gross, not F4's OB. | -| `DUAL_ENTITLEMENT_SEQUENCE` | F2 below the PIA from the January a cohort can turn 50; F3 below the ordinary rate and F6, each only where historical carryover can change own RIB | 20 CFR 404.411(b) reduces a DIB after a reduced RIB and, for "all individuals born before January 2, 1928" or a disability before 1990, after a WIB. The schema omits the onset, so only age limits F2: no cohort reaches a reduced benefit before 50 (round 7). 404.411(c)(2) reduces an old-age benefit "by the larger of the following" for a person born before January 2, 1928, even one who met every WIB condition "except that the old-age benefit equals or exceeds the primary insurance amount", so no current WIB or auxiliary record needs to appear. Both only lower a rate, so the ordinary rate stays the cap (round 6). RS 00615.005A.8 says "Eliminated the carry-over reduction in RIB or DIB due to WIB before age 62" and applies the RIB change to workers born January 2, 1928 or later. RS 00615.010 preserves the earlier rule: "If there was prior entitlement to a reduced WIB in any month before the month of attainment of age 62 reduce the RIB per RS 00615.160 and RS 00615.170." The schema omits that history. Modern WIB/DWB election instead requires "if all eligibility requirements are met" and preserves "the PIA and the reduction factors remain the same" (RS 00615.315). It does not waive F6, which covers every test of an actual own RIB: widow(er), mother or father, and parent (round 7). A nonnegative own RIB cannot be less than a zero deemed-death PIA. The spouse raw own-PIA test stays F5. | -| `REDUCED_BENEFIT_HISTORY_BEFORE_1978` | F2 below the PIA and, within the carryover scope above, F3 below the ordinary rate and F6; each only before cohort 1928. Before cohort 1916, or with no cohort, F3 and F6 in both directions | RS 00615.005C.2 requires historical money reductions. That does not change the original benefit determined before reduction, but the 404.411 rules above carry such a reduction into a later DIB or RIB. RS 00615.005A.7 gives age 50 as the earliest reduced disabled widow(er), so cohort 1928 reached no reduced benefit before 1978 (round 6). A declared money history can exceed today's fraction, so it lifts the F3 cap where it can reach an own RIB, and F6 follows the same amount (round 7). | +| `DUAL_ENTITLEMENT_SEQUENCE` | F2 below the PIA from the month after a reduced RIB or WIB could first start; F3 below the ordinary rate and F6, each only where historical carryover can change own RIB | 20 CFR 404.411(b) reduces a DIB after a reduced RIB and, for "all individuals born before January 2, 1928" or a disability before 1990, after a WIB. The schema omits the onset, so only each route's age and date limit F2 (rounds 7 and 8). 404.411(c)(2) reduces an old-age benefit "by the larger of the following" for a person born before January 2, 1928, even one who met every WIB condition "except that the old-age benefit equals or exceeds the primary insurance amount", so no current WIB or auxiliary record needs to appear. Both only lower a rate, so the ordinary rate stays the cap (round 6). RS 00615.005A.8 says "Eliminated the carry-over reduction in RIB or DIB due to WIB before age 62" and applies the RIB change to workers born January 2, 1928 or later. RS 00615.010 preserves the earlier rule: "If there was prior entitlement to a reduced WIB in any month before the month of attainment of age 62 reduce the RIB per RS 00615.160 and RS 00615.170." The schema omits that history. Modern WIB/DWB election instead requires "if all eligibility requirements are met" and preserves "the PIA and the reduction factors remain the same" (RS 00615.315). It does not waive F6, which covers every test of an actual own RIB: widow(er), mother or father, and parent (round 7). A nonnegative own RIB cannot be less than a zero deemed-death PIA, whatever its own history (round 8). The spouse raw own-PIA test stays F5. | +| `REDUCED_BENEFIT_HISTORY_BEFORE_1978` | F2 below the PIA and, within the carryover scope above, F3 below the ordinary rate and F6; each only before cohort 1928. Before cohort 1916, or with no cohort, F3 and F6 in both directions, up to the PIA for F3 with no delayed credits (round 8) | RS 00615.005C.2 requires historical money reductions. That does not change the original benefit determined before reduction, but the 404.411 rules above carry such a reduction into a later DIB or RIB. RS 00615.005A.7 gives age 50 as the earliest reduced disabled widow(er), so cohort 1928 reached no reduced benefit before 1978 (round 6). A declared money history can exceed today's fraction, so it lifts the F3 cap where it can reach an own RIB, and F6 follows the same amount (round 7). | | `INDEPENDENT_DIVORCED_SPOUSE` | None | RS 00202.100 identifies the unfiled NH and requires the applicable WEP PIA; the declared PIA and eligibility facts are still the inputs. | | `COMBINED_FAMILY_MAXIMUM`, `MULTIPLE_AUXILIARY_RECORDS`, `DEEMED_SPOUSE`, `NON_AIME_FORMULA_PIA`, `DIB_GUARANTEE_PIA`, `GOVERNMENT_PENSION_OFFSET` | None | The condition table's captured maximum-membership, maximum-formula and payable-offset rules apply equally when the reason is deferred. | | `PARISI_AMBIGUOUS`, `PARISI_BEFORE_OCTOBER_1999` | None | RS 00615.768E says the change affects benefits "after reduction for the maximum" and "Beneficiaries will still be limited by the original benefit amount." | @@ -2361,7 +2361,7 @@ after a reduced WIB (404.411(b)) didn't enter its verdict. The session tested it and found the same lost row: $398.10 on PIA $400 raised under `dual_entitlement_sequence`. F2 now stays open below the PIA for that reason, because the schema omits the disability onset that scopes -404.411(b)(2). Round 7 limits this to months a cohort can reach age 50. `OWN_RIB_HISTORY_BEFORE_1978` and +404.411(b)(2). Round 7 limits this by age, and round 8 corrects that limit to each route's first month. `OWN_RIB_HISTORY_BEFORE_1978` and `REDUCED_BENEFIT_HISTORY_BEFORE_1978` open it too, before cohort 1928 only: a later cohort reached age 50 after 1977. @@ -2386,7 +2386,7 @@ a later cohort reached age 50 after 1977. | Every rate 404.411(c)(2)(ii) can reach stays a counted refusal, and the preflight changes nothing about it | `test_published_rule_carryover_keeps_its_refusal`; Hypothesis `test_every_carryover_rate_keeps_its_row` | | The carryover ends at cohort 1928, reaches only an old-age benefit, and an unknown cohort can't rule it out | `test_carryover_ends_at_cohort_1928`; `test_the_carryover_reaches_only_an_old_age_benefit`; `test_an_unknown_cohort_cannot_rule_out_the_carryover`; `test_a_zero_pia_leaves_no_rate_for_the_carryover_to_lower` | | Each NH rate has a cap: a declaration above it raises, and one at or below it keeps its row | `test_a_reducing_hold_bounds_a_dib_at_its_pia`; `test_rib_above_the_canonical_rate_stays_an_input_error`; `test_rib_at_the_canonical_rate_keeps_its_refusal`; `test_workers_compensation_caps_a_rib_at_its_canonical_rate`; Hypothesis `test_every_dib_at_or_below_the_cap_keeps_its_row` | -| Outside round 7's history scope, only finality lifts a cap | `test_finality_still_protects_a_rate_above_the_cap`; `test_finality_still_protects_a_rib_above_the_cap`; `test_only_finality_lifts_an_nh_rate_cap` | +| Outside round 7's history scope, only finality lifts a cap | `test_finality_still_protects_a_rate_above_the_cap`; `test_finality_still_protects_a_rib_above_the_cap`; `test_only_finality_lifts_an_nh_rate_cap_outside_money_history_scope` | | Every G refusal reason classifies a lower DIB and a lower RIB against a written-out expectation | `test_each_reason_classifies_a_lower_dib`; `test_each_reason_classifies_a_lower_rib` | | Pre-1978 reasons reach only cohorts old enough for a reduced benefit by then | `test_pre_1978_history_reaches_only_cohorts_old_enough_for_it`; `test_an_unknown_cohort_cannot_rule_out_a_pre_1978_history` | | Each quotation above sits in its capture | `test_the_captures_carry_each_quoted_rule` | @@ -2412,7 +2412,8 @@ already put in doubt. One kept a row that no filling can make lawful. ### What changed -**A declared history reaches past an omitted cohort.** An omitted cohort +**A declared history reaches past an omitted cohort.** Round 8 keeps the PIA +as the cap this paragraph drops. An omitted cohort keeps the current formula, and that stays the rule for an undated input. A declared `OWN_RIB_HISTORY_BEFORE_1978` or `REDUCED_BENEFIT_HISTORY_BEFORE_1978` says more: RS 00615.005C.2's money @@ -2441,7 +2442,8 @@ own PIA (F5), which no history changes, and a child's has no amount test. `REDUCED_BENEFIT_HISTORY_BEFORE_1978` now opens F6 in the same scope, because it carries through the same rule that already opened F3. -**Age rules out a prior reduced benefit.** RS 00615.010 says "DIB is not +**Age rules out a prior reduced benefit.** Round 8 corrects this paragraph's +floor to each route's first month. RS 00615.010 says "DIB is not reduced unless there was prior entitlement to reduced RIB (or WIB prior to 1/90)." RS 00615.005 starts those benefits at 62 and, for a disabled widow(er), at 50. A cohort attains 50 no earlier than January of its birth @@ -2487,14 +2489,120 @@ meant a RIB alone, and a loose refusal moves no money. | Invariant | Executing tests in `test_track_b_ret_ledger_fix_round_7.py` | | --- | --- | | Money history lands above today's formula on every rounding path, from the captured COLAs | `test_money_history_lands_above_todays_formula_on_every_path` | -| A declared history keeps every rate in its scope, in both directions, and the preflight changes nothing about it | `test_declared_history_keeps_a_rate_above_todays_formula`; `test_a_history_reaching_rib_keeps_either_direction`; Hypothesis `test_history_keeps_every_rate_in_its_scope` | +| A declared history keeps every rate in its scope, in both directions up to the PIA (round 8), and the preflight changes nothing about it | `test_declared_history_keeps_a_rate_above_todays_formula`; `test_a_history_reaching_rib_keeps_either_direction`; Hypothesis `test_history_keeps_every_rate_in_its_scope` | | Past that scope the cap holds: cohort 1916 on, no remaining reduction, no declared history, and every DIB | `test_a_cohort_past_1915_keeps_todays_formula_as_a_cap`; `test_a_cohort_past_1915_keeps_exact_own_history`; `test_no_remaining_reduction_needs_no_money_history`; `test_only_a_declared_history_reaches_past_an_omitted_cohort`; `test_history_leaves_a_dib_cap_alone`; Hypothesis `test_past_1915_every_reduction_only_hold_keeps_the_cap` | | A mother's carried rate keeps its row where the ordinary rate fails her test, in a pre-FRA year too | `test_a_mothers_carried_rib_passes_where_the_ordinary_one_fails`; `test_a_pre_fra_mother_keeps_the_historical_year_row`; `test_a_mothers_own_rib_opens_only_in_each_holds_scope` | | Every actual-RIB test shares the carryover, and no other role or a DIB does | `test_every_actual_rib_test_shares_the_carryover`; `test_a_role_with_no_rib_amount_test_stays_settled`; `test_a_disability_own_benefit_faces_no_rib_amount_test`; Hypothesis `test_f6_matches_a_table_written_from_the_sources` | | A zero PIA fails every RIB on every filling, a deemed PIA counts as the tested PIA, and a money history needs an old-age benefit with a PIA | `test_a_zero_pia_fails_every_rib_on_every_filling`; `test_a_deemed_pia_keeps_a_history_open_on_a_zero_record_pia`; `test_a_reduced_dib_opens_no_money_history`; `test_a_zero_own_pia_leaves_no_money_history` | | Before a cohort can reach 50, a DIB rate equals its PIA or raises and leaves no row | `test_a_cohort_too_young_for_any_reduced_benefit_has_one_dib_rate`; `test_before_age_50_a_dib_below_the_pia_raises`; Hypothesis `test_a_young_dib_rate_equals_its_pia_or_raises` | -| The floor opens in January of the year a cohort turns 50, and needs a cohort and a month | `test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50`; `test_the_floor_needs_a_cohort_and_a_month`; `test_a_pre_1978_hold_needs_both_the_cohort_and_the_age` | +| The floor opens the month after a cohort turns 50, and needs a cohort and a month (round 8 corrects January to February) | `test_the_floor_opens_the_month_after_a_cohort_turns_50`; `test_the_floor_needs_a_cohort_and_a_month`; `test_a_pre_1978_hold_needs_both_the_cohort_and_the_age` | | No age limits a hold that needs no prior reduced benefit | `test_a_hold_no_age_limits_keeps_a_young_row`; `test_an_independent_hold_survives_a_young_dual_declaration`; Hypothesis `test_f2_matches_a_table_written_from_the_sources` | | Each quotation above sits in its capture | `test_the_captures_carry_each_quoted_rule` | Forty-two fresh mutations each fail a named test on the final test bytes, and 44 of the module's 158 tests fail against `3212f823`. A first pass killed 39 of 43. One survivor showed that a month comparison added nothing, so the rule now compares years and that mutation went away. The other three exposed test gaps, and each gained a test before this run. + + +## PR 563 round 8: the PIA cap, zero thresholds and the first reduced DIB + +GPT-6.1 Sol reviewed `fbe491d4` and asked for changes, with three medium +findings and a nit. All three findings reproduced, and each one's reading +matches its capture. Each kept a counted row for a declaration no filling can +make lawful. Round 7 caused the first and third by reading too far past an +exact comparison. + +### What changed + +**History leaves a RIB at or below its PIA.** Round 7 opened F3 in both +directions under a money history, and that dropped every cap with the exact +rate. RS 00615.005C.2 says "The new money amount of reduction is subtracted +from the new PIA", and a reduction can't go below zero. So a RIB with no +delayed credits can't exceed its PIA on any filling. A rate of $333.40 on PIA +$333.30 kept a row at cohort 1915. It now raises before `evaluate_ret` and +leaves no row. So does $0.20 on PIA $0.10. The canonical own-benefit refusal +hid the same rate for a known cohort before 1916 with no declaration, and the +check reaches that record too. `_fact_is_settled` takes `pia_cap`, a narrower +question than the ordinary upper bound. `_PIA_CAP_KEEPING_HOLDS` lists the +holds that leave that answer alone: the reduction-only holds, money history +among them, and a delayed-credit hold on a record with no credits. Finality +keeps its row, because it can protect a rate above the PIA. So do positive +delayed credits, which add to the base. A month before 1983 keeps its row, +because the fact table leaves F3 open there. A rate at or below the PIA keeps +its row under a history hold, and round 7's reasoning for it stands. + +**A zero threshold fails every RIB.** Act 202(g)(1)(C) needs a mother's or +father's own RIB below three-quarters of the PIA, so at PIA $0 no nonnegative +RIB qualifies. Round 7 settled that for an undated own RIB. A known cohort +before 1916 still opened F6, and the own-benefit computation refused anyway, +so a mother with own PIA $0.10 kept a row on PIA $0. `_hold_unsettles_fact` +now settles F6 at a zero tested PIA. The preflight then tests any RIB it can't +compute at zero, the lowest RIB there is. A test that a zero RIB fails holds +on every filling, and a positive threshold passes at zero and keeps its row. +That one line also reaches early delayed credits with no reduction, which +never opened F6 at all. The tested PIA follows `_tested_pia`, so a deemed +widow(er) PIA keeps a history open on a zero record PIA. Finality keeps its +row. An RET record can't hold a parent, so that role meets this only through +the fact table. + +**A reduced DIB needs a month before it.** Round 7's floor compared years, and +it read only the age. RS 00615.010 reduces a DIB "only for months of WIB +entitlement before the first MOET to DIB", and it needs "prior entitlement to +reduced RIB". So a route opens the month after its first month. RS 00615.005 +dates each route: + +| Route | First month | Earliest age | Capture | +| --- | --- | --- | --- | +| Reduced RIB | November 1956 | 62 | A.1 | +| Reduced WIB | September 1965 | 60 | A.3 | +| Reduced disabled WIB | February 1968 | 50 | A.4 | + +A.3 also starts the reduced DIB itself in September 1965, so no route opens +before then. A DIB of $404.90 on PIA $405 for cohort 1974 in January 2024 kept +a row, and it now raises. February 2024 keeps the row, and so does a rate at +the PIA in January. Payments of $99.90 on PIA $100 in February 1958 for cohort +1908, February 1966 for cohort 1916 and February 1968 for cohort 1918 each +raise too, because no route had opened. March 1968 for cohort 1918 keeps its +row. Each row in `test_each_route_dates_the_first_reduced_dib` names the route +it turns on. + +The floor reads the payment month, not `first_dib_entitlement`. That field +holds the first-ever DIB month, and RS 00615.010 counts from the first month +of the most recent entitlement. Only the payment month bounds that later month. + +The session also renamed round 6's +`test_only_finality_lifts_an_nh_rate_cap_outside_money_history_scope`, because +its old name claimed more than its comment did. + +### What stayed + +- **Every hold still shares the earliest route.** `DIB_AFTER_REDUCED_RIB` names + a RIB, but the schema has no separate declaration for a DIB after a reduced + WIB. So from the month after a cohort turns 50 the row stays a named refusal. +- **Modern cohorts keep the WIB route.** RS 00615.005A.8 ends that carryover for + a DIB for workers born January 2, 1928 or later with onsets on or after + January 1, 1990. The schema omits the onset, so the rule can't show that + every filling fails. A loose refusal moves no money. +- **The exact rate under a history stays refused.** The PIA cap says what a rate + can't be, and it computes nothing. +- **No money moved.** This round changes classification only. +- **Sol's `needs_max` items need no new call.** Each one keeps a standing ruling + or resolves inside these fixes. + +### New executed invariants + +| Invariant | Executing tests in `test_track_b_ret_ledger_fix_round_8.py` | +| --- | --- | +| With no delayed credits, no history admits a RIB above its PIA, declared or implied by a known cohort | `test_history_leaves_a_rib_at_or_below_its_pia`; `test_a_known_cohort_keeps_the_pia_cap_with_no_declaration`; `test_no_other_hold_lifts_a_known_cohort_past_the_pia`; Hypothesis `test_no_history_admits_a_rib_above_its_pia` | +| The cap leaves every rate at or below the PIA its row, and the preflight changes nothing about it | `test_a_rate_at_the_pia_keeps_its_history_row`; round 7's Hypothesis `test_history_keeps_every_rate_in_its_scope` | +| Finality, positive delayed credits and a month before 1983 keep a rate above the PIA | `test_finality_can_lift_a_rib_past_its_pia`; `test_a_deferred_finality_can_lift_a_rib_past_its_pia`; `test_delayed_credits_can_lift_a_history_rib_past_its_pia`; `test_a_month_before_1983_leaves_the_rate_unsettled_past_the_pia` | +| A zero threshold fails every RIB on every filling, and only a zero threshold does | `test_a_zero_pia_fails_a_known_cohorts_rib`; `test_a_zero_pia_fails_a_rib_with_early_credits`; `test_a_zero_threshold_settles_every_actual_rib_test`; `test_only_a_zero_threshold_settles_a_rib_with_early_credits`; Hypothesis `test_only_a_zero_threshold_rules_out_a_history_rib` | +| A positive threshold, a deemed PIA and finality each keep their row | `test_a_positive_threshold_keeps_the_own_history_row`; `test_early_credits_keep_their_row_on_a_positive_threshold`; `test_a_deemed_pia_keeps_a_known_cohorts_history_open`; `test_finality_keeps_a_zero_threshold_row`; `test_a_deferred_finality_keeps_a_zero_threshold_row` | +| A route opens the month after its first month, on its own age and date, and no route opens before September 1965 | `test_each_route_dates_the_first_reduced_dib`; Hypothesis `test_the_floor_matches_month_counts_written_from_the_sources`; round 7's Hypothesis `test_f2_matches_a_table_written_from_the_sources` | +| Before a route opens a DIB rate equals its PIA or raises, and once one opens the row stays | `test_a_modern_january_of_cohort_plus_50_has_one_dib_rate`; `test_before_a_route_exists_a_dib_rate_equals_its_pia_or_raises`; `test_a_historical_route_keeps_its_row_once_it_opens`; `test_a_pre_1978_hold_shares_the_first_route` | +| Unknown facts stay open, and no route limits a hold that needs no predecessor | `test_an_unknown_month_leaves_every_route_open`; `test_a_hold_that_needs_no_predecessor_keeps_its_row` | +| Each quotation above sits in its capture | `test_the_captures_carry_each_quoted_rule` | + +Thirty-nine fresh mutations each fail a named test on the final test bytes, +and 96 of the module's 148 tests fail against `fbe491d4`. A first pass killed +38 of 39. The survivor let a positive threshold settle F6 under an early +delayed-credit hold, which changes that fact and no outcome, and +`test_only_a_zero_threshold_settles_a_rib_with_early_credits` now kills it. diff --git a/src/populace_dynamics/track_b/gross_benefits.py b/src/populace_dynamics/track_b/gross_benefits.py index 6558e2ee0..6ce2e2c57 100644 --- a/src/populace_dynamics/track_b/gross_benefits.py +++ b/src/populace_dynamics/track_b/gross_benefits.py @@ -431,7 +431,15 @@ _FIRST_COHORT_WITHOUT_PRE_1978_REDUCTION = 1928 # RS 00615.005A.4 starts reduced disabled widow(er)'s benefits at age 50. RIB # and spouse's benefits start at 62 (A.1, A.2) and aged WIB at 60 (A.3). -_EARLIEST_REDUCED_BENEFIT_AGE = 50 +# RS 00615.005A.3 starts reduced DIBs. A.1, A.3 and A.4 give each benefit that +# can come first as (first month, earliest age). The schema records no sex, so +# women's dates stand for men's later ones. +_FIRST_REDUCED_DIB_MONTH = (1965, 9) +_PRIOR_REDUCED_BENEFIT_ROUTES = ( + ((1956, 11), 62), + ((1965, 9), 60), + ((1968, 2), 50), +) # This cohort attains 62 no earlier than January 1978 (RS 00615.005C.2). _FIRST_COHORT_WITHOUT_PRE_1978_OWN_RIB = 1916 @@ -1827,6 +1835,10 @@ class BeneficiaryCondition(Enum): # _is_entitled compares these roles' actual own RIB. A spouse's test reads the # raw own PIA (F5), which no reduction history changes. _OWN_RIB_AMOUNT_TEST_ROLES = _WIDOW_ROLES | {Role.MOTHER_FATHER, Role.PARENT} +# With no delayed credits, none of these can lift an own RIB past its PIA. +_PIA_CAP_KEEPING_HOLDS = _NH_REDUCTION_ONLY_HOLDS | { + UnsupportedReason.DELAYED_CREDITS_BEFORE_1917, +} def _declared_fact_holds(state, beneficiary=None): @@ -1876,21 +1888,35 @@ def _historical_own_rib_possible(own, birth_year): def _prior_reduced_benefit_possible(birth_year, payment_month): - """Whether any reduced benefit could precede this payment month. + """Whether a reduced benefit could precede and lower this DIB month. RS 00615.010 says "DIB is not reduced unless there was prior entitlement - to reduced RIB (or WIB prior to 1/90)." RS 00615.005A.1-A.4 start those - benefits no earlier than age 50, and an SSA cohort attains an age no - earlier than January of that year. The schema doesn't say which route a - hold took, so every hold shares the earliest age of any route. + to reduced RIB (or WIB prior to 1/90)", and it counts "months of WIB + entitlement before the first MOET to DIB". So a route needs a month + before this one. RS 00615.005A.1-A.4 date each route, and an SSA cohort + attains an age no earlier than January of that year. The schema doesn't + say which route a hold took, so every hold shares the earliest of any + route. ``first_dib_entitlement`` is the first-ever DIB month, not the + latest period's, so only the payment month bounds that period's start. """ - return ( - birth_year is None - or payment_month is None - or payment_month.year >= birth_year + _EARLIEST_REDUCED_BENEFIT_AGE + if payment_month is None: + return True + month = (payment_month.year, payment_month.month) + if month < _FIRST_REDUCED_DIB_MONTH: + return False + return birth_year is None or any( + max(first_month, (birth_year + age, 1)) < month + for first_month, age in _PRIOR_REDUCED_BENEFIT_ROUTES ) +def _tested_pia(state, beneficiary): + """The PIA an own-RIB test reads; a widow(er)'s OB can deem a higher one.""" + if beneficiary is None: + return state.pia + return beneficiary.original_benefit_basis or state.pia + + def _hold_unsettles_fact( hold, fact, @@ -1901,18 +1927,18 @@ def _hold_unsettles_fact( beneficiaries, params, upper_bound=False, + pia_cap=False, ): if fact not in _PREFLIGHT_FACT_UNSETTLERS[hold]: return False + if pia_cap and hold in _PIA_CAP_KEEPING_HOLDS: + return False + tested_pia = _tested_pia(state, beneficiary) if fact in ("F3", "F6") and hold in _PRE_1978_HISTORY_HOLDS: - own, cohort, tested_pia = ( - (state.worker, state.worker_birth_year, state.pia) + own, cohort = ( + (state.worker, state.worker_birth_year) if beneficiary is None - else ( - beneficiary.own_benefit, - beneficiary.birth_year, - beneficiary.original_benefit_basis or state.pia, - ) + else (beneficiary.own_benefit, beneficiary.birth_year) ) # A declared history reaches past the undated current formula, in # either direction. A zero PIA fails every RIB on every filling. @@ -1925,8 +1951,8 @@ def _hold_unsettles_fact( ): return False # 404.411(b) reduces a DIB after a reduced RIB and after a WIB under - # (b)(2). The schema omits the onset that scopes (b)(2), so only age and - # the pre-1978 cohort limit a hold that works through either benefit. + # (b)(2). The schema omits the onset that scopes (b)(2), so only each + # route's dates and the pre-1978 cohort limit a hold on either benefit. if ( fact == "F2" and hold in _PRIOR_REDUCED_BENEFIT_HOLDS @@ -1952,6 +1978,10 @@ def _hold_unsettles_fact( own = state.worker if beneficiary is None else beneficiary.own_benefit if own is None: return False + # Every nonnegative RIB meets a zero threshold, so its amount can't + # change the result. + if fact == "F6" and tested_pia == 0: + return False try: _own_monthly_benefit_validated(own, params) except FamilyConfigurationUnsupported: @@ -2026,7 +2056,7 @@ def _hold_unsettles_fact( # less than a zero deemed-death PIA (402(e)(1)(D)). return ( beneficiary.role in _OWN_RIB_AMOUNT_TEST_ROLES - and (beneficiary.original_benefit_basis or state.pia) > 0 + and tested_pia > 0 and _wib_carryover_possible( beneficiary.own_benefit, beneficiary.birth_year ) @@ -2043,6 +2073,7 @@ def _fact_is_settled( beneficiaries=(), params=None, upper_bound=False, + pia_cap=False, ): """Whether ordinary G can establish this fact before a coverage hold. @@ -2052,6 +2083,8 @@ def _fact_is_settled( Canonical money helpers may still refuse a fact that passes this test. An upper-bound request asks only for a cap: the one-parent OB without an exact parent count, or an NH rate a reduction-only hold can lower. + A PIA-cap request asks only whether a RIB with no delayed credits stays + at or below its PIA, a weaker cap that survives money history. """ if beneficiary is not None: beneficiary = _with_effective_cohort(beneficiary) @@ -2066,6 +2099,7 @@ def _fact_is_settled( beneficiaries=beneficiaries, params=params, upper_bound=upper_bound, + pia_cap=pia_cap, ) for hold in holds ): @@ -2123,6 +2157,7 @@ def _fact_is_settled( beneficiaries=beneficiaries, params=params, upper_bound=upper_bound, + pia_cap=pia_cap, ) for hold in holds ) diff --git a/src/populace_dynamics/track_b/ret_ledger.py b/src/populace_dynamics/track_b/ret_ledger.py index 7632ebe32..2bfd5aaae 100644 --- a/src/populace_dynamics/track_b/ret_ledger.py +++ b/src/populace_dynamics/track_b/ret_ledger.py @@ -1175,6 +1175,7 @@ def settled( member=None, *, upper_bound=False, + pia_cap=False, state=state, payment_month=payment_month, context=context, @@ -1187,6 +1188,7 @@ def settled( beneficiaries=context.beneficiaries, params=context.params, upper_bound=upper_bound, + pia_cap=pia_cap, ) if record.kind is not RecordKind.DECEASED: @@ -1205,20 +1207,32 @@ def settled( raise InvalidFamilyInput( "G context does not match RET rates" ) - elif settled("F3", upper_bound=True): - try: - gross = g._own_monthly_benefit_validated( - state.worker, context.params - )[1] - except FamilyConfigurationUnsupported: - pass - else: - if declared > gross or ( - settled("F3") and declared != gross - ): - raise InvalidFamilyInput( - "G context does not match RET rates" - ) + else: + # RS 00615.005C.2 subtracts a money reduction from the + # new PIA, so with no delayed credits history leaves a + # RIB at or below that PIA, whatever the exact rate. + if ( + declared > state.pia + and state.worker.delayed_credit_months == 0 + and settled("F3", pia_cap=True) + ): + raise InvalidFamilyInput( + "G context does not match RET rates" + ) + if settled("F3", upper_bound=True): + try: + gross = g._own_monthly_benefit_validated( + state.worker, context.params + )[1] + except FamilyConfigurationUnsupported: + pass + else: + if declared > gross or ( + settled("F3") and declared != gross + ): + raise InvalidFamilyInput( + "G context does not match RET rates" + ) parent_count = None parent_count_known = False for auxiliary in context.beneficiaries: @@ -1250,22 +1264,23 @@ def settled( if settled(fact, auxiliary) and not ( auxiliary.role is g.Role.PARENT and original is None ): - try: - own_mba = None - if auxiliary.own_benefit is not None and fact == "F6": + own_mba = None + if auxiliary.own_benefit is not None and fact == "F6": + try: own_mba = g._own_monthly_benefit_validated( auxiliary.own_benefit, context.params )[1] - entitled, _ = g._is_entitled( - auxiliary, state.pia, own_mba, parent_ob=original + except FamilyConfigurationUnsupported: + # No RIB falls below zero, so a test that a zero RIB + # fails holds on every filling of the missing amount. + own_mba = Fraction(0) + entitled, _ = g._is_entitled( + auxiliary, state.pia, own_mba, parent_ob=original + ) + if not entitled: + raise InvalidFamilyInput( + "G and RET auxiliary entitlement facts differ" ) - except FamilyConfigurationUnsupported: - pass - else: - if not entitled: - raise InvalidFamilyInput( - "G and RET auxiliary entitlement facts differ" - ) if ( settled("F4", auxiliary) and original is not None diff --git a/tests/README-tiers.md b/tests/README-tiers.md index f0ed6c644..ea402feb7 100644 --- a/tests/README-tiers.md +++ b/tests/README-tiers.md @@ -39,9 +39,9 @@ pytest --collect-only -q -m oracle_policyengine | tail -1 | Tier | Tests at HEAD | |---|---:| -| `unit` | 21,186 | +| `unit` | 21,347 | | `artifact` | 4,271 | | `integration_psid` | 1,471 | | `reproduction_legacy` | 520 | | `oracle_policyengine` | 308 | -| **Total** | **27,756** | +| **Total** | **27,917** | diff --git a/tests/test_track_b_ret_ledger_fix_round_6.py b/tests/test_track_b_ret_ledger_fix_round_6.py index d3456371c..513b0f684 100644 --- a/tests/test_track_b_ret_ledger_fix_round_6.py +++ b/tests/test_track_b_ret_ledger_fix_round_6.py @@ -610,7 +610,9 @@ def test_each_reason_classifies_a_lower_rib(reason): @pytest.mark.parametrize("reason", list(UR), ids=lambda reason: reason.value) @pytest.mark.parametrize("kind", ["dib", "rib"]) -def test_only_finality_lifts_an_nh_rate_cap(reason, kind): +def test_only_finality_lifts_an_nh_rate_cap_outside_money_history_scope( + reason, kind +): # Cohort 1927 sits past the money-history scope that round 7 opens. pia = F(400) case = ( diff --git a/tests/test_track_b_ret_ledger_fix_round_7.py b/tests/test_track_b_ret_ledger_fix_round_7.py index 50b1b8825..87d33e642 100644 --- a/tests/test_track_b_ret_ledger_fix_round_7.py +++ b/tests/test_track_b_ret_ledger_fix_round_7.py @@ -93,7 +93,15 @@ def _deferred(reason): def _rib_record( - pia, gross, *, reason=None, cohort=None, months=8, conditions=() + pia, + gross, + *, + reason=None, + cohort=None, + months=8, + conditions=(), + credits=0, + year=2000, ): state = g.RecordState( g.FamilyKind.RETIREMENT, @@ -103,6 +111,7 @@ def _rib_record( g.OwnBenefitKind.OLD_AGE, pia, reduction_months=months, + delayed_credit_months=credits, birth_year=cohort, ), worker_birth_year=cohort, @@ -110,7 +119,7 @@ def _rib_record( deferred_refusal=_deferred(reason), ) return r.RecordYear( - 2000, + year, "nh", r.RecordKind.RETIREMENT, ( @@ -184,6 +193,9 @@ def _mother_record( year=2000, eligibility=1990, maximum=None, + credits=0, + conditions=(), + member_conditions=(), ): state = g.RecordState( g.FamilyKind.SURVIVOR, @@ -191,6 +203,7 @@ def _mother_record( g.floor_dime(pia * F(3, 2)) if maximum is None else maximum, eligibility_year=eligibility, widow_drc_savings_clause=False, + conditions=conditions, deferred_refusal=_deferred(reason), ) members = ( @@ -202,8 +215,10 @@ def _mother_record( g.OwnBenefitKind.OLD_AGE, own, reduction_months=months, + delayed_credit_months=credits, birth_year=cohort, ), + conditions=member_conditions, ), g.Beneficiary("c", g.Role.CHILD), ) @@ -259,7 +274,15 @@ def _f2_settled(birth, year, month, *, conditions=(), reason=None): def _f6_settled( - role, reason, cohort, *, pia=F(480), months=12, kind=None, own_pia=F(400) + role, + reason, + cohort, + *, + pia=F(480), + months=12, + kind=None, + own_pia=F(400), + credits=0, ): state = g.RecordState( g.FamilyKind.SURVIVOR, @@ -277,6 +300,7 @@ def _f6_settled( g.OwnBenefitKind.OLD_AGE if kind is None else kind, own_pia, reduction_months=months, + delayed_credit_months=credits, birth_year=cohort, ), own_benefit_first=True if role in SPOUSE_ROLES else None, @@ -492,7 +516,7 @@ def test_history_leaves_a_dib_cap_alone(reason, birth): def test_history_keeps_every_rate_in_its_scope( pia, months, cohort, reason, gap ): - gross = max(F(0), _ordinary(pia, months) + gap) + gross = min(pia, max(F(0), _ordinary(pia, months) + gap)) _assert_refusal( _rib_record(pia, gross, reason=reason, cohort=cohort, months=months), reason, @@ -693,10 +717,11 @@ def test_f6_matches_a_table_written_from_the_sources( and role in (g.Role.MOTHER_FATHER, g.Role.PARENT) and (cohort is None or cohort < 1928) ) - # A known cohort refuses its own history whatever the record declares. + # A known cohort refuses its own history whatever the record declares, + # and a zero PIA fails every RIB on every filling. implicit_history = months > 0 and cohort is not None and cohort < 1916 - expected_open = implicit_history or ( - pia > 0 and (money_history or carryover) + expected_open = pia > 0 and ( + implicit_history or money_history or carryover ) settled = _f6_settled(role, reason, cohort, months=months, pia=pia) assert settled is not expected_open @@ -752,13 +777,16 @@ def test_before_age_50_a_dib_below_the_pia_raises( "birth,year,month,keeps", [ (1974, 2023, 12, False), - (1974, 2024, 1, True), + (1974, 2024, 1, False), + (1974, 2024, 2, True), + (1973, 2023, 1, False), + (1973, 2023, 2, True), (1973, 2023, 12, True), (1960, 2024, 1, True), (None, 2024, 1, True), ], ) -def test_the_floor_opens_in_january_of_the_year_a_cohort_turns_50( +def test_the_floor_opens_the_month_after_a_cohort_turns_50( conditions, reason, named, birth, year, month, keeps ): pia = F(405) @@ -829,8 +857,10 @@ def test_the_floor_needs_a_cohort_and_a_month(): "birth,year,month,settled", [ (1927, 1976, 12, True), - (1927, 1977, 1, False), - (1926, 1976, 12, False), + (1927, 1977, 1, True), + (1927, 1977, 2, False), + (1926, 1976, 1, True), + (1926, 1976, 2, False), (1928, 1990, 1, True), ], ) @@ -859,6 +889,7 @@ def test_a_pre_1978_hold_needs_both_the_cohort_and_the_age( ) @example(birth=1974, year=2023, month=12, hold=DUAL) @example(birth=1974, year=2024, month=1, hold=DUAL) +@example(birth=1974, year=2024, month=2, hold=DUAL) @settings(max_examples=250, deadline=None) def test_f2_matches_a_table_written_from_the_sources(birth, year, month, hold): if hold in ( @@ -868,7 +899,7 @@ def test_f2_matches_a_table_written_from_the_sources(birth, year, month, hold): ): expected_open = True else: - expected_open = year >= birth + 50 + expected_open = (year, month) > (birth + 50, 1) if hold in PRE_1978_REASONS: expected_open = expected_open and birth < 1928 conditions, reason = ({hold}, None) if isinstance(hold, RC) else ((), hold) diff --git a/tests/test_track_b_ret_ledger_fix_round_8.py b/tests/test_track_b_ret_ledger_fix_round_8.py new file mode 100644 index 000000000..f90bf33c6 --- /dev/null +++ b/tests/test_track_b_ret_ledger_fix_round_8.py @@ -0,0 +1,505 @@ +"""Round 8: the PIA as a RIB's cap, zero thresholds and the first reduced DIB. + +Every record is invented or built from a captured SSA rule. Nothing here +admits a population, behavioral or forecast claim. +""" + +from __future__ import annotations + +from fractions import Fraction as F + +import pytest +from hypothesis import example, given, settings +from hypothesis import strategies as st + +from populace_dynamics.track_b import gross_benefits as g +from tests.test_track_b_ret_ledger_fix_round_7 import ( + AGE_FREE_HOLDS, + AMOUNT_TEST_ROLES, + DUAL, + OWN_HISTORY, + PRE_1978_REASONS, + PRIOR_REDUCED_HOLDS, + RC, + REDUCED_HISTORY, + UR, + _assert_invalid, + _assert_preflight_neutral, + _assert_refusal, + _deferred, + _dib_record, + _f6_settled, + _mother_record, + _rib_record, +) +from tests.track_b_gross_benefit_support import source_text, ssa_params + +ENTITLEMENT = "auxiliary entitlement facts differ" +BC = g.BeneficiaryCondition +HOLDS_PLUS_NONE = (None, OWN_HISTORY, REDUCED_HISTORY, DUAL) +# Each row: cohort, payment year, payment month, whether a reduced benefit +# could precede that month. RS 00615.005A.1-A.4 date the routes, and the +# route each row turns on sits in its comment. +ROUTE_ROWS = ( + # No reduced DIB exists before A.3's 9/65, on any route. + (1900, 1965, 8, False), + (None, 1965, 8, False), + (1908, 1958, 2, False), + # A.1: a RIB at 62 from 11/56. Its first month need only come first. + (1903, 1965, 9, True), + (None, 1965, 9, True), + (1904, 1965, 9, False), + # A.3: a WIB at 60 from 9/65, one month before the DIB. + (1904, 1965, 10, True), + (1905, 1965, 10, True), + (1907, 1967, 1, False), + (1907, 1967, 2, True), + (1908, 1968, 1, False), + (1908, 1968, 2, True), + # A.4: a disabled WIB at 50 from 2/68, one month before the DIB. + (1916, 1966, 2, False), + (1918, 1968, 2, False), + (1918, 1968, 3, True), + (1910, 1968, 2, False), + (1910, 1968, 3, True), + (1974, 2024, 1, False), + (1974, 2024, 2, True), + (None, 2024, 1, True), +) + + +def _first_month_dib(pia, gross, birth, year, month, *, maximum=None, **holds): + return _dib_record( + pia, + gross, + birth=birth, + year=year, + month=month, + maximum=maximum, + first=g.YearMonth(year, month), + **holds, + ) + + +def test_the_captures_carry_each_quoted_rule(): + reduced = source_text("poms_rs_00615_005") + for quote in ( + "1956 Amendments Effective 11/56", + "1965 Amendments Effective 9/65", + "Allowed entitlement to reduced DIB after entitlement to reduced " + "RIB or reduced WIB.", + "1967 Amendments Effective 2/68", + "The new money amount of reduction is subtracted from the new PIA", + ): + assert quote in reduced + assert ( + "months of WIB entitlement before the first MOET to DIB." + in source_text("poms_rs_00615_010") + ) + + +@pytest.mark.parametrize("reason", PRE_1978_REASONS) +@pytest.mark.parametrize("cohort", [None, 1900, 1915]) +@pytest.mark.parametrize( + "pia,gross,months", + [("333.30", "333.40", 8), ("1000", "1000.10", 2), ("0.10", "0.20", 1)], +) +def test_history_leaves_a_rib_at_or_below_its_pia( + reason, cohort, pia, gross, months +): + _assert_invalid( + _rib_record( + F(pia), F(gross), reason=reason, cohort=cohort, months=months + ) + ) + + +@pytest.mark.parametrize("reason", PRE_1978_REASONS) +@pytest.mark.parametrize("cohort", [None, 1915]) +def test_a_rate_at_the_pia_keeps_its_history_row(reason, cohort): + pia = F("333.30") + case = _rib_record(pia, pia, reason=reason, cohort=cohort) + _assert_refusal(case, reason) + _assert_preflight_neutral(case) + + +@pytest.mark.parametrize("cohort", [1900, 1915]) +def test_a_known_cohort_keeps_the_pia_cap_with_no_declaration(cohort): + pia = F("333.30") + _assert_invalid(_rib_record(pia, pia + F(1, 10), cohort=cohort)) + _assert_refusal(_rib_record(pia, pia, cohort=cohort), OWN_HISTORY) + + +@pytest.mark.parametrize( + "conditions,reason", + [ + ({RC.WORKERS_COMPENSATION_OFFSET}, None), + ((), UR.WORKERS_COMPENSATION_OFFSET), + ((), DUAL), + ((), UR.DELAYED_CREDITS_BEFORE_1917), + ], +) +def test_no_other_hold_lifts_a_known_cohort_past_the_pia(conditions, reason): + pia = F("333.30") + _assert_invalid( + _rib_record( + pia, + pia + F(1, 10), + conditions=conditions, + reason=reason, + cohort=1915, + ) + ) + + +@pytest.mark.parametrize("reason", (None,) + PRE_1978_REASONS) +@pytest.mark.parametrize("cohort", [None, 1915]) +def test_finality_can_lift_a_rib_past_its_pia(reason, cohort): + pia = F("333.30") + case = _rib_record( + pia, + pia + F(1, 10), + conditions={RC.ADMINISTRATIVE_FINALITY}, + reason=reason, + cohort=cohort, + ) + _assert_refusal(case, UR.ADMINISTRATIVE_FINALITY) + _assert_preflight_neutral(case) + + +@pytest.mark.parametrize("cohort", [None, 1915]) +def test_a_deferred_finality_can_lift_a_rib_past_its_pia(cohort): + pia = F("333.30") + _assert_refusal( + _rib_record( + pia, + pia + F(1, 10), + reason=UR.ADMINISTRATIVE_FINALITY, + cohort=cohort, + ), + UR.ADMINISTRATIVE_FINALITY, + ) + + +@pytest.mark.parametrize("reason", PRE_1978_REASONS) +def test_delayed_credits_can_lift_a_history_rib_past_its_pia(reason): + pia = F("333.30") + case = _rib_record( + pia, pia + F(1, 10), reason=reason, cohort=1915, credits=12 + ) + _assert_refusal(case, reason) + _assert_preflight_neutral(case) + + +def test_a_month_before_1983_leaves_the_rate_unsettled_past_the_pia(): + pia = F("333.30") + case = _rib_record( + pia, pia + F(1, 10), reason=OWN_HISTORY, cohort=1915, year=1982 + ) + _assert_refusal(case, OWN_HISTORY) + + +@given( + pia=st.integers(1, 30_000).map(lambda n: F(n, 10)), + months=st.integers(1, 36), + cohort=st.sampled_from((None, 1900, 1913, 1915)), + reason=st.sampled_from(PRE_1978_REASONS + (None,)), + gap=st.integers(1, 40).map(lambda n: F(n, 10)), +) +@example( + pia=F("0.10"), months=1, cohort=None, reason=OWN_HISTORY, gap=F(1, 10) +) +@settings(max_examples=150, deadline=None) +def test_no_history_admits_a_rib_above_its_pia( + pia, months, cohort, reason, gap +): + case = _rib_record( + pia, pia + gap, reason=reason, cohort=cohort, months=months + ) + _assert_invalid(case) + + +@pytest.mark.parametrize("reason", HOLDS_PLUS_NONE) +@pytest.mark.parametrize("cohort", [1900, 1915]) +@pytest.mark.parametrize("own,months", [("0.10", 1), ("400", 12)]) +def test_a_zero_pia_fails_a_known_cohorts_rib(reason, cohort, own, months): + _assert_invalid( + _mother_record( + reason, + cohort=cohort, + pia=F(0), + own=F(own), + months=months, + gross=F(0), + ), + ENTITLEMENT, + ) + + +@pytest.mark.parametrize("reason", (None, UR.DELAYED_CREDITS_BEFORE_1917)) +def test_a_zero_pia_fails_a_rib_with_early_credits(reason): + _assert_invalid( + _mother_record( + reason, cohort=1915, pia=F(0), months=0, credits=12, gross=F(0) + ), + ENTITLEMENT, + ) + + +@pytest.mark.parametrize("reason", (None, OWN_HISTORY)) +@pytest.mark.parametrize("pia", ["0.10", "480"]) +def test_a_positive_threshold_keeps_the_own_history_row(reason, pia): + case = _mother_record( + reason, cohort=1915, pia=F(pia), own=F("0.10"), months=1, gross=F(0) + ) + _assert_refusal(case, OWN_HISTORY) + _assert_preflight_neutral(case) + + +@pytest.mark.parametrize("pia", ["0.10", "480"]) +def test_early_credits_keep_their_row_on_a_positive_threshold(pia): + case = _mother_record( + None, + cohort=1915, + pia=F(pia), + own=F("0.10"), + months=0, + credits=12, + gross=F(0), + ) + _assert_refusal(case, UR.DELAYED_CREDITS_BEFORE_1917) + + +@pytest.mark.parametrize( + "holds,named", + [ + ( + {"conditions": {RC.ADMINISTRATIVE_FINALITY}}, + UR.ADMINISTRATIVE_FINALITY, + ), + ({"member_conditions": {BC.RATE_PROTECTED_BY_FINALITY}}, OWN_HISTORY), + ], +) +def test_finality_keeps_a_zero_threshold_row(holds, named): + case = _mother_record( + None, + cohort=1915, + pia=F(0), + own=F("0.10"), + months=1, + gross=F(0), + **holds, + ) + _assert_refusal(case, named) + + +def test_a_deferred_finality_keeps_a_zero_threshold_row(): + case = _mother_record( + UR.ADMINISTRATIVE_FINALITY, + cohort=1915, + pia=F(0), + own=F("0.10"), + months=1, + gross=F(0), + ) + _assert_refusal(case, UR.ADMINISTRATIVE_FINALITY) + + +@pytest.mark.parametrize("role", AMOUNT_TEST_ROLES) +@pytest.mark.parametrize("reason", (None, OWN_HISTORY)) +def test_a_zero_threshold_settles_every_actual_rib_test(role, reason): + assert _f6_settled(role, reason, 1915, pia=F(0), months=1) is True + assert _f6_settled(role, reason, 1915, pia=F("0.10"), months=1) is False + + +@pytest.mark.parametrize("role", AMOUNT_TEST_ROLES) +def test_only_a_zero_threshold_settles_a_rib_with_early_credits(role): + def settled(pia): + return _f6_settled( + role, + UR.DELAYED_CREDITS_BEFORE_1917, + 1915, + pia=pia, + months=0, + credits=12, + ) + + assert settled(F(0)) is True + assert settled(F("0.10")) is False + + +def test_a_deemed_pia_keeps_a_known_cohorts_history_open(): + state = g.RecordState( + g.FamilyKind.SURVIVOR, + F(0), + F(0), + eligibility_year=1990, + widow_drc_savings_clause=False, + ) + member = g.Beneficiary( + "w", + g.Role.DISABLED_WIDOW, + birth_year=1915, + original_benefit_basis=F(100), + own_benefit=g.OwnBenefit( + g.OwnBenefitKind.OLD_AGE, + F(400), + reduction_months=12, + birth_year=1915, + ), + ) + assert not g._fact_is_settled( + "F6", + state, + member, + payment_month=g.YearMonth(2000, 1), + beneficiaries=(member,), + params=ssa_params(), + ) + + +@given( + pia=st.integers(0, 30_000).map(lambda n: F(n, 10)), + own=st.integers(1, 30_000).map(lambda n: F(n, 10)), + months=st.integers(1, 36), + cohort=st.integers(1900, 1915), + reason=st.sampled_from(HOLDS_PLUS_NONE), +) +@example(pia=F(0), own=F("0.10"), months=1, cohort=1915, reason=None) +@example(pia=F("0.10"), own=F("0.10"), months=1, cohort=1915, reason=None) +@settings(max_examples=120, deadline=None) +def test_only_a_zero_threshold_rules_out_a_history_rib( + pia, own, months, cohort, reason +): + case = _mother_record( + reason, cohort=cohort, pia=pia, own=own, months=months, gross=F(0) + ) + if pia == 0: + _assert_invalid(case, ENTITLEMENT) + else: + _assert_refusal(case, reason or OWN_HISTORY) + + +@pytest.mark.parametrize("birth,year,month,possible", ROUTE_ROWS) +def test_each_route_dates_the_first_reduced_dib(birth, year, month, possible): + assert ( + g._prior_reduced_benefit_possible(birth, g.YearMonth(year, month)) + is possible + ) + + +def test_an_unknown_month_leaves_every_route_open(): + assert g._prior_reduced_benefit_possible(1990, None) is True + assert g._prior_reduced_benefit_possible(None, None) is True + + +@given( + birth=st.one_of(st.none(), st.integers(1880, 2005)), + year=st.integers(1955, 2060), + month=st.integers(1, 12), +) +@example(birth=1974, year=2024, month=1) +@example(birth=1903, year=1965, month=9) +@example(birth=1905, year=1965, month=10) +@settings(max_examples=400, deadline=None) +def test_the_floor_matches_month_counts_written_from_the_sources( + birth, year, month +): + payment = year * 12 + month + if payment < 1965 * 12 + 9: + expected = False + elif birth is None: + expected = True + else: + rib = max(1956 * 12 + 11, (birth + 62) * 12 + 1) + widow = max(1965 * 12 + 9, (birth + 60) * 12 + 1) + disabled_widow = max(1968 * 12 + 2, (birth + 50) * 12 + 1) + expected = min(rib, widow, disabled_widow) < payment + assert ( + g._prior_reduced_benefit_possible(birth, g.YearMonth(year, month)) + is expected + ) + + +@pytest.mark.parametrize("conditions,reason,named", PRIOR_REDUCED_HOLDS) +@pytest.mark.parametrize( + "pia,gross", [(F(405), F("404.90")), (F("0.10"), F(0))] +) +def test_a_modern_january_of_cohort_plus_50_has_one_dib_rate( + conditions, reason, named, pia, gross +): + holds = {"conditions": conditions, "reason": reason, "maximum": pia} + _assert_invalid(_first_month_dib(pia, gross, 1974, 2024, 1, **holds)) + _assert_refusal(_first_month_dib(pia, pia, 1974, 2024, 1, **holds), named) + case = _first_month_dib(pia, gross, 1974, 2024, 2, **holds) + _assert_refusal(case, named) + _assert_preflight_neutral(case) + + +@pytest.mark.parametrize("conditions,reason,named", PRIOR_REDUCED_HOLDS) +@pytest.mark.parametrize( + "birth,year", [(1908, 1958), (1916, 1966), (1918, 1968)] +) +@pytest.mark.parametrize( + "pia,gross", [(F(100), F("99.90")), (F("0.10"), F(0))] +) +def test_before_a_route_exists_a_dib_rate_equals_its_pia_or_raises( + conditions, reason, named, birth, year, pia, gross +): + holds = {"conditions": conditions, "reason": reason} + _assert_invalid(_first_month_dib(pia, gross, birth, year, 2, **holds)) + case = _first_month_dib(pia, pia, birth, year, 2, **holds) + _assert_refusal(case, UR.ELIGIBILITY_BEFORE_1983) + + +@pytest.mark.parametrize("conditions,reason,named", PRIOR_REDUCED_HOLDS) +def test_a_historical_route_keeps_its_row_once_it_opens( + conditions, reason, named +): + case = _first_month_dib( + F(100), F("99.90"), 1918, 1968, 3, conditions=conditions, reason=reason + ) + _assert_refusal(case, UR.ELIGIBILITY_BEFORE_1983) + _assert_preflight_neutral(case) + + +@pytest.mark.parametrize("conditions,reason,named", AGE_FREE_HOLDS) +@pytest.mark.parametrize( + "birth,year", [(1908, 1958), (1918, 1968), (1974, 2024)] +) +def test_a_hold_that_needs_no_predecessor_keeps_its_row( + conditions, reason, named, birth, year +): + case = _first_month_dib( + F(100), + F("99.90"), + birth, + year, + 1, + conditions=conditions, + reason=reason, + ) + outcome_reason = UR.ELIGIBILITY_BEFORE_1983 if year < 1983 else named + _assert_refusal(case, outcome_reason) + _assert_preflight_neutral(case) + + +@pytest.mark.parametrize("reason", PRE_1978_REASONS) +def test_a_pre_1978_hold_shares_the_first_route(reason): + assert ( + g._fact_is_settled( + "F2", + g.RecordState( + g.FamilyKind.DISABILITY, + F(100), + F(150), + worker_birth_year=1918, + eligibility_year=1968, + first_dib_entitlement=g.YearMonth(1968, 2), + deferred_refusal=_deferred(reason), + ), + payment_month=g.YearMonth(1968, 2), + params=ssa_params(), + ) + is True + ) diff --git a/tests/tier_counts.json b/tests/tier_counts.json index aa07d4b42..bade4ba34 100644 --- a/tests/tier_counts.json +++ b/tests/tier_counts.json @@ -1,7 +1,7 @@ { "schema_version": 1, "counts": { - "unit": 21186, + "unit": 21347, "artifact": 4271, "integration_psid": 1471, "reproduction_legacy": 520, From 40f2c176a5817f9580ecdf77e8494b3c39c51997 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 1 Nov 2026 16:05:50 -0500 Subject: [PATCH 14/17] Track B R2: read the child-in-care minimum under the month's deductions Sol's eighth review of aa86a4da found two mediums, and both reproduced. - The child-in-care minimum read the family before the month's deductions. 402(q)(5)(D) sets it by what a mother or father would get "for such month". A child's full deduction frees room, so a mother takes more and a widow did not: $0.80 where the rule pays $1.00, and $612.80 where it pays $750. The comparison now takes the month's events and households, each caregiver compares alone, and a deductee keeps the ordinary minimum. - RET skipped G on an unbound month. A surviving divorced spouse sits outside the actual maximum and the mother it compares with sits inside, so the comparison can bind when the actual maximum doesn't. RET now reaches G wherever a minimum can move, and asks for family facts by the existing refusal where it has none. - A partial deduction refuses by name where it can move the rate. No capture carries a partial amount to a comparison rate, so the ordinary and all-full comparisons bound every reading, and only a rate at or above the higher one computes. - A month before 1983 keeps the PIA cap. Upward dime rounding can't pass a PIA G holds to dimes, so a no-credit RIB above its PIA raises and leaves no row. Finality and positive credits keep their rows. Money moves for child-in-care widow(er)s on a month with another person's deduction, and only theirs. The conformance lattice stays identical, with one new named witness. Invariants: the minimum equals the better of the reduced rate and what a mother or father receives this month. It moves only the caregiver's own money. A partial deduction computes only where every amount between the two bounds agrees. RET asks for family facts exactly where a minimum can move. With no delayed credits, no RIB exceeds its PIA in any month. Co-Authored-By: Claude Opus 5.5 --- docs/design/track_b_g2_r2b_mutations.json | 1948 ++++++++++++++++- docs/design/track_b_g2_r2b_verification.json | 80 +- docs/design/track_b_g_conformance_report.json | 12 +- docs/design/track_b_g_gross_benefits.md | 7 +- docs/design/track_b_r2_ret_ledger.md | 133 +- scripts/track_b_g_conformance_report.py | 31 + .../track_b/gross_benefits.py | 174 +- src/populace_dynamics/track_b/ret_ledger.py | 34 +- tests/README-tiers.md | 4 +- tests/test_track_b_gross_benefits.py | 25 + ...ack_b_gross_benefits_conformance_report.py | 6 +- tests/test_track_b_ret_ledger_fix_round_8.py | 4 +- tests/test_track_b_ret_ledger_fix_round_9.py | 961 ++++++++ tests/tier_counts.json | 2 +- 14 files changed, 3387 insertions(+), 34 deletions(-) create mode 100644 tests/test_track_b_ret_ledger_fix_round_9.py diff --git a/docs/design/track_b_g2_r2b_mutations.json b/docs/design/track_b_g2_r2b_mutations.json index b017499f7..f1cedc4e5 100644 --- a/docs/design/track_b_g2_r2b_mutations.json +++ b/docs/design/track_b_g2_r2b_mutations.json @@ -2,12 +2,12 @@ "schema_version": 1, "verification_class": "statutory_conformance", "admitted_scope": "Mutation sensitivity of statutory rules on invented and captured worked cases only; no population, behavioral or forecast claim.", - "confirmed_mutation_count": 199, + "confirmed_mutation_count": 233, "counts_by_layer": { "g_deductions": 18, - "g_preflight": 126, + "g_preflight": 149, "g_savings": 12, - "r2": 42, + "r2": 53, "shared_provenance": 1 }, "environment_contract": { @@ -11342,6 +11342,1942 @@ } }, "layer": "g_preflight" + }, + { + "id": "round9-can_move_adds_unentitled", + "round": 9, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": [ + { + "before": " entitled = [b for b in record.beneficiaries if month in b.entitled_months]\n", + "after": " entitled = list(record.beneficiaries)\n" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_no_minimum_can_move_on_these_records[child", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_no_minimum_can_move_on_these_records[survivor" + ], + "failed_test_count": 2, + "log": { + "path": "scratch/review/round9-mutations/can_move_adds_unentitled.log", + "sha256": "8e7baf6782209ea1cca3a877c204eddbe425952f7296fbf4d3ad04f6422757c2", + "failure_summary": "2 failed, 208 passed in 11.87s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "r2" + }, + { + "id": "round9-can_move_any_benefit_type", + "round": 9, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": [ + { + "before": " and b.benefit_types[month - 1] in (BenefitType.WIDOW, BenefitType.DWB)\n", + "after": "" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_no_minimum_can_move_on_these_records[a" + ], + "failed_test_count": 1, + "log": { + "path": "scratch/review/round9-mutations/can_move_any_benefit_type.log", + "sha256": "254357a7e2d236defdd8b08058582dad09ff3e468112c3d53307371cf6766d9a", + "failure_summary": "1 failed, 209 passed in 12.55s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "r2" + }, + { + "id": "round9-can_move_any_rate", + "round": 9, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": [ + { + "before": " and b.gross_rates[month - 1] < b.original_rates[month - 1]\n", + "after": "" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_an_unreduced_survivor_needs_no_family_facts" + ], + "failed_test_count": 1, + "log": { + "path": "scratch/review/round9-mutations/can_move_any_rate.log", + "sha256": "fa85447148a5ac45275bab66d10582e5e080704aeb645d12e8ecbb00f6d0056e", + "failure_summary": "1 failed, 209 passed in 11.45s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "r2" + }, + { + "id": "round9-can_move_any_record", + "round": 9, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": [ + { + "before": " if record.kind is not RecordKind.DECEASED:\n return False\n context = record.family_months.get(month)\n", + "after": " context = record.family_months.get(month)\n" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_living_workers_record_has_no_care_minimum" + ], + "failed_test_count": 1, + "log": { + "path": "scratch/review/round9-mutations/can_move_any_record.log", + "sha256": "306c2bd5af81aca564224269798e7de044b10a5e24a3f75e5e274917722e2537", + "failure_summary": "1 failed, 209 passed in 11.24s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "r2" + }, + { + "id": "round9-can_move_counts_the_deductee", + "round": 9, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": [ + { + "before": " b.beneficiary_id not in deductees\n and b.benefit_types[month - 1] in (BenefitType.WIDOW, BenefitType.DWB)\n", + "after": " b.benefit_types[month - 1] in (BenefitType.WIDOW, BenefitType.DWB)\n" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_no_minimum_can_move_on_these_records[the" + ], + "failed_test_count": 1, + "log": { + "path": "scratch/review/round9-mutations/can_move_counts_the_deductee.log", + "sha256": "fedaacc384014658afa2b195c8efdf71df8fb57a5bf180a799c815956acdc0ad", + "failure_summary": "1 failed, 209 passed in 11.58s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "r2" + }, + { + "id": "round9-can_move_equal_rate", + "round": 9, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": [ + { + "before": " and b.gross_rates[month - 1] < b.original_rates[month - 1]\n", + "after": " and b.gross_rates[month - 1] <= b.original_rates[month - 1]\n" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_an_unreduced_survivor_needs_no_family_facts" + ], + "failed_test_count": 1, + "log": { + "path": "scratch/review/round9-mutations/can_move_equal_rate.log", + "sha256": "40dcf9b2203a8f876c17e149117da9a32596f1330df6e04f4fca12589cb6ea76", + "failure_summary": "1 failed, 209 passed in 11.17s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "r2" + }, + { + "id": "round9-can_move_needs_no_child", + "round": 9, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": [ + { + "before": " return any(\n b.benefit_types[month - 1] in (BenefitType.CHILD, BenefitType.CDB)\n for b in entitled\n ) and any(\n", + "after": " return any(\n" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_no_minimum_can_move_on_these_records[no", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_no_minimum_can_move_on_these_records[child" + ], + "failed_test_count": 2, + "log": { + "path": "scratch/review/round9-mutations/can_move_needs_no_child.log", + "sha256": "e49848f2988f12905a4b7a4b21c163b0336747d6f219ad2d4fdc263e91a3a662", + "failure_summary": "2 failed, 208 passed in 11.77s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "r2" + }, + { + "id": "round9-can_move_no_context", + "round": 9, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": [ + { + "before": " return bool(g._current_caregivers(context.beneficiaries))\n", + "after": " return False\n" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_ret_pays_the_minimum_on_a_month_with_no_binding_maximum" + ], + "failed_test_count": 1, + "log": { + "path": "scratch/review/round9-mutations/can_move_no_context.log", + "sha256": "95d183f879ba22023cfdf6370f46c0dde27e14a14c5700279975ee62cfa41256", + "failure_summary": "1 failed, 209 passed in 11.33s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "r2" + }, + { + "id": "round9-can_move_widow_type_only", + "round": 9, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": [ + { + "before": " and b.benefit_types[month - 1] in (BenefitType.WIDOW, BenefitType.DWB)\n", + "after": " and b.benefit_types[month - 1] is BenefitType.WIDOW\n" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_reduced_survivor_beside_a_child_needs_the_family_facts[BenefitType.DWB]" + ], + "failed_test_count": 1, + "log": { + "path": "scratch/review/round9-mutations/can_move_widow_type_only.log", + "sha256": "5ecb377d4342b607ebd8c8792f6ec7ebc696a88210e826d772615ae0e309be0b", + "failure_summary": "1 failed, 209 passed in 12.45s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "r2" + }, + { + "id": "round9-cap_drops_before_1983", + "round": 9, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " UnsupportedReason.DELAYED_CREDITS_BEFORE_1917,\n UnsupportedReason.PAYMENT_MONTH_BEFORE_1983,\n}\n", + "after": " UnsupportedReason.DELAYED_CREDITS_BEFORE_1917,\n}\n" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_rib_above_its_pia_is_an_input_error_before_1983[0-0.10-0.20-1981]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_rib_above_its_pia_is_an_input_error_before_1983[0-0.10-0.20-1982]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_rib_above_its_pia_is_an_input_error_before_1983[0-400-400.10-1981]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_rib_above_its_pia_is_an_input_error_before_1983[0-400-400.10-1982]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_rib_above_its_pia_is_an_input_error_before_1983[0-1000-1000.10-1981]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_rib_above_its_pia_is_an_input_error_before_1983[0-1000-1000.10-1982]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_rib_above_its_pia_is_an_input_error_before_1983[8-0.10-0.20-1981]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_rib_above_its_pia_is_an_input_error_before_1983[8-0.10-0.20-1982]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_rib_above_its_pia_is_an_input_error_before_1983[8-400-400.10-1981]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_rib_above_its_pia_is_an_input_error_before_1983[8-400-400.10-1982]" + ], + "failed_test_count": 14, + "log": { + "path": "scratch/review/round9-mutations/cap_drops_before_1983.log", + "sha256": "4630db61ec66757860af3f86126c77d391fe7c77f0fdfc1868fad1155ad46fff", + "failure_summary": "14 failed, 196 passed in 11.70s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "g_preflight" + }, + { + "id": "round9-caregivers_any_flag", + "round": 9, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " if member.role in _WIDOW_ROLES\n and isinstance(member.child_in_care, str)\n", + "after": " if member.role in _WIDOW_ROLES\n and member.child_in_care is not None\n" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_full_deduction_raises_the_care_minimum[1.40-2.10-60-0.80-1-1]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_full_deduction_raises_the_care_minimum[4-6-60-2.40-3-3]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_full_deduction_raises_the_care_minimum[1000-1500-60-612.80-750-750]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_full_deduction_raises_the_care_minimum[0.30-0.40-1-0.10-0.20-0]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_partial_deduction_computes_or_refuses_within_bounds", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_ret_leaves_a_family_with_no_care_alone", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_with_no_caregiver_an_unbound_month_matches_g" + ], + "failed_test_count": 7, + "log": { + "path": "scratch/review/round9-mutations/caregivers_any_flag.log", + "sha256": "042afaff1b9653f6580ee7f079f31393feb622b9b0342ccbb96a1f19e4adb9d3", + "failure_summary": "7 failed, 203 passed in 24.98s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "g_preflight" + }, + { + "id": "round9-caregivers_any_role", + "round": 9, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " if member.role in _WIDOW_ROLES\n and isinstance(member.child_in_care, str)\n", + "after": " if isinstance(member.child_in_care, str)\n" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_living_workers_divorced_spouse_has_no_care_minimum" + ], + "failed_test_count": 1, + "log": { + "path": "scratch/review/round9-mutations/caregivers_any_role.log", + "sha256": "b8ba1ce3f5f0bb8d0578e46819dabb77fe78fa5486ec8e50d7bcface4a8fca50", + "failure_summary": "1 failed, 209 passed in 10.75s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "g_preflight" + }, + { + "id": "round9-ceiling_never_refuses", + "round": 9, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " if minimum.ceiling > age_adjusted:\n", + "after": " if False:\n" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_partial_deduction_refuses_where_it_can_move_the_rate", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_partial_deduction_refuses_outside_the_maximum_too", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_full_and_a_partial_event_share_the_partial_refusal", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_partial_deduction_computes_or_refuses_within_bounds", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_ret_refuses_a_partial_month_the_minimum_turns_on" + ], + "failed_test_count": 5, + "log": { + "path": "scratch/review/round9-mutations/ceiling_never_refuses.log", + "sha256": "49d639ace739d703600fa50f045079512d292ea547c9a73c9c95aa40f01119ca", + "failure_summary": "5 failed, 205 passed in 36.65s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "g_preflight" + }, + { + "id": "round9-ceiling_refuses_at_equality", + "round": 9, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " if minimum.ceiling > age_adjusted:\n", + "after": " if minimum.ceiling >= age_adjusted:\n" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_full_deduction_raises_the_care_minimum[1.40-2.10-60-0.80-1-1]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_full_deduction_raises_the_care_minimum[4-6-60-2.40-3-3]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_full_deduction_raises_the_care_minimum[1000-1500-60-612.80-750-750]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_full_deduction_raises_the_care_minimum[0.30-0.40-1-0.10-0.20-0]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_the_minimum_moves_only_the_caregivers_own_money", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_temporary_deduction_reaches_only_its_own_household", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_divorced_caregiver_outside_the_maximum_keeps_the_minimum", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_disabled_widow_reaches_the_same_minimum", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_each_caregiver_compares_alone", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_deduction_on_one_caregiver_raises_the_others_minimum" + ], + "failed_test_count": 17, + "log": { + "path": "scratch/review/round9-mutations/ceiling_refuses_at_equality.log", + "sha256": "0ea59c636ab8db100672820439f2fc50b0005bc8e5629dd7f8643d76634116b8", + "failure_summary": "17 failed, 193 passed in 7.88s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "g_preflight" + }, + { + "id": "round9-comparison_drops_events", + "round": 9, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " bid: _replace_declared(event, payable=Fraction(0))\n for bid, event in events.items()\n", + "after": " bid: _replace_declared(event, payable=Fraction(0))\n for bid, event in ()\n" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_full_deduction_raises_the_care_minimum[1.40-2.10-60-0.80-1-1]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_full_deduction_raises_the_care_minimum[4-6-60-2.40-3-3]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_full_deduction_raises_the_care_minimum[1000-1500-60-612.80-750-750]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_full_deduction_raises_the_care_minimum[0.30-0.40-1-0.10-0.20-0]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_temporary_deduction_reaches_only_its_own_household", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_divorced_caregiver_outside_the_maximum_keeps_the_minimum", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_disabled_widow_reaches_the_same_minimum", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_each_caregiver_compares_alone", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_deduction_on_one_caregiver_raises_the_others_minimum", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_partial_deduction_refuses_where_it_can_move_the_rate" + ], + "failed_test_count": 17, + "log": { + "path": "scratch/review/round9-mutations/comparison_drops_events.log", + "sha256": "d87e0153fbba9146c51a128ab89d706c06920d593d25f424fc8d16fe8a0eddc0", + "failure_summary": "17 failed, 193 passed in 5.44s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "g_preflight" + }, + { + "id": "round9-comparison_drops_households", + "round": 9, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " },\n households,\n {},\n )\n ceiling = highest.by_id()[cid].age_adjusted_rate\n", + "after": " },\n {},\n {},\n )\n ceiling = highest.by_id()[cid].age_adjusted_rate\n" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_temporary_deduction_reaches_only_its_own_household", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_partial_deduction_keeps_a_minimum_it_cannot_change", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_the_minimum_equals_the_better_of_the_two_public_families" + ], + "failed_test_count": 3, + "log": { + "path": "scratch/review/round9-mutations/comparison_drops_households.log", + "sha256": "926b970fdc29581edca61219bf68f864f0c5266cbb9af56f140f58e3ee5eb3c6", + "failure_summary": "3 failed, 207 passed in 32.57s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "g_preflight" + }, + { + "id": "round9-comparison_keeps_payable", + "round": 9, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " bid: _replace_declared(event, payable=Fraction(0))\n for bid, event in events.items()\n", + "after": " bid: event\n for bid, event in events.items()\n" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_partial_deduction_refuses_outside_the_maximum_too", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_partial_deduction_computes_or_refuses_within_bounds" + ], + "failed_test_count": 2, + "log": { + "path": "scratch/review/round9-mutations/comparison_keeps_payable.log", + "sha256": "a6c3620531c8201bb10c094a08a40b852aec3ff9d75e0fad19315feac7a31d0c", + "failure_summary": "2 failed, 208 passed in 25.73s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "g_preflight" + }, + { + "id": "round9-deductee_caregiver_compares", + "round": 9, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " if member.beneficiary_id not in events\n and by_id[member.beneficiary_id].entitled\n", + "after": " if by_id[member.beneficiary_id].entitled\n" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_deducted_caregiver_reaches_no_comparison" + ], + "failed_test_count": 1, + "log": { + "path": "scratch/review/round9-mutations/deductee_caregiver_compares.log", + "sha256": "de56418d0524f68f4e6aa52f7da472acfa48777d8a54141e94a532cd19db224d", + "failure_summary": "1 failed, 209 passed in 12.12s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "g_preflight" + }, + { + "id": "round9-every_event_settled", + "round": 9, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " settled = all(event.payable == 0 for event in events.values())\n", + "after": " settled = True\n" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_partial_deduction_refuses_where_it_can_move_the_rate", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_partial_deduction_refuses_outside_the_maximum_too", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_full_and_a_partial_event_share_the_partial_refusal", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_partial_deduction_computes_or_refuses_within_bounds", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_ret_refuses_a_partial_month_the_minimum_turns_on" + ], + "failed_test_count": 5, + "log": { + "path": "scratch/review/round9-mutations/every_event_settled.log", + "sha256": "358e3c8b6fef2c6591e29bd49e60c8f66bdb4713b961abb331c59fa24113f33e", + "failure_summary": "5 failed, 205 passed in 32.32s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "g_preflight" + }, + { + "id": "round9-floor_always_ordinary", + "round": 9, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " ceiling if settled else ordinary.by_id()[cid].age_adjusted_rate,\n", + "after": " ordinary.by_id()[cid].age_adjusted_rate,\n" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_full_deduction_raises_the_care_minimum[1.40-2.10-60-0.80-1-1]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_full_deduction_raises_the_care_minimum[4-6-60-2.40-3-3]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_full_deduction_raises_the_care_minimum[1000-1500-60-612.80-750-750]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_full_deduction_raises_the_care_minimum[0.30-0.40-1-0.10-0.20-0]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_the_minimum_moves_only_the_caregivers_own_money", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_temporary_deduction_reaches_only_its_own_household", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_divorced_caregiver_outside_the_maximum_keeps_the_minimum", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_disabled_widow_reaches_the_same_minimum", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_each_caregiver_compares_alone", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_deduction_on_one_caregiver_raises_the_others_minimum" + ], + "failed_test_count": 13, + "log": { + "path": "scratch/review/round9-mutations/floor_always_ordinary.log", + "sha256": "ce3bc40098aeaf9af3009081213b1fef6add85082e28abf8d31d72c5cf433591", + "failure_summary": "13 failed, 197 passed in 8.93s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "g_preflight" + }, + { + "id": "round9-nh_reaches_the_comparison", + "round": 9, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " if any(worker_deductions.values()):\n raise _computed(\n FamilyConfigurationUnsupported,\n UnsupportedReason.DEDUCTION_AGE_WORK_INTERACTION,\n \"Concurrent NH reservations and a child-in-care comparison have \"\n", + "after": " if False:\n raise _computed(\n FamilyConfigurationUnsupported,\n UnsupportedReason.DEDUCTION_AGE_WORK_INTERACTION,\n \"Concurrent NH reservations and a child-in-care comparison have \"\n" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_nh_reservations_refuse_on_a_comparison" + ], + "failed_test_count": 1, + "log": { + "path": "scratch/review/round9-mutations/nh_reaches_the_comparison.log", + "sha256": "356555e41043aff64b254357b3d100f75b34007750111941ba1a6e237607fa6b", + "failure_summary": "1 failed, 209 passed in 10.94s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "g_preflight" + }, + { + "id": "round9-no_event_settled", + "round": 9, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " settled = all(event.payable == 0 for event in events.values())\n", + "after": " settled = False\n" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_full_deduction_raises_the_care_minimum[1.40-2.10-60-0.80-1-1]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_full_deduction_raises_the_care_minimum[4-6-60-2.40-3-3]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_full_deduction_raises_the_care_minimum[1000-1500-60-612.80-750-750]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_full_deduction_raises_the_care_minimum[0.30-0.40-1-0.10-0.20-0]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_the_minimum_moves_only_the_caregivers_own_money", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_temporary_deduction_reaches_only_its_own_household", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_divorced_caregiver_outside_the_maximum_keeps_the_minimum", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_disabled_widow_reaches_the_same_minimum", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_each_caregiver_compares_alone", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_deduction_on_one_caregiver_raises_the_others_minimum" + ], + "failed_test_count": 13, + "log": { + "path": "scratch/review/round9-mutations/no_event_settled.log", + "sha256": "229e4c9de479de9d877d7d32e7fae0143582cc0fb7cc2ecdbd224b43e39b05ff", + "failure_summary": "13 failed, 197 passed in 8.79s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "g_preflight" + }, + { + "id": "round9-rerate_skips_floor", + "round": 9, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " if minimum is not None:\n row.mother_father_rate = minimum.floor\n", + "after": "" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_full_deduction_raises_the_care_minimum[1.40-2.10-60-0.80-1-1]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_full_deduction_raises_the_care_minimum[4-6-60-2.40-3-3]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_full_deduction_raises_the_care_minimum[1000-1500-60-612.80-750-750]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_full_deduction_raises_the_care_minimum[0.30-0.40-1-0.10-0.20-0]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_the_minimum_moves_only_the_caregivers_own_money", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_temporary_deduction_reaches_only_its_own_household", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_disabled_widow_reaches_the_same_minimum", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_each_caregiver_compares_alone", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_partial_deduction_keeps_a_minimum_it_cannot_change", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_the_minimum_equals_the_better_of_the_two_public_families" + ], + "failed_test_count": 11, + "log": { + "path": "scratch/review/round9-mutations/rerate_skips_floor.log", + "sha256": "b05faa2bd54225801f07f197a0a17ebcf5b86f13d63735ade3355d967f436961", + "failure_summary": "11 failed, 199 passed in 8.18s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "g_preflight" + }, + { + "id": "round9-rerate_skips_refusal", + "round": 9, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " if minimum is not None:\n _refuse_unsettled_care_minimum(minimum, age_adjusted, bid)\n", + "after": "" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_partial_deduction_refuses_where_it_can_move_the_rate", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_full_and_a_partial_event_share_the_partial_refusal", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_partial_deduction_computes_or_refuses_within_bounds", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_ret_refuses_a_partial_month_the_minimum_turns_on" + ], + "failed_test_count": 4, + "log": { + "path": "scratch/review/round9-mutations/rerate_skips_refusal.log", + "sha256": "2e20b8eca32252987b171871747c99739cbb0e23191db39d649bd00815e2f61e", + "failure_summary": "4 failed, 206 passed in 41.79s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "g_preflight" + }, + { + "id": "round9-ret_binding_months_only", + "round": 9, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": [ + { + "before": " m not in record.family_maximum_binding_months\n and not _care_minimum_can_move(record, m, deductees)\n", + "after": " m not in record.family_maximum_binding_months\n" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_ret_pays_the_minimum_on_a_month_with_no_binding_maximum", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_ret_needs_the_family_facts_where_a_minimum_can_move", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_reduced_survivor_beside_a_child_needs_the_family_facts[BenefitType.WIDOW]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_reduced_survivor_beside_a_child_needs_the_family_facts[BenefitType.DWB]" + ], + "failed_test_count": 4, + "log": { + "path": "scratch/review/round9-mutations/ret_binding_months_only.log", + "sha256": "a6f51090f6d0897389574c517593a9232bff85a293223f9f76e955b5d0f49340", + "failure_summary": "4 failed, 206 passed in 12.11s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "r2" + }, + { + "id": "round9-ret_every_month_reaches_g", + "round": 9, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": [ + { + "before": " m not in record.family_maximum_binding_months\n and not _care_minimum_can_move(record, m, deductees)\n", + "after": " False\n" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_an_unreduced_survivor_needs_no_family_facts", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_no_minimum_can_move_on_these_records[no", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_no_minimum_can_move_on_these_records[child", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_no_minimum_can_move_on_these_records[the", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_no_minimum_can_move_on_these_records[survivor", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_no_minimum_can_move_on_these_records[a", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_living_workers_record_has_no_care_minimum" + ], + "failed_test_count": 7, + "log": { + "path": "scratch/review/round9-mutations/ret_every_month_reaches_g.log", + "sha256": "0db11e63aa877ad52eda409ae013909f2a9bdeabcbd6db7b87d75374c09a435b", + "failure_summary": "7 failed, 203 passed in 18.82s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "r2" + }, + { + "id": "round9-settled_any_full_event", + "round": 9, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " settled = all(event.payable == 0 for event in events.values())\n", + "after": " settled = any(event.payable == 0 for event in events.values())\n" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_full_and_a_partial_event_share_the_partial_refusal" + ], + "failed_test_count": 1, + "log": { + "path": "scratch/review/round9-mutations/settled_any_full_event.log", + "sha256": "b78fe4b83356998d88123eb68e71ac7f3ab411d5ae91649af6063bdd58ee1d72", + "failure_summary": "1 failed, 209 passed in 11.34s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "g_preflight" + }, + { + "id": "round9-unentitled_caregiver_compares", + "round": 9, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " if member.beneficiary_id not in events\n and by_id[member.beneficiary_id].entitled\n", + "after": " if member.beneficiary_id not in events\n" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_an_unentitled_caregiver_reaches_no_comparison" + ], + "failed_test_count": 1, + "log": { + "path": "scratch/review/round9-mutations/unentitled_caregiver_compares.log", + "sha256": "4f93702d091873616f9d9feff12ecfef25f57a53c0c794970e540a11db27fb1f", + "failure_summary": "1 failed, 209 passed in 11.58s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "g_preflight" + }, + { + "id": "round9-unrated_row_keeps_whole_dollars", + "round": 9, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " auxiliary_payable=payable,\n whole_dollar_auxiliary=_whole_dollars_validated(payable),\n )\n results.append(_computed(BeneficiaryBenefit, **values))\n", + "after": " auxiliary_payable=payable,\n )\n results.append(_computed(BeneficiaryBenefit, **values))\n" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_divorced_caregiver_outside_the_maximum_keeps_the_minimum", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_deduction_on_one_caregiver_raises_the_others_minimum", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_the_minimum_equals_the_better_of_the_two_public_families", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_ret_pays_the_minimum_on_a_month_with_no_binding_maximum" + ], + "failed_test_count": 4, + "log": { + "path": "scratch/review/round9-mutations/unrated_row_keeps_whole_dollars.log", + "sha256": "85cbaecb6f59a4077dd443a517d8ffd5b67f145fcbbea4566752da9e53ec7df7", + "failure_summary": "4 failed, 206 passed in 9.08s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "g_preflight" + }, + { + "id": "round9-unrated_row_no_offset", + "round": 9, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " if old.own_benefit is None\n", + "after": " if True\n" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_dual_caregiver_takes_the_offset_after_the_minimum", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_dual_caregiver_outside_the_maximum_takes_the_same_offset[100-3000-750-650]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_dual_caregiver_outside_the_maximum_takes_the_same_offset[100-1500-715-615]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_dual_caregiver_outside_the_maximum_takes_the_same_offset[800-1500-715-0]" + ], + "failed_test_count": 4, + "log": { + "path": "scratch/review/round9-mutations/unrated_row_no_offset.log", + "sha256": "7fd36819e2c902b59613cdf39ade1906e62c426029fa71158e3803deee0bf06f", + "failure_summary": "4 failed, 206 passed in 12.28s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "g_preflight" + }, + { + "id": "round9-unrated_row_offset_unclipped", + "round": 9, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " else max(Fraction(0), age_adjusted - old.own_benefit)\n", + "after": " else age_adjusted - old.own_benefit\n" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_dual_caregiver_outside_the_maximum_takes_the_same_offset[800-1500-715-0]" + ], + "failed_test_count": 1, + "log": { + "path": "scratch/review/round9-mutations/unrated_row_offset_unclipped.log", + "sha256": "b326c9d050dc60b719bae0f56f1fb4f6d47c1e32ef4ff65ce9a25dad98046451", + "failure_summary": "1 failed, 209 passed in 10.99s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "g_preflight" + }, + { + "id": "round9-unrated_row_skips_minimum", + "round": 9, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " elif bid in care_minimums:\n", + "after": " elif False:\n" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_divorced_caregiver_outside_the_maximum_keeps_the_minimum", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_deduction_on_one_caregiver_raises_the_others_minimum", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_partial_deduction_refuses_outside_the_maximum_too", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_the_minimum_equals_the_better_of_the_two_public_families", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_ret_pays_the_minimum_on_a_month_with_no_binding_maximum" + ], + "failed_test_count": 5, + "log": { + "path": "scratch/review/round9-mutations/unrated_row_skips_minimum.log", + "sha256": "dc7c1a24630f2263a7a5421e9c6db067151a0b5f0ea8b963dde3e7a147c2200a", + "failure_summary": "5 failed, 205 passed in 9.35s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "g_preflight" + }, + { + "id": "round9-unrated_row_skips_refusal", + "round": 9, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " age_adjusted = max(old.age_adjusted_rate, minimum.floor)\n _refuse_unsettled_care_minimum(minimum, age_adjusted, bid)\n", + "after": " age_adjusted = max(old.age_adjusted_rate, minimum.floor)\n" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_partial_deduction_refuses_outside_the_maximum_too", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_partial_deduction_computes_or_refuses_within_bounds" + ], + "failed_test_count": 2, + "log": { + "path": "scratch/review/round9-mutations/unrated_row_skips_refusal.log", + "sha256": "fe6250c608f8a9b3ee96306fe3bdcb0ac958d8949d5fd7f7d0820c1a5ef00eb8", + "failure_summary": "2 failed, 208 passed in 27.14s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "g_preflight" + }, + { + "id": "round9-unrated_row_takes_floor_alone", + "round": 9, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "before": " age_adjusted = max(old.age_adjusted_rate, minimum.floor)\n", + "after": " age_adjusted = minimum.floor\n" + } + ], + "command": [ + "python", + "scratch/review/run_round9_named.py", + "-p", + "no:xdist", + "-p", + "no:cacheprovider", + "-q", + "--tb=line", + "-rf", + "tests/test_track_b_ret_ledger_fix_round_9.py", + "tests/test_track_b_ret_ledger_fix_round_8.py" + ], + "outer_command": [ + "python", + "scratch/review/round9_mutate.py" + ], + "environment": { + "POPULACE_DYNAMICS_PSID_DIR": "/nonexistent/trackb-round9", + "POPULACE_DYNAMICS_EPUF_DIR": "/nonexistent/trackb-round9", + "OMP_NUM_THREADS": "1", + "POLARS_MAX_THREADS": "1" + }, + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_each_caregiver_compares_alone", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_dual_caregiver_outside_the_maximum_takes_the_same_offset[100-1500-715-615]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_dual_caregiver_outside_the_maximum_takes_the_same_offset[800-1500-715-0]", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_the_minimum_equals_the_better_of_the_two_public_families", + "tests/test_track_b_ret_ledger_fix_round_9.py::test_a_partial_deduction_computes_or_refuses_within_bounds" + ], + "failed_test_count": 5, + "log": { + "path": "scratch/review/round9-mutations/unrated_row_takes_floor_alone.log", + "sha256": "35fbaa56939c06d432640392b3fd7590f4c04b38b225b1b3c63220d26c2ad891", + "failure_summary": "5 failed, 205 passed in 20.02s" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + } + }, + "layer": "g_preflight" } ], "restoration_verification_snapshot": { @@ -11409,5 +13345,11 @@ "round_8_restoration_snapshot": { "src/populace_dynamics/track_b/gross_benefits.py": "96ef26ad39fc7f26d2e1f93659928821a6edc7e13c32844866527c74c131b38a", "src/populace_dynamics/track_b/ret_ledger.py": "78c24f9f94ab8cf90efcd0ca5c5b92686fd0cad71911594e204517313135c999" + }, + "round_9_head": "aa86a4da87dde6664d5475a197632ca685579e1e", + "round_9_note": "34 fresh one-line semantic mutations failed named tests in tests/test_track_b_ret_ledger_fix_round_9.py and tests/test_track_b_ret_ledger_fix_round_8.py on the final test bytes. A first pass of 35 killed 24. Ten survivors gained tests before this run. A second pass caught two of those new cases testing nothing, because fra_month=0 sets a worker past full retirement age, and each of them now asserts the deduction. The eleventh survivor, can_move_any_context, always reaches G on a month with a context and no caregiver. It changes no outcome, and test_with_no_caregiver_an_unbound_month_matches_g holds the two answers together, so it stays out of this count. The session ran these in copied source trees, and production sources stayed unchanged. Earlier records remain historical.", + "round_9_restoration_snapshot": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" } } diff --git a/docs/design/track_b_g2_r2b_verification.json b/docs/design/track_b_g2_r2b_verification.json index 8842a238c..9ac6e4572 100644 --- a/docs/design/track_b_g2_r2b_verification.json +++ b/docs/design/track_b_g2_r2b_verification.json @@ -13243,5 +13243,83 @@ ] } }, - "round_8_current_evidence_note": "Fresh reviewed-head failing-first, named module gates, cross-head diagnostic and copied-tree mutation evidence sits under round_8. Earlier heads, counts and commands remain historical." + "round_8_current_evidence_note": "Fresh reviewed-head failing-first, named module gates, cross-head diagnostic and copied-tree mutation evidence sits under round_8. Earlier heads, counts and commands remain historical.", + "round_9": { + "reviewed_head": "aa86a4da87dde6664d5475a197632ca685579e1e", + "workspace": "/Users/maxghenis/PolicyEngine/_clones/mdyn-trackb-g2-20261023", + "verification_class": "statutory_conformance", + "admitted_scope": "Invented declarations and captured published examples only; no population, behavioral or forecast claim.", + "fixed_by": "the session, because review lanes were queued and lane clocks run slowly", + "named_test_gate": { + "selection": "tests/test_track_b_*.py", + "result": "14261 passed, 7 skipped in 966.46s (0:16:06)", + "environment": "both data roots set to a nonexistent path" + }, + "failing_first": { + "reviewed_head": "aa86a4da87dde6664d5475a197632ca685579e1e", + "module": "tests/test_track_b_ret_ledger_fix_round_9.py", + "result": "34 failed, 28 passed in 28.15s" + }, + "cross_head": { + "r2_stable_rows": 240, + "r3_stable_rows": 240, + "identical_declared_output_bytes": true, + "stable_sha256": "799fc9e23a902ac1ca0c2563579ceb094d0dbcd631a912305c40062cf21a5f55" + }, + "conformance_report_sha256": "b5dfc011181eb5fdaf795719ae7557dbc23d0a680058f24c6a5aa03ba28f2a70", + "conformance_report_change": "One new named refusal witness, care_minimum_partial_deduction, with its counts. Lattice rows stay identical.", + "tier_policy": "Left to CI; no local whole-suite collection.", + "final_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", + "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + }, + "final_test_sha256": { + "tests/test_track_b_ret_ledger_fix_round_4.py": "02c5c86b64070f9e7350868f8d94dcc9233bedc32cbcae32b3264f9ae570d1bb", + "tests/test_track_b_ret_ledger_fix_round_5.py": "c86ef045d797e31d6db09ef11bc7fbfbcf7c1fa54d32f04e7b6b42e8b813c9cd", + "tests/test_track_b_ret_ledger_fix_round_6.py": "8ec899e262d6e242f67f860e1722f465882573bbcb481b8459f2ff13946f92b0", + "tests/test_track_b_ret_ledger_fix_round_7.py": "6f8f1cdc4f90e594759225870e1ec36a905fa1cd6eea7d142747ac13bec066c4", + "tests/test_track_b_ret_ledger_fix_round_8.py": "ca0e937eedf4fd5aaad8279775bf9af78b37e3f2ee9f45161d591bc4c638802b", + "tests/test_track_b_ret_ledger_fix_round_9.py": "258d3f13850d639c5f261d1091debed016946b15aaaaf4631db6d63a842629c4" + }, + "mutations": { + "count": 34, + "ids": [ + "round9-can_move_adds_unentitled", + "round9-can_move_any_benefit_type", + "round9-can_move_any_rate", + "round9-can_move_any_record", + "round9-can_move_counts_the_deductee", + "round9-can_move_equal_rate", + "round9-can_move_needs_no_child", + "round9-can_move_no_context", + "round9-can_move_widow_type_only", + "round9-cap_drops_before_1983", + "round9-caregivers_any_flag", + "round9-caregivers_any_role", + "round9-ceiling_never_refuses", + "round9-ceiling_refuses_at_equality", + "round9-comparison_drops_events", + "round9-comparison_drops_households", + "round9-comparison_keeps_payable", + "round9-deductee_caregiver_compares", + "round9-every_event_settled", + "round9-floor_always_ordinary", + "round9-nh_reaches_the_comparison", + "round9-no_event_settled", + "round9-rerate_skips_floor", + "round9-rerate_skips_refusal", + "round9-ret_binding_months_only", + "round9-ret_every_month_reaches_g", + "round9-settled_any_full_event", + "round9-unentitled_caregiver_compares", + "round9-unrated_row_keeps_whole_dollars", + "round9-unrated_row_no_offset", + "round9-unrated_row_offset_unclipped", + "round9-unrated_row_skips_minimum", + "round9-unrated_row_skips_refusal", + "round9-unrated_row_takes_floor_alone" + ] + } + }, + "round_9_current_evidence_note": "Fresh reviewed-head failing-first, named module gates, cross-head diagnostic and copied-tree mutation evidence sits under round_9. Earlier heads, counts and commands remain historical." } diff --git a/docs/design/track_b_g_conformance_report.json b/docs/design/track_b_g_conformance_report.json index 3b7a71751..f4a524c67 100644 --- a/docs/design/track_b_g_conformance_report.json +++ b/docs/design/track_b_g_conformance_report.json @@ -315,6 +315,7 @@ }, "refused_by_reason": { "administrative_finality": 9831, + "care_minimum_partial_deduction": 0, "combined_family_maximum": 4860, "deduction_age_work_interaction": 0, "deemed_or_putative_spouse": 9720, @@ -563,12 +564,13 @@ "supplemental_refusal_witnesses": { "denominator": { "invalid": 0, - "refused": 38, - "rows": 38, + "refused": 39, + "rows": 39, "supported": 0 }, "refused_by_reason": { "administrative_finality": 1, + "care_minimum_partial_deduction": 1, "combined_family_maximum": 1, "deduction_age_work_interaction": 1, "deemed_or_putative_spouse": 1, @@ -615,6 +617,12 @@ "reason": "administrative_finality", "status": "refused" }, + { + "description": "No source carries a partial deduction to a child-in-care comparison", + "id": "care_minimum_partial_deduction", + "reason": "care_minimum_partial_deduction", + "status": "refused" + }, { "description": "One child on retirement and survivor records", "id": "combined_family_maximum", diff --git a/docs/design/track_b_g_gross_benefits.md b/docs/design/track_b_g_gross_benefits.md index ceee8370e..6e2a6b7ba 100644 --- a/docs/design/track_b_g_gross_benefits.md +++ b/docs/design/track_b_g_gross_benefits.md @@ -340,7 +340,10 @@ For one worker's record and one benefit month: mother or father would receive after the maximum, when that is larger (RS 00615.340; .010). The comparison uses the mother/father 75-percent OB under 202(g)(2), its maximum share and any settled dual-entitlement - redistribution; the actual widow's own-benefit offset follows. + redistribution; the actual widow's own-benefit offset follows. After a + deduction the comparison takes the month's events and households + (402(q)(5)(D); RS 00615.340), and a partial deduction refuses where it + can change the rate. 6. **Dual entitlement** (402(k)(3)(A)). The auxiliary benefit is reduced, but not below zero, by the own benefit after 402(q). - An aged spouse entitled to the own benefit in or before the spouse @@ -673,6 +676,7 @@ G never falls back to a single-worker computation. | `parisi_redistribution_ambiguous` | Own delayed credits, an actually limiting RIB-LIM after maximum and age reduction, or dual zero reached only after auxiliary age reduction remain unsettled by GN 02603.050A/C | | `parisi_before_october_1999` | A binding maximum with dual entitlement before 10/99 | | `sole_full_deduction_zero_dual_composition` | GN 02603.050 A.1's sole full permanent deduction and A.2's zero dual rate admit different subject payments depending on composition order; equal-payment cases compute | +| `care_minimum_partial_deduction` | A partial deduction beside a child-in-care widow(er), where the highest minimum the month can reach exceeds the computed rate. No capture carries a partial amount to the mother or father comparison (402(q)(5)(D); RS 00615.340) | | `independently_entitled_divorced_spouse` | IEDS before January 1985 or a WEP-affected worker record before January 2024 (RS 00202.100) | | `non_aime_formula_pia` | Old-start, special-minimum and frozen-minimum PIAs (RS 00615.740B.1) | | `savings_clause_403a5` | Under explicit `LITERAL_REFUSAL`, a governed month whose total fell below a 403(a)(5) protected total, and every later governed month | @@ -2685,6 +2689,7 @@ $83.50 child rates and $83 whole-dollar payments. | Missing election certificate | `election_certificate_suspension` | | Concurrent subject number-holder reservations and subject age reductions | `deduction_age_work_interaction` | | Sole full permanent subject deduction and zero dual rows whose A.1/A.2 compositions change payment | `sole_full_deduction_zero_dual_composition` | +| A partial deduction that can change a child-in-care minimum | `care_minimum_partial_deduction` | | Combined maxima; multiple auxiliary records | Existing named refusals remain | The computation first obtains the ordinary G maximum-adjusted rates and diff --git a/docs/design/track_b_r2_ret_ledger.md b/docs/design/track_b_r2_ret_ledger.md index afe43805a..c22eaaf40 100644 --- a/docs/design/track_b_r2_ret_ledger.md +++ b/docs/design/track_b_r2_ret_ledger.md @@ -538,9 +538,10 @@ prior year's amount or relabelled as a statutory coverage refusal. 5. **Other workers' charging.** After NH charging, charge each auxiliary or survivor's excess against that person's remaining benefit only. Do not charge an already exhausted month again. When this frees - binding family-maximum room for another beneficiary, readjust through - G using that month's declared `RETFamilyMonth` statutory and household - facts. Without those facts, retain the named refusal + binding family-maximum room for another beneficiary, or can raise a + child-in-care minimum with or without a binding maximum, readjust + through G using that month's declared `RETFamilyMonth` statutory and + household facts. Without those facts, retain the named refusal `deduction_readjustment_requires_family_context` (20 CFR 404.434(b)(2)-(3); RS 02501.095B.3-4, .155A.3-4; GN 02603.020-.050). @@ -831,7 +832,7 @@ not a reconstruction of monetary RET under pre-1978 law. | Protested partial current-year suspension | `PROTEST_PARTIAL_SUSPENSION` / `protested_partial_work_suspension` | RS 02501.100B.3 requires a different provisional path | | Auxiliary/survivor own deduction with a binding maximum and complete monthly G facts | Supported full/partial permanent deductions and full estimated suspensions | Act 203(a)(4); RS 02501.155A.2–4; GN 02603.050C/D | | Separate-household nondeductees | Final increases are paid; estimated increases wait unless in the worker's household | RS 02501.160; GN 02603.090 | -| Binding readjustment without monthly G facts | `FAMILY_CONTEXT_REQUIRED` / `deduction_readjustment_requires_family_context` | Reduced rates do not identify original age and dual-entitlement facts | +| Binding readjustment, or a month where a child-in-care minimum can move, without monthly G facts | `FAMILY_CONTEXT_REQUIRED` / `deduction_readjustment_requires_family_context` | Reduced rates do not identify original age and dual-entitlement facts | | NH reservation combined with auxiliary age reduction | G `deduction_age_work_interaction` | GN 02603.050C/D reserves both amounts; current captures do not settle the interacting reduced-rate derivation | | Two-record entitlement with actual or estimated excess | `TWO_RECORD_EARNINGS` / `excess_earnings_on_two_records` | RS 02501.145-.150 require coordinated records | | Noncovered foreign work | `FOREIGN_WORK` / `noncovered_foreign_work` | Act 203(c); 20 CFR 404.417-.418 | @@ -2152,6 +2153,7 @@ member separately. | `SAVINGS_CLAUSE`, `SAVINGS_CLAUSE_HISTORY_UNKNOWN`, `SAVINGS_CLAUSE_MEMBERSHIP_CHANGE`, `SAVINGS_CLAUSE_RATE_PROCEDURE` | None for F1–F6 | RS 00630.400 says "Any person's benefit may not exceed the original benefit (OB)" and adds "the new PIA in a life case" to the savings maximum. The refusal concerns carried allocation/rate procedure rather than the ordinary OB, NH own benefit or raw own-benefit entitlement. | | `PRISONER_SUSPENSION`, `DRUG_ADDICTION_SUSPENSION`, `FOREIGN_WORK_DEDUCTION`, `PENALTY_DEDUCTION`, `MARITIME_DEDUCTION`, `ELECTION_CERTIFICATE_SUSPENSION` | None | GN 02603.040 calls these "deductions" and suspensions. GN 02603.050B first applies the maximum, then deductions, then redistribution. They do not alter the pre-reduction facts F1–F6. | | `DEDUCTION_AGE_WORK_INTERACTION`, `SOLE_FULL_DEDUCTION_ZERO_DUAL_COMPOSITION` | None | GN 02603.050A and C concern deduction exceptions and reserved age reductions during redistribution. The unresolved composition changes family cash after the original rates and entitlement tests. | +| `CARE_MINIMUM_PARTIAL_DEDUCTION` | None | RS 00615.340 compares "the amount a mother and father would receive", and no capture carries a partial deduction to that comparison. The refusal says nothing about an F1–F6 fact. | | Deferred `ADMINISTRATIVE_FINALITY`, `DIB_AFTER_REDUCED_RIB`, `WORKERS_COMPENSATION_OFFSET` | Same scoped facts as the named condition | Deferring a known reason does not turn its potentially lawful monetary difference into an input error. | Maximum binding and auxiliary gross deliberately stay after G. Maximum @@ -2525,9 +2527,10 @@ question than the ordinary upper bound. `_PIA_CAP_KEEPING_HOLDS` lists the holds that leave that answer alone: the reduction-only holds, money history among them, and a delayed-credit hold on a record with no credits. Finality keeps its row, because it can protect a rate above the PIA. So do positive -delayed credits, which add to the base. A month before 1983 keeps its row, -because the fact table leaves F3 open there. A rate at or below the PIA keeps -its row under a history hold, and round 7's reasoning for it stands. +delayed credits, which add to the base. This round also kept a row for a month +before 1983, because the fact table leaves F3 open there, and round 9 corrects +that. A rate at or below the PIA keeps its row under a history hold, and +round 7's reasoning for it stands. **A zero threshold fails every RIB.** Act 202(g)(1)(C) needs a mother's or father's own RIB below three-quarters of the PIA, so at PIA $0 no nonnegative @@ -2580,7 +2583,9 @@ its old name claimed more than its comment did. - **Modern cohorts keep the WIB route.** RS 00615.005A.8 ends that carryover for a DIB for workers born January 2, 1928 or later with onsets on or after January 1, 1990. The schema omits the onset, so the rule can't show that - every filling fails. A loose refusal moves no money. + every filling fails for most cohorts. A birth from 1990 on rules out an + earlier onset by itself, so a later round could tighten those cohorts. A + loose refusal moves no money. - **The exact rate under a history stays refused.** The PIA cap says what a rate can't be, and it computes nothing. - **No money moved.** This round changes classification only. @@ -2593,7 +2598,7 @@ its old name claimed more than its comment did. | --- | --- | | With no delayed credits, no history admits a RIB above its PIA, declared or implied by a known cohort | `test_history_leaves_a_rib_at_or_below_its_pia`; `test_a_known_cohort_keeps_the_pia_cap_with_no_declaration`; `test_no_other_hold_lifts_a_known_cohort_past_the_pia`; Hypothesis `test_no_history_admits_a_rib_above_its_pia` | | The cap leaves every rate at or below the PIA its row, and the preflight changes nothing about it | `test_a_rate_at_the_pia_keeps_its_history_row`; round 7's Hypothesis `test_history_keeps_every_rate_in_its_scope` | -| Finality, positive delayed credits and a month before 1983 keep a rate above the PIA | `test_finality_can_lift_a_rib_past_its_pia`; `test_a_deferred_finality_can_lift_a_rib_past_its_pia`; `test_delayed_credits_can_lift_a_history_rib_past_its_pia`; `test_a_month_before_1983_leaves_the_rate_unsettled_past_the_pia` | +| Finality and positive delayed credits keep a rate above the PIA | `test_finality_can_lift_a_rib_past_its_pia`; `test_a_deferred_finality_can_lift_a_rib_past_its_pia`; `test_delayed_credits_can_lift_a_history_rib_past_its_pia` | | A zero threshold fails every RIB on every filling, and only a zero threshold does | `test_a_zero_pia_fails_a_known_cohorts_rib`; `test_a_zero_pia_fails_a_rib_with_early_credits`; `test_a_zero_threshold_settles_every_actual_rib_test`; `test_only_a_zero_threshold_settles_a_rib_with_early_credits`; Hypothesis `test_only_a_zero_threshold_rules_out_a_history_rib` | | A positive threshold, a deemed PIA and finality each keep their row | `test_a_positive_threshold_keeps_the_own_history_row`; `test_early_credits_keep_their_row_on_a_positive_threshold`; `test_a_deemed_pia_keeps_a_known_cohorts_history_open`; `test_finality_keeps_a_zero_threshold_row`; `test_a_deferred_finality_keeps_a_zero_threshold_row` | | A route opens the month after its first month, on its own age and date, and no route opens before September 1965 | `test_each_route_dates_the_first_reduced_dib`; Hypothesis `test_the_floor_matches_month_counts_written_from_the_sources`; round 7's Hypothesis `test_f2_matches_a_table_written_from_the_sources` | @@ -2606,3 +2611,113 @@ and 96 of the module's 148 tests fail against `fbe491d4`. A first pass killed 38 of 39. The survivor let a positive threshold settle F6 under an early delayed-credit hold, which changes that fact and no outcome, and `test_only_a_zero_threshold_settles_a_rib_with_early_credits` now kills it. + +## PR 563 round 9: the child-in-care minimum under a month's deductions + +GPT-6.1 Sol reviewed `aa86a4da` and asked for changes, with two medium +findings. Both reproduced. The first underpaid a supported widow(er) through G +and through RET. The second kept a counted row for a RIB no filling can make +lawful, and round 8's own exception caused it. + +### What changed + +**The minimum reads the month.** Act 202(q)(5)(D) holds a widow's or widower's +benefit at the amount the person would have had "had he or she been entitled +for such month to mother's or father's insurance benefits". RS 00615.340 says +"they cannot receive less than the amount a mother and father would receive". +G took that comparison from the family before the month's deductions. When a +child's deduction freed room under the maximum, a mother or father took that +room and the widow(er) did not: + +| PIA | Maximum | Reduction | Rate at `aa86a4da` | Rate now | +| --- | --- | --- | --- | --- | +| $1.40 | $2.10 | 60 of 60 | $0.80 | $1.00 | +| $4.00 | $6.00 | 60 of 60 | $2.40 | $3.00 | +| $1,000 | $1,500 | 60 of 60 | $612.80 | $750 | +| $0.30 | $0.40 | 1 of 60 | $0.10 | $0.20 | + +`_care_minimums_after_deductions` now builds the comparison family and runs +that month's events and households through the same readjustment. A temporary +deduction in another household frees nothing, so that widow(er) stays at $500 +in the third row. Each caregiver compares alone, so a deduction on one can +raise the other's minimum. A deductee keeps G's ordinary minimum, because GN +02603.050B.3 redistributes only to people "not subject to a deduction", in +either family. + +**The minimum reaches a rate nothing else re-rates.** A surviving divorced +spouse sits outside the actual maximum (403(a)(3)(C)), while the mother or +father the spouse compares with sits inside it (RS 00615.682). So the actual +maximum can stay unbound while the comparison binds. At PIA $2.70 and maximum +$4.10 the spouse's $1.90 becomes $2.00. `_readjust_deduction_rows` has a branch +for that row, and it takes the own-benefit offset after the minimum. + +**RET reads the minimum on an unbound month.** `apply_ret_year` reached G only +on a month in `family_maximum_binding_months`, so the $2.00 above never reached +the ledger. `_care_minimum_can_move` now sends such a month to G. Where a +context names the people, it asks for a caregiver. Without one, a reduced +widow(er) or disabled widow(er) beside an entitled child stays open, and the +existing `FAMILY_CONTEXT_REQUIRED` refusal names the missing facts. Both +reproductions from the review now pay $1 and $2. + +**A partial deduction refuses where it can move the rate.** An event's +`payable` belongs to the actual family's rate, and no capture carries a partial +amount to a comparison rate. The ordinary comparison gives the lowest minimum +the month can have. Treating every event as full gives the highest. Between the +two, `care_minimum_partial_deduction` refuses by name and keeps the row and its +weight. A rate at or above the highest minimum computes, because every reading +then agrees. + +**A month before 1983 keeps the PIA cap.** Round 8 kept a row above the PIA for +a month before 1983, because the fact table leaves F3 open there. RS 00615.101 +says "Round the result down to the next dime for benefits after 5/82 and up to +the next dime for benefits prior to 6/82", and upward rounding can't pass a PIA +that G already holds to dimes. RS 00615.005C.2 subtracts a money reduction from +that PIA. So `PAYMENT_MONTH_BEFORE_1983` joins `_PIA_CAP_KEEPING_HOLDS`, and +$0.20 on PIA $0.10 in 1981 or 1982 now raises before `evaluate_ret` and leaves +no row. So do $400.10 on PIA $400 and $1,000.10 on PIA $1,000. The exact rate +stays refused, and finality and positive delayed credits keep their rows. + +### What stayed + +- **A dual comparison keeps its fixed rate.** A dual row takes no redistribution + in the actual family, and the comparison treats a dual mother or father the + same way. So a deduction doesn't raise a dual caregiver's minimum. +- **Number-holder reservations stay refused.** A reservation beside a comparison + raises `deduction_age_work_interaction`. A survivor record has no living + number holder, so this guards the public entry only. +- **R3 reads a declared month.** `ARFClaim.mother_father_rate_months` stays a + caller's declaration, so a month this round raises reaches R3 through that + declaration. +- **One trigger stays a skip.** With a context and no caregiver, RET still skips + G on an unbound month. Always reaching G changes no outcome, and + `test_with_no_caregiver_an_unbound_month_matches_g` holds the two answers + together, so that mutation counts as equivalent and stays out of the ledger. +- **Sol's `needs_max` items need no new call.** Each one keeps a standing ruling + or resolves inside these fixes. Sol read the child-in-care minimum as settled + by the sources, and a named refusal for the partial case adopts no reading. + +### New executed invariants + +| Invariant | Executing tests in `test_track_b_ret_ledger_fix_round_9.py` | +| --- | --- | +| The minimum equals the better of the reduced rate and what a mother or father receives this month, under this month's events and households | `test_a_full_deduction_raises_the_care_minimum`; `test_a_temporary_deduction_reaches_only_its_own_household`; Hypothesis `test_the_minimum_equals_the_better_of_the_two_public_families` | +| The minimum moves only the caregiver's own money, and leaves the maximum accounting alone | `test_the_minimum_moves_only_the_caregivers_own_money` | +| The rule reaches a caregiver outside the maximum and a disabled widow(er) | `test_a_divorced_caregiver_outside_the_maximum_keeps_the_minimum`; `test_a_disabled_widow_reaches_the_same_minimum` | +| Each caregiver compares alone, and a deductee keeps the ordinary minimum | `test_each_caregiver_compares_alone`; `test_a_deduction_on_one_caregiver_raises_the_others_minimum`; `test_a_deducted_caregiver_keeps_the_ordinary_minimum` | +| Only a current, entitled, undeducted widow(er) reaches a comparison | `test_a_deducted_caregiver_reaches_no_comparison`; `test_an_unentitled_caregiver_reaches_no_comparison`; `test_a_living_workers_divorced_spouse_has_no_care_minimum` | +| A dual caregiver takes the offset after the minimum, and the offset stops at zero | `test_a_dual_caregiver_takes_the_offset_after_the_minimum`; `test_a_dual_caregiver_outside_the_maximum_takes_the_same_offset` | +| A partial deduction computes only where every amount between the two bounds agrees, and otherwise refuses with its row and weight | Hypothesis `test_any_partial_amount_stays_between_the_two_bounds`; Hypothesis `test_a_partial_deduction_computes_or_refuses_within_bounds`; `test_a_partial_deduction_refuses_where_it_can_move_the_rate`; `test_ret_refuses_a_partial_month_the_minimum_turns_on` | +| RET pays the minimum with or without a binding maximum | `test_ret_pays_the_minimum_on_a_binding_month`; `test_ret_pays_the_minimum_on_a_month_with_no_binding_maximum` | +| RET asks for family facts exactly where a minimum can move | `test_a_reduced_survivor_beside_a_child_needs_the_family_facts`; `test_no_minimum_can_move_on_these_records`; `test_an_unreduced_survivor_needs_no_family_facts`; `test_a_living_workers_record_has_no_care_minimum` | +| With no caregiver, an unbound RET month equals G | Hypothesis `test_with_no_caregiver_an_unbound_month_matches_g` | +| With no delayed credits, no RIB exceeds its PIA in any month, 1981 and 1982 included | `test_a_rib_above_its_pia_is_an_input_error_before_1983`; `test_money_history_keeps_the_same_cap_before_1983` | +| Before 1983, delayed credits, finality and a rate at or below the PIA keep their refusal | `test_delayed_credits_keep_the_refusal_before_1983`; `test_finality_keeps_its_refusal_before_1983`; `test_a_rate_at_or_below_the_pia_keeps_the_refusal_before_1983` | +| Each quotation above sits in its capture | `test_the_captures_carry_each_quoted_rule` | + +Thirty-four fresh mutations each fail a named test on the final test bytes, +and 34 of the module's 62 tests fail against `aa86a4da`. A first pass of 35 +killed 24. Ten of the eleven survivors showed test gaps, and new tests closed +them. A second pass caught two of those new cases testing nothing: they set +`fra_month=0`, past full retirement age, so no deduction applied. The older +survivor-alone test had the same flaw. Each of them now asserts the deduction. +The eleventh survivor stays out of the ledger as equivalent, as above. diff --git a/scripts/track_b_g_conformance_report.py b/scripts/track_b_g_conformance_report.py index b52b1853d..0d0deb9fb 100644 --- a/scripts/track_b_g_conformance_report.py +++ b/scripts/track_b_g_conformance_report.py @@ -282,6 +282,33 @@ def _deduction_witness(reason, *, age_worker=False): ) +def _care_minimum_partial_witness(): + """A partial deduction leaves the 402(q)(5)(D) comparison open.""" + return g.family_benefits_after_deductions( + _survivor(), + ( + g.Beneficiary( + "w", + g.Role.WIDOW, + reduction_months=60, + reduction_period_months=60, + child_in_care="c1", + ), + g.Beneficiary("c1", g.Role.CHILD), + g.Beneficiary("c2", g.Role.CHILD), + ), + payment_month=NOW, + params=PARAMS, + deductions={ + "c2": g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST, F(100), True + ) + }, + households={"w": "h", "c1": "h", "c2": "h"}, + standalone=True, + ) + + def _zero_dual_composition_witness(): """GN 02603.050 A.1/A.2 disagree on C's $175 versus $200 rate.""" return g.family_benefits_after_deductions( @@ -622,6 +649,10 @@ def multiple_records(child): "GN 02603.050 A.1 and A.2 compose differently: child 175 versus 200", _zero_dual_composition_witness, ), + reasons.CARE_MINIMUM_PARTIAL_DEDUCTION: ( + "No source carries a partial deduction to a child-in-care comparison", + _care_minimum_partial_witness, + ), reasons.WIDOW_DRC_SAVINGS_CLAUSE: ( "May 1978 survivor protected from widow deceased-worker DRCs", lambda: _family(_survivor(widow_drc_savings_clause=True)), diff --git a/src/populace_dynamics/track_b/gross_benefits.py b/src/populace_dynamics/track_b/gross_benefits.py index 6ce2e2c57..63303668f 100644 --- a/src/populace_dynamics/track_b/gross_benefits.py +++ b/src/populace_dynamics/track_b/gross_benefits.py @@ -495,6 +495,7 @@ class UnsupportedReason(Enum): #: Deferred coverage: no NH-reservation/age-reduction allocation #: procedure has been derived; no competing authoritative algorithms. DEDUCTION_AGE_WORK_INTERACTION = "deduction_age_work_interaction" + CARE_MINIMUM_PARTIAL_DEDUCTION = "care_minimum_partial_deduction" SOLE_FULL_DEDUCTION_ZERO_DUAL_COMPOSITION = ( "sole_full_deduction_zero_dual_composition" ) @@ -1802,6 +1803,7 @@ class BeneficiaryCondition(Enum): UnsupportedReason.MARITIME_DEDUCTION: frozenset(), UnsupportedReason.ELECTION_CERTIFICATE_SUSPENSION: frozenset(), UnsupportedReason.DEDUCTION_AGE_WORK_INTERACTION: frozenset(), + UnsupportedReason.CARE_MINIMUM_PARTIAL_DEDUCTION: frozenset(), UnsupportedReason.SOLE_FULL_DEDUCTION_ZERO_DUAL_COMPOSITION: frozenset(), } # These holds can only lower an NH rate (402(q)(2), 224; 20 CFR 404.408(c)(1), @@ -1836,8 +1838,11 @@ class BeneficiaryCondition(Enum): # raw own PIA (F5), which no reduction history changes. _OWN_RIB_AMOUNT_TEST_ROLES = _WIDOW_ROLES | {Role.MOTHER_FATHER, Role.PARENT} # With no delayed credits, none of these can lift an own RIB past its PIA. +# RS 00615.101 rounds a reduced RIB up to the next dime before 6/82, and a +# dime rounding cannot pass a PIA that G already holds to dimes. _PIA_CAP_KEEPING_HOLDS = _NH_REDUCTION_ONLY_HOLDS | { UnsupportedReason.DELAYED_CREDITS_BEFORE_1917, + UnsupportedReason.PAYMENT_MONTH_BEFORE_1983, } @@ -3905,6 +3910,12 @@ def _mother_father_care_rate( is applied by the actual widow computation. Other care flags are cleared so this comparison cannot recursively compare widow floors. """ + comparison = _mother_father_comparison(beneficiaries, caregiver) + result = _family_benefits(state, comparison, payment_month, params) + return result.by_id()[caregiver.beneficiary_id].age_adjusted_rate + + +def _mother_father_comparison(beneficiaries, caregiver): comparison = [] for member in beneficiaries: if member.beneficiary_id == caregiver.beneficiary_id: @@ -3922,8 +3933,7 @@ def _mother_father_care_rate( comparison.append(_replace_declared(member, child_in_care=False)) else: comparison.append(member) - result = _family_benefits(state, comparison, payment_month, params) - return result.by_id()[caregiver.beneficiary_id].age_adjusted_rate + return comparison def _refuse_widow_drc_savings_clause( @@ -4568,6 +4578,8 @@ def family_benefits_after_deductions( Concurrent NH reservations and auxiliary age reductions have deferred allocation coverage and refuse as ``deduction_age_work_interaction``; no procedure has been derived for that combination. + A widow(er) with a child in care keeps the mother or father amount for + this month, under these same events (402(q)(5)(D)). R2 owns earnings, charge order, grace years and permanent determinations. """ if standalone is not True: @@ -4661,6 +4673,124 @@ def _after_deductions( } if not events and not any(worker_deductions.values()): return baseline + return _readjusted_for_events( + state, + beneficiaries, + payment_month, + params, + baseline, + events, + households, + worker_deductions, + ) + + +def _current_caregivers(beneficiaries): + """Widow(er)s whom 402(q)(5)(D) compares with a mother or father.""" + return [ + member + for member in beneficiaries + if member.role in _WIDOW_ROLES + and isinstance(member.child_in_care, str) + ] + + +@dataclass(frozen=True) +class _CareMinimum: + """A month's 402(q)(5)(D) minimum: what it sets and how high it can go.""" + + floor: Fraction + ceiling: Fraction + + +def _care_minimums_after_deductions( + state, + beneficiaries, + payment_month, + params, + baseline, + events, + households, + worker_deductions, +): + """402(q)(5)(D): the minimum "for such month", with its deductions. + + RS 00615.340 compares what a mother or father would receive, so the + comparison family takes this month's events and households. A deductee + keeps its rate in either family (GN 02603.050B.3), so its own minimum + stays G's ordinary one. + + An event's ``payable`` belongs to the actual family's rate, and no source + carries a partial amount to a comparison rate. Treating every event as + full gives the highest minimum the month can reach, and the ordinary + minimum is the lowest. The two bound any reading, and a rate between + them refuses (``_refuse_unsettled_care_minimum``). + """ + by_id = baseline.by_id() + caregivers = [ + member + for member in _current_caregivers(beneficiaries) + if member.beneficiary_id not in events + and by_id[member.beneficiary_id].entitled + ] + if not caregivers: + return {} + if any(worker_deductions.values()): + raise _computed( + FamilyConfigurationUnsupported, + UnsupportedReason.DEDUCTION_AGE_WORK_INTERACTION, + "Concurrent NH reservations and a child-in-care comparison have " + "deferred allocation coverage", + ) + minimums = {} + for caregiver in caregivers: + cid = caregiver.beneficiary_id + comparison = _mother_father_comparison(beneficiaries, caregiver) + ordinary = _family_benefits(state, comparison, payment_month, params) + highest = _readjusted_for_events( + state, + comparison, + payment_month, + params, + ordinary, + { + bid: _replace_declared(event, payable=Fraction(0)) + for bid, event in events.items() + }, + households, + {}, + ) + ceiling = highest.by_id()[cid].age_adjusted_rate + settled = all(event.payable == 0 for event in events.values()) + minimums[cid] = _CareMinimum( + ceiling if settled else ordinary.by_id()[cid].age_adjusted_rate, + ceiling, + ) + return minimums + + +def _refuse_unsettled_care_minimum(minimum, age_adjusted, beneficiary_id): + if minimum.ceiling > age_adjusted: + raise _computed( + FamilyConfigurationUnsupported, + UnsupportedReason.CARE_MINIMUM_PARTIAL_DEDUCTION, + "A partial deduction leaves the child-in-care comparison open " + "where it can change this rate; no source carries a partial " + "amount to the mother or father family", + beneficiary_id=beneficiary_id, + ) + + +def _readjusted_for_events( + state, + beneficiaries, + payment_month, + params, + baseline, + events, + households, + worker_deductions, +): subject = [ row for row in baseline.beneficiaries if row.subject_to_family_maximum ] @@ -4706,6 +4836,16 @@ def _after_deductions( events, households, worker_deductions, + _care_minimums_after_deductions( + state, + beneficiaries, + payment_month, + params, + baseline, + events, + households, + worker_deductions, + ), ) result = _readjust_deduction_rows(*arguments, disregard_full) zero_dual = { @@ -4755,6 +4895,7 @@ def _readjust_deduction_rows( events, households, worker_deductions, + care_minimums, disregard_full, ): """Use GN 02603.050C-D with one explicit A.1 disregard decision.""" @@ -4869,14 +5010,12 @@ def _readjust_deduction_rows( rate=rate, counted=rate, ) - if ( - isinstance(member.child_in_care, str) - and member.role in _WIDOW_ROLES - ): - row.mother_father_rate = _mother_father_care_rate( - state, beneficiaries, member, payment_month, params - ) + minimum = care_minimums.get(bid) + if minimum is not None: + row.mother_father_rate = minimum.floor age_adjusted, payable = _reduce_and_offset(row, state, params) + if minimum is not None: + _refuse_unsettled_care_minimum(minimum, age_adjusted, bid) values.update( family_maximum_rate=rate, counted_against_maximum=rate + worker_deductions.get(bid, 0), @@ -4900,6 +5039,23 @@ def _readjust_deduction_rows( deduction=nh_deduction, reserved_work_deduction=nh_deduction, ) + elif bid in care_minimums: + # 402(q)(5)(D) also reaches a rate no redistribution re-rates. A + # surviving divorced caregiver sits outside the actual maximum, + # while the mother or father it compares with sits inside. + minimum = care_minimums[bid] + age_adjusted = max(old.age_adjusted_rate, minimum.floor) + _refuse_unsettled_care_minimum(minimum, age_adjusted, bid) + payable = ( + age_adjusted + if old.own_benefit is None + else max(Fraction(0), age_adjusted - old.own_benefit) + ) + values.update( + age_adjusted_rate=age_adjusted, + auxiliary_payable=payable, + whole_dollar_auxiliary=_whole_dollars_validated(payable), + ) results.append(_computed(BeneficiaryBenefit, **values)) family = { item.name: getattr(baseline, item.name) for item in fields(baseline) diff --git a/src/populace_dynamics/track_b/ret_ledger.py b/src/populace_dynamics/track_b/ret_ledger.py index 2bfd5aaae..3a8acdd85 100644 --- a/src/populace_dynamics/track_b/ret_ledger.py +++ b/src/populace_dynamics/track_b/ret_ledger.py @@ -1145,6 +1145,30 @@ def _divorced_excluded(b: RETBeneficiary, month: int) -> bool: ) +def _care_minimum_can_move(record, month, deductees): + """Whether another person's deduction can raise a 402(q)(5)(D) minimum. + + G settles it where a context names the caregiver. Without one, any + reduced surviving-spouse rate beside an entitled child stays open, and the + caller's refusal names the missing facts. + """ + if record.kind is not RecordKind.DECEASED: + return False + context = record.family_months.get(month) + if context is not None: + return bool(g._current_caregivers(context.beneficiaries)) + entitled = [b for b in record.beneficiaries if month in b.entitled_months] + return any( + b.benefit_types[month - 1] in (BenefitType.CHILD, BenefitType.CDB) + for b in entitled + ) and any( + b.beneficiary_id not in deductees + and b.benefit_types[month - 1] in (BenefitType.WIDOW, BenefitType.DWB) + and b.gross_rates[month - 1] < b.original_rates[month - 1] + for b in entitled + ) + + def _check_settled_family_facts(record: RecordYear) -> None: """Compare declarations only where G can establish the underlying fact. @@ -1556,7 +1580,10 @@ def charge(provisional: bool): # RS 02501.155A.2: charge every worker against their own adjusted # rate first. Redistribute only after all that month's workers have # been charged, so changing beneficiary order cannot change excess. - for m in sorted(record.family_maximum_binding_months): + # 402(q)(5)(D) reads this month's deductions with or without a + # binding actual maximum, because a surviving divorced caregiver + # sits outside it and the mother or father it compares with inside. + for m in range(1, 13): deductees = { k: net[k, m] for k in people @@ -1570,6 +1597,11 @@ def charge(provisional: bool): if k not in deductees ): continue + if ( + m not in record.family_maximum_binding_months + and not _care_minimum_can_move(record, m, deductees) + ): + continue if m not in record.family_months: raise _computed( RETConfigurationUnsupported, diff --git a/tests/README-tiers.md b/tests/README-tiers.md index 175db2e74..24ee27005 100644 --- a/tests/README-tiers.md +++ b/tests/README-tiers.md @@ -39,9 +39,9 @@ pytest --collect-only -q -m oracle_policyengine | tail -1 | Tier | Tests at HEAD | |---|---:| -| `unit` | 21,804 | +| `unit` | 21,868 | | `artifact` | 4,271 | | `integration_psid` | 1,471 | | `reproduction_legacy` | 520 | | `oracle_policyengine` | 308 | -| **Total** | **28,374** | +| **Total** | **28,438** | diff --git a/tests/test_track_b_gross_benefits.py b/tests/test_track_b_gross_benefits.py index 4418dd470..f094ab434 100644 --- a/tests/test_track_b_gross_benefits.py +++ b/tests/test_track_b_gross_benefits.py @@ -1937,6 +1937,31 @@ def _unsupported_cases(): g.UnsupportedReason.SOLE_FULL_DEDUCTION_ZERO_DUAL_COMPOSITION: ( lambda: _zero_dual_composition_case() ), + g.UnsupportedReason.CARE_MINIMUM_PARTIAL_DEDUCTION: lambda: ( + g.family_benefits_after_deductions( + _survivor_state(), + ( + g.Beneficiary( + "W", + g.Role.WIDOW, + reduction_months=60, + reduction_period_months=60, + child_in_care="C1", + ), + g.Beneficiary("C1", g.Role.CHILD), + g.Beneficiary("C2", g.Role.CHILD), + ), + payment_month=NOW, + params=PARAMS, + deductions={ + "C2": g.BenefitDeduction( + g.DeductionReason.OWN_EARNINGS_TEST, F(100), True + ) + }, + households={"W": "h", "C1": "h", "C2": "h"}, + standalone=True, + ) + ), g.UnsupportedReason.SAVINGS_CLAUSE_HISTORY_UNKNOWN: lambda: ( _guard(NOV, unknown=True).admit(_review_m2_path()[0]) ), diff --git a/tests/test_track_b_gross_benefits_conformance_report.py b/tests/test_track_b_gross_benefits_conformance_report.py index 1c1ce7163..91ee820de 100644 --- a/tests/test_track_b_gross_benefits_conformance_report.py +++ b/tests/test_track_b_gross_benefits_conformance_report.py @@ -188,11 +188,11 @@ def test_every_retained_refusal_has_an_executed_named_witness(reason): def test_named_witness_denominator_is_separate_from_the_lattice(regenerated): witnesses = regenerated["supplemental_refusal_witnesses"] - assert len(g.UnsupportedReason) == 38 + assert len(g.UnsupportedReason) == 39 assert witnesses["denominator"] == { - "rows": 38, + "rows": 39, "supported": 0, - "refused": 38, + "refused": 39, "invalid": 0, } expected = {reason.value for reason in g.UnsupportedReason} diff --git a/tests/test_track_b_ret_ledger_fix_round_8.py b/tests/test_track_b_ret_ledger_fix_round_8.py index f90bf33c6..356eb8809 100644 --- a/tests/test_track_b_ret_ledger_fix_round_8.py +++ b/tests/test_track_b_ret_ledger_fix_round_8.py @@ -191,12 +191,12 @@ def test_delayed_credits_can_lift_a_history_rib_past_its_pia(reason): _assert_preflight_neutral(case) -def test_a_month_before_1983_leaves_the_rate_unsettled_past_the_pia(): +def test_a_month_before_1983_keeps_the_pia_cap(): pia = F("333.30") case = _rib_record( pia, pia + F(1, 10), reason=OWN_HISTORY, cohort=1915, year=1982 ) - _assert_refusal(case, OWN_HISTORY) + _assert_invalid(case) @given( diff --git a/tests/test_track_b_ret_ledger_fix_round_9.py b/tests/test_track_b_ret_ledger_fix_round_9.py new file mode 100644 index 000000000..7a961d850 --- /dev/null +++ b/tests/test_track_b_ret_ledger_fix_round_9.py @@ -0,0 +1,961 @@ +"""Round 9: the child-in-care minimum under a month's deductions. + +Also the PIA cap on a RIB before 1983. Every record is invented or built from +a captured SSA rule. Nothing here admits a population, behavioral or forecast +claim. +""" + +from __future__ import annotations + +from fractions import Fraction as F +from pathlib import Path + +import pytest +from hypothesis import assume, example, given, settings +from hypothesis import strategies as st + +from populace_dynamics.track_b import gross_benefits as g +from populace_dynamics.track_b import ret_ledger as r +from populace_dynamics.track_b.ret_grace import BenefitType as T +from populace_dynamics.track_b.ret_params import load_ret_parameters +from tests.test_track_b_ret_ledger_fix_round_7 import ( + OWN_HISTORY, + RC, + UR, + _assert_invalid, + _assert_refusal, + _outcome, + _rib_record, +) +from tests.track_b_gross_benefit_support import source_text, ssa_params + +PARAMS = ssa_params() +RET_PARAMS = load_ret_parameters() +MONTH = g.YearMonth(2026, 1) +OWN_WORK = g.DeductionReason.OWN_EARNINGS_TEST +CAPTURES = Path(__file__).parent / "data/track_b/arf_recompute_sources" +ONE_HOUSEHOLD = {"w": "one", "c1": "one", "c2": "one"} +TWO_HOUSEHOLDS = {"w": "one", "c1": "one", "c2": "two"} + + +def _state(pia, maximum): + return g.RecordState( + g.FamilyKind.SURVIVOR, + F(pia), + F(maximum), + eligibility_year=2026, + widow_drc_savings_clause=False, + ) + + +def _caregiver(role, months=60, period=60, *, care="c1", own=None): + if role is g.Role.DISABLED_WIDOW: + return g.Beneficiary("w", role, child_in_care=care, own_benefit=own) + return g.Beneficiary( + "w", + role, + reduction_months=months, + reduction_period_months=period, + child_in_care=care, + own_benefit=own, + ) + + +def _mother(own=None): + return g.Beneficiary("w", g.Role.MOTHER_FATHER, own_benefit=own) + + +def _family(caregiver): + return ( + caregiver, + g.Beneficiary("c1", g.Role.CHILD), + g.Beneficiary("c2", g.Role.CHILD), + ) + + +def _after(state, members, events, households=ONE_HOUSEHOLD): + return g.family_benefits_after_deductions( + state, + members, + payment_month=MONTH, + params=PARAMS, + deductions=events, + households=households, + standalone=True, + ) + + +def _ordinary(state, members): + return g.family_benefits( + state, members, payment_month=MONTH, params=PARAMS, standalone=True + ) + + +def _full(permanent=True): + return g.BenefitDeduction(OWN_WORK, F(0), permanent) + + +def _partial(payable, permanent=True): + return g.BenefitDeduction(OWN_WORK, F(payable), permanent) + + +def _refuses(reason, action): + with pytest.raises(g.FamilyConfigurationUnsupported) as error: + action() + assert error.value.reason is reason + + +# --------------------------------------------------------------------------- +# Sources +# --------------------------------------------------------------------------- +def test_the_captures_carry_each_quoted_rule(): + statute = " ".join( + (CAPTURES / "lii_usc_402q_415f_excerpts.txt").read_text().split() + ) + assert ( + "had he or she been entitled for such month to mother's or father's" + " insurance benefits" in statute + ) + regulation = " ".join( + (CAPTURES / "ecfr_20cfr_404_410.xml").read_text().split() + ) + assert ( + "the benefit amount you would receive as a mother or father for any" + " month" in regulation + ) + assert ( + "they cannot receive less than the amount a mother and father would" + " receive" in source_text("poms_rs_00615_340") + ) + assert ( + "disregard that beneficiary when distributing the family maximum" + in source_text("poms_gn_02603_050") + ) + assert "not subject to a deduction" in source_text("poms_gn_02603_050") + assert ( + "Round the result down to the next dime for benefits after 5/82 and" + " up to the next dime for benefits prior to 6/82" + in source_text("poms_rs_00615_101") + ) + assert ( + "The new money amount of reduction is subtracted from the new PIA" + in source_text("poms_rs_00615_005") + ) + + +# --------------------------------------------------------------------------- +# G: the minimum reads this month's events +# --------------------------------------------------------------------------- +@pytest.mark.parametrize( + ("pia", "maximum", "months", "before", "after", "whole"), + [ + ("1.40", "2.10", 60, "0.80", "1", 1), + ("4", "6", 60, "2.40", "3", 3), + ("1000", "1500", 60, "612.80", "750", 750), + ("0.30", "0.40", 1, "0.10", "0.20", 0), + ], +) +def test_a_full_deduction_raises_the_care_minimum( + pia, maximum, months, before, after, whole +): + state = _state(pia, maximum) + members = _family(_caregiver(g.Role.WIDOW, months)) + events = {"c2": _full()} + result = _after(state, members, events) + row = result.by_id()["w"] + assert row.age_adjusted_rate == row.auxiliary_payable == F(after) + assert row.whole_dollar_auxiliary == whole + unfloored = _after( + state, _family(_caregiver(g.Role.WIDOW, months, care=False)), events + ) + assert unfloored.by_id()["w"].auxiliary_payable == F(before) + + +def test_the_minimum_moves_only_the_caregivers_own_money(): + state = _state(1000, 1500) + events = {"c2": _full()} + result = _after(state, _family(_caregiver(g.Role.WIDOW)), events) + plain = _after( + state, _family(_caregiver(g.Role.WIDOW, care=False)), events + ) + for key in ("c1", "c2"): + assert result.by_id()[key] == plain.by_id()[key] + raised, rate = result.by_id()["w"], plain.by_id()["w"] + assert raised.family_maximum_rate == rate.family_maximum_rate + assert raised.counted_against_maximum == rate.counted_against_maximum + assert result.subject_total == plain.subject_total + assert result.record_total - plain.record_total == ( + raised.auxiliary_payable - rate.auxiliary_payable + ) + + +def test_a_temporary_deduction_reaches_only_its_own_household(): + state = _state(1000, 1500) + members = _family(_caregiver(g.Role.WIDOW)) + same = _after(state, members, {"c2": _full(False)}) + assert same.by_id()["w"].auxiliary_payable == 750 + other = _after(state, members, {"c2": _full(False)}, TWO_HOUSEHOLDS) + assert other.by_id()["w"].auxiliary_payable == 500 + assert other.by_id()["w"] == _ordinary(state, members).by_id()["w"] + + +def test_a_divorced_caregiver_outside_the_maximum_keeps_the_minimum(): + # The actual family never binds, and only the comparison family does. + state = _state("2.70", "4.10") + members = _family(_caregiver(g.Role.SURVIVING_DIVORCED_SPOUSE)) + assert not _ordinary(state, members).family_maximum_binding + assert _ordinary(state, members).by_id()["w"].auxiliary_payable == F( + "1.90" + ) + result = _after(state, members, {"c2": _full()}) + row = result.by_id()["w"] + assert row.auxiliary_payable == 2 + assert row.whole_dollar_auxiliary == 2 + assert not row.subject_to_family_maximum + assert result.record_total == 2 + 2 + + +def test_a_disabled_widow_reaches_the_same_minimum(): + state = _state(1000, 1500) + members = _family(_caregiver(g.Role.DISABLED_WIDOW)) + assert _after(state, members, {"c2": _full()}).by_id()[ + "w" + ].auxiliary_payable == F(750) + + +def test_a_deducted_caregiver_keeps_the_ordinary_minimum(): + # GN 02603.050B.3 redistributes only to people not subject to a deduction, + # in the actual family and in the comparison alike. + state = _state(1000, 1500) + members = _family(_caregiver(g.Role.WIDOW)) + ordinary = _ordinary(state, members).by_id()["w"] + result = _after( + state, members, {"w": _partial(400), "c2": _full()} + ).by_id()["w"] + assert result.auxiliary_payable == 400 + assert result.age_adjusted_rate == ordinary.age_adjusted_rate + + +def test_each_caregiver_compares_alone(): + state = _state(1000, 1800) + members = ( + _caregiver(g.Role.WIDOW), + g.Beneficiary( + "s", + g.Role.SURVIVING_DIVORCED_SPOUSE, + reduction_months=60, + reduction_period_months=60, + child_in_care="c1", + ), + g.Beneficiary("c1", g.Role.CHILD), + g.Beneficiary("c2", g.Role.CHILD), + ) + households = {"w": "one", "s": "one", "c1": "one", "c2": "one"} + events = {"c2": _full()} + result = _after(state, members, events, households) + + def alone(key, first): + other = "s" if key == "w" else "w" + comparison = tuple( + ( + first + if m.beneficiary_id == key + else ( + g.Beneficiary( + other, + m.role, + reduction_months=60, + reduction_period_months=60, + child_in_care=False, + ) + if m.beneficiary_id == other + else m + ) + ) + for m in members + ) + return _after(state, comparison, events, households) + + widow = alone("w", _mother()).by_id()["w"].auxiliary_payable + divorced = ( + alone("s", g.Beneficiary("s", g.Role.MOTHER_FATHER)) + .by_id()["s"] + .auxiliary_payable + ) + # The widow's comparison leaves the divorced spouse outside the maximum, + # so the mother takes her full 750. The divorced spouse's comparison counts + # the widow, and 1,800 / 2,500 of her 750 gives 540. + assert (widow, divorced) == (750, 540) + # 71.5% of 1,000 gives each of them 715 before the minimum. + assert result.by_id()["w"].age_adjusted_rate == 750 + assert result.by_id()["s"].age_adjusted_rate == 715 + + +def test_a_deduction_on_one_caregiver_raises_the_others_minimum(): + state = _state(1000, 1500) + members = ( + _caregiver(g.Role.WIDOW), + g.Beneficiary( + "s", + g.Role.SURVIVING_DIVORCED_SPOUSE, + reduction_months=60, + reduction_period_months=60, + child_in_care="c1", + ), + g.Beneficiary("c1", g.Role.CHILD), + ) + households = {"w": "one", "s": "one", "c1": "one"} + # With the widow counted, 1,500 / 2,500 of the mother's 750 gives 450, and + # 715 stands. Her full deduction leaves the comparison 750. + assert ( + _after(state, members, {}, households).by_id()["s"].age_adjusted_rate + == 715 + ) + result = _after(state, members, {"w": _full()}, households).by_id() + assert result["w"].auxiliary_payable == 0 + assert result["s"].age_adjusted_rate == 750 + assert result["s"].auxiliary_payable == 750 + + +def test_a_dual_caregiver_takes_the_offset_after_the_minimum(): + own = g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, F(100), birth_year=1960) + state = _state(1000, 1500) + members = _family(_caregiver(g.Role.WIDOW, 60, 80, own=own)) + events = {"c2": _full()} + result = _after(state, members, events).by_id()["w"] + mother = _after(state, _family(_mother(own)), events).by_id()["w"] + plain = _after( + state, + _family(_caregiver(g.Role.WIDOW, 60, 80, care=False, own=own)), + events, + ).by_id()["w"] + assert result.age_adjusted_rate == max( + plain.age_adjusted_rate, mother.age_adjusted_rate + ) + assert result.auxiliary_payable == max( + F(0), result.age_adjusted_rate - result.own_benefit + ) + + +@pytest.mark.parametrize( + "own, maximum, rate, payable", + [ + # With room under the maximum G's minimum already raised 715 to 750, + # and the offset follows it. + (100, 3000, 750, 650), + # A dual rate takes no redistribution in either family, so the + # comparison stays below 715 under a binding maximum. + (100, 1500, 715, 615), + # A RIB at three-quarters of the PIA fails the mother's test, so the + # minimum stays out, and the offset stops at zero. + (800, 1500, 715, 0), + ], +) +def test_a_dual_caregiver_outside_the_maximum_takes_the_same_offset( + own, maximum, rate, payable +): + benefit = g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, F(own), birth_year=1960) + members = _family( + _caregiver(g.Role.SURVIVING_DIVORCED_SPOUSE, 80, 80, own=benefit) + ) + result = _after(_state(1000, maximum), members, {"c2": _full()}).by_id()[ + "w" + ] + assert result.age_adjusted_rate == rate + assert result.auxiliary_payable == payable + + +def test_a_family_with_no_events_keeps_its_ordinary_result(): + state = _state(1000, 1500) + members = _family(_caregiver(g.Role.WIDOW)) + assert _after(state, members, {}) == _ordinary(state, members) + + +# --------------------------------------------------------------------------- +# G: a partial event +# --------------------------------------------------------------------------- +def test_a_partial_deduction_refuses_where_it_can_move_the_rate(): + state = _state(1000, 1500) + members = _family(_caregiver(g.Role.WIDOW)) + _refuses( + g.UnsupportedReason.CARE_MINIMUM_PARTIAL_DEDUCTION, + lambda: _after(state, members, {"c2": _partial(350)}), + ) + + +def test_a_partial_deduction_refuses_outside_the_maximum_too(): + state = _state("2.70", "4.10") + members = _family(_caregiver(g.Role.SURVIVING_DIVORCED_SPOUSE)) + _refuses( + g.UnsupportedReason.CARE_MINIMUM_PARTIAL_DEDUCTION, + lambda: _after(state, members, {"c2": _partial("1")}), + ) + + +def test_a_partial_deduction_computes_where_the_minimum_cannot_reach(): + state = _state(1000, 2400) + members = _family(_caregiver(g.Role.WIDOW, 1)) + events = {"c2": _partial(700)} + result = _after(state, members, events).by_id()["w"] + plain = _after( + state, _family(_caregiver(g.Role.WIDOW, 1, care=False)), events + ).by_id()["w"] + assert result.auxiliary_payable == plain.auxiliary_payable > 750 + + +def test_a_partial_deduction_keeps_a_minimum_it_cannot_change(): + # Another household's temporary event moves no comparison rate. + state = _state(1000, 1500) + members = _family(_caregiver(g.Role.WIDOW)) + result = _after( + state, members, {"c2": _partial(350, False)}, TWO_HOUSEHOLDS + ) + assert result.by_id()["w"].auxiliary_payable == 500 + + +def test_a_full_and_a_partial_event_share_the_partial_refusal(): + state = _state(1000, 1800) + members = ( + _caregiver(g.Role.WIDOW), + g.Beneficiary("c1", g.Role.CHILD), + g.Beneficiary("c2", g.Role.CHILD), + g.Beneficiary("c3", g.Role.CHILD), + ) + households = {"w": "one", "c1": "one", "c2": "one", "c3": "one"} + _refuses( + g.UnsupportedReason.CARE_MINIMUM_PARTIAL_DEDUCTION, + lambda: _after( + state, + members, + {"c2": _full(), "c3": _partial(100)}, + households, + ), + ) + + +def test_the_refusal_keeps_the_input_checks_first(): + state = _state(1000, 1500) + members = _family(_caregiver(g.Role.WIDOW)) + with pytest.raises(g.InvalidFamilyInput): + _after(state, members, {"c2": _partial(4000)}) + + +def test_nh_reservations_refuse_on_a_comparison(): + state = _state(1000, 1500) + members = _family(_caregiver(g.Role.SURVIVING_DIVORCED_SPOUSE)) + _refuses( + g.UnsupportedReason.DEDUCTION_AGE_WORK_INTERACTION, + lambda: g.family_benefits_after_deductions( + state, + members, + payment_month=MONTH, + params=PARAMS, + deductions={"c2": _full()}, + households=ONE_HOUSEHOLD, + worker_deductions={"c1": F(100)}, + standalone=True, + ), + ) + + +def _with_nh_reservation(state, members, events): + return g.family_benefits_after_deductions( + state, + members, + payment_month=MONTH, + params=PARAMS, + deductions=events, + households=ONE_HOUSEHOLD, + worker_deductions={"c1": F(100)}, + standalone=True, + ) + + +def test_a_deducted_caregiver_reaches_no_comparison(): + # The refusal above needs a comparison, and this month's only caregiver + # keeps G's ordinary minimum. + members = _family(_caregiver(g.Role.SURVIVING_DIVORCED_SPOUSE)) + result = _with_nh_reservation( + _state(1000, 1500), members, {"w": _full()} + ).by_id() + assert result["w"].auxiliary_payable == 0 + assert result["c1"].reserved_work_deduction == 100 + + +def test_an_unentitled_caregiver_reaches_no_comparison(): + own = g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, F(1200), birth_year=1960) + members = _family( + _caregiver(g.Role.SURVIVING_DIVORCED_SPOUSE, 60, 80, own=own) + ) + result = _with_nh_reservation( + _state(1000, 1500), members, {"c2": _full()} + ).by_id() + assert result["w"].entitled is False + assert result["w"].auxiliary_payable == 0 + + +def test_a_living_workers_divorced_spouse_has_no_care_minimum(): + # 402(q)(5)(D) names a widow's or widower's benefit, and a divorced spouse + # of a living worker can still declare a child in care. + state = g.RecordState( + g.FamilyKind.RETIREMENT, + F(1000), + F(1500), + worker=g.OwnBenefit(g.OwnBenefitKind.OLD_AGE, F(1000)), + ) + members = ( + g.Beneficiary("w", g.Role.DIVORCED_SPOUSE, child_in_care="c1"), + g.Beneficiary("c1", g.Role.CHILD), + g.Beneficiary("c2", g.Role.CHILD), + ) + ordinary = _ordinary(state, members).by_id()["w"] + result = _after(state, members, {"c2": _full()}).by_id()["w"] + assert result.auxiliary_payable == ordinary.auxiliary_payable + + +# --------------------------------------------------------------------------- +# G: invariants over random families, through the public API +# --------------------------------------------------------------------------- +ROLES = st.sampled_from( + (g.Role.WIDOW, g.Role.SURVIVING_DIVORCED_SPOUSE, g.Role.DISABLED_WIDOW) +) +families = st.tuples( + st.integers(3, 30_000).map(lambda n: F(n, 10)), + st.integers(100, 190), + ROLES, + st.sampled_from((1, 12, 30, 60)), +) + + +def _maximum(pia, percent): + return g.floor_dime(pia * F(percent, 100)) + + +@given(family=families, permanent=st.booleans(), same=st.booleans()) +@example(family=(F("1.40"), 150, g.Role.WIDOW, 60), permanent=True, same=True) +@example( + family=(F("2.70"), 152, g.Role.SURVIVING_DIVORCED_SPOUSE, 60), + permanent=True, + same=True, +) +@settings(max_examples=250, deadline=None) +def test_the_minimum_equals_the_better_of_the_two_public_families( + family, permanent, same +): + pia, percent, role, months = family + state = _state(pia, _maximum(pia, percent)) + households = ONE_HOUSEHOLD if same else TWO_HOUSEHOLDS + events = {"c2": _full(permanent)} + care = _family(_caregiver(role, months)) + plain = _family(_caregiver(role, months, care=False)) + mother = _family(_mother()) + # An own-work event must withhold something in each family. + assume(_ordinary(state, plain).by_id()["c2"].auxiliary_payable > 0) + assume(_ordinary(state, mother).by_id()["c2"].auxiliary_payable > 0) + actual = _after(state, care, events, households).by_id() + without = _after(state, plain, events, households).by_id() + comparison = _after(state, mother, events, households).by_id() + assert actual["w"].age_adjusted_rate == max( + without["w"].age_adjusted_rate, comparison["w"].auxiliary_payable + ) + assert actual["c1"] == without["c1"] + assert actual["c2"] == without["c2"] + + +@given( + family=families, + permanent=st.booleans(), + same=st.booleans(), + second=st.booleans(), + share=st.fractions(0, 1), +) +@settings(max_examples=250, deadline=None) +def test_any_partial_amount_stays_between_the_two_bounds( + family, permanent, same, second, share +): + pia, percent, _, _ = family + state = _state(pia, _maximum(pia, percent)) + households = ONE_HOUSEHOLD if same else TWO_HOUSEHOLDS + mother = _family(_mother()) + ordinary = _ordinary(state, mother).by_id() + gross = ordinary["c2"].auxiliary_payable + assume(gross >= F(2, 10)) + assume(ordinary["c1"].auxiliary_payable > 0) + payable = min(g.floor_dime(gross * share), gross - F(1, 10)) + extra = {"c1": _full(permanent)} if second else {} + filled = _after( + state, + mother, + {"c2": _partial(payable, permanent), **extra}, + households, + ).by_id()["w"] + highest = _after( + state, mother, {"c2": _full(permanent), **extra}, households + ).by_id()["w"] + low = ordinary["w"].age_adjusted_rate + assert low <= filled.age_adjusted_rate <= highest.age_adjusted_rate + + +@given(family=families, payable_share=st.fractions(0, 1)) +@settings(max_examples=250, deadline=None) +def test_a_partial_deduction_computes_or_refuses_within_bounds( + family, payable_share +): + pia, percent, role, months = family + state = _state(pia, _maximum(pia, percent)) + care = _family(_caregiver(role, months)) + plain = _family(_caregiver(role, months, care=False)) + mother = _family(_mother()) + gross = _ordinary(state, care).by_id()["c2"].auxiliary_payable + assume(gross >= F(2, 10)) + assume(_ordinary(state, mother).by_id()["c2"].auxiliary_payable > 0) + payable = min(g.floor_dime(gross * payable_share), gross - F(1, 10)) + assume(payable > 0) + events = {"c2": _partial(payable)} + without = _after(state, plain, events).by_id()["w"].age_adjusted_rate + ordinary = _ordinary(state, mother).by_id()["w"].age_adjusted_rate + highest = _after(state, mother, {"c2": _full()}).by_id()["w"] + try: + actual = _after(state, care, events).by_id()["w"].age_adjusted_rate + except g.FamilyConfigurationUnsupported as error: + assert ( + error.reason is g.UnsupportedReason.CARE_MINIMUM_PARTIAL_DEDUCTION + ) + assert highest.age_adjusted_rate > max(without, ordinary) + else: + assert highest.age_adjusted_rate <= max(without, ordinary) + assert actual == max(without, ordinary) + + +# --------------------------------------------------------------------------- +# RET: the ledger reads the same minimum +# --------------------------------------------------------------------------- +def _wages(excess): + return RET_PARAMS.for_year(2026).lower_exempt_amount.value + 2 * excess + + +def _ret_case( + state, members, excess, *, households=ONE_HOUSEHOLD, context=True +): + baseline = _ordinary(state, members) + people = [] + for row in baseline.beneficiaries: + kind = T.CHILD if row.role is g.Role.CHILD else T.WIDOW + wages = ( + _wages(excess[row.beneficiary_id]) + if (row.beneficiary_id in excess) + else F(0) + ) + people.append( + r.RETBeneficiary( + row.beneficiary_id, + (kind,) * 12, + {1}, + (row.auxiliary_payable,) + (F(0),) * 11, + (row.original_benefit,) * 12, + earnings=r.WorkEarnings((wages,) + (F(0),) * 11), + fra_month=( + 0 + if kind is T.WIDOW and row.beneficiary_id not in excess + else None + ), + ) + ) + return r.RecordYear( + 2026, + "nh", + r.RecordKind.DECEASED, + tuple(people), + family_maximum_binding_months=( + frozenset({1}) if baseline.family_maximum_binding else frozenset() + ), + family_months=( + {1: r.RETFamilyMonth(state, members, PARAMS, households)} + if context + else {} + ), + ) + + +def _ret(case): + return r.evaluate_ret( + "round9", F(1), lambda: r.apply_ret_year(case, RET_PARAMS) + ) + + +def _january(outcome, key): + return next( + row for row in outcome.ledger.for_beneficiary(key) if row.month == 1 + ) + + +def test_ret_pays_the_minimum_on_a_binding_month(): + case = _ret_case( + _state("1.40", "2.10"), + _family(_caregiver(g.Role.WIDOW)), + {"c2": 1}, + ) + assert case.family_maximum_binding_months == {1} + outcome = _ret(case) + assert outcome.supported + row = _january(outcome, "w") + assert row.net_due == 1 + assert row.payment == 1 + assert row.deduction == 0 + + +def test_ret_pays_the_minimum_on_a_month_with_no_binding_maximum(): + case = _ret_case( + _state("2.70", "4.10"), + _family(_caregiver(g.Role.SURVIVING_DIVORCED_SPOUSE)), + {"c2": 2}, + ) + assert not case.family_maximum_binding_months + outcome = _ret(case) + assert outcome.supported + row = _january(outcome, "w") + assert row.net_due == 2 + assert row.payment == 2 + + +def test_ret_leaves_a_family_with_no_care_alone(): + case = _ret_case( + _state("2.70", "4.10"), + _family(_caregiver(g.Role.SURVIVING_DIVORCED_SPOUSE, care=False)), + {"c2": 2}, + ) + outcome = _ret(case) + assert outcome.supported + assert _january(outcome, "w").net_due == F("1.90") + + +def test_ret_refuses_a_partial_month_the_minimum_turns_on(): + case = _ret_case( + _state(1000, 1500), _family(_caregiver(g.Role.WIDOW)), {"c2": 100} + ) + outcome = _ret(case) + assert not outcome.supported + assert ( + outcome.unsupported.reason + is g.UnsupportedReason.CARE_MINIMUM_PARTIAL_DEDUCTION + ) + counts = r.count_ret_outcomes([outcome]) + assert (counts.rows, counts.unsupported_weight) == (1, 1) + + +def test_ret_needs_the_family_facts_where_a_minimum_can_move(): + case = _ret_case( + _state("2.70", "4.10"), + _family(_caregiver(g.Role.SURVIVING_DIVORCED_SPOUSE)), + {"c2": 2}, + context=False, + ) + outcome = _ret(case) + assert not outcome.supported + assert ( + outcome.unsupported.reason + is r.UnsupportedReason.FAMILY_CONTEXT_REQUIRED + ) + + +def test_an_unreduced_survivor_needs_no_family_facts(): + state = _state("2.70", "4.10") + case = _ret_case( + state, + _family(_caregiver(g.Role.SURVIVING_DIVORCED_SPOUSE, 0, None)), + {"c2": 2}, + context=False, + ) + assert _ret(case).supported + + +def test_a_deduction_on_a_survivor_alone_needs_no_family_facts(): + state = _state("2.70", "4.10") + members = (_caregiver(g.Role.SURVIVING_DIVORCED_SPOUSE, care=None),) + case = _ret_case(state, members, {"w": 1}, context=False) + outcome = _ret(case) + assert outcome.supported + assert _january(outcome, "w").deduction == 1 + + +def _beneficiary(key, kind, gross, original, excess, months): + rate = F(gross) if 1 in months else F(0) + wages = _wages(excess) if excess else F(0) + return r.RETBeneficiary( + key, + (kind,) * 12, + months, + (rate,) + (F(0),) * 11, + (F(original),) * 12, + earnings=r.WorkEarnings((wages,) + (F(0),) * 11), + fra_month=None if kind is T.CHILD or excess else 0, + ) + + +def _deceased(*people): + return r.RecordYear( + 2026, + "nh", + r.RecordKind.DECEASED, + tuple(_beneficiary(*person) for person in people), + ) + + +CHILD = ("c1", T.CHILD, 500, 500, 0, {1}) +WORKING_CHILD = ("c2", T.CHILD, 500, 500, 100, {1}) + + +@pytest.mark.parametrize("kind", [T.WIDOW, T.DWB]) +def test_a_reduced_survivor_beside_a_child_needs_the_family_facts(kind): + outcome = _ret( + _deceased(("w", kind, 715, 1000, 0, {1}), CHILD, WORKING_CHILD) + ) + assert not outcome.supported + assert ( + outcome.unsupported.reason + is r.UnsupportedReason.FAMILY_CONTEXT_REQUIRED + ) + + +@pytest.mark.parametrize( + "people", + [ + pytest.param( + ( + ("w", T.WIDOW, 715, 1000, 0, {1}), + ("s", T.WIDOW, 715, 1000, 100, {1}), + ), + id="no child", + ), + pytest.param( + ( + ("w", T.WIDOW, 715, 1000, 0, {1}), + ("s", T.WIDOW, 715, 1000, 100, {1}), + ("c1", T.CHILD, 500, 500, 0, {2}), + ), + id="child outside the month", + ), + pytest.param( + (("w", T.WIDOW, 715, 1000, 100, {1}), CHILD), + id="the only reduced survivor takes the deduction", + ), + pytest.param( + (("w", T.WIDOW, 715, 1000, 0, {2}), CHILD, WORKING_CHILD), + id="survivor outside the month", + ), + pytest.param( + (("m", T.MOTHER_FATHER, 700, 750, 0, {1}), CHILD, WORKING_CHILD), + id="a mother has no minimum", + ), + ], +) +def test_no_minimum_can_move_on_these_records(people): + outcome = _ret(_deceased(*people)) + assert outcome.supported + working = [person[0] for person in people if person[4]] + assert working + for key in working: + assert _january(outcome, key).deduction > 0 + + +def test_a_living_workers_record_has_no_care_minimum(): + record = r.RecordYear( + 2026, + "n", + r.RecordKind.RETIREMENT, + ( + _beneficiary("n", T.RIB, 1000, 1000, 0, {1}), + _beneficiary("w", T.WIDOW, 715, 1000, 0, {1}), + _beneficiary(*WORKING_CHILD), + ), + ) + assert _ret(record).supported + + +# The ledger skips G on these months. A mutation that always reaches G changes +# no outcome, and this differential holds the two answers together. +@given( + pia=st.integers(10, 30_000).map(lambda n: F(n, 10)), + percent=st.integers(150, 190), + excess=st.integers(1, 3000), +) +@settings(max_examples=60, deadline=None) +def test_with_no_caregiver_an_unbound_month_matches_g(pia, percent, excess): + state = _state(pia, _maximum(pia, percent)) + members = _family(_caregiver(g.Role.SURVIVING_DIVORCED_SPOUSE, care=False)) + baseline = _ordinary(state, members) + assume(not baseline.family_maximum_binding) + assume(baseline.by_id()["c2"].auxiliary_payable > 0) + case = _ret_case(state, members, {"c2": excess}) + outcome = _ret(case) + assert outcome.supported + direct = _after( + state, members, {"c2": _partial(_january(outcome, "c2").net_due)} + ) + for row in direct.beneficiaries: + assert ( + _january(outcome, row.beneficiary_id).net_due + == row.auxiliary_payable + ) + + +# --------------------------------------------------------------------------- +# The PIA cap before 1983 +# --------------------------------------------------------------------------- +@pytest.mark.parametrize("year", [1981, 1982]) +@pytest.mark.parametrize( + ("pia", "gross"), + [("0.10", "0.20"), ("400", "400.10"), ("1000", "1000.10")], +) +@pytest.mark.parametrize("months", [0, 8]) +def test_a_rib_above_its_pia_is_an_input_error_before_1983( + year, pia, gross, months +): + _assert_invalid(_rib_record(F(pia), F(gross), months=months, year=year)) + + +def test_money_history_keeps_the_same_cap_before_1983(): + pia = F("333.30") + _assert_invalid( + _rib_record( + pia, pia + F(1, 10), reason=OWN_HISTORY, cohort=1915, year=1982 + ) + ) + + +def test_delayed_credits_keep_the_refusal_before_1983(): + pia = F("333.30") + _assert_refusal( + _rib_record( + pia, + pia + F(1, 10), + reason=OWN_HISTORY, + cohort=1915, + credits=12, + year=1982, + ), + OWN_HISTORY, + ) + + +def test_a_rate_at_or_below_the_pia_keeps_the_refusal_before_1983(): + pia = F("333.30") + for gross in (pia, pia - F(1, 10), F(1)): + _assert_refusal( + _rib_record(pia, gross, year=1982), UR.PAYMENT_MONTH_BEFORE_1983 + ) + + +def test_finality_keeps_its_refusal_before_1983(): + # RS 00615.754A.3 protects a rate above the correct PIA. + pia = F("333.30") + _assert_refusal( + _rib_record( + pia, + pia + F(1, 10), + conditions=(RC.ADMINISTRATIVE_FINALITY,), + year=1982, + ), + UR.ADMINISTRATIVE_FINALITY, + ) + assert _outcome(_rib_record(pia, pia, year=1982)).unsupported is not None diff --git a/tests/tier_counts.json b/tests/tier_counts.json index 0358b6b75..99f1783bb 100644 --- a/tests/tier_counts.json +++ b/tests/tier_counts.json @@ -1,7 +1,7 @@ { "schema_version": 1, "counts": { - "unit": 21804, + "unit": 21868, "artifact": 4271, "integration_psid": 1471, "reproduction_legacy": 520, From bc460e3266ce99ecf5f4f0a87a8e59b39733585e Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 1 Nov 2026 19:13:37 -0500 Subject: [PATCH 15/17] Take CI's tier count for round 9 The new refusal reason also adds four parametrized cases in tests/test_track_b_ret_ledger_fix_round_6.py, outside the round's count, so CI collects 22,032 unit tests. Co-Authored-By: Claude Opus 5.5 --- tests/README-tiers.md | 4 ++-- tests/tier_counts.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/README-tiers.md b/tests/README-tiers.md index a50c86470..cf4eaef49 100644 --- a/tests/README-tiers.md +++ b/tests/README-tiers.md @@ -39,9 +39,9 @@ pytest --collect-only -q -m oracle_policyengine | tail -1 | Tier | Tests at HEAD | |---|---:| -| `unit` | 22,028 | +| `unit` | 22,032 | | `artifact` | 4,271 | | `integration_psid` | 1,471 | | `reproduction_legacy` | 520 | | `oracle_policyengine` | 308 | -| **Total** | **28,598** | +| **Total** | **28,602** | diff --git a/tests/tier_counts.json b/tests/tier_counts.json index aed170c96..eb147e2e5 100644 --- a/tests/tier_counts.json +++ b/tests/tier_counts.json @@ -1,7 +1,7 @@ { "schema_version": 1, "counts": { - "unit": 22028, + "unit": 22032, "artifact": 4271, "integration_psid": 1471, "reproduction_legacy": 520, From 434a39c618cc26f0a1cd4c37eac99e58e58b48d0 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Mon, 2 Nov 2026 10:14:26 -0500 Subject: [PATCH 16/17] Track B R2: keep another caregiver's care facts in each comparison Sol's ninth review of bc460e32 found one medium and one low, and both reproduced. - The child-in-care comparison cleared every other widow(er)'s care flag. 402(q)(5)(D) replaces one entitlement, so another caregiver keeps its own minimum there. Without it, G counted a deducted caregiver's whole age reduction against the maximum, and the first caregiver's comparison came out low: $1,287 where the rule pays $1,349.30, and $715 where it pays $746.60, through G, the household entry and RET's provisional ledger. The comparison now changes only the caregiver it compares. Each nesting converts one more caregiver, so the recursion ends. - One call computes each comparison family once. A family depends only on which caregivers it has converted, so a call with k caregivers runs at most 2^k families. - RET asked for family facts below any widow(er)'s original rate. A survivor child's OB and a mother's are both 3/4 of the PIA, and no comparison passes a mother's OB, so RET now asks only below the lower of the widow(er)'s original rate and an entitled child's. A widow at $905 beside a child at $750 now computes, and pays what G pays with the facts. Money moves for a child-in-care widow(er) beside another caregiver who takes a deduction, and only there. A seeded sweep of 4,000 invented two-caregiver families moved 11, all on a month with a deduction. Invariants: each caregiver gets the better of its reduced rate and what it would receive as a mother or father where only its entitlement changes. No comparison passes a mother's OB. One call computes each comparison family once. A month RET settles without family facts pays what G pays with them. Co-Authored-By: Claude Opus 5.5 --- docs/design/track_b_g_gross_benefits.md | 7 +- docs/design/track_b_r2_ret_ledger.md | 107 ++- .../track_b/gross_benefits.py | 120 +++- src/populace_dynamics/track_b/ret_ledger.py | 20 +- tests/README-tiers.md | 4 +- tests/test_track_b_ret_ledger_fix_round_10.py | 645 ++++++++++++++++++ tests/test_track_b_ret_ledger_fix_round_9.py | 34 +- tests/tier_counts.json | 2 +- 8 files changed, 866 insertions(+), 73 deletions(-) create mode 100644 tests/test_track_b_ret_ledger_fix_round_10.py diff --git a/docs/design/track_b_g_gross_benefits.md b/docs/design/track_b_g_gross_benefits.md index 6e2a6b7ba..201d829c5 100644 --- a/docs/design/track_b_g_gross_benefits.md +++ b/docs/design/track_b_g_gross_benefits.md @@ -343,7 +343,9 @@ For one worker's record and one benefit month: redistribution; the actual widow's own-benefit offset follows. After a deduction the comparison takes the month's events and households (402(q)(5)(D); RS 00615.340), and a partial deduction refuses where it - can change the rate. + can change the rate. The comparison replaces only that caregiver's + entitlement, so another caregiver keeps its care facts and its own + minimum there. 6. **Dual entitlement** (402(k)(3)(A)). The auxiliary benefit is reduced, but not below zero, by the own benefit after 402(q). - An aged spouse entitled to the own benefit in or before the spouse @@ -1477,7 +1479,8 @@ stays outside the maximum and does not lower anyone else's share. The comparison replaces the caregiver with a mother/father entitlement, whose OB is 75 percent of the death PIA (202(g)(2)), applies the family maximum and settled Parisi rules as that entitlement would be paid, and -keeps any own-benefit offset. The widow gets whichever amount is larger. +keeps any own-benefit offset. Every other member keeps its declared facts, +another caregiver's care included. The widow gets whichever amount is larger. With PIA $1,000 and maximum $1,750, a 1935 widow reduced for 60 months and one child receives $750 with the child in care, rather than $715 without; the child receives $750 in either case and the caring total is $1,500. diff --git a/docs/design/track_b_r2_ret_ledger.md b/docs/design/track_b_r2_ret_ledger.md index c22eaaf40..b39c46dd6 100644 --- a/docs/design/track_b_r2_ret_ledger.md +++ b/docs/design/track_b_r2_ret_ledger.md @@ -2639,8 +2639,9 @@ room and the widow(er) did not: `_care_minimums_after_deductions` now builds the comparison family and runs that month's events and households through the same readjustment. A temporary deduction in another household frees nothing, so that widow(er) stays at $500 -in the third row. Each caregiver compares alone, so a deduction on one can -raise the other's minimum. A deductee keeps G's ordinary minimum, because GN +in the third row. Each caregiver's comparison replaces only its own +entitlement (round 10 corrected a reading that cleared the other's care), so a +deduction on one can raise the other's minimum. A deductee keeps G's ordinary minimum, because GN 02603.050B.3 redistributes only to people "not subject to a deduction", in either family. @@ -2703,12 +2704,12 @@ stays refused, and finality and positive delayed credits keep their rows. | The minimum equals the better of the reduced rate and what a mother or father receives this month, under this month's events and households | `test_a_full_deduction_raises_the_care_minimum`; `test_a_temporary_deduction_reaches_only_its_own_household`; Hypothesis `test_the_minimum_equals_the_better_of_the_two_public_families` | | The minimum moves only the caregiver's own money, and leaves the maximum accounting alone | `test_the_minimum_moves_only_the_caregivers_own_money` | | The rule reaches a caregiver outside the maximum and a disabled widow(er) | `test_a_divorced_caregiver_outside_the_maximum_keeps_the_minimum`; `test_a_disabled_widow_reaches_the_same_minimum` | -| Each caregiver compares alone, and a deductee keeps the ordinary minimum | `test_each_caregiver_compares_alone`; `test_a_deduction_on_one_caregiver_raises_the_others_minimum`; `test_a_deducted_caregiver_keeps_the_ordinary_minimum` | +| Each caregiver compares with only its own entitlement replaced (round 10 corrected "compares alone"), and a deductee keeps the ordinary minimum | `test_each_caregiver_compares_with_only_its_entitlement_replaced`; `test_a_deduction_on_one_caregiver_raises_the_others_minimum`; `test_a_deducted_caregiver_keeps_the_ordinary_minimum` | | Only a current, entitled, undeducted widow(er) reaches a comparison | `test_a_deducted_caregiver_reaches_no_comparison`; `test_an_unentitled_caregiver_reaches_no_comparison`; `test_a_living_workers_divorced_spouse_has_no_care_minimum` | | A dual caregiver takes the offset after the minimum, and the offset stops at zero | `test_a_dual_caregiver_takes_the_offset_after_the_minimum`; `test_a_dual_caregiver_outside_the_maximum_takes_the_same_offset` | | A partial deduction computes only where every amount between the two bounds agrees, and otherwise refuses with its row and weight | Hypothesis `test_any_partial_amount_stays_between_the_two_bounds`; Hypothesis `test_a_partial_deduction_computes_or_refuses_within_bounds`; `test_a_partial_deduction_refuses_where_it_can_move_the_rate`; `test_ret_refuses_a_partial_month_the_minimum_turns_on` | | RET pays the minimum with or without a binding maximum | `test_ret_pays_the_minimum_on_a_binding_month`; `test_ret_pays_the_minimum_on_a_month_with_no_binding_maximum` | -| RET asks for family facts exactly where a minimum can move | `test_a_reduced_survivor_beside_a_child_needs_the_family_facts`; `test_no_minimum_can_move_on_these_records`; `test_an_unreduced_survivor_needs_no_family_facts`; `test_a_living_workers_record_has_no_care_minimum` | +| RET asks for family facts wherever a minimum can move. Without a context it can't tell every such month apart, so it also asks on some months where G leaves the rate alone (round 10 narrowed that request) | `test_a_reduced_survivor_beside_a_child_needs_the_family_facts`; `test_no_minimum_can_move_on_these_records`; `test_an_unreduced_survivor_needs_no_family_facts`; `test_a_living_workers_record_has_no_care_minimum` | | With no caregiver, an unbound RET month equals G | Hypothesis `test_with_no_caregiver_an_unbound_month_matches_g` | | With no delayed credits, no RIB exceeds its PIA in any month, 1981 and 1982 included | `test_a_rib_above_its_pia_is_an_input_error_before_1983`; `test_money_history_keeps_the_same_cap_before_1983` | | Before 1983, delayed credits, finality and a rate at or below the PIA keep their refusal | `test_delayed_credits_keep_the_refusal_before_1983`; `test_finality_keeps_its_refusal_before_1983`; `test_a_rate_at_or_below_the_pia_keeps_the_refusal_before_1983` | @@ -2721,3 +2722,101 @@ them. A second pass caught two of those new cases testing nothing: they set `fra_month=0`, past full retirement age, so no deduction applied. The older survivor-alone test had the same flaw. Each of them now asserts the deduction. The eleventh survivor stays out of the ledger as equivalent, as above. + +## PR 563 round 10: a caregiver keeps its care facts in another's comparison + +GPT-6.1 Sol reviewed `bc460e32` and asked for changes, with one medium and one +low finding. Both reproduced. The medium underpaid a supported surviving +spouse through G and through RET's provisional ledger. The low kept a refusal +where no minimum could reach the rate. + +### What changed + +**Another caregiver keeps its care facts.** Act 202(q)(5)(D) compares a +widow's or widower's benefit with what the person would have had "had he or +she been entitled for such month to mother's or father's insurance benefits". +That text replaces one entitlement. Round 9's comparison also cleared every +other widow(er)'s care flag, so a second caregiver lost its own minimum inside +the first one's comparison. When that second caregiver took a deduction, G +counted its whole age reduction against the maximum, though its minimum +leaves less of its share unpaid, and the first caregiver's comparison came out +low. Sol's cases put a surviving divorced spouse and a widow in care of one +child, with a temporary own-work deduction on the widow in the same household: + +| PIA | Maximum | Cohort and reduction | Rate at `bc460e32` | Rate now | +| --- | --- | --- | --- | --- | +| $2.70 | $4.20 | 1960, 80 of 80 | $1.90 | $2.00 | +| $1,000 | $1,600 | 1966, 84 of 84 | $715 | $746.60 | +| $1,688 | $2,586.90 | 1966, 84 of 84 | $1,206.90 | $1,207.20 | +| $1,800 | $2,891.50 | 1966, 84 of 84 | $1,287 | $1,349.30 | + +In the last row the widow's share in the former spouse's comparison is +$1,156.60 and the widow's minimum pays $963.80, so the deduction leaves +$192.80 counted against the maximum (GN 02603.050C). The mother then takes +$1,350 × ($2,891.50 − $192.80) / $2,700 = $1,349.30. The $1,688 row uses that +PIA's 2026 formula maximum, and its whole-dollar payment moves from $1,206 to +$1,207. + +`_mother_father_comparison` now changes only the caregiver it compares. Every +other member keeps its declared facts, care included, so each nested +comparison applies the same rule in a family where one more caregiver has +become a mother or father. Each nesting converts one more caregiver, so the +recursion ends. The fix reaches a disabled widow(er) deductee, a dual +deductee on a temporary or permanent event, and RET's provisional ledger: +Sol's provisional case now pays $746.60 where `bc460e32` paid $715, and the +final $750 stays. + +**One call computes each comparison family once.** Nested comparisons reach +the same family in different orders. A family depends only on which +caregivers it has converted, so `_care_scope` opens one cache for each call to +`_family_benefits` or `_after_deductions`, and `_care_comparison` keys each +family by its record, members, month and parameters, plus its events and +households for the deduction comparison. A call with k caregivers runs at most +2^k families. Without the cache, six caregivers ran 1,957 family +computations; with it they run 64. G sets no bound on how many +caregivers a family holds, so the cost still grows with that number. + +**RET asks for family facts only where a minimum can reach the rate.** +Without a context, round 9 asked for facts wherever a widow(er)'s rate sat +below its original rate beside an entitled child. A survivor child's OB and a +mother's are both 3/4 of the PIA (402(d)(2), 402(g)(2)). A readjusted rate +stops at its OB, and the new property finds no comparison above a mother's +OB. So no minimum reaches a rate at or above a child's original rate, and +`_care_minimum_can_move` now asks only below the lower of the two. Sol's +record, a widow at $905 of $1,000 beside a working child at $750, now computes +without the facts. It pays what G pays with them: $905 to the widow and the +child's $750 withheld, final and provisional. + +**Round 9's tests.** `test_each_caregiver_compares_alone` built each +comparison with the other caregiver's care cleared. It now keeps that care, as +`test_each_caregiver_compares_with_only_its_entitlement_replaced`, and its +amounts stand: in that family neither caregiver's minimum changes the other's +comparison. Two RET records gave a child a $500 OB beside a widow's $1,000. A +survivor child's OB on that PIA is $750, and the records now say so. + +### What stayed + +- **A deductee keeps G's ordinary minimum** (GN 02603.050B.3), in the actual + family and now in each comparison too. +- **The ordinary family.** A seeded sweep of 4,000 invented two-caregiver + families moved 11, all on a month with a deduction. The 2,016 without a + deduction kept every outcome, refusals and input errors included. +- **The partial-deduction refusal** and its two bounds. +- **Sol's `needs_max` items need no new call.** Sol read 402(q)(5)(D) as + replacing only the one entitlement, and no source clears another + caregiver's care. + +### New executed invariants + +| Invariant | Executing tests in `test_track_b_ret_ledger_fix_round_10.py` | +| --- | --- | +| Each caregiver's rate equals the better of its own reduced rate and what it would receive as a mother or father where only its entitlement changes, under the month's events and households | `test_another_deducted_caregiver_keeps_its_minimum`; `test_a_deducted_disabled_widow_keeps_the_minimum`; `test_a_formula_maximum_moves_a_whole_dollar`; `test_a_dual_deductee_keeps_its_minimum_either_way`; `test_each_event_reaches_the_comparison_as_it_reaches_the_family`; `test_three_caregivers_each_compare_with_one_entitlement_replaced`; Hypothesis `test_each_caregiver_takes_the_better_of_its_rate_and_its_comparison` | +| The family and household entries agree | `test_the_family_and_household_entries_agree` | +| No comparison passes a mother's OB | Hypothesis `test_each_caregiver_takes_the_better_of_its_rate_and_its_comparison` | +| One call computes each comparison family once, at most 2^k for k caregivers; the cache ends with its call and keeps records, households and events apart | `test_each_comparison_family_runs_once`; `test_the_comparison_cache_ends_with_its_call`; `test_one_scope_keeps_records_households_and_events_apart` | +| RET's provisional ledger pays the same minimum | `test_ret_pays_the_minimum_on_the_provisional_ledger` | +| Without a context, RET asks for family facts only below the lower of a widow(er)'s original rate and an entitled child's, and a month it settles without them pays what G pays with them | `test_a_rate_past_any_minimum_needs_no_family_facts`; `test_a_childs_original_rate_bounds_the_request`; `test_the_higher_of_two_declared_child_rates_bounds_the_request`; `test_a_widows_own_original_rate_still_bounds_the_request`; Hypothesis `test_a_month_ret_settles_without_family_facts_matches_g` | + +25 of the module's 37 tests fail against `bc460e32`, and round 9's 62 +all pass there. `scratch/review/round10_mutate.py` lists 22 mutations; a +Fleet ops hold on local mutation runs puts their results in a later commit. diff --git a/src/populace_dynamics/track_b/gross_benefits.py b/src/populace_dynamics/track_b/gross_benefits.py index 63303668f..5bbe3d26d 100644 --- a/src/populace_dynamics/track_b/gross_benefits.py +++ b/src/populace_dynamics/track_b/gross_benefits.py @@ -258,6 +258,7 @@ import math from collections import Counter from collections.abc import Callable, Iterable, Mapping, Sequence +from contextvars import ContextVar from dataclasses import dataclass, field, fields from datetime import date from decimal import Decimal @@ -3907,33 +3908,41 @@ def _mother_father_care_rate( for a surviving divorced caregiver (RS 00615.682). Only the actual 202(e)/(f) surviving divorced spouse stays outside (403(a)(3)(C)). The comparison has no age reduction or RIB-LIM; its own-benefit offset - is applied by the actual widow computation. Other care flags are - cleared so this comparison cannot recursively compare widow floors. + is applied by the actual widow computation. 402(q)(5)(D) substitutes + only this caregiver's entitlement, so another caregiver keeps its care + facts and its own minimum in the comparison. """ comparison = _mother_father_comparison(beneficiaries, caregiver) - result = _family_benefits(state, comparison, payment_month, params) + result = _care_comparison( + ("ordinary", state, comparison, payment_month, id(params)), + lambda: _family_benefits(state, comparison, payment_month, params), + ) return result.by_id()[caregiver.beneficiary_id].age_adjusted_rate def _mother_father_comparison(beneficiaries, caregiver): - comparison = [] - for member in beneficiaries: - if member.beneficiary_id == caregiver.beneficiary_id: - comparison.append( - _replace_declared( - member, - role=Role.MOTHER_FATHER, - reduction_months=0, - reduction_period_months=None, - original_benefit_basis=None, - child_in_care=None, - ) + return tuple( + ( + _replace_declared( + member, + role=Role.MOTHER_FATHER, + reduction_months=0, + reduction_period_months=None, + original_benefit_basis=None, + child_in_care=None, ) - elif member.role in _WIDOW_ROLES: - comparison.append(_replace_declared(member, child_in_care=False)) - else: - comparison.append(member) - return comparison + if member.beneficiary_id == caregiver.beneficiary_id + else member + ) + for member in beneficiaries + ) + + +def _care_comparison(key, compute): + cache = _CARE_COMPARISONS.get() + if key not in cache: + cache[key] = compute() + return cache[key] def _refuse_widow_drc_savings_clause( @@ -4114,6 +4123,28 @@ def _declared_worker_entitled(state: RecordState) -> bool: ) +# Each nested comparison turns one more caregiver into a mother or father, so +# the recursion ends. A family is fixed by which caregivers it has turned, so +# one call computes each of its at most 2**k comparison families once. +_CARE_COMPARISONS = ContextVar("_CARE_COMPARISONS", default=None) + + +def _care_scope(function): + """Share one call's comparison families with each nested comparison.""" + + def scoped(*args): + if _CARE_COMPARISONS.get() is not None: + return function(*args) + token = _CARE_COMPARISONS.set({}) + try: + return function(*args) + finally: + _CARE_COMPARISONS.reset(token) + + return scoped + + +@_care_scope def _family_benefits( state: RecordState, beneficiaries: Sequence[Beneficiary], @@ -4617,6 +4648,7 @@ def family_benefits_after_deductions( ) +@_care_scope def _after_deductions( state, beneficiaries, @@ -4718,7 +4750,8 @@ def _care_minimums_after_deductions( RS 00615.340 compares what a mother or father would receive, so the comparison family takes this month's events and households. A deductee keeps its rate in either family (GN 02603.050B.3), so its own minimum - stays G's ordinary one. + stays G's ordinary one. Another caregiver keeps its care facts in the + comparison, so a deducted one keeps that ordinary minimum there too. An event's ``payable`` belongs to the actual family's rate, and no source carries a partial amount to a comparison rate. Treating every event as @@ -4743,22 +4776,41 @@ def _care_minimums_after_deductions( "deferred allocation coverage", ) minimums = {} + full = { + bid: _replace_declared(event, payable=Fraction(0)) + for bid, event in events.items() + } for caregiver in caregivers: cid = caregiver.beneficiary_id comparison = _mother_father_comparison(beneficiaries, caregiver) - ordinary = _family_benefits(state, comparison, payment_month, params) - highest = _readjusted_for_events( - state, - comparison, - payment_month, - params, - ordinary, - { - bid: _replace_declared(event, payable=Fraction(0)) - for bid, event in events.items() - }, - households, - {}, + ordinary = _care_comparison( + ("ordinary", state, comparison, payment_month, id(params)), + lambda comparison=comparison: _family_benefits( + state, comparison, payment_month, params + ), + ) + highest = _care_comparison( + ( + "events", + state, + comparison, + payment_month, + id(params), + tuple(sorted(full.items())), + tuple(sorted(households.items())), + ), + lambda comparison=comparison, ordinary=ordinary: ( + _readjusted_for_events( + state, + comparison, + payment_month, + params, + ordinary, + full, + households, + {}, + ) + ), ) ceiling = highest.by_id()[cid].age_adjusted_rate settled = all(event.payable == 0 for event in events.values()) diff --git a/src/populace_dynamics/track_b/ret_ledger.py b/src/populace_dynamics/track_b/ret_ledger.py index 3a8acdd85..288115a95 100644 --- a/src/populace_dynamics/track_b/ret_ledger.py +++ b/src/populace_dynamics/track_b/ret_ledger.py @@ -1148,9 +1148,12 @@ def _divorced_excluded(b: RETBeneficiary, month: int) -> bool: def _care_minimum_can_move(record, month, deductees): """Whether another person's deduction can raise a 402(q)(5)(D) minimum. - G settles it where a context names the caregiver. Without one, any - reduced surviving-spouse rate beside an entitled child stays open, and the - caller's refusal names the missing facts. + G settles it where a context names the caregiver. Without one, a reduced + surviving-spouse rate below an entitled child's original rate stays open, + and the caller's refusal names the missing facts. A survivor child's OB + and a mother's are both 3/4 of the PIA (402(d)(2), 402(g)(2)), and no + readjustment pays past an OB, so no minimum reaches a rate at or above + a child's. """ if record.kind is not RecordKind.DECEASED: return False @@ -1158,13 +1161,16 @@ def _care_minimum_can_move(record, month, deductees): if context is not None: return bool(g._current_caregivers(context.beneficiaries)) entitled = [b for b in record.beneficiaries if month in b.entitled_months] - return any( - b.benefit_types[month - 1] in (BenefitType.CHILD, BenefitType.CDB) + children = [ + b.original_rates[month - 1] for b in entitled - ) and any( + if b.benefit_types[month - 1] in (BenefitType.CHILD, BenefitType.CDB) + ] + return bool(children) and any( b.beneficiary_id not in deductees and b.benefit_types[month - 1] in (BenefitType.WIDOW, BenefitType.DWB) - and b.gross_rates[month - 1] < b.original_rates[month - 1] + and b.gross_rates[month - 1] + < min(b.original_rates[month - 1], max(children)) for b in entitled ) diff --git a/tests/README-tiers.md b/tests/README-tiers.md index cf4eaef49..494f3607d 100644 --- a/tests/README-tiers.md +++ b/tests/README-tiers.md @@ -39,9 +39,9 @@ pytest --collect-only -q -m oracle_policyengine | tail -1 | Tier | Tests at HEAD | |---|---:| -| `unit` | 22,032 | +| `unit` | 22,069 | | `artifact` | 4,271 | | `integration_psid` | 1,471 | | `reproduction_legacy` | 520 | | `oracle_policyengine` | 308 | -| **Total** | **28,602** | +| **Total** | **28,639** | diff --git a/tests/test_track_b_ret_ledger_fix_round_10.py b/tests/test_track_b_ret_ledger_fix_round_10.py new file mode 100644 index 000000000..b309f851f --- /dev/null +++ b/tests/test_track_b_ret_ledger_fix_round_10.py @@ -0,0 +1,645 @@ +"""Round 10: a caregiver keeps its care facts in another's comparison. + +Also the bound on RET's request for family facts. Every record is invented or +built from a captured SSA rule. Nothing here admits a population, behavioral +or forecast claim. +""" + +from __future__ import annotations + +from fractions import Fraction as F + +import pytest +from hypothesis import example, given, settings +from hypothesis import strategies as st + +from populace_dynamics.track_b import gross_benefits as g +from populace_dynamics.track_b import ret_ledger as r +from populace_dynamics.track_b.ret_grace import BenefitType as T +from tests.test_track_b_ret_ledger_fix_round_9 import ( + MONTH, + OWN_WORK, + PARAMS, + RET_PARAMS, + _january, + _ret, +) + +HOUSEHOLD = {"former": "one", "spouse": "one", "child": "one"} +SPOUSE_WORKS = {"spouse": g.BenefitDeduction(OWN_WORK, F(0), False)} +DUAL_OWN = g.OwnBenefit( + g.OwnBenefitKind.OLD_AGE, F(100), reduction_months=24, birth_year=1960 +) + + +def _state(pia, maximum): + return g.RecordState( + g.FamilyKind.SURVIVOR, + F(pia), + F(maximum), + eligibility_year=2026, + widow_drc_savings_clause=False, + ) + + +def _carer(key, role, birth, months, *, period=None, care="child", own=None): + return g.Beneficiary( + key, + role, + birth_year=birth, + reduction_months=months, + reduction_period_months=months if period is None else period, + child_in_care=care, + own_benefit=own, + ) + + +def _pair(birth=1966, months=84, *, own=None): + return ( + _carer("former", g.Role.SURVIVING_DIVORCED_SPOUSE, birth, months), + _carer("spouse", g.Role.WIDOW, birth, months, own=own), + g.Beneficiary("child", g.Role.CHILD), + ) + + +def _after(state, members, events, households=HOUSEHOLD): + return g.family_benefits_after_deductions( + state, + members, + payment_month=MONTH, + params=PARAMS, + deductions=events, + households=households, + standalone=True, + ) + + +def _household(state, members, events, households=HOUSEHOLD): + return g.household_benefits_after_deductions( + {"r": g.HouseholdRecord("nh", state, members)}, + payment_month=MONTH, + params=PARAMS, + deductions=events, + households=households, + ).records["r"] + + +def _ordinary(state, members): + return g.family_benefits( + state, members, payment_month=MONTH, params=PARAMS, standalone=True + ) + + +def _replaced(members, key): + """402(q)(5)(D)'s family: only ``key`` turns into a mother or father.""" + return tuple( + ( + g.Beneficiary( + key, + g.Role.MOTHER_FATHER, + birth_year=member.birth_year, + own_benefit=member.own_benefit, + ) + if member.beneficiary_id == key + else member + ) + for member in members + ) + + +def _without_care(members, key): + return tuple( + ( + g.Beneficiary( + key, + member.role, + birth_year=member.birth_year, + reduction_months=member.reduction_months, + reduction_period_months=member.reduction_period_months, + child_in_care=False, + own_benefit=member.own_benefit, + ) + if member.beneficiary_id == key + else member + ) + for member in members + ) + + +# --------------------------------------------------------------------------- +# G: another caregiver keeps its care facts in the comparison +# --------------------------------------------------------------------------- +def test_another_deducted_caregiver_keeps_its_minimum(): + state = _state(1800, "2891.50") + assert g.retirement_survivor_family_maximum(F(1800), 2026, PARAMS) == F( + "2891.50" + ) + members = _pair() + # In the former spouse's comparison the widow keeps her care facts. Her + # share is 1,156.60 and her minimum pays 963.80, so her deduction leaves + # 192.80 counted against the maximum (GN 02603.050C). The mother takes + # 1,350 x (2,891.50 - 192.80) / 2,700 = 1,349.30. + widow = _ordinary(state, _replaced(members, "former")).by_id()["spouse"] + assert widow.family_maximum_rate == F("1156.60") + assert widow.age_adjusted_rate == F("963.80") + plain = _after(state, _without_care(members, "former"), SPOUSE_WORKS) + assert plain.by_id()["former"].age_adjusted_rate == 1287 + result = _after(state, members, SPOUSE_WORKS).by_id() + assert result["former"].age_adjusted_rate == F("1349.30") + assert result["former"].whole_dollar_auxiliary == 1349 + assert result["spouse"].auxiliary_payable == 0 + assert result["child"].auxiliary_payable == 1350 + + +@pytest.mark.parametrize( + ("pia", "maximum", "expected"), + [(1800, "2891.50", F("1349.30")), (1000, 1600, F("746.60"))], +) +def test_a_deducted_disabled_widow_keeps_the_minimum(pia, maximum, expected): + state = _state(pia, maximum) + members = ( + _carer("former", g.Role.SURVIVING_DIVORCED_SPOUSE, 1966, 84), + g.Beneficiary("spouse", g.Role.DISABLED_WIDOW, child_in_care="child"), + g.Beneficiary("child", g.Role.CHILD), + ) + former = _after(state, members, SPOUSE_WORKS).by_id()["former"] + assert former.age_adjusted_rate == expected + assert ( + former.age_adjusted_rate + == _after(state, _replaced(members, "former"), SPOUSE_WORKS) + .by_id()["former"] + .age_adjusted_rate + ) + + +def test_a_formula_maximum_moves_a_whole_dollar(): + maximum = g.retirement_survivor_family_maximum(F(1688), 2026, PARAMS) + assert maximum == F("2586.90") + state = _state(1688, maximum) + members = _pair() + # 1,034.70 less the widow's 862.30 minimum leaves 172.40 counted, and + # 1,266 x (2,586.90 - 172.40) / 2,532 = 1,207.20. + widow = _ordinary(state, _replaced(members, "former")).by_id()["spouse"] + assert (widow.family_maximum_rate, widow.age_adjusted_rate) == ( + F("1034.70"), + F("862.30"), + ) + former = _after(state, members, SPOUSE_WORKS).by_id()["former"] + assert former.age_adjusted_rate == F("1207.20") + assert former.whole_dollar_auxiliary == 1207 + + +@pytest.mark.parametrize("entry", [_after, _household]) +def test_the_family_and_household_entries_agree(entry): + state = _state("2.70", "4.20") + members = _pair(1960, 80) + # The widow's 1.60 share pays her 1.40 minimum and leaves 0.20 counted, so + # the mother takes 2.00 x (4.20 - 0.20) / 4.00 = 2.00. + widow = _ordinary(state, _replaced(members, "former")).by_id()["spouse"] + assert (widow.family_maximum_rate, widow.age_adjusted_rate) == ( + F("1.60"), + F("1.40"), + ) + former = entry(state, members, SPOUSE_WORKS).by_id()["former"] + assert former.age_adjusted_rate == 2 + assert former.whole_dollar_auxiliary == 2 + + +@pytest.mark.parametrize("permanent", [True, False]) +@pytest.mark.parametrize( + ("pia", "maximum", "expected"), + [(1000, 1600, F("746.60")), (1800, "2891.50", F("1349.30"))], +) +def test_a_dual_deductee_keeps_its_minimum_either_way( + permanent, pia, maximum, expected +): + # A dual row counts as permanent (GN 02603.050), so a temporary event on + # it redistributes as a permanent one does. + state = _state(pia, maximum) + members = _pair(1960, 80, own=DUAL_OWN) + events = {"spouse": g.BenefitDeduction(OWN_WORK, F(0), permanent)} + former = _after(state, members, events).by_id()["former"] + assert former.age_adjusted_rate == expected + assert ( + former.age_adjusted_rate + == _after(state, _replaced(members, "former"), events) + .by_id()["former"] + .age_adjusted_rate + ) + + +@pytest.mark.parametrize( + ("permanent", "spouse_home", "expected"), + [ + pytest.param(False, "one", F("1349.30"), id="temporary, same home"), + pytest.param(False, "two", F(1287), id="temporary, other home"), + pytest.param(True, "one", F(1350), id="permanent, same home"), + pytest.param(True, "two", F(1350), id="permanent, other home"), + ], +) +def test_each_event_reaches_the_comparison_as_it_reaches_the_family( + permanent, spouse_home, expected +): + state = _state(1800, "2891.50") + members = _pair() + households = {**HOUSEHOLD, "spouse": spouse_home} + events = {"spouse": g.BenefitDeduction(OWN_WORK, F(0), permanent)} + former = _after(state, members, events, households).by_id()["former"] + comparison = _after( + state, _replaced(members, "former"), events, households + ).by_id()["former"] + plain = _after( + state, _without_care(members, "former"), events, households + ).by_id()["former"] + assert former.age_adjusted_rate == expected + assert former.age_adjusted_rate == max( + plain.age_adjusted_rate, comparison.age_adjusted_rate + ) + + +def test_three_caregivers_each_compare_with_one_entitlement_replaced(): + state = _state(1800, "2891.50") + members = ( + _carer("former", g.Role.SURVIVING_DIVORCED_SPOUSE, 1966, 84), + _carer("other", g.Role.SURVIVING_DIVORCED_SPOUSE, 1966, 60, period=84), + _carer("spouse", g.Role.WIDOW, 1966, 84), + g.Beneficiary("child", g.Role.CHILD), + ) + households = {**HOUSEHOLD, "other": "one"} + result = _after(state, members, SPOUSE_WORKS, households).by_id() + for key in ("former", "other"): + comparison = _after( + state, _replaced(members, key), SPOUSE_WORKS, households + ).by_id()[key] + plain = _after( + state, _without_care(members, key), SPOUSE_WORKS, households + ).by_id()[key] + assert result[key].age_adjusted_rate == max( + plain.age_adjusted_rate, comparison.age_adjusted_rate + ) + assert result["former"].age_adjusted_rate > 1287 + + +@pytest.mark.parametrize("count", [1, 2, 3, 4]) +@pytest.mark.parametrize("events", [{}, SPOUSE_WORKS]) +def test_each_comparison_family_runs_once(monkeypatch, count, events): + # A family is fixed by which caregivers it has turned into mothers, so a + # call with k caregivers runs at most 2**k families, the actual one + # included, however the comparisons nest. + members = (_carer("spouse", g.Role.WIDOW, 1966, 84),) + tuple( + _carer(f"s{n}", g.Role.SURVIVING_DIVORCED_SPOUSE, 1966, 84) + for n in range(count - 1) + ) + members += (g.Beneficiary("child", g.Role.CHILD),) + households = {member.beneficiary_id: "one" for member in members} + family = g._family_benefits + seen = [] + + def counted(state, beneficiaries, *args): + seen.append(tuple(beneficiaries)) + return family(state, beneficiaries, *args) + + monkeypatch.setattr(g, "_family_benefits", counted) + _after(_state(1800, "2891.50"), members, events, households) + assert len(seen) == 2**count + assert len(set(seen)) == len(seen) + + +def test_the_comparison_cache_ends_with_its_call(): + _after(_state(1800, "2891.50"), _pair(), SPOUSE_WORKS) + assert g._CARE_COMPARISONS.get() is None + + +def test_one_scope_keeps_records_households_and_events_apart(): + # The household entry runs its records one after another, each in its own + # scope. A scope that held several would still keep each family apart. + members = _pair() + widow = _state(1800, "2891.50") + cases = [ + (widow, SPOUSE_WORKS, HOUSEHOLD), + (_state(1000, 1600), SPOUSE_WORKS, HOUSEHOLD), + (widow, SPOUSE_WORKS, {**HOUSEHOLD, "spouse": "two"}), + ( + widow, + {"spouse": g.BenefitDeduction(OWN_WORK, F(0), True)}, + HOUSEHOLD, + ), + ] + + def rates(): + return [ + _after(state, members, events, households) + .by_id()["former"] + .age_adjusted_rate + for state, events, households in cases + ] + + expected = [F("1349.30"), F("746.60"), F(1287), F(1350)] + assert rates() == expected + assert g._care_scope(rates)() == expected + + +# --------------------------------------------------------------------------- +# G: invariants over random caregiver pairs, through the public API +# --------------------------------------------------------------------------- +ROLES = st.sampled_from( + (g.Role.WIDOW, g.Role.SURVIVING_DIVORCED_SPOUSE, g.Role.DISABLED_WIDOW) +) +MONTHS = st.sampled_from((1, 12, 30, 60)) + + +def _member(key, role, months, care="child"): + if role is g.Role.DISABLED_WIDOW: + return g.Beneficiary(key, role, child_in_care=care) + return g.Beneficiary( + key, + role, + reduction_months=months, + reduction_period_months=60, + child_in_care=care, + ) + + +pairs = st.tuples( + st.integers(3, 30_000).map(lambda n: F(n, 10)), + st.integers(150, 188), + st.tuples(ROLES, MONTHS, ROLES, MONTHS), + st.booleans(), +) +events = st.dictionaries( + st.sampled_from(("former", "spouse", "child", "second")), + st.booleans().map(lambda p: g.BenefitDeduction(OWN_WORK, F(0), p)), + min_size=1, + max_size=2, +) +homes = st.fixed_dictionaries( + { + key: st.sampled_from(("one", "two")) + for key in ("former", "spouse", "child", "second") + } +) + + +def _random_family(pair): + pia, percent, (first, months, second, other), two = pair + state = _state(pia, g.floor_dime(pia * F(percent, 100))) + members = ( + _member("former", first, months), + _member("spouse", second, other), + g.Beneficiary("child", g.Role.CHILD), + ) + if two: + members += (g.Beneficiary("second", g.Role.CHILD),) + return state, members + + +SOL_PAIR = ( + F(1000), + 160, + (g.Role.SURVIVING_DIVORCED_SPOUSE, 60, g.Role.WIDOW, 60), + False, +) + + +@given(pair=pairs, chosen=events, households=homes) +@example( + pair=SOL_PAIR, + chosen={"spouse": g.BenefitDeduction(OWN_WORK, F(0), False)}, + households={k: "one" for k in ("former", "spouse", "child", "second")}, +) +@settings(max_examples=250, deadline=None) +def test_each_caregiver_takes_the_better_of_its_rate_and_its_comparison( + pair, chosen, households +): + state, members = _random_family(pair) + keys = {member.beneficiary_id for member in members} + chosen = {key: event for key, event in chosen.items() if key in keys} + households = {key: households[key] for key in keys} + try: + result = _after(state, members, chosen, households).by_id() + except (g.InvalidFamilyInput, g.FamilyConfigurationUnsupported): + return + for key in ("former", "spouse"): + if key in chosen or not result[key].entitled: + continue + try: + comparison = _after( + state, _replaced(members, key), chosen, households + ).by_id()[key] + plain = _after( + state, _without_care(members, key), chosen, households + ).by_id()[key] + except g.InvalidFamilyInput: + # A full own-work event must withhold something in each family, + # and a mother's share can leave a child nothing to withhold. + continue + assert result[key].age_adjusted_rate == max( + plain.age_adjusted_rate, comparison.age_adjusted_rate + ) + # No minimum passes a mother's original benefit (402(g)(2)), which + # bounds RET's request for family facts below. + mother = g.original_benefit( + g.Role.MOTHER_FATHER, g.FamilyKind.SURVIVOR, state.pia + ) + assert comparison.age_adjusted_rate <= mother + assert result[key].age_adjusted_rate <= max( + plain.age_adjusted_rate, mother + ) + + +# --------------------------------------------------------------------------- +# RET: the provisional ledger reads the same minimum +# --------------------------------------------------------------------------- +KINDS = { + g.Role.CHILD: T.CHILD, + g.Role.WIDOW: T.WIDOW, + g.Role.SURVIVING_DIVORCED_SPOUSE: T.WIDOW, + g.Role.DISABLED_WIDOW: T.DWB, +} + + +def _ret_record(state, members, households, wages, *, context=True): + baseline = _ordinary(state, members) + people = tuple( + r.RETBeneficiary( + row.beneficiary_id, + (KINDS[row.role],) * 12, + {1}, + (row.auxiliary_payable,) + (F(0),) * 11, + (row.original_benefit,) * 12, + earnings=r.WorkEarnings( + (wages.get(row.beneficiary_id, F(0)),) + (F(0),) * 11 + ), + fra_month=None, + ) + for row in baseline.beneficiaries + ) + return r.RecordYear( + 2026, + "nh", + r.RecordKind.DECEASED, + people, + family_maximum_binding_months=( + frozenset({1}) if baseline.family_maximum_binding else frozenset() + ), + family_months=( + {1: r.RETFamilyMonth(state, members, PARAMS, households)} + if context + else {} + ), + ) + + +def test_ret_pays_the_minimum_on_the_provisional_ledger(): + state = _state(1000, 1600) + members = _pair() + lower = RET_PARAMS.for_year(2026).lower_exempt_amount.value + # 25,980 is 1,500 over the exempt amount, so the widow's 750 goes. + outcome = _ret( + _ret_record(state, members, HOUSEHOLD, {"spouse": lower + 1500}) + ) + assert outcome.supported + former = _january(outcome, "former") + assert former.provisional_net == F("746.60") + assert former.provisional_payment == 746 + assert former.net_due == 750 + assert _january(outcome, "spouse").deduction == 750 + + +# --------------------------------------------------------------------------- +# RET: family facts only where a minimum can reach the rate +# --------------------------------------------------------------------------- +def _person(key, kind, gross, original, wages=F(0)): + return r.RETBeneficiary( + key, + (kind,) * 12, + {1}, + (F(gross),) + (F(0),) * 11, + (F(original),) * 12, + earnings=r.WorkEarnings((F(wages),) + (F(0),) * 11), + fra_month=0 if kind is not T.CHILD else None, + ) + + +def _deceased(*people, family_months=None): + return r.RecordYear( + 2026, + "nh", + r.RecordKind.DECEASED, + people, + family_months=family_months or {}, + ) + + +WORKING_CHILD = ("c", T.CHILD, 750, 750, 25980) + + +def test_a_rate_past_any_minimum_needs_no_family_facts(): + alone = _ret( + _deceased(_person("w", T.WIDOW, 905, 1000), _person(*WORKING_CHILD)) + ) + assert alone.supported + # The same record with G's facts: a 20-of-60 widow beside the child, and + # a maximum the two OBs exactly reach. + state = _state(1000, 1750) + members = ( + g.Beneficiary( + "w", + g.Role.WIDOW, + reduction_months=20, + reduction_period_months=60, + child_in_care="c", + ), + g.Beneficiary("c", g.Role.CHILD), + ) + assert _ordinary(state, members).by_id()["w"].auxiliary_payable == 905 + context = { + 1: r.RETFamilyMonth(state, members, PARAMS, {"w": "one", "c": "one"}) + } + told = _ret( + _deceased( + _person("w", T.WIDOW, 905, 1000), + _person(*WORKING_CHILD), + family_months=context, + ) + ) + assert told.supported + for outcome in (alone, told): + widow = _january(outcome, "w") + assert (widow.net_due, widow.provisional_net) == (905, 905) + child = _january(outcome, "c") + assert (child.deduction, child.provisional_deduction) == (750, 750) + + +@pytest.mark.parametrize( + ("gross", "supported"), + [(F(750), True), (F("749.90"), False), (F(600), False)], +) +@pytest.mark.parametrize("kind", [T.WIDOW, T.DWB]) +def test_a_childs_original_rate_bounds_the_request(gross, supported, kind): + outcome = _ret( + _deceased(_person("w", kind, gross, 1000), _person(*WORKING_CHILD)) + ) + assert outcome.supported is supported + if not supported: + assert ( + outcome.unsupported.reason + is r.UnsupportedReason.FAMILY_CONTEXT_REQUIRED + ) + + +def test_the_higher_of_two_declared_child_rates_bounds_the_request(): + # Survivor children's OBs agree under 402(d)(2). Declarations that don't + # keep the higher bound, the side that asks for facts. + outcome = _ret( + _deceased( + _person("w", T.WIDOW, 700, 1000), + _person("a", T.CHILD, 600, 600), + _person(*WORKING_CHILD), + ) + ) + assert not outcome.supported + assert ( + outcome.unsupported.reason + is r.UnsupportedReason.FAMILY_CONTEXT_REQUIRED + ) + + +def test_a_widows_own_original_rate_still_bounds_the_request(): + # An unreduced rate has no age reduction for a minimum to undo. + outcome = _ret( + _deceased(_person("w", T.WIDOW, 500, 500), _person(*WORKING_CHILD)) + ) + assert outcome.supported + + +# A skipped month must pay what G pays once RET has the facts. +@given(pair=pairs, excess=st.integers(1, 3000), worker=st.booleans()) +@settings(max_examples=120, deadline=None) +def test_a_month_ret_settles_without_family_facts_matches_g( + pair, excess, worker +): + state, members = _random_family(pair) + households = {member.beneficiary_id: "one" for member in members} + lower = RET_PARAMS.for_year(2026).lower_exempt_amount.value + earner = "child" if worker else "spouse" + wages = {earner: lower + 2 * excess} + try: + _ordinary(state, members) + alone = _ret( + _ret_record(state, members, households, wages, context=False) + ) + except (g.InvalidFamilyInput, g.FamilyConfigurationUnsupported): + return + if not alone.supported: + return + told = _ret(_ret_record(state, members, households, wages)) + assert told.supported + for member in members: + key = member.beneficiary_id + a, b = _january(alone, key), _january(told, key) + assert (a.net_due, a.provisional_net, a.deduction) == ( + b.net_due, + b.provisional_net, + b.deduction, + ) diff --git a/tests/test_track_b_ret_ledger_fix_round_9.py b/tests/test_track_b_ret_ledger_fix_round_9.py index 7a961d850..9c86afabd 100644 --- a/tests/test_track_b_ret_ledger_fix_round_9.py +++ b/tests/test_track_b_ret_ledger_fix_round_9.py @@ -236,7 +236,7 @@ def test_a_deducted_caregiver_keeps_the_ordinary_minimum(): assert result.age_adjusted_rate == ordinary.age_adjusted_rate -def test_each_caregiver_compares_alone(): +def test_each_caregiver_compares_with_only_its_entitlement_replaced(): state = _state(1000, 1800) members = ( _caregiver(g.Role.WIDOW), @@ -254,31 +254,17 @@ def test_each_caregiver_compares_alone(): events = {"c2": _full()} result = _after(state, members, events, households) - def alone(key, first): - other = "s" if key == "w" else "w" + # Round 10: 402(q)(5)(D) replaces only the one entitlement, so the other + # caregiver keeps its care facts in the comparison. + def replaced(key, first): comparison = tuple( - ( - first - if m.beneficiary_id == key - else ( - g.Beneficiary( - other, - m.role, - reduction_months=60, - reduction_period_months=60, - child_in_care=False, - ) - if m.beneficiary_id == other - else m - ) - ) - for m in members + first if m.beneficiary_id == key else m for m in members ) return _after(state, comparison, events, households) - widow = alone("w", _mother()).by_id()["w"].auxiliary_payable + widow = replaced("w", _mother()).by_id()["w"].auxiliary_payable divorced = ( - alone("s", g.Beneficiary("s", g.Role.MOTHER_FATHER)) + replaced("s", g.Beneficiary("s", g.Role.MOTHER_FATHER)) .by_id()["s"] .auxiliary_payable ) @@ -801,8 +787,10 @@ def _deceased(*people): ) -CHILD = ("c1", T.CHILD, 500, 500, 0, {1}) -WORKING_CHILD = ("c2", T.CHILD, 500, 500, 100, {1}) +# A survivor child's OB is 3/4 of the PIA (402(d)(2)), so 750 beside a +# widow(er)'s 1,000. The maximum leaves each child 500. +CHILD = ("c1", T.CHILD, 500, 750, 0, {1}) +WORKING_CHILD = ("c2", T.CHILD, 500, 750, 100, {1}) @pytest.mark.parametrize("kind", [T.WIDOW, T.DWB]) diff --git a/tests/tier_counts.json b/tests/tier_counts.json index eb147e2e5..d8b561af8 100644 --- a/tests/tier_counts.json +++ b/tests/tier_counts.json @@ -1,7 +1,7 @@ { "schema_version": 1, "counts": { - "unit": 22032, + "unit": 22069, "artifact": 4271, "integration_psid": 1471, "reproduction_legacy": 520, From f5a18c84dfbb9494374b17b601c9c8a2545e5ab6 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Mon, 2 Nov 2026 13:17:17 -0500 Subject: [PATCH 17/17] Record round 10's cloud mutation run (#563, docs only) A cloud session ran round 10's 22 listed mutations at 03530e8b, each in a copied source tree with its own Hypothesis database. 19 failed a named test, and the runner's audit counted no restricted open, subprocess or os.system call. Three change no result and stay out of the count as equivalent: dropping the month or the parameters from the care comparison key (every key in one cache carries the opening call's month and parameters), and giving the events key the ordinary tag (the two keys differ in length). The ledger holds the driver and runner sources, the verification file records the run and its Track B gate, and the RET note cites the committed ledger in place of a scratch script. Co-Authored-By: Claude Opus 5.5 --- docs/design/track_b_g2_r2b_mutations.json | 720 ++++++++++++++++++- docs/design/track_b_g2_r2b_verification.json | 56 +- docs/design/track_b_r2_ret_ledger.md | 14 +- 3 files changed, 783 insertions(+), 7 deletions(-) diff --git a/docs/design/track_b_g2_r2b_mutations.json b/docs/design/track_b_g2_r2b_mutations.json index f1cedc4e5..7445ce1f9 100644 --- a/docs/design/track_b_g2_r2b_mutations.json +++ b/docs/design/track_b_g2_r2b_mutations.json @@ -2,12 +2,12 @@ "schema_version": 1, "verification_class": "statutory_conformance", "admitted_scope": "Mutation sensitivity of statutory rules on invented and captured worked cases only; no population, behavioral or forecast claim.", - "confirmed_mutation_count": 233, + "confirmed_mutation_count": 252, "counts_by_layer": { "g_deductions": 18, - "g_preflight": 149, + "g_preflight": 162, "g_savings": 12, - "r2": 53, + "r2": 59, "shared_provenance": 1 }, "environment_contract": { @@ -13278,6 +13278,675 @@ } }, "layer": "g_preflight" + }, + { + "id": "round10-comparison_clears_other_care", + "round": 10, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "after": " if member.beneficiary_id == caregiver.beneficiary_id\n else (\n _replace_declared(member, child_in_care=False)\n if member.role in _WIDOW_ROLES\n else member\n )\n )\n for member in beneficiaries\n", + "before": " if member.beneficiary_id == caregiver.beneficiary_id\n else member\n )\n for member in beneficiaries\n" + } + ], + "command": "env POPULACE_DYNAMICS_PSID_DIR=/nonexistent/trackb-round10 POPULACE_DYNAMICS_EPUF_DIR=/nonexistent/trackb-round10 OMP_NUM_THREADS=1 OMP_WAIT_POLICY=PASSIVE POLARS_MAX_THREADS=1 PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=$PWD/scratch/review/round10-mutations-shard0/comparison_clears_other_care/src:$PWD TRACKB_ROUND10_TREE=$PWD/scratch/review/round10-mutations-shard0/comparison_clears_other_care/src HYPOTHESIS_STORAGE_DIRECTORY=scratch/review/round10-mutations-shard0/hyp-comparison_clears_other_care /tmp/tbvenv/bin/python scratch/review/run_round10_named.py -p no:xdist -p no:cacheprovider -q --tb=line -rf tests/test_track_b_ret_ledger_fix_round_10.py tests/test_track_b_ret_ledger_fix_round_9.py", + "outer_command": [ + "python", + "scratch/review/round10_mutate.py" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_10.py::test_another_deducted_caregiver_keeps_its_minimum" + ], + "failed_test_count": 21, + "evidence": { + "cloud_comment": "https://github.com/PolicyEngine/microcosm-dynamics/pull/563#issuecomment-6584667595", + "results_sha256": "d3ab07eb2e589613e8be609135869076b699ea019f7122f656623daadc817a83" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "ad65407af7c69507095e03244c5d463a355d20b674d3ece1f0d8176f6987a5a9", + "src/populace_dynamics/track_b/ret_ledger.py": "edd9a4823d38a3157ba0bbf055e18ef9ba40fa787ccba0acd37b4ad3cbbca4bd" + } + }, + "layer": "g_preflight" + }, + { + "id": "round10-comparison_clears_widow_care", + "round": 10, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "after": " if member.beneficiary_id == caregiver.beneficiary_id\n else (\n _replace_declared(member, child_in_care=False)\n if member.role is Role.WIDOW\n else member\n )\n )\n for member in beneficiaries\n", + "before": " if member.beneficiary_id == caregiver.beneficiary_id\n else member\n )\n for member in beneficiaries\n" + } + ], + "command": "env POPULACE_DYNAMICS_PSID_DIR=/nonexistent/trackb-round10 POPULACE_DYNAMICS_EPUF_DIR=/nonexistent/trackb-round10 OMP_NUM_THREADS=1 OMP_WAIT_POLICY=PASSIVE POLARS_MAX_THREADS=1 PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=$PWD/scratch/review/round10-mutations-shard1/comparison_clears_widow_care/src:$PWD TRACKB_ROUND10_TREE=$PWD/scratch/review/round10-mutations-shard1/comparison_clears_widow_care/src HYPOTHESIS_STORAGE_DIRECTORY=scratch/review/round10-mutations-shard1/hyp-comparison_clears_widow_care /tmp/tbvenv/bin/python scratch/review/run_round10_named.py -p no:xdist -p no:cacheprovider -q --tb=line -rf tests/test_track_b_ret_ledger_fix_round_10.py tests/test_track_b_ret_ledger_fix_round_9.py", + "outer_command": [ + "python", + "scratch/review/round10_mutate.py" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_10.py::test_another_deducted_caregiver_keeps_its_minimum" + ], + "failed_test_count": 13, + "evidence": { + "cloud_comment": "https://github.com/PolicyEngine/microcosm-dynamics/pull/563#issuecomment-6584667595", + "results_sha256": "d3ab07eb2e589613e8be609135869076b699ea019f7122f656623daadc817a83" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "ad65407af7c69507095e03244c5d463a355d20b674d3ece1f0d8176f6987a5a9", + "src/populace_dynamics/track_b/ret_ledger.py": "edd9a4823d38a3157ba0bbf055e18ef9ba40fa787ccba0acd37b4ad3cbbca4bd" + } + }, + "layer": "g_preflight" + }, + { + "id": "round10-comparison_clears_disabled_widow_care", + "round": 10, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "after": " if member.beneficiary_id == caregiver.beneficiary_id\n else (\n _replace_declared(member, child_in_care=False)\n if member.role is Role.DISABLED_WIDOW\n else member\n )\n )\n for member in beneficiaries\n", + "before": " if member.beneficiary_id == caregiver.beneficiary_id\n else member\n )\n for member in beneficiaries\n" + } + ], + "command": "env POPULACE_DYNAMICS_PSID_DIR=/nonexistent/trackb-round10 POPULACE_DYNAMICS_EPUF_DIR=/nonexistent/trackb-round10 OMP_NUM_THREADS=1 OMP_WAIT_POLICY=PASSIVE POLARS_MAX_THREADS=1 PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=$PWD/scratch/review/round10-mutations-shard2/comparison_clears_disabled_widow_care/src:$PWD TRACKB_ROUND10_TREE=$PWD/scratch/review/round10-mutations-shard2/comparison_clears_disabled_widow_care/src HYPOTHESIS_STORAGE_DIRECTORY=scratch/review/round10-mutations-shard2/hyp-comparison_clears_disabled_widow_care /tmp/tbvenv/bin/python scratch/review/run_round10_named.py -p no:xdist -p no:cacheprovider -q --tb=line -rf tests/test_track_b_ret_ledger_fix_round_10.py tests/test_track_b_ret_ledger_fix_round_9.py", + "outer_command": [ + "python", + "scratch/review/round10_mutate.py" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_10.py::test_a_deducted_disabled_widow_keeps_the_minimum[1800-2891.50-expected0]" + ], + "failed_test_count": 3, + "evidence": { + "cloud_comment": "https://github.com/PolicyEngine/microcosm-dynamics/pull/563#issuecomment-6584667595", + "results_sha256": "d3ab07eb2e589613e8be609135869076b699ea019f7122f656623daadc817a83" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "ad65407af7c69507095e03244c5d463a355d20b674d3ece1f0d8176f6987a5a9", + "src/populace_dynamics/track_b/ret_ledger.py": "edd9a4823d38a3157ba0bbf055e18ef9ba40fa787ccba0acd37b4ad3cbbca4bd" + } + }, + "layer": "g_preflight" + }, + { + "id": "round10-cache_never_stores", + "round": 10, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "after": " return compute()\n", + "before": " if key not in cache:\n cache[key] = compute()\n return cache[key]\n" + } + ], + "command": "env POPULACE_DYNAMICS_PSID_DIR=/nonexistent/trackb-round10 POPULACE_DYNAMICS_EPUF_DIR=/nonexistent/trackb-round10 OMP_NUM_THREADS=1 OMP_WAIT_POLICY=PASSIVE POLARS_MAX_THREADS=1 PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=$PWD/scratch/review/round10-mutations-shard3/cache_never_stores/src:$PWD TRACKB_ROUND10_TREE=$PWD/scratch/review/round10-mutations-shard3/cache_never_stores/src HYPOTHESIS_STORAGE_DIRECTORY=scratch/review/round10-mutations-shard3/hyp-cache_never_stores /tmp/tbvenv/bin/python scratch/review/run_round10_named.py -p no:xdist -p no:cacheprovider -q --tb=line -rf tests/test_track_b_ret_ledger_fix_round_10.py tests/test_track_b_ret_ledger_fix_round_9.py", + "outer_command": [ + "python", + "scratch/review/round10_mutate.py" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_10.py::test_each_comparison_family_runs_once[events0-2]" + ], + "failed_test_count": 6, + "evidence": { + "cloud_comment": "https://github.com/PolicyEngine/microcosm-dynamics/pull/563#issuecomment-6584667595", + "results_sha256": "d3ab07eb2e589613e8be609135869076b699ea019f7122f656623daadc817a83" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "ad65407af7c69507095e03244c5d463a355d20b674d3ece1f0d8176f6987a5a9", + "src/populace_dynamics/track_b/ret_ledger.py": "edd9a4823d38a3157ba0bbf055e18ef9ba40fa787ccba0acd37b4ad3cbbca4bd" + } + }, + "layer": "g_preflight" + }, + { + "id": "round10-cache_recomputes_each_hit", + "round": 10, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "after": " cache[key] = compute()\n return cache[key]\n", + "before": " if key not in cache:\n cache[key] = compute()\n return cache[key]\n" + } + ], + "command": "env POPULACE_DYNAMICS_PSID_DIR=/nonexistent/trackb-round10 POPULACE_DYNAMICS_EPUF_DIR=/nonexistent/trackb-round10 OMP_NUM_THREADS=1 OMP_WAIT_POLICY=PASSIVE POLARS_MAX_THREADS=1 PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=$PWD/scratch/review/round10-mutations-shard0/cache_recomputes_each_hit/src:$PWD TRACKB_ROUND10_TREE=$PWD/scratch/review/round10-mutations-shard0/cache_recomputes_each_hit/src HYPOTHESIS_STORAGE_DIRECTORY=scratch/review/round10-mutations-shard0/hyp-cache_recomputes_each_hit /tmp/tbvenv/bin/python scratch/review/run_round10_named.py -p no:xdist -p no:cacheprovider -q --tb=line -rf tests/test_track_b_ret_ledger_fix_round_10.py tests/test_track_b_ret_ledger_fix_round_9.py", + "outer_command": [ + "python", + "scratch/review/round10_mutate.py" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_10.py::test_each_comparison_family_runs_once[events0-2]" + ], + "failed_test_count": 6, + "evidence": { + "cloud_comment": "https://github.com/PolicyEngine/microcosm-dynamics/pull/563#issuecomment-6584667595", + "results_sha256": "d3ab07eb2e589613e8be609135869076b699ea019f7122f656623daadc817a83" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "ad65407af7c69507095e03244c5d463a355d20b674d3ece1f0d8176f6987a5a9", + "src/populace_dynamics/track_b/ret_ledger.py": "edd9a4823d38a3157ba0bbf055e18ef9ba40fa787ccba0acd37b4ad3cbbca4bd" + } + }, + "layer": "g_preflight" + }, + { + "id": "round10-scope_opens_per_call", + "round": 10, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "after": " if False:\n return function(*args)\n", + "before": " if _CARE_COMPARISONS.get() is not None:\n return function(*args)\n" + } + ], + "command": "env POPULACE_DYNAMICS_PSID_DIR=/nonexistent/trackb-round10 POPULACE_DYNAMICS_EPUF_DIR=/nonexistent/trackb-round10 OMP_NUM_THREADS=1 OMP_WAIT_POLICY=PASSIVE POLARS_MAX_THREADS=1 PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=$PWD/scratch/review/round10-mutations-shard1/scope_opens_per_call/src:$PWD TRACKB_ROUND10_TREE=$PWD/scratch/review/round10-mutations-shard1/scope_opens_per_call/src HYPOTHESIS_STORAGE_DIRECTORY=scratch/review/round10-mutations-shard1/hyp-scope_opens_per_call /tmp/tbvenv/bin/python scratch/review/run_round10_named.py -p no:xdist -p no:cacheprovider -q --tb=line -rf tests/test_track_b_ret_ledger_fix_round_10.py tests/test_track_b_ret_ledger_fix_round_9.py", + "outer_command": [ + "python", + "scratch/review/round10_mutate.py" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_10.py::test_each_comparison_family_runs_once[events0-2]" + ], + "failed_test_count": 6, + "evidence": { + "cloud_comment": "https://github.com/PolicyEngine/microcosm-dynamics/pull/563#issuecomment-6584667595", + "results_sha256": "d3ab07eb2e589613e8be609135869076b699ea019f7122f656623daadc817a83" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "ad65407af7c69507095e03244c5d463a355d20b674d3ece1f0d8176f6987a5a9", + "src/populace_dynamics/track_b/ret_ledger.py": "edd9a4823d38a3157ba0bbf055e18ef9ba40fa787ccba0acd37b4ad3cbbca4bd" + } + }, + "layer": "g_preflight" + }, + { + "id": "round10-scope_never_resets", + "round": 10, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "after": " finally:\n pass\n", + "before": " finally:\n _CARE_COMPARISONS.reset(token)\n" + } + ], + "command": "env POPULACE_DYNAMICS_PSID_DIR=/nonexistent/trackb-round10 POPULACE_DYNAMICS_EPUF_DIR=/nonexistent/trackb-round10 OMP_NUM_THREADS=1 OMP_WAIT_POLICY=PASSIVE POLARS_MAX_THREADS=1 PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=$PWD/scratch/review/round10-mutations-shard2/scope_never_resets/src:$PWD TRACKB_ROUND10_TREE=$PWD/scratch/review/round10-mutations-shard2/scope_never_resets/src HYPOTHESIS_STORAGE_DIRECTORY=scratch/review/round10-mutations-shard2/hyp-scope_never_resets /tmp/tbvenv/bin/python scratch/review/run_round10_named.py -p no:xdist -p no:cacheprovider -q --tb=line -rf tests/test_track_b_ret_ledger_fix_round_10.py tests/test_track_b_ret_ledger_fix_round_9.py", + "outer_command": [ + "python", + "scratch/review/round10_mutate.py" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_10.py::test_each_comparison_family_runs_once[events1-2]" + ], + "failed_test_count": 2, + "evidence": { + "cloud_comment": "https://github.com/PolicyEngine/microcosm-dynamics/pull/563#issuecomment-6584667595", + "results_sha256": "d3ab07eb2e589613e8be609135869076b699ea019f7122f656623daadc817a83" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "ad65407af7c69507095e03244c5d463a355d20b674d3ece1f0d8176f6987a5a9", + "src/populace_dynamics/track_b/ret_ledger.py": "edd9a4823d38a3157ba0bbf055e18ef9ba40fa787ccba0acd37b4ad3cbbca4bd" + } + }, + "layer": "g_preflight" + }, + { + "id": "round10-family_entry_unscoped", + "round": 10, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "after": "def _family_benefits(\n", + "before": "@_care_scope\ndef _family_benefits(\n" + } + ], + "command": "env POPULACE_DYNAMICS_PSID_DIR=/nonexistent/trackb-round10 POPULACE_DYNAMICS_EPUF_DIR=/nonexistent/trackb-round10 OMP_NUM_THREADS=1 OMP_WAIT_POLICY=PASSIVE POLARS_MAX_THREADS=1 PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=$PWD/scratch/review/round10-mutations-shard3/family_entry_unscoped/src:$PWD TRACKB_ROUND10_TREE=$PWD/scratch/review/round10-mutations-shard3/family_entry_unscoped/src HYPOTHESIS_STORAGE_DIRECTORY=scratch/review/round10-mutations-shard3/hyp-family_entry_unscoped /tmp/tbvenv/bin/python scratch/review/run_round10_named.py -p no:xdist -p no:cacheprovider -q --tb=line -rf tests/test_track_b_ret_ledger_fix_round_10.py tests/test_track_b_ret_ledger_fix_round_9.py", + "outer_command": [ + "python", + "scratch/review/round10_mutate.py" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_10.py::test_another_deducted_caregiver_keeps_its_minimum" + ], + "failed_test_count": 17, + "evidence": { + "cloud_comment": "https://github.com/PolicyEngine/microcosm-dynamics/pull/563#issuecomment-6584667595", + "results_sha256": "d3ab07eb2e589613e8be609135869076b699ea019f7122f656623daadc817a83" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "ad65407af7c69507095e03244c5d463a355d20b674d3ece1f0d8176f6987a5a9", + "src/populace_dynamics/track_b/ret_ledger.py": "edd9a4823d38a3157ba0bbf055e18ef9ba40fa787ccba0acd37b4ad3cbbca4bd" + } + }, + "layer": "g_preflight" + }, + { + "id": "round10-deduction_entry_unscoped", + "round": 10, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "after": "def _after_deductions(\n", + "before": "@_care_scope\ndef _after_deductions(\n" + } + ], + "command": "env POPULACE_DYNAMICS_PSID_DIR=/nonexistent/trackb-round10 POPULACE_DYNAMICS_EPUF_DIR=/nonexistent/trackb-round10 OMP_NUM_THREADS=1 OMP_WAIT_POLICY=PASSIVE POLARS_MAX_THREADS=1 PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=$PWD/scratch/review/round10-mutations-shard0/deduction_entry_unscoped/src:$PWD TRACKB_ROUND10_TREE=$PWD/scratch/review/round10-mutations-shard0/deduction_entry_unscoped/src HYPOTHESIS_STORAGE_DIRECTORY=scratch/review/round10-mutations-shard0/hyp-deduction_entry_unscoped /tmp/tbvenv/bin/python scratch/review/run_round10_named.py -p no:xdist -p no:cacheprovider -q --tb=line -rf tests/test_track_b_ret_ledger_fix_round_10.py tests/test_track_b_ret_ledger_fix_round_9.py", + "outer_command": [ + "python", + "scratch/review/round10_mutate.py" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_10.py::test_another_deducted_caregiver_keeps_its_minimum" + ], + "failed_test_count": 48, + "evidence": { + "cloud_comment": "https://github.com/PolicyEngine/microcosm-dynamics/pull/563#issuecomment-6584667595", + "results_sha256": "d3ab07eb2e589613e8be609135869076b699ea019f7122f656623daadc817a83" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "ad65407af7c69507095e03244c5d463a355d20b674d3ece1f0d8176f6987a5a9", + "src/populace_dynamics/track_b/ret_ledger.py": "edd9a4823d38a3157ba0bbf055e18ef9ba40fa787ccba0acd37b4ad3cbbca4bd" + } + }, + "layer": "g_preflight" + }, + { + "id": "round10-rate_key_drops_state", + "round": 10, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "after": " (\"ordinary\", comparison, payment_month, id(params)),\n lambda: _family_benefits(state, comparison, payment_month, params),\n", + "before": " (\"ordinary\", state, comparison, payment_month, id(params)),\n lambda: _family_benefits(state, comparison, payment_month, params),\n" + }, + { + "after": " (\"ordinary\", comparison, payment_month, id(params)),\n lambda comparison=comparison: _family_benefits(\n", + "before": " (\"ordinary\", state, comparison, payment_month, id(params)),\n lambda comparison=comparison: _family_benefits(\n" + } + ], + "command": "env POPULACE_DYNAMICS_PSID_DIR=/nonexistent/trackb-round10 POPULACE_DYNAMICS_EPUF_DIR=/nonexistent/trackb-round10 OMP_NUM_THREADS=1 OMP_WAIT_POLICY=PASSIVE POLARS_MAX_THREADS=1 PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=$PWD/scratch/review/round10-mutations-shard1/rate_key_drops_state/src:$PWD TRACKB_ROUND10_TREE=$PWD/scratch/review/round10-mutations-shard1/rate_key_drops_state/src HYPOTHESIS_STORAGE_DIRECTORY=scratch/review/round10-mutations-shard1/hyp-rate_key_drops_state /tmp/tbvenv/bin/python scratch/review/run_round10_named.py -p no:xdist -p no:cacheprovider -q --tb=line -rf tests/test_track_b_ret_ledger_fix_round_10.py tests/test_track_b_ret_ledger_fix_round_9.py", + "outer_command": [ + "python", + "scratch/review/round10_mutate.py" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_10.py::test_one_scope_keeps_records_households_and_events_apart" + ], + "failed_test_count": 1, + "evidence": { + "cloud_comment": "https://github.com/PolicyEngine/microcosm-dynamics/pull/563#issuecomment-6584667595", + "results_sha256": "d3ab07eb2e589613e8be609135869076b699ea019f7122f656623daadc817a83" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "ad65407af7c69507095e03244c5d463a355d20b674d3ece1f0d8176f6987a5a9", + "src/populace_dynamics/track_b/ret_ledger.py": "edd9a4823d38a3157ba0bbf055e18ef9ba40fa787ccba0acd37b4ad3cbbca4bd" + } + }, + "layer": "g_preflight" + }, + { + "id": "round10-event_key_drops_state", + "round": 10, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "after": " \"events\",\n comparison,\n", + "before": " \"events\",\n state,\n comparison,\n" + } + ], + "command": "env POPULACE_DYNAMICS_PSID_DIR=/nonexistent/trackb-round10 POPULACE_DYNAMICS_EPUF_DIR=/nonexistent/trackb-round10 OMP_NUM_THREADS=1 OMP_WAIT_POLICY=PASSIVE POLARS_MAX_THREADS=1 PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=$PWD/scratch/review/round10-mutations-shard0/event_key_drops_state/src:$PWD TRACKB_ROUND10_TREE=$PWD/scratch/review/round10-mutations-shard0/event_key_drops_state/src HYPOTHESIS_STORAGE_DIRECTORY=scratch/review/round10-mutations-shard0/hyp-event_key_drops_state /tmp/tbvenv/bin/python scratch/review/run_round10_named.py -p no:xdist -p no:cacheprovider -q --tb=line -rf tests/test_track_b_ret_ledger_fix_round_10.py tests/test_track_b_ret_ledger_fix_round_9.py", + "outer_command": [ + "python", + "scratch/review/round10_mutate.py" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_10.py::test_one_scope_keeps_records_households_and_events_apart" + ], + "failed_test_count": 1, + "evidence": { + "cloud_comment": "https://github.com/PolicyEngine/microcosm-dynamics/pull/563#issuecomment-6584667595", + "results_sha256": "d3ab07eb2e589613e8be609135869076b699ea019f7122f656623daadc817a83" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "ad65407af7c69507095e03244c5d463a355d20b674d3ece1f0d8176f6987a5a9", + "src/populace_dynamics/track_b/ret_ledger.py": "edd9a4823d38a3157ba0bbf055e18ef9ba40fa787ccba0acd37b4ad3cbbca4bd" + } + }, + "layer": "g_preflight" + }, + { + "id": "round10-event_key_drops_events", + "round": 10, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "after": "", + "before": " tuple(sorted(full.items())),\n" + } + ], + "command": "env POPULACE_DYNAMICS_PSID_DIR=/nonexistent/trackb-round10 POPULACE_DYNAMICS_EPUF_DIR=/nonexistent/trackb-round10 OMP_NUM_THREADS=1 OMP_WAIT_POLICY=PASSIVE POLARS_MAX_THREADS=1 PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=$PWD/scratch/review/round10-mutations-shard1/event_key_drops_events/src:$PWD TRACKB_ROUND10_TREE=$PWD/scratch/review/round10-mutations-shard1/event_key_drops_events/src HYPOTHESIS_STORAGE_DIRECTORY=scratch/review/round10-mutations-shard1/hyp-event_key_drops_events /tmp/tbvenv/bin/python scratch/review/run_round10_named.py -p no:xdist -p no:cacheprovider -q --tb=line -rf tests/test_track_b_ret_ledger_fix_round_10.py tests/test_track_b_ret_ledger_fix_round_9.py", + "outer_command": [ + "python", + "scratch/review/round10_mutate.py" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_10.py::test_one_scope_keeps_records_households_and_events_apart" + ], + "failed_test_count": 1, + "evidence": { + "cloud_comment": "https://github.com/PolicyEngine/microcosm-dynamics/pull/563#issuecomment-6584667595", + "results_sha256": "d3ab07eb2e589613e8be609135869076b699ea019f7122f656623daadc817a83" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "ad65407af7c69507095e03244c5d463a355d20b674d3ece1f0d8176f6987a5a9", + "src/populace_dynamics/track_b/ret_ledger.py": "edd9a4823d38a3157ba0bbf055e18ef9ba40fa787ccba0acd37b4ad3cbbca4bd" + } + }, + "layer": "g_preflight" + }, + { + "id": "round10-event_key_drops_households", + "round": 10, + "source": "src/populace_dynamics/track_b/gross_benefits.py", + "change": [ + { + "after": "", + "before": " tuple(sorted(households.items())),\n" + } + ], + "command": "env POPULACE_DYNAMICS_PSID_DIR=/nonexistent/trackb-round10 POPULACE_DYNAMICS_EPUF_DIR=/nonexistent/trackb-round10 OMP_NUM_THREADS=1 OMP_WAIT_POLICY=PASSIVE POLARS_MAX_THREADS=1 PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=$PWD/scratch/review/round10-mutations-shard2/event_key_drops_households/src:$PWD TRACKB_ROUND10_TREE=$PWD/scratch/review/round10-mutations-shard2/event_key_drops_households/src HYPOTHESIS_STORAGE_DIRECTORY=scratch/review/round10-mutations-shard2/hyp-event_key_drops_households /tmp/tbvenv/bin/python scratch/review/run_round10_named.py -p no:xdist -p no:cacheprovider -q --tb=line -rf tests/test_track_b_ret_ledger_fix_round_10.py tests/test_track_b_ret_ledger_fix_round_9.py", + "outer_command": [ + "python", + "scratch/review/round10_mutate.py" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_10.py::test_one_scope_keeps_records_households_and_events_apart" + ], + "failed_test_count": 1, + "evidence": { + "cloud_comment": "https://github.com/PolicyEngine/microcosm-dynamics/pull/563#issuecomment-6584667595", + "results_sha256": "d3ab07eb2e589613e8be609135869076b699ea019f7122f656623daadc817a83" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "ad65407af7c69507095e03244c5d463a355d20b674d3ece1f0d8176f6987a5a9", + "src/populace_dynamics/track_b/ret_ledger.py": "edd9a4823d38a3157ba0bbf055e18ef9ba40fa787ccba0acd37b4ad3cbbca4bd" + } + }, + "layer": "g_preflight" + }, + { + "id": "round10-bound_original_only", + "round": 10, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": [ + { + "after": " < b.original_rates[month - 1]\n", + "before": " < min(b.original_rates[month - 1], max(children))\n" + } + ], + "command": "env POPULACE_DYNAMICS_PSID_DIR=/nonexistent/trackb-round10 POPULACE_DYNAMICS_EPUF_DIR=/nonexistent/trackb-round10 OMP_NUM_THREADS=1 OMP_WAIT_POLICY=PASSIVE POLARS_MAX_THREADS=1 PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=$PWD/scratch/review/round10-mutations-shard0/bound_original_only/src:$PWD TRACKB_ROUND10_TREE=$PWD/scratch/review/round10-mutations-shard0/bound_original_only/src HYPOTHESIS_STORAGE_DIRECTORY=scratch/review/round10-mutations-shard0/hyp-bound_original_only /tmp/tbvenv/bin/python scratch/review/run_round10_named.py -p no:xdist -p no:cacheprovider -q --tb=line -rf tests/test_track_b_ret_ledger_fix_round_10.py tests/test_track_b_ret_ledger_fix_round_9.py", + "outer_command": [ + "python", + "scratch/review/round10_mutate.py" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_10.py::test_a_rate_past_any_minimum_needs_no_family_facts" + ], + "failed_test_count": 3, + "evidence": { + "cloud_comment": "https://github.com/PolicyEngine/microcosm-dynamics/pull/563#issuecomment-6584667595", + "results_sha256": "d3ab07eb2e589613e8be609135869076b699ea019f7122f656623daadc817a83" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "ad65407af7c69507095e03244c5d463a355d20b674d3ece1f0d8176f6987a5a9", + "src/populace_dynamics/track_b/ret_ledger.py": "edd9a4823d38a3157ba0bbf055e18ef9ba40fa787ccba0acd37b4ad3cbbca4bd" + } + }, + "layer": "r2" + }, + { + "id": "round10-bound_child_only", + "round": 10, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": [ + { + "after": " < max(children)\n", + "before": " < min(b.original_rates[month - 1], max(children))\n" + } + ], + "command": "env POPULACE_DYNAMICS_PSID_DIR=/nonexistent/trackb-round10 POPULACE_DYNAMICS_EPUF_DIR=/nonexistent/trackb-round10 OMP_NUM_THREADS=1 OMP_WAIT_POLICY=PASSIVE POLARS_MAX_THREADS=1 PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=$PWD/scratch/review/round10-mutations-shard1/bound_child_only/src:$PWD TRACKB_ROUND10_TREE=$PWD/scratch/review/round10-mutations-shard1/bound_child_only/src HYPOTHESIS_STORAGE_DIRECTORY=scratch/review/round10-mutations-shard1/hyp-bound_child_only /tmp/tbvenv/bin/python scratch/review/run_round10_named.py -p no:xdist -p no:cacheprovider -q --tb=line -rf tests/test_track_b_ret_ledger_fix_round_10.py tests/test_track_b_ret_ledger_fix_round_9.py", + "outer_command": [ + "python", + "scratch/review/round10_mutate.py" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_10.py::test_a_widows_own_original_rate_still_bounds_the_request" + ], + "failed_test_count": 1, + "evidence": { + "cloud_comment": "https://github.com/PolicyEngine/microcosm-dynamics/pull/563#issuecomment-6584667595", + "results_sha256": "d3ab07eb2e589613e8be609135869076b699ea019f7122f656623daadc817a83" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "ad65407af7c69507095e03244c5d463a355d20b674d3ece1f0d8176f6987a5a9", + "src/populace_dynamics/track_b/ret_ledger.py": "edd9a4823d38a3157ba0bbf055e18ef9ba40fa787ccba0acd37b4ad3cbbca4bd" + } + }, + "layer": "r2" + }, + { + "id": "round10-bound_lowest_child", + "round": 10, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": [ + { + "after": " < min(b.original_rates[month - 1], min(children))\n", + "before": " < min(b.original_rates[month - 1], max(children))\n" + } + ], + "command": "env POPULACE_DYNAMICS_PSID_DIR=/nonexistent/trackb-round10 POPULACE_DYNAMICS_EPUF_DIR=/nonexistent/trackb-round10 OMP_NUM_THREADS=1 OMP_WAIT_POLICY=PASSIVE POLARS_MAX_THREADS=1 PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=$PWD/scratch/review/round10-mutations-shard2/bound_lowest_child/src:$PWD TRACKB_ROUND10_TREE=$PWD/scratch/review/round10-mutations-shard2/bound_lowest_child/src HYPOTHESIS_STORAGE_DIRECTORY=scratch/review/round10-mutations-shard2/hyp-bound_lowest_child /tmp/tbvenv/bin/python scratch/review/run_round10_named.py -p no:xdist -p no:cacheprovider -q --tb=line -rf tests/test_track_b_ret_ledger_fix_round_10.py tests/test_track_b_ret_ledger_fix_round_9.py", + "outer_command": [ + "python", + "scratch/review/round10_mutate.py" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_10.py::test_the_higher_of_two_declared_child_rates_bounds_the_request" + ], + "failed_test_count": 1, + "evidence": { + "cloud_comment": "https://github.com/PolicyEngine/microcosm-dynamics/pull/563#issuecomment-6584667595", + "results_sha256": "d3ab07eb2e589613e8be609135869076b699ea019f7122f656623daadc817a83" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "ad65407af7c69507095e03244c5d463a355d20b674d3ece1f0d8176f6987a5a9", + "src/populace_dynamics/track_b/ret_ledger.py": "edd9a4823d38a3157ba0bbf055e18ef9ba40fa787ccba0acd37b4ad3cbbca4bd" + } + }, + "layer": "r2" + }, + { + "id": "round10-bound_at_equality", + "round": 10, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": [ + { + "after": " <= min(b.original_rates[month - 1], max(children))\n", + "before": " < min(b.original_rates[month - 1], max(children))\n" + } + ], + "command": "env POPULACE_DYNAMICS_PSID_DIR=/nonexistent/trackb-round10 POPULACE_DYNAMICS_EPUF_DIR=/nonexistent/trackb-round10 OMP_NUM_THREADS=1 OMP_WAIT_POLICY=PASSIVE POLARS_MAX_THREADS=1 PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=$PWD/scratch/review/round10-mutations-shard3/bound_at_equality/src:$PWD TRACKB_ROUND10_TREE=$PWD/scratch/review/round10-mutations-shard3/bound_at_equality/src HYPOTHESIS_STORAGE_DIRECTORY=scratch/review/round10-mutations-shard3/hyp-bound_at_equality /tmp/tbvenv/bin/python scratch/review/run_round10_named.py -p no:xdist -p no:cacheprovider -q --tb=line -rf tests/test_track_b_ret_ledger_fix_round_10.py tests/test_track_b_ret_ledger_fix_round_9.py", + "outer_command": [ + "python", + "scratch/review/round10_mutate.py" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_10.py::test_a_childs_original_rate_bounds_the_request[BenefitType.WIDOW-gross0-True]" + ], + "failed_test_count": 3, + "evidence": { + "cloud_comment": "https://github.com/PolicyEngine/microcosm-dynamics/pull/563#issuecomment-6584667595", + "results_sha256": "d3ab07eb2e589613e8be609135869076b699ea019f7122f656623daadc817a83" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "ad65407af7c69507095e03244c5d463a355d20b674d3ece1f0d8176f6987a5a9", + "src/populace_dynamics/track_b/ret_ledger.py": "edd9a4823d38a3157ba0bbf055e18ef9ba40fa787ccba0acd37b4ad3cbbca4bd" + } + }, + "layer": "r2" + }, + { + "id": "round10-bound_any_beneficiary", + "round": 10, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": [ + { + "after": " children = [b.original_rates[month - 1] for b in entitled]\n", + "before": " children = [\n b.original_rates[month - 1]\n for b in entitled\n if b.benefit_types[month - 1] in (BenefitType.CHILD, BenefitType.CDB)\n ]\n" + } + ], + "command": "env POPULACE_DYNAMICS_PSID_DIR=/nonexistent/trackb-round10 POPULACE_DYNAMICS_EPUF_DIR=/nonexistent/trackb-round10 OMP_NUM_THREADS=1 OMP_WAIT_POLICY=PASSIVE POLARS_MAX_THREADS=1 PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=$PWD/scratch/review/round10-mutations-shard0/bound_any_beneficiary/src:$PWD TRACKB_ROUND10_TREE=$PWD/scratch/review/round10-mutations-shard0/bound_any_beneficiary/src HYPOTHESIS_STORAGE_DIRECTORY=scratch/review/round10-mutations-shard0/hyp-bound_any_beneficiary /tmp/tbvenv/bin/python scratch/review/run_round10_named.py -p no:xdist -p no:cacheprovider -q --tb=line -rf tests/test_track_b_ret_ledger_fix_round_10.py tests/test_track_b_ret_ledger_fix_round_9.py", + "outer_command": [ + "python", + "scratch/review/round10_mutate.py" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_10.py::test_a_rate_past_any_minimum_needs_no_family_facts" + ], + "failed_test_count": 5, + "evidence": { + "cloud_comment": "https://github.com/PolicyEngine/microcosm-dynamics/pull/563#issuecomment-6584667595", + "results_sha256": "d3ab07eb2e589613e8be609135869076b699ea019f7122f656623daadc817a83" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "ad65407af7c69507095e03244c5d463a355d20b674d3ece1f0d8176f6987a5a9", + "src/populace_dynamics/track_b/ret_ledger.py": "edd9a4823d38a3157ba0bbf055e18ef9ba40fa787ccba0acd37b4ad3cbbca4bd" + } + }, + "layer": "r2" + }, + { + "id": "round10-bound_skips_the_child_check", + "round": 10, + "source": "src/populace_dynamics/track_b/ret_ledger.py", + "change": [ + { + "after": " return any(\n", + "before": " return bool(children) and any(\n" + } + ], + "command": "env POPULACE_DYNAMICS_PSID_DIR=/nonexistent/trackb-round10 POPULACE_DYNAMICS_EPUF_DIR=/nonexistent/trackb-round10 OMP_NUM_THREADS=1 OMP_WAIT_POLICY=PASSIVE POLARS_MAX_THREADS=1 PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=$PWD/scratch/review/round10-mutations-shard1/bound_skips_the_child_check/src:$PWD TRACKB_ROUND10_TREE=$PWD/scratch/review/round10-mutations-shard1/bound_skips_the_child_check/src HYPOTHESIS_STORAGE_DIRECTORY=scratch/review/round10-mutations-shard1/hyp-bound_skips_the_child_check /tmp/tbvenv/bin/python scratch/review/run_round10_named.py -p no:xdist -p no:cacheprovider -q --tb=line -rf tests/test_track_b_ret_ledger_fix_round_10.py tests/test_track_b_ret_ledger_fix_round_9.py", + "outer_command": [ + "python", + "scratch/review/round10_mutate.py" + ], + "mutated_exit_code": 1, + "failed_tests": [ + "tests/test_track_b_ret_ledger_fix_round_9.py::test_no_minimum_can_move_on_these_records[no child]" + ], + "failed_test_count": 2, + "evidence": { + "cloud_comment": "https://github.com/PolicyEngine/microcosm-dynamics/pull/563#issuecomment-6584667595", + "results_sha256": "d3ab07eb2e589613e8be609135869076b699ea019f7122f656623daadc817a83" + }, + "mutation_method": "One-line semantic mutation in a copied source tree under scratch/review; production sources untouched.", + "restoration": { + "reverted": true, + "production_sources_unchanged": true, + "production_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "ad65407af7c69507095e03244c5d463a355d20b674d3ece1f0d8176f6987a5a9", + "src/populace_dynamics/track_b/ret_ledger.py": "edd9a4823d38a3157ba0bbf055e18ef9ba40fa787ccba0acd37b4ad3cbbca4bd" + } + }, + "layer": "r2" } ], "restoration_verification_snapshot": { @@ -13351,5 +14020,50 @@ "round_9_restoration_snapshot": { "src/populace_dynamics/track_b/gross_benefits.py": "bda57ecc5b3ac35d9db4c1554964c5472cdb469b831106841404032ac6c54402", "src/populace_dynamics/track_b/ret_ledger.py": "5a54d9adb8e0ebd09070566447f1372249e03a14aee6533d0802fde58d6b3ea1" + }, + "round_10_head": "03530e8bd99db9608ecfb60ae4f17508fde1b3be", + "round_10_note": "A cloud session ran round 10's 22 listed mutations at the final source and test bytes on 03530e8b (https://github.com/PolicyEngine/microcosm-dynamics/pull/563#issuecomment-6584667595), each in a copied source tree with its own Hypothesis database, through tests/test_track_b_ret_ledger_fix_round_10.py and tests/test_track_b_ret_ledger_fix_round_9.py. 19 failed a named test, and the runner's audit counted no restricted open, subprocess.Popen or os.system call. rate_key_drops_month, rate_key_drops_params and event_key_shares_the_ordinary_tag passed every test and stay out of this count as equivalent; round_10_equivalent_survivors gives each argument. round_10_mutation_driver_source and round_10_runner_source hold the exact scripts. Earlier records remain historical.", + "round_10_equivalent_survivors": { + "rate_key_drops_month": { + "change": [ + { + "after": " (\"ordinary\", state, comparison, id(params)),\n lambda: _family_benefits(state, comparison, payment_month, params),\n", + "before": " (\"ordinary\", state, comparison, payment_month, id(params)),\n lambda: _family_benefits(state, comparison, payment_month, params),\n" + }, + { + "after": " (\"ordinary\", state, comparison, id(params)),\n lambda comparison=comparison: _family_benefits(\n", + "before": " (\"ordinary\", state, comparison, payment_month, id(params)),\n lambda comparison=comparison: _family_benefits(\n" + } + ], + "argument": "Only _family_benefits and _after_deductions open a comparison cache, and only when none is open. RET calls G once per month and the household entry once per record, each outside any cache, and every nested comparison passes the opening call's payment_month through unchanged. So every key in one cache carries the same month, and dropping it merges no two families." + }, + "rate_key_drops_params": { + "change": [ + { + "after": " (\"ordinary\", state, comparison, payment_month),\n lambda: _family_benefits(state, comparison, payment_month, params),\n", + "before": " (\"ordinary\", state, comparison, payment_month, id(params)),\n lambda: _family_benefits(state, comparison, payment_month, params),\n" + }, + { + "after": " (\"ordinary\", state, comparison, payment_month),\n lambda comparison=comparison: _family_benefits(\n", + "before": " (\"ordinary\", state, comparison, payment_month, id(params)),\n lambda comparison=comparison: _family_benefits(\n" + } + ], + "argument": "Every nested comparison passes the opening call's params object through unchanged, and that call keeps the object alive, so every key in one cache carries the same id(params). Dropping it merges no two families." + }, + "event_key_shares_the_ordinary_tag": { + "change": [ + { + "after": " \"ordinary\",\n", + "before": " \"events\",\n" + } + ], + "argument": "An events key has seven fields (tag, state, comparison, month, id(params), events, households) and an ordinary key five, and tuples of different lengths never compare equal. Giving both the same tag merges no two keys." + } + }, + "round_10_mutation_driver_source": "\"\"\"Round 10 mutations, each in a copied source tree under scratch/review.\"\"\"\nimport hashlib, json, os, re, shlex, shutil, subprocess, sys\nfrom pathlib import Path\n\nG = \"src/populace_dynamics/track_b/gross_benefits.py\"\nR = \"src/populace_dynamics/track_b/ret_ledger.py\"\nPY = sys.executable\nMODULES = [\n \"tests/test_track_b_ret_ledger_fix_round_10.py\",\n \"tests/test_track_b_ret_ledger_fix_round_9.py\",\n]\nKEEP_OTHERS = \" if member.beneficiary_id == caregiver.beneficiary_id\\n else member\\n )\\n for member in beneficiaries\\n\"\nCLEAR_OTHERS = (\n \" if member.beneficiary_id == caregiver.beneficiary_id\\n\"\n \" else (\\n\"\n \" _replace_declared(member, child_in_care=False)\\n\"\n \" if member.role in _WIDOW_ROLES\\n\"\n \" else member\\n\"\n \" )\\n\"\n \" )\\n for member in beneficiaries\\n\"\n)\nSTORE = \" if key not in cache:\\n cache[key] = compute()\\n return cache[key]\\n\"\nSCOPE_OPEN = \" if _CARE_COMPARISONS.get() is not None:\\n return function(*args)\\n\"\nSCOPE_RESET = \" finally:\\n _CARE_COMPARISONS.reset(token)\\n\"\nRATE_KEY = \" (\\\"ordinary\\\", state, comparison, payment_month, id(params)),\\n lambda: _family_benefits(state, comparison, payment_month, params),\\n\"\nMIN_KEY = \" (\\\"ordinary\\\", state, comparison, payment_month, id(params)),\\n lambda comparison=comparison: _family_benefits(\\n\"\nEVENT_STATE = \" \\\"events\\\",\\n state,\\n comparison,\\n\"\nEVENT_EVENTS = \" tuple(sorted(full.items())),\\n\"\nEVENT_HOUSEHOLDS = \" tuple(sorted(households.items())),\\n\"\nEVENT_TAG = \" \\\"events\\\",\\n\"\nAFTER_SCOPE = \"@_care_scope\\ndef _after_deductions(\\n\"\nFAMILY_SCOPE = \"@_care_scope\\ndef _family_benefits(\\n\"\nBOUND = \" < min(b.original_rates[month - 1], max(children))\\n\"\nCHILDREN = \" children = [\\n b.original_rates[month - 1]\\n for b in entitled\\n if b.benefit_types[month - 1] in (BenefitType.CHILD, BenefitType.CDB)\\n ]\\n\"\nNEEDS_CHILD = \" return bool(children) and any(\\n\"\n\nM = [\n (\"comparison_clears_other_care\", G, [(KEEP_OTHERS, CLEAR_OTHERS)]),\n (\"comparison_clears_widow_care\", G, [(KEEP_OTHERS, CLEAR_OTHERS.replace(\"if member.role in _WIDOW_ROLES\", \"if member.role is Role.WIDOW\"))]),\n (\"comparison_clears_disabled_widow_care\", G, [(KEEP_OTHERS, CLEAR_OTHERS.replace(\"if member.role in _WIDOW_ROLES\", \"if member.role is Role.DISABLED_WIDOW\"))]),\n (\"cache_never_stores\", G, [(STORE, \" return compute()\\n\")]),\n (\"cache_recomputes_each_hit\", G, [(STORE, \" cache[key] = compute()\\n return cache[key]\\n\")]),\n (\"scope_opens_per_call\", G, [(SCOPE_OPEN, \" if False:\\n return function(*args)\\n\")]),\n (\"scope_never_resets\", G, [(SCOPE_RESET, \" finally:\\n pass\\n\")]),\n (\"family_entry_unscoped\", G, [(FAMILY_SCOPE, \"def _family_benefits(\\n\")]),\n (\"deduction_entry_unscoped\", G, [(AFTER_SCOPE, \"def _after_deductions(\\n\")]),\n (\"rate_key_drops_state\", G, [(RATE_KEY, RATE_KEY.replace(\"(\\\"ordinary\\\", state, \", \"(\\\"ordinary\\\", \")), (MIN_KEY, MIN_KEY.replace(\"(\\\"ordinary\\\", state, \", \"(\\\"ordinary\\\", \"))]),\n (\"rate_key_drops_month\", G, [(RATE_KEY, RATE_KEY.replace(\"comparison, payment_month, id\", \"comparison, id\")), (MIN_KEY, MIN_KEY.replace(\"comparison, payment_month, id\", \"comparison, id\"))]),\n (\"rate_key_drops_params\", G, [(RATE_KEY, RATE_KEY.replace(\", id(params))\", \")\")), (MIN_KEY, MIN_KEY.replace(\", id(params))\", \")\"))]),\n (\"event_key_drops_state\", G, [(EVENT_STATE, \" \\\"events\\\",\\n comparison,\\n\")]),\n (\"event_key_drops_events\", G, [(EVENT_EVENTS, \"\")]),\n (\"event_key_drops_households\", G, [(EVENT_HOUSEHOLDS, \"\")]),\n (\"event_key_shares_the_ordinary_tag\", G, [(EVENT_TAG, \" \\\"ordinary\\\",\\n\")]),\n (\"bound_original_only\", R, [(BOUND, \" < b.original_rates[month - 1]\\n\")]),\n (\"bound_child_only\", R, [(BOUND, \" < max(children)\\n\")]),\n (\"bound_lowest_child\", R, [(BOUND, BOUND.replace(\"max(children)\", \"min(children)\"))]),\n (\"bound_at_equality\", R, [(BOUND, BOUND.replace(\" < \", \" <= \"))]),\n (\"bound_any_beneficiary\", R, [(CHILDREN, \" children = [b.original_rates[month - 1] for b in entitled]\\n\")]),\n (\"bound_skips_the_child_check\", R, [(NEEDS_CHILD, \" return any(\\n\")]),\n]\nshard, shards = map(int, os.environ.get(\"TRACKB_SHARD\", \"0/1\").split(\"/\"))\nonly = {name for index, (name, _, _) in enumerate(M) if index % shards == shard}\nbase = Path(f\"scratch/review/round10-mutations-shard{shard}\")\nbase.mkdir(exist_ok=True)\nreport = Path(f\"scratch/review/round10-mutations-shard{shard}.json\")\nrecords = json.loads(report.read_text()) if report.exists() else {}\nenv = dict(os.environ)\nenv.update(\n POPULACE_DYNAMICS_PSID_DIR=\"/nonexistent/trackb-round10\",\n POPULACE_DYNAMICS_EPUF_DIR=\"/nonexistent/trackb-round10\",\n OMP_NUM_THREADS=\"1\", OMP_WAIT_POLICY=\"PASSIVE\", POLARS_MAX_THREADS=\"1\",\n PYTHONDONTWRITEBYTECODE=\"1\",\n)\ncwd = os.getcwd()\nfor name, path, changes in M:\n if only and name not in only:\n continue\n tree = base / name\n if tree.exists():\n shutil.rmtree(tree)\n shutil.copytree(\"src\", tree / \"src\", ignore=shutil.ignore_patterns(\"__pycache__\"))\n target = tree / path\n source = target.read_text()\n for before, after in changes:\n assert source.count(before) == 1, (name, before, source.count(before))\n source = source.replace(before, after)\n target.write_text(source)\n log = base / f\"{name}.log\"\n hyp = base / f\"hyp-{name}\"\n shutil.rmtree(hyp, ignore_errors=True)\n run_env = dict(env, PYTHONPATH=f\"{cwd}/{tree}/src:{cwd}\", TRACKB_ROUND10_TREE=f\"{cwd}/{tree}/src\", HYPOTHESIS_STORAGE_DIRECTORY=str(hyp))\n shown = {key: run_env[key] for key in ('POPULACE_DYNAMICS_PSID_DIR', 'POPULACE_DYNAMICS_EPUF_DIR', 'OMP_NUM_THREADS', 'OMP_WAIT_POLICY', 'POLARS_MAX_THREADS', 'PYTHONDONTWRITEBYTECODE', 'PYTHONPATH', 'TRACKB_ROUND10_TREE', 'HYPOTHESIS_STORAGE_DIRECTORY')}\n args = [PY, \"scratch/review/run_round10_named.py\", \"-p\", \"no:xdist\", \"-p\", \"no:cacheprovider\", \"-q\", \"--tb=line\", \"-rf\", *MODULES]\n with open(log, \"w\") as out:\n code = subprocess.run(args, env=run_env, stdout=out, stderr=subprocess.STDOUT).returncode\n text = log.read_text()\n failed = re.findall(r\"^FAILED (\\S+)\", text, flags=re.M)\n audit = re.findall(r\"^OPEN_AUDIT (.*)$\", text, flags=re.M)\n assert \"MUTATED_TREE\" in text, name\n records[name] = {\n \"name\": name, \"file\": path,\n \"source_sha256\": hashlib.sha256(Path(path).read_bytes()).hexdigest(),\n \"changes\": [{\"before\": b, \"after\": a} for b, a in changes],\n \"modules\": MODULES, \"exit_code\": code,\n \"command\": shlex.join([\"env\", *(f\"{k}={v}\" for k, v in shown.items()), *args]),\n \"failing_test_count\": len(failed),\n \"first_failing_test\": failed[0] if failed else None,\n \"open_audit\": json.loads(audit[-1]) if audit else None,\n }\n shutil.rmtree(tree)\n report.write_text(json.dumps(records, indent=1))\n print(name, \"exit\", code, \"failed\", len(failed), (failed[0].split(\"::\")[-1][:60] if failed else \"SURVIVED\"), flush=True)\n", + "round_10_runner_source": "\"\"\"Run named invented-data conformance tests with open-event auditing.\"\"\"\n\nimport json\nimport os\nfrom pathlib import Path\nimport sys\n\nCOUNTS = {\"restricted_opens\": 0, \"subprocess.Popen\": 0, \"os.system\": 0}\nBARRED = {\n \"gates.yaml\", \"adjusted_poverty.py\", \"rows.py\",\n \"ssa_trust_fund_interest_rates_2026.json\",\n \"urban2010_cola_comparison.md\", \"urban2010_fra68_comparison.md\",\n \"boomers2004_uniform_cut_comparison.md\", \"minimum_benefits_comparison.md\",\n \"m6_projection_engine.md\", \"mint8_table_user_guide.source.html\",\n \"test_anchor_provenance_erratum.py\",\n \"s0_1_power_results.json\", \"s0_1_source_audit.md\", \"s0_1_power.py\",\n \"test_s0_1_invariants.py\", \"test_s0_1_power.py\",\n \"test_s0_1_thresholds.py\",\n}\n\n\ndef audit(event, arguments):\n if event == \"open\" and isinstance(arguments[0], (str, bytes)):\n path = os.fsdecode(arguments[0])\n name = Path(path).name\n if (\n name in BARRED\n or name.startswith((\"adjusted_poverty.\", \"rows.\"))\n or \"/PolicyEngine/psid-data/\" in path\n or \"/microcosm-launch-evidence/\" in path\n or \"/dynasim-refs/\" in path\n or \"/claude-501/\" in path\n or \"/tests/s0_1/\" in path\n ):\n COUNTS[\"restricted_opens\"] += 1\n raise RuntimeError(path)\n elif event in (\"subprocess.Popen\", \"os.system\"):\n COUNTS[event] += 1\n\n\ndef main():\n for name in (\"POPULACE_DYNAMICS_PSID_DIR\", \"POPULACE_DYNAMICS_EPUF_DIR\"):\n assert os.environ[name] == \"/nonexistent/trackb-round10\"\n assert sys.argv[1:]\n sys.addaudithook(audit)\n import populace_dynamics\n\n expected = os.environ.get(\"TRACKB_ROUND10_TREE\")\n if expected:\n assert str(Path(populace_dynamics.__file__)).startswith(expected)\n print(\"MUTATED_TREE\", expected, flush=True)\n import pytest\n\n try:\n return pytest.main(sys.argv[1:])\n finally:\n print(\"OPEN_AUDIT\", json.dumps(COUNTS, sort_keys=True), flush=True)\n\n\nif __name__ == \"__main__\":\n raise SystemExit(main())\n", + "round_10_restoration_snapshot": { + "src/populace_dynamics/track_b/gross_benefits.py": "ad65407af7c69507095e03244c5d463a355d20b674d3ece1f0d8176f6987a5a9", + "src/populace_dynamics/track_b/ret_ledger.py": "edd9a4823d38a3157ba0bbf055e18ef9ba40fa787ccba0acd37b4ad3cbbca4bd" } } diff --git a/docs/design/track_b_g2_r2b_verification.json b/docs/design/track_b_g2_r2b_verification.json index 9ac6e4572..4c9ebd986 100644 --- a/docs/design/track_b_g2_r2b_verification.json +++ b/docs/design/track_b_g2_r2b_verification.json @@ -13321,5 +13321,59 @@ ] } }, - "round_9_current_evidence_note": "Fresh reviewed-head failing-first, named module gates, cross-head diagnostic and copied-tree mutation evidence sits under round_9. Earlier heads, counts and commands remain historical." + "round_9_current_evidence_note": "Fresh reviewed-head failing-first, named module gates, cross-head diagnostic and copied-tree mutation evidence sits under round_9. Earlier heads, counts and commands remain historical.", + "round_10": { + "reviewed_head": "03530e8bd99db9608ecfb60ae4f17508fde1b3be", + "verification_class": "statutory_conformance", + "admitted_scope": "Invented declarations and captured published examples only; no population, behavioral or forecast claim.", + "mutation_run": { + "where": "cloud session (Fleet ops held local mutation runs)", + "comment": "https://github.com/PolicyEngine/microcosm-dynamics/pull/563#issuecomment-6584667595", + "results_sha256": "d3ab07eb2e589613e8be609135869076b699ea019f7122f656623daadc817a83" + }, + "named_test_gate": { + "command": "env POPULACE_DYNAMICS_PSID_DIR=/nonexistent/trackb-round10 POPULACE_DYNAMICS_EPUF_DIR=/nonexistent/trackb-round10 OMP_NUM_THREADS=1 OMP_WAIT_POLICY=PASSIVE POLARS_MAX_THREADS=1 PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=$PWD/src:$PWD HYPOTHESIS_STORAGE_DIRECTORY=scratch/review/hyp-gate $PY -m pytest -n 4 -q -p no:cacheprovider tests/test_track_b_*.py", + "result": "1 failed, 14284 passed, 20 skipped in 865.53s (0:14:25)", + "failing_node": "tests/test_track_b_b0_1_review_root.py::test_every_engine_match_of_a_spelled_denied_name_is_flagged[bun]", + "failing_node_note": "The cloud container had bun 1.4.4, so the B0.1 review-root differential ran its bun case, which skips where bun is absent, as in CI. This PR changes no B0.1 file, and the node fails the same way at #562's head. It is outside this PR." + }, + "final_source_sha256": { + "src/populace_dynamics/track_b/gross_benefits.py": "ad65407af7c69507095e03244c5d463a355d20b674d3ece1f0d8176f6987a5a9", + "src/populace_dynamics/track_b/ret_ledger.py": "edd9a4823d38a3157ba0bbf055e18ef9ba40fa787ccba0acd37b4ad3cbbca4bd" + }, + "final_test_sha256": { + "tests/test_track_b_ret_ledger_fix_round_10.py": "33c93d502d639b3b6dbac97bf144a7195a9f2f970c39bcdeb61cc5dd87c1ae04", + "tests/test_track_b_ret_ledger_fix_round_9.py": "03b8152dd80e24f0336840a29522ca4d5213cb797b3d74590ffb4054c1e12923" + }, + "mutations": { + "count": 19, + "ids": [ + "round10-comparison_clears_other_care", + "round10-comparison_clears_widow_care", + "round10-comparison_clears_disabled_widow_care", + "round10-cache_never_stores", + "round10-cache_recomputes_each_hit", + "round10-scope_opens_per_call", + "round10-scope_never_resets", + "round10-family_entry_unscoped", + "round10-deduction_entry_unscoped", + "round10-rate_key_drops_state", + "round10-event_key_drops_state", + "round10-event_key_drops_events", + "round10-event_key_drops_households", + "round10-bound_original_only", + "round10-bound_child_only", + "round10-bound_lowest_child", + "round10-bound_at_equality", + "round10-bound_any_beneficiary", + "round10-bound_skips_the_child_check" + ], + "equivalent": [ + "rate_key_drops_month", + "rate_key_drops_params", + "event_key_shares_the_ordinary_tag" + ] + } + }, + "round_10_current_evidence_note": "Round 10's copied-tree mutation evidence sits under round_10 and in the mutation ledger. Earlier heads, counts and commands remain historical." } diff --git a/docs/design/track_b_r2_ret_ledger.md b/docs/design/track_b_r2_ret_ledger.md index b39c46dd6..66c49e011 100644 --- a/docs/design/track_b_r2_ret_ledger.md +++ b/docs/design/track_b_r2_ret_ledger.md @@ -2817,6 +2817,14 @@ survivor child's OB on that PIA is $750, and the records now say so. | RET's provisional ledger pays the same minimum | `test_ret_pays_the_minimum_on_the_provisional_ledger` | | Without a context, RET asks for family facts only below the lower of a widow(er)'s original rate and an entitled child's, and a month it settles without them pays what G pays with them | `test_a_rate_past_any_minimum_needs_no_family_facts`; `test_a_childs_original_rate_bounds_the_request`; `test_the_higher_of_two_declared_child_rates_bounds_the_request`; `test_a_widows_own_original_rate_still_bounds_the_request`; Hypothesis `test_a_month_ret_settles_without_family_facts_matches_g` | -25 of the module's 37 tests fail against `bc460e32`, and round 9's 62 -all pass there. `scratch/review/round10_mutate.py` lists 22 mutations; a -Fleet ops hold on local mutation runs puts their results in a later commit. +25 of the module's 37 tests fail against `bc460e32`, and round 9's 62 all pass +there. A cloud session ran this round's 22 mutations at the final bytes on +`03530e8b`, and 19 failed a named test with no restricted open (the `round10-` +records in `docs/design/track_b_g2_r2b_mutations.json`, which also holds the +driver and runner sources). `rate_key_drops_month` and `rate_key_drops_params` +change no result. Each top-level call opens its own comparison cache (RET calls +G once per month, the household entry once per record), and each nested +comparison passes that call's month and parameters through unchanged, so every +key in one cache carries the same month and parameters. +`event_key_shares_the_ordinary_tag` changes none either: an events key has +seven fields and an ordinary key five, so the tag never decides a match.