Repository navigation
Medicaid MAGI household composition from co-resident parent ids (fixes #9404) - #9406
Merged
Merged
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #9406 +/- ##
==========================================
Coverage 100.00% 100.00%
==========================================
Files 4 12 +8
Lines 76 278 +202
Branches 2 6 +4
==========================================
+ Hits 76 278 +202
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…olds Three invariants over seeded random households, so a failure reproduces: explicit zero parent ids give the same Medicaid and demographic outputs as omitted ids; when own_children_in_household counts exactly the people whose ids name a person, is_parent from ids agrees with the count path; and is_parent/is_mother do not depend on member order. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
force-pushed
the
medicaid-magi-parent-ids
branch
from
September 26, 2026 00:28
e1849f2 to
08eaff9
Compare
Rework per the independent review of #9406 (REQUEST_CHANGES, six findings). - is_parent is now per person: own_children_in_household > 0 OR a co-resident person's parent id names them. Without ids it is main's expression; with consistent links both sources agree; one family's links can no longer erase another family's count-only parent (finding 2). - Households with no nonzero parent id keep main's family-sum expressions verbatim. Households with ids use medicaid_non_filer_member_sum, one pairwise 42 CFR 435.603(f)(3) predicate over co-residents: self, spouse, own child-age children (reverse links, for applicants of any age), and for child-age applicants their parents and child-age siblings. Each member is counted once (findings 1 and 4). - Main's family proxy survives only among unlinked people: child-age members without ids and members whose own_children_in_household exceeds the links naming them. The same rule drives the zero-id fallbacks of the claimed-by-parent test and the both-parents exception (finding 2). - medicaid_household_size, medicaid_household_income and California's ca_medicaid_household_pregnancies sum over that same membership, so an excluded aunt's pregnancy no longer enlarges a niece's household (finding 3). - Sums accumulate in float64; storage rounds (finding 5). - Parent ids resolve among tax-unit members for the claimed-by-parent test (identity) and among household members where the rule requires living together (non-filer membership, both-parents exception) (finding 6). - parent_1_id/parent_2_id document step and adoptive parents, 0 = unknown, nonzero ids, and int32 comparison. Test expectation changes, all from the rules above: - test_parent_links.py: the linked adult's household drops the unrelated child (size 3 -> 2, income 10,300.875 -> 10,100.375). The unrelated child has no ids and no family member reports a child the links omit, so its household is itself (size 3 -> 1, income -> 200.5). Previously the adult branch counted every child-age family member regardless of links. - Demographic parent_ids.yaml and the absent-parent Medicaid case: an adult whose own_children_in_household is positive stays a parent even when no child's id names them. Two resolution-only cases now set that count to 0 so they still isolate id resolution. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The zero-id differential found that, for 1986-1987 emergency Medicaid cases where both main and this branch raise ParameterNotFoundError, the branch raised a different error because it read filing_status before main's own terms. Evaluate main's terms first and compute the link-based condition only when some person has a parent id, so simulations without ids make exactly main's calls. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…perties - parent_ids_composition.yaml: teen parent (G40/T17/B1), mixed families (A35/C10 + B40/D8, as separate and as one family entity), another family's linked parent and the both-parents exception, California pregnancies (G60/M35/A30/C10/B2), adult sibling (G60/A25/B15), claimant in another household (P55/C26), stepfamily, married 18-year-olds, and the age-19 boundary for siblings and children. Expected values follow 42 CFR 435.603(f)(3) and ACWDL 20-10; 8 of the 10 fail on 08eaff9. - test_parent_links.py: float64 accumulation (2**24 + 1 + 1) in both member orders. - test_parent_links_properties.py: on seeded random households with teen parents, absent parents, spouses and pregnancies, the linked composition equals the regulation's on consistent data and a scalar statement of the documented rule on data with dropped ids, extra counts and split families; size >= 1; CA pregnancies and income sum over the same members; outputs are invariant to member order; is_parent is exactly the union of the child count and the links. - Changelog fragment describes the reworked behavior. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An independent r2 review confirmed all six r1 findings fixed and found: - Blocker: a married dependent lost a co-resident spouse who files separately, because the linked spouse test required a tax-unit role. A spouse is now a co-resident partner in a two-person marital unit, whatever either partner's tax role, or the other head or spouse of a joint return (42 CFR 435.603(f)(3)(i), (f)(4)). People linked as parent and child are never spouses, since PE puts everyone in one marital unit when a situation omits marital units. - A link in one household made its parent the presumed parent of a zero-id dependent in another household through a shared tax unit. The claimed-by-parent and both-parents fallbacks now use reports_unlinked_children (own_children_in_household exceeds the ids naming the person), which equals the original is_parent without links. - Inherited gap: a child claimed on a parent's return in another known tax unit never got the both-parents exception. With parent ids, a known external claiming unit headed by a co-resident parent now counts as being claimed by one parent (42 CFR 435.603(f)(2)(ii)). - The helper docstring no longer claims links never change another family's composition; switching a household to the linked rule can remove another family's legacy over-count. The exception formulas evaluate main's terms in main's order, and the composition file gains a regression per finding; each fails on 5934620. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…spouses An independent r3 review found: - Blocker (from the r2 fix): with every parent id zero, the claimed-by- parent and both-parents fallbacks read own_children_in_household instead of is_parent, so an explicit is_parent input no longer matched main (C10 with unmarried P40/Q39 marked is_parent: main 3/$50,000, r2 head 2/$20,000). The fallbacks and the composition proxy now use unlinked_parent: is_parent (formula or input) and either no id names the person or own_children_in_household exceeds the ids that do. Without links this is is_parent exactly; with links a parent whose children are all named is never another child's presumed parent, which keeps the r2 cross-household fix. - PE puts everyone in one marital unit when a situation omits marital units, so two adult siblings with ids became spouses. People sharing a parent id are no longer spouses, as linked parent-child pairs already were not. Each new regression fails on 2e92217. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An independent r4 review confirmed the r1-r3 fixes and found that PE's synthesized marital unit (one unit containing everyone when a situation omits marital units) still paired two unrelated roommates as spouses. A married couple living together is one family, so the linked spouse test now also requires the marital-unit partners to share a family entity; joint-return spouses are unchanged. The married dependent from r2 keeps their spouse. Also pins the intended cross-household behavior r4 flagged: a filer whose only reported child is linked is not the presumed parent of a zero-id dependent in another household of the same tax unit. So the no-ids guarantee is for simulations with every parent id zero; a household without ids keeps main's composition expressions but its tax-unit proxies can see links held by a co-member elsewhere. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An independent r5 review found that spouses who are also step siblings (their parents later married each other) lost each other: the r3 guard against PE's synthesized marital unit rejected any pair sharing a parent id, even with a cohabiting-spouses flag. A joint return or a cohabiting- spouses flag on either partner's tax unit now shows the marriage; only a bare two-person marital unit still needs a shared family and no shared parent id. Linked parent-child pairs are never spouses. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… zero The r6 review noted the changelog still promised that any household without parent ids keeps its outputs, which the pinned cross-household regression contradicts by design. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A mutation check over the membership rule showed three branches that no test isolated: every joint couple also had an explicit two-person marital unit, every marital-unit spouse also had a joint return or a cohabiting flag, and no linked parent and child shared a synthesized marital unit. Add one regulation-derived case for each: a joint return with omitted marital units, a married dependent whose non-filing spouse has no flag, and a parent with a 20-year-old child in a default marital unit. Each case fails when its branch is removed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Link-aware claim recognition correctly routes a married adult child whose id names the parent claiming them to the tax-household rules, but that branch never added the dependent's own spouse. P40 alone claims T19; T lives with spouse S18, who earns $30,000 and files separately. Main routes T to the non-filer rules by mistake and gets 2/$30,000; the rework gave 2/$0; 42 CFR 435.603(f)(2) and (f)(4) give the parent's tax household plus the spouse, 3/$30,000. In households with parent links, a tax dependent on the tax-household branch now counts, once, the co-resident spouse the non-filer spouse rule finds, unless the claiming tax household already holds them (same return, or claimed into it from another unit). Size, income and California pregnancies use the same membership. The spouse rule moves into _spouse_rule so both branches share it. Households without ids keep main's expressions through where(), so the no-ids path is unchanged. Five regressions: the review's case, a California pregnant-spouse variant, a teen claimed by the one parent she lives with, a known claiming unit elsewhere, and a spouse on the same return who must count once. The first four fail on eaf6cc4; the fifth guards against double counting. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Found by the new married-dependent property test. A minor alone in a tax unit has no head, so PE makes them that unit's dependent. When medicaid_claiming_tax_unit_id names a parent's unit elsewhere (main's known-claimant fixtures use exactly this shape), the claimed-by-parent test resolved the child's ids only in the child's own unit, found no parent, and applied the 42 CFR 435.603(f)(2)(i) exception. A child of 10 living apart from the claiming parent got 1/$0 instead of the parent's household, 2/$30,000, which main gives. With ids, a known claiming tax unit other than the dependent's own is the claimant: the ids resolve among its members (person ids are distinct within a tax unit), and its head or spouse must be named. A grandparent's unit still is not a parent's. The no-ids path is unchanged. Adds the two regressions and a seeded property test: parents claiming a child whose id names them, on their return or as a known claiming unit, with the child's spouse unmarried, flagged, in one family, on the same return, claimed into the parent's unit or living elsewhere. It checks size, income and California pregnancies against set-based oracles for the parent and the child, and invariance to member order. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…he changelog The changelog keeps the current guarantee: simulations in which every parent id is zero keep their outputs, and a household without ids keeps its composition formulas though a shared tax unit or family can change who is presumed a parent. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…households Tests for branches the new code adds that no test reached yet: - a joint claiming return whose spouse, not its head, is the parent the child's ids name; - a head whose known claiming unit is their own: the unit's cohabiting-spouses flag already counts the spouse, so the tax-dependent spouse rule must not add them again; - the married-dependent scenarios without ids give the same values alone and next to their linked copies, so the spouse rule stays inside linked households. Also drops a redundant presence check: a claiming unit with nobody in a role yields id 0, which no nonzero parent id matches. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…hold The mutation check found that the married-dependent property test never exercised "exactly once" for a spouse on the parent's return or claimed into it: those spouses sat in a family of their own with no flag, so the spouse rule never saw the marriage and nothing could be double counted. They now share the child's family, as the same-family placement does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… 4, 6) r7 finding 2: ids are only distinct within a household and within a tax unit, so a claimant in another household can share the person_id of the co-resident parent a child's id names. The claimed-by-parent test then took the claimant for the parent. M35 (id 1) lives with C10 (parent_1_id 1); a grandparent (also id 1) elsewhere claims C, through a known claiming unit or on the grandparent's own return. Main and the r7 head give C the grandparent's household, 2/$30,000; (f)(2)(i) gives the non-filer household of C and M, 2/$20,000. An id that names a co-resident now names that person, in both resolutions the claimed-by-parent test uses: tax_unit_parent_indices drops a tax-unit match that is not the co-resident the id names, and a known claiming unit's head or spouse matches an id only if the id names no co-resident or names that head or spouse. A repeated second id is the first parent again. The no-ids path is unchanged (both helpers return before reading any variable). r7 finding 4: the same-return spouse case's comment now says its income follows main's tax-branch reading of (d)(2)(ii), which a literal reading would contest. r7 finding 6: the changelog limits the tax-route spouse to dependents whose household is the claiming taxpayer's, and states the co-resident rule. The id documentation states it too. Regressions: both collision cases (they fail on f5151b4) and a unit test for a repeated id naming a co-resident. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…indings 1-3, 5, 6) - Infer a lone named co-resident parent's established spouse (joint return, or two-person marital unit with the cohabiting-spouses flag) as a step parent for claimant recognition, the both-parents exception and non-filer membership, including step siblings (42 CFR 435.603(b)). - Add a head's or spouse's co-resident spouse outside the unit to the unit's tax household in linked households, deduplicated against same-unit membership, claims into the unit and the cohabiting-spouses flag (435.603(f)(1), (f)(2), (f)(4)). - An id matching two members of one group resolves to neither, and a co-resident resolution no longer depends on tax unit member order. - Document the simulation-wide unique id contract for cross-household tax units and known claiming units. - Add the r8 YAML regressions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…id order; reword the changelog (r8 findings 5-7) - test_named_parent_must_be_claiming_head_or_spouse: a named parent who is another dependent on the claiming return, or files elsewhere, is not the claiming taxpayer (42 CFR 435.603(f)(2)(i)). - test_both_parent_joint_return_requires_same_filing_unit: (f)(2)(ii) holds unless the two co-resident parents head one filed joint return. - Extend the married-dependent property to the spouse's own household with and without the cohabiting-spouses flag, and the random-household oracle to step parents (435.603(b)). - test_duplicate_ids_resolve_the_same_way_in_every_member_order. - Changelog: co-resident ids resolve to that person, the linked both-parent exception, the id contract and the whole-simulation zero-id guarantee. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
added a commit
that referenced
this pull request
Oct 6, 2026
…ive dependents the claimant's separate spouse Two findings from review r1: - A non-filer household's parents and siblings are read from the whole family, which can include people outside the household, such as a grandparent who is also a parent there. With signed amounts, a grandmother's $5,000 loss cut her granddaughter's household income from $12,000 to $7,000, though 42 CFR 435.603(f)(3)(iii) leaves her out. Those relatives' amounts are now added only when positive: each child's, and each couple's parents' netted together, so married parents' losses still offset each other. The individual's and spouse's amounts stay signed. #9406's co-resident parent IDs fix the membership itself. - A dependent's tax household is the claimant's (435.603(f)(2)), which includes the claimant's cohabiting spouse who files separately (f)(4). Household size already counted that spouse; household income now does too. Also corrects two comments to the 2025 standard deduction, $15,750. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
added a commit
that referenced
this pull request
Oct 6, 2026
…ive dependents the claimant's separate spouse Two findings from review r1: - A non-filer household's parents and siblings are read from the whole family, which can include people outside the household, such as a grandparent who is also a parent there. With signed amounts, a grandmother's $5,000 loss cut her granddaughter's household income from $12,000 to $7,000, though 42 CFR 435.603(f)(3)(iii) leaves her out. Those relatives' amounts are now added only when positive: each child's, and each couple's parents' netted together, so married parents' losses still offset each other. The individual's and spouse's amounts stay signed. #9406's co-resident parent IDs fix the membership itself. - A dependent's tax household is the claimant's (435.603(f)(2)), which includes the claimant's cohabiting spouse who files separately (f)(4). Household size already counted that spouse; household income now does too. Also corrects two comments to the 2025 standard deduction, $15,750. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
added a commit
that referenced
this pull request
Oct 6, 2026
…ive dependents the claimant's separate spouse Two findings from review r1: - A non-filer household's parents and siblings are read from the whole family, which can include people outside the household, such as a grandparent who is also a parent there. With signed amounts, a grandmother's $5,000 loss cut her granddaughter's household income from $12,000 to $7,000, though 42 CFR 435.603(f)(3)(iii) leaves her out. Those relatives' amounts are now added only when positive: each child's, and each couple's parents' netted together, so married parents' losses still offset each other. The individual's and spouse's amounts stay signed. #9406's co-resident parent IDs fix the membership itself. - A dependent's tax household is the claimant's (435.603(f)(2)), which includes the claimant's cohabiting spouse who files separately (f)(4). Household size already counted that spouse; household income now does too. Also corrects two comments to the 2025 standard deduction, $15,750. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
added a commit
that referenced
this pull request
Oct 6, 2026
…ive dependents the claimant's separate spouse Two findings from review r1: - A non-filer household's parents and siblings are read from the whole family, which can include people outside the household, such as a grandparent who is also a parent there. With signed amounts, a grandmother's $5,000 loss cut her granddaughter's household income from $12,000 to $7,000, though 42 CFR 435.603(f)(3)(iii) leaves her out. Those relatives' amounts are now added only when positive: each child's, and each couple's parents' netted together, so married parents' losses still offset each other. The individual's and spouse's amounts stay signed. #9406's co-resident parent IDs fix the membership itself. - A dependent's tax household is the claimant's (435.603(f)(2)), which includes the claimant's cohabiting spouse who files separately (f)(4). Household size already counted that spouse; household income now does too. Also corrects two comments to the 2025 standard deduction, $15,750. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CI on 38880d4 failed test_tax_dependent_counts_a_co_resident_spouse_exactly_once at s13_spouse: a 16-year-old spouse alone on a filing return. PE infers only an adult (age 18 or over) as a tax unit head, so the generator's spouse headed no return and became a non-filing dependent with zero MAGI, while the property assumes a taxpayer filing alone. The generator now states every head: the parent, a child on a return of their own only as an adult (as inferred), and a spouse off the parent's return at any age. Only minor spouses on their own returns change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
added a commit
that referenced
this pull request
Oct 7, 2026
…ive dependents the claimant's separate spouse Two findings from review r1: - A non-filer household's parents and siblings are read from the whole family, which can include people outside the household, such as a grandparent who is also a parent there. With signed amounts, a grandmother's $5,000 loss cut her granddaughter's household income from $12,000 to $7,000, though 42 CFR 435.603(f)(3)(iii) leaves her out. Those relatives' amounts are now added only when positive: each child's, and each couple's parents' netted together, so married parents' losses still offset each other. The individual's and spouse's amounts stay signed. #9406's co-resident parent IDs fix the membership itself. - A dependent's tax household is the claimant's (435.603(f)(2)), which includes the claimant's cohabiting spouse who files separately (f)(4). Household size already counted that spouse; household income now does too. Also corrects two comments to the 2025 standard deduction, $15,750. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
added a commit
to MaxGhenis/policyengine-us
that referenced
this pull request
Oct 7, 2026
MaxGhenis
marked this pull request as ready for review
October 7, 2026 11:15
Contributor
Author
|
US + core hub merge audit, us#9406 at
|
MaxGhenis
added a commit
that referenced
this pull request
Oct 14, 2026
…each spouse their own deductions (#9860) * Give each spouse their own above-the-line deductions in per-person AGI adjusted_gross_income_person split every above-the-line deduction other than the three self-employment ones 50/50 between head and spouse on a joint return. Each person now takes their own deductions through above_the_line_deductions_person; only tax-unit-level inputs (HSA, tuition and fees, domestic production, possession income) are divided equally. Adds alimony_expense_ald_person, loss_ald_person and limited_capital_loss_person, moves Medicaid's per-person AGI and Montana's Social Security worksheet onto the same attribution, and applies Montana's capital loss rule for spouses filing separately (MCA 15-30-2110(6)). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Split loss_ald into limited_business_loss and the capital loss deduction loss_ald_person now divides the Section 461(l)-limited business loss by each spouse's business losses and the rest of loss_ald by their capital losses, so it stays right when loss_ald gains capital components (#9788). Adds the filer_share helper used by the per-person deduction variables. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Leave Medicaid AGI to a separate fix Attributing each spouse's deductions in Medicaid AGI without also netting the couple's MAGI before medicaid_magi_person's zero floor moved Medicaid eligibility in both directions; the two belong in one Medicaid change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * WIP: drop the Montana capital loss override (ARM 42.15.206(3)(a)); review r1 fixes; strengthen property test The property test's new independent 461(l) check still has a test-side indexing bug: the model gives the right limited_business_loss (256,000 for a 2026 single filer with a 1.5M loss). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Restore main's Medicaid AGI tests after the rebase * Leave filer amounts recorded on a dependent off the dependent's own deductions above_the_line_deductions_person gave a tax unit dependent every person-level deduction recorded on them, including employer adoption assistance and education savings bond interest, which gov.irs.ald.filer_amounts_recorded_on_dependents marks as the filer's. Those now count only for the head and spouse, whose parts already take them up through above_the_line_deductions. The dependent's part matters once Medicaid AGI reads it for a dependent's own return. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Divide a filer amount recorded on a dependent equally between head and spouse Education savings bond interest and employer adoption assistance recorded on a dependent are the filer's (gov.irs.ald.filer_amounts_recorded_on_dependents), but which spouse's is not recorded. They reached the head's and spouse's parts through the reconciliation to above_the_line_deductions, in proportion to each spouse's other deductions, so the spouse's IRA deduction changed the head's share. They are now divided equally, as the other amounts recorded only for the return are. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Fix the spouse deduction invariant test's harness and numpy references - Units that set a tax-unit deduction directly run in their own simulation. An input given for one tax unit is an input for every unit in a simulation, so one unit's loss_ald set to 0 zeroed every other unit's. - The Section 461(l) reference keeps each business source's gain and loss separate (aggregate income against aggregate deductions), as the model does, rather than netting a person's sources first. - The capital loss reference nets losses against capital gains and distributions before the 1211(b) limit, as main does since #9788. - The alimony identity skips units that set alimony_expense_ald directly: alimony_expense_ald_person stays each payer's own alimony there. - The reference gives a dependent's filer amounts to the head and spouse equally. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Give the determinism test's stand-in ALD parameters the filer amount list above_the_line_deductions_person now reads gov.irs.ald.filer_amounts_recorded_on_dependents. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Floor Michigan and Pennsylvania withholding at zero for a negative spouse AGI With each spouse's own deductions, a spouse with a business loss or an IRA deduction above their income has negative AGI, and these two withholding estimates multiplied it by the rate. Every other state's withholding formula already floors its base at zero. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Prorate Virginia additions by each spouse's positive federal AGI va_agi_person divides tax-unit additions by each spouse's share of federal AGI. A spouse with negative AGI got a negative share and the other spouse more than all of it. A spouse with negative AGI now gets none, as #9878 does for Delaware's itemized deductions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Skip only directly set alimony in the spouse identity check Directly set loss_ald still reconciles through loss_ald_person, so its identity is checked. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep Montana's losses divided equally between spouses until its own rules are modeled Montana spouses who filed separately on one form through 2023 allocate capital losses by one of two elections (ARM 42.15.206(3)) and recompute the Section 461(l) limit with the single filer's threshold. Neither is modeled. Giving each spouse their own federal losses instead of half moved Montana away from both. With one spouse's $1,000 gain against the other's $3,000 loss, the loss spouse's AGI was $7,000, though separate tracking caps the loss at $1,500 ($8,500). A $600,000 business loss on one spouse used the joint limit, lowering tax by $45.65 against main. mt_loss_ald_reallocation adds back to each spouse's federal AGI the difference between their own loss_ald_person and an equal share of the return's loss_ald, so Montana divides losses as before. The IRA and other deductions still go to the spouse who has them (former MCA 15-30-2110(8); ARM 42.15.206(1)). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Base Montana's joint standard deduction and medical floor on the joint return's AGI mt_standard_deduction_joint and mt_medical_expense_deduction_joint added each spouse's mt_agi_indiv, which is floored at zero. With each spouse's own deductions, a spousal IRA above that spouse's income was lost to the floor: head wages $30,000 and a $6,000 spousal IRA gave a joint deduction of $6,000 (20% of $30,000) instead of $4,920 (the floor, 20% of the joint $24,000 being less). Both now read mt_agi_joint, the joint column's Montana AGI through 2023. Their tests take mt_agi_joint as the input. Adds the spousal IRA case, a single filer's loss and a case with student loan interest and an IRA in each spouse's own column. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Use the joint Montana AGI for the medical floor only through 2023 Review r5: the medical floor had no year gate, so reading mt_agi_joint also changed 2024 and later, when mt_agi_indiv is zero for everyone and main's floor was zero. From 2024 Montana starts from federal itemized deductions, whose floor is a share of federal AGI, a separate fix. The joint AGI now applies while married filing separately on the same return is allowed (through 2023); 2024 on is unchanged from main. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Note that Montana's 2024+ medical floor is zero, as on main Comment only (review r6). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Limit DC separate-filing capital losses per spouse; stop Montana spouse allocation from 2024 Per Max's d1014 ruling: - DC: spouses filing separately on the same return each deduct their own capital losses up to their own capital gains plus the $1,500 married filing separately limit (D-40 instructions, line c), via dc_separate_capital_loss_adjustment. It applies only to the separate column; dc_taxable_income_joint keeps the federal joint deduction. - Montana: mt_loss_ald_reallocation and mt_applicable_ald_deductions apply only while spouses may file separately on the same form (through 2023). Adds YAML cases and DC/Montana invariants to the spouse property test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Net household members' Medicaid MAGI before the zero floor, and attribute each spouse's own deductions medicaid_magi_person floored each person's MAGI at zero, and medicaid_household_income added the floored amounts, so a spouse's business loss never offset the other spouse's wages on their joint return. Household income is the sum of every member's MAGI-based income (42 CFR 435.603(d)(1)), and the 36B methodology the regulation adopts (435.603(e)) combines the taxpayer's and dependents' modified AGIs "even if one or both of them are negative" before entering a negative total as zero (Form 8962, line 3). medicaid_magi_person is now unfloored and medicaid_household_income floors only the household's total. medicaid_adjusted_gross_income_person now subtracts above_the_line_deductions_person, so each spouse's own IRA deduction, student loan interest, alimony and business and capital losses lower only their own amount, and a dependent's own deductions, alimony paid included, lower the dependent's own AGI. Tax-unit-only MAGI additions are divided equally between the head and spouse with filer_share. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Count only gross income other than wages and self-employment as unearned in the Medicaid filing test medicaid_person_is_required_to_file took unearned income as gross income less earned_income. Gross income counts each source's positive amount, so a self-employment loss made other income look unearned: a dependent with a 5,000 loss and 100 of interest had 5,100 of unearned income and was required to file. With household members' MAGI no longer floored, that would count the dependent's negative income. Unearned income is now gross income less the positive wage and self-employment sources it includes (Pub. 501, Table 2), which also stops 401(k) deferrals, left out of box 1 wages, from hiding unearned income. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Add property tests for Medicaid household income with members' losses Hypothesis draws batches of joint filers with dependent children, non-filing couples, cohabiting spouses filing separately and single filers, with losses, own deductions and children who may be required to file. For every household: joint filers' household income is max(0, J + D), with J the couple's MAGI figured from the tax unit's AGI; the spouses' MAGIs add up to J; spouses outside a joint return are netted before the floor; income is never negative and is zero exactly when the unfloored sum is not positive; and three metamorphic relations hold (the spouse's own deductions never change the head's, swapping spouses changes nothing, and lowering the spouse's self-employment income never raises household income). 20 examples plus a seeded population of 200 households: 44 s wall and 1.17 GB peak locally (macOS, loaded host). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep family-wide relatives' losses out of non-filer households, and give dependents the claimant's separate spouse Two findings from review r1: - A non-filer household's parents and siblings are read from the whole family, which can include people outside the household, such as a grandparent who is also a parent there. With signed amounts, a grandmother's $5,000 loss cut her granddaughter's household income from $12,000 to $7,000, though 42 CFR 435.603(f)(3)(iii) leaves her out. Those relatives' amounts are now added only when positive: each child's, and each couple's parents' netted together, so married parents' losses still offset each other. The individual's and spouse's amounts stay signed. #9406's co-resident parent IDs fix the membership itself. - A dependent's tax household is the claimant's (435.603(f)(2)), which includes the claimant's cohabiting spouse who files separately (f)(4). Household size already counted that spouse; household income now does too. Also corrects two comments to the 2025 standard deduction, $15,750. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Document the non-filer limits and test married non-filer parents Review r2 notes: - A non-filer child's own amount and their siblings' enter with the family's children, only when positive, and unmarried co-resident parents are each counted only when positive. The documentation now says so, rather than "always added signed". - Medicaid AGI documentation says a dependent's own business and capital losses are not modeled. - New case: married non-filer parents, $12,000 of wages and a $5,000 business loss, give their child's household $7,000. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Base DC's separate-filing capital adjustment on the capital part of loss_ald Review r7: dc_separate_capital_loss_adjustment removed the computed capital loss deduction even when loss_ald was set directly, so it took out an amount federal AGI did not contain. It now removes the capital part of each spouse's loss_ald_person (loss_ald less the business loss, by own capital losses). Adds YAML cases with loss_ald set to $0 and $1,000, and the property test checks every unit against that capital part, keeping the nonnegative couple sum for computed units only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Take DC's self-employment loss add-back from the business part of loss_ald Review r8: with loss_ald set directly and both business and capital losses, dc_self_employment_loss_addition isolated the business loss by subtracting the computed capital deduction, while loss_ald_person (and so federal AGI and the DC capital adjustment) takes the business part first. Use min(limited_business_loss, loss_ald), as loss_ald_person does; the amount is unchanged when loss_ald is computed. Adds computed and direct mixed-loss YAML cases. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Date linked Medicaid household property IDs to the tested year * Reconcile HSA attribution coverage with main's person input * Describe how a joint business loss is divided in Medicaid person AGI The documentation said a spouse's business loss lowers only that spouse's amount. loss_ald_person divides it in proportion to each spouse's own net business losses, and equally when neither has one. Documentation only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Point the Medicaid person AGI documentation to loss_ald_person Restating the allocation left out the equal share of a Form 4797 loss. Refer to loss_ald_person instead. Documentation only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes policyengine-us#9404.
Use optional
parent_1_idandparent_2_idinputs to identify co-resident parents and siblings when constructing Medicaid MAGI households. Resolve a dependent's effective claiming tax unit first, then add the dependent's own co-resident spouse once. Linked filers also count their co-resident spouses reciprocally, including separately filing spouses without a cohabiting flag. A spouse added to a dependent's household does not thereby enter the claimant's household.The Ohio 2026 regression is a stylized reconstruction of Microcosm Build P household 1009324, not the production record: the 56-year-old's income is set to the $94,504 residual that reproduces the previous $141,848 pooled income, and child ages are placeholders. With parent IDs, four children of the 30-year-old have size 5 and income $23,334, and the 27-year-old's child has size 2 and income $24,010. Those five children qualify for Medicaid; the 17- and 16-year-olds retain size 3 and income $94,504 and remain ineligible. Without parent IDs, the regression retains size 10 and income $141,848 for all seven children. These are fixture results, not a national impact estimate.
Input contract and compatibility
The compatibility guarantee is exact existing behavior when all parent IDs are zero throughout the simulation. It does not guarantee that an isolated zero-ID household stays unchanged inside every mixed simulation. Zero means unknown. Nonzero
person_idand parent IDs are signed int32 values; person IDs must be unique across the simulation whenever tax units span households or known claiming-unit IDs are supplied. Household-local reuse is supported only for self-contained household and tax-unit graphs. Duplicate-ID fixtures pin deterministic fallback behavior; duplicate IDs cannot establish legal identity.An ID naming a co-resident resolves to that person. A named parent must be the claiming tax unit's head or spouse, rather than another dependent, for parental claimant recognition. The linked both-parent exception requires the same actually filing parental unit for the joint-return exclusion and correct membership in the identified claiming unit. Raw IDs, including absent-parent links, remain intact.
When exactly one distinct named parent is resident, Medicaid may also recognize that parent's established resident spouse as a stepparent. Evidence is bounded to joint head/spouse roles or a two-person marital unit with a spouse flag. The same effective relationship feeds claimant recognition, the both-parent exception, and non-filer parent/child membership. Two ID slots and this bounded inference do not represent every larger parent or step-relative graph.
cohabitating_spousesdescribes the tax-unit head's separately filing spouse; attaching the flag to an unrelated claimant's unit can overcount.The companion data export is microcosm#884; its production ID/link coverage still needs verification. The paper disclosure is obbba-paper#2.
Changes in this fix round
Recovered the six approved commits through
34c6562e2, retained the later fixes already published at62aee62351, and merged current maindd9cb3f683through merge commitb6ad6626ba. The clean merge tree was8351b88; the new main changes were release-only and did not overlap model files. No history was rewritten.a4ca85f6fbgives cross-household married-dependent property scenarios globally unique person IDs and matching parent links; all 11 property tests passed with expected outputs unchanged.Validation
Recovered head
62aee62351passed 34/34 CI checks, including the partner contracts, in run 37563630113. Current maindd9cb3f683also passed Household API Partners. These are recorded CI results, not local suite runs. No partner expected outputs were edited. Saved targeted local logs at the recovered head show 6 core tests and 11 property tests passed.Earlier CI at
38880d4aa0passed the three parent-ID YAML files (11 + 43 + 5 cases) but failed the spouse property for a minor whose inferred tax unit had no head:s13_spouseproduced $0 versus the generator's expected $13,979. The explicit head inputs in7d4ad6901afixed that setup error; the recovered property file subsequently passed all 11 tests.34c6562e2reproduced 5 failures/6 passes across the 11 r8 fix-round cases in an independent archived source tree. The four new recovery-audit cases also failed before the final edits (one ancestor-inference case and three flagged-spouse cases); logs are retained.409e65e8b2, all 63 YAML cases (47 composition + 11 Medicaid parent-ID + 5 demographic) and 17 Python tests (11 properties + 6 core) passed. Composition includes all 11 r8 fix-round cases and the four new recovery regressions. These were sequential single-file runs; no suites or microsimulations were run locally.dd9cb3f683versus409e65e8b2: 48 synthetic API cases (24 worlds), 13 variables, 624 arrays identical by dtype/shape/bytes, zero errors and zero differences. Omitted and explicit-zero inputs also matched within each source. Both model processes ran sequentially with the same Core environment and verified source paths; this is bounded compatibility coverage, not production-data parity.make formatpassed after the final membership edits: 6,656 files unchanged and Ruff lint passed.Historical r8 checks against pristine
ca1805cf0found zero differences across 22,581 arrays (plus an explicit-zero repeat and 1,440 random-world arrays), with 50 matching errors. The current-main comparison above independently verifies this round and replaces reliance on the old class-restoring AST guard.Before/after fixtures, logs, differential results and replay commands are retained with the fix-round report and evidence.
Impact and integration
Default-dataset microsimulation (hub runner): merge base against this head
409e65e8b2, onpopulace_us_2024.h5@populace-us-2024-spm-20260909, for 2024 and 2026. It ran under the shared heavy lock, one run per side, compared record by record.Exactly zero change.
is_medicaid_eligible,medicaid,medicaid_household_size,medicaid_household_income,is_chip_eligible,chip,aca_ptcandhousehold_net_incomeare identical on every record in both years.This is the required all-zero-ID check on real data. The default dataset has no
parent_1_idorparent_2_idcolumns (see below), so every parent ID is zero and the PR reproduces main exactly. It does not measure the feature's effect: that needs a dataset with populated parent links. The other outputs listed below (is_parent, the exception and routing flags,medicaid_income_level, CA pregnancies andpremium_tax_credit) were not separately recorded in this run. With all IDs zero they follow the same unchanged inputs.Read-only metadata and a narrow
person_idfield inspection of the cached defaultpopulace-us-2024-spm-20260909build (snapshot9a814a3b3b53c0ecd6e1737b6ec862c31300ef6f) found 166,321 globally unique nonzero person IDs, all within int32 range. Bothparent_1_idandparent_2_idcolumns are absent. Raw CPSPEPAR1/PEPAR2fields exist, but no transformation into model links was run or verified. This is schema evidence, not a simulation or a weighted impact estimate. A populated-link export or verified transformation is needed to measure feature impact.Stratify linked and zero-ID populations, children, teen parents, married dependents, multigenerational households, and state. Repeat with all parent IDs zero and require exact zero changes. National net effects and weighted counts remain unknown. No new performance benchmark was run; the historical r8 partial-model benchmark had 199,713 synthetic people and seven variables, taking 0.163 seconds with zero IDs and 1.49 seconds with links.
The separate
medicaid-magi-joint-floorwork overlapsmedicaid_household_income.py,medicaid_household_income_member.py,medicaid_magi_person.py, andmedicaid_person_is_required_to_file.py. Its branch was not imported. Integration must retain this PR's claimant/spouse membership and aggregate signed member income before applying the final household zero floor.Methodology choices for Max
Final head:
409e65e8b2.axiom: needed — rulespec-us parity review is pending; no public issue was filed.