Repository navigation
Charge the Medicare Part B premium only to people who pay it - #10634
Conversation
medicare_enrolled covers Part A and/or Part B, so a Part A-only enrollee was charged the Part B premium with no way to say otherwise. Add a medicare_part_b_enrolled input (default true for Medicare enrollees) and gate the Part B premium and its readers on it. States pay the standard Part B premium for SSI recipients through their Part B buy-in agreements, but only MSP coverage was netted out, so a reported SSI recipient above the modeled MSP limits paid it. Add the buy-in coverage for SSI recipients in 1634 and SSI-criteria states. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LwQq6GJWihZvhCyeHucLHi
medicare_part_b_enrolled needs a formula: an input-only variable ignores defined_for, so it was true for people without Medicare. Existing Part B premium tests used zero-income people, whom the model now (correctly) finds SSI recipients with a state buy-in; they now say ssi: 0 to keep testing the no-coverage premium. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LwQq6GJWihZvhCyeHucLHi
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LwQq6GJWihZvhCyeHucLHi
|
Ready for hub review Head: What the item asked, and how I resolved it
Tests run (locally, one file per process)
Hand computations
Mutants (each run in a separate worktree and process, code restored after each)
CIDraft, so the Pull request workflow at Judgment calls
Proposed follow-up issues
Generated by Claude Code |
|
Hub review in progress Independent review of Rechecked at this head (third session)
Findings so far
Generated by Claude Code |
|
Ready for hub review Independent review of #10634 at Sources: from this VM, ecfr.gov, govinfo.gov, uscode.house.gov, law.cornell.edu and ssa.gov all failed at the proxy. I quote only the texts the hub supplied: 42 CFR 407.10, 407.40 and 407.42 (eCFR), and 42 U.S.C. 1395v, 1395o, 1383c and 1396a(a)(10)(E). FindingsP2-1. December SSI buys in all 12 months; SSI that ends before December buys in none
Witness: TX, age 70, $30,000 interest, 2026,
Under 42 U.S.C. 1395v(d)(2)(C), coverage starts with "the first month in which he is both an eligible individual and a member of a coverage group". Under (d)(3)(A), it ends with the month he is found ineligible for money payments. So the State pays about one month either way: 202.90 of buy-in, 2,231.90 paid by the enrollee. For the December case the head is off by 2,231.90, where main was off by 202.90. This PR makes that reader worse. Fix (the second line keeps monthly_premium = person("base_part_b_premium", period) / MONTHS_IN_YEAR
coverage = 0
for month in period.get_subperiods(MONTH):
receives_ssi = (person("ssi", month) > 0) | person("receives_ssi", month)
covered = receives_ssi & is_covered & covered_classification
coverage += where(covered, monthly_premium, 0)
return coverageOn a scratch tree this gives buy-in 202.90 and premium 2,231.90 for both rows. It still gives 2,220 for CA full-year SSI. At this patch, the premium (19), buy-in (4) and Idaho (24) YAML files and Follow-up, same on main: P2-2. The 209(b) gap closes cheaply, and the test that pins it uses someone who isn't on Medicaid
A real witness adds The cycle has two arms: the 209(b) test reads
Result: no CycleError, and the CT witness gives buy-in 2,220 and premium 0. Across all 104 YAML files that mention the premium, its aggregate, 209(b), the SSI-recipient Medicaid test, the countable income or medically needy expenses (partners excluded), 1,797 cases pass and 2 fail. Both failures enter The reading this takes, that Medicaid eligibility counts premiums the person owes before the State's buy-in starts, is a methodology choice. If the author keeps the exclusion instead, please (a) replace the CT case with the spend-down witness above, expecting buy-in 0 and premium 2,220, and (b) say in the body that 209(b) SSI recipients who get Medicaid still pay Part B in the model. The hub would then file a follow-up. P3-1. The property test restates the formula from inputs
Suggestion: keep the bounds, and drop line 465 or move it into the YAML overlap case that already exists. P3-2. Citations should point at the sections the code relies on
P3-3. The body has stale lines
Checked and sound
Baseline movement for the hub's impact pair (2026)
If P2-2's change lands, add What I couldn't check
Generated by Claude Code |
|
Picking this up for the US hub. I'll post a hand-off comment here when it's ready. Generated by Claude Code |
The buy-in read the year's receives_ssi, which is December's value, so December-only SSI bought in all twelve months and January-only none. 42 USC 1395v(d)(2)(C) and (d)(3)(A) run coverage month by month, so count each month with SSI. 42 CFR 407.42(b)(1)(i) puts SSI recipients covered as categorically needy in buy-in group 1 with no 209(b) exception. Medicaid eligibility now counts the Part B premium before the buy-in (new medicare_part_b_premium_before_buy_in and medicaid_eligibility_health_insurance_premiums), since the buy-in starts only once Medicaid finds the person eligible. That removes the cycle that kept 209(b) recipients out. Two tests that entered medicare_part_b_premium for Medicaid to read now enter the premium before the buy-in. Also cite 42 CFR 407.40(c)(5), 407.42(b)(1)(i) and 408.28 for the buy-in, 1395o(a) and 407.10 for Part B enrollment, and drop the property test's restatement of the formula. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LwQq6FbZsW3L5YBNR9g5e9
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LwQq6FbZsW3L5YBNR9g5e9
Conflicts were only in files this PR doesn't change (CHANGELOG.md, pyproject.toml, uv.lock, the trustees reform and its test, an MO YAML test); took main's version of each. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LwQq6FbZsW3L5YBNR9g5e9
|
Ready for hub review Fix round 1 on #10634, answering the round 1 review. The head was Items
Tests (local, after the merge with
|
| Mutant | Result |
|---|---|
M3 sum instead of max (medicare_part_b_premium.py) |
killed by medicare_part_b_premium.yaml (2: "MSP and buy-in coverage of the same premium are not added twice.", "MSP coverage preserves IRMAA above the standard Part B premium") and test_medicare_part_b_premium_preserves_only_irmaa_above_msp_support. The property test no longer kills it, as expected once the restatement is gone. |
M8 SSI receipt ignored (covered = ssi_medicaid_state) |
killed: premium 12, buy-in 4, CA countable income 2, Idaho 1, Python 1 (…does_not_depend_on_calculation_order) |
M13 reported receives_ssi ignored |
killed: buy-in 5 (including both CT cases and TX December/January), premium 1 |
Read the year's receives_ssi again inside the loop |
killed by buy-in 3: TX December-only, TX January-only, CT December-only |
209(b) countable income reads medicare_part_b_premium (after the buy-in) |
killed with CycleError: premium 16 failed, buy-in 6, CA countable income 33, Idaho 2, Python 4. Medically needy expenses still passed 3/3, since that file doesn't reach the buy-in. |
CI
Pull request run 41737420675 at 790a9116: still in progress at 60 minutes after the push (00:14Z). 35 of 36 jobs had finished, all success; still running: Contrib tests / Full Suite - Contrib (other-shard-1). No job had failed. The hub should read the run's final conclusion before landing.
Judgment calls
- The
medicare_part_b_premium_before_buy_inreferences add 42 U.S.C. 1395v(d) next to 42 CFR 407.42, since (d)(2)(C) is the rule that the buy-in starts only once the person is eligible. medicaid_eligibility_health_insurance_premiumslives next tomedical_expense_health_insurance_premiumsinvariables/household/expense/health/.medical_expense_health_insurance_premiumsstill reads the premium after the buy-in, so tax, SNAP, HUD, LIHEAP and SPM readers see what the person pays.- The merge conflicts were only in files this PR doesn't change:
CHANGELOG.md,pyproject.toml,uv.lock, the trustees 2026 reform and its test, and an MO itemized-deductions YAML. I tookmain's version of each, andgit diff origin/main --statshows only the PR's 19 files. - I couldn't fetch eCFR or the U.S. Code from this VM to re-check the quotes; the ones in the body and code come from the hub's brief.
Proposed follow-up
- Read SSI receipt month by month in the SSI-recipient Medicaid tests.
is_ssi_recipient_for_medicaidandis_209b_ssi_recipient_for_medicaidread the year'sreceives_ssi, which is December's value. So the SSI route to Medicaid follows December alone, and a January-only 209(b) recipient gets no buy-in month.
Generated by Claude Code
|
Hub review in progress Done: the full review is at #10634 (comment). Generated by Claude Code |
|
Ready for hub review Round 2 review of #10634. The head hasn't moved from The code does what the hub's rulings ask:
All hand values reproduce, every mutant is killed by a named test, and CI is green. Nothing here is a P1.
The PR picks readings where the law leaves room:
The hub ruled on the last two. Sources. From this VM, ecfr.gov, uscode.house.gov, govinfo.gov and law.cornell.edu all failed: refused at the proxy, or not resolved. I could not re-read 42 CFR 407.40, 407.42, 408.28, 435.121 or 435.831, or 42 U.S.C. 1395v. Everything below rests on the hub's quoted texts in the brief, and I quote no law beyond them. Nothing in the code contradicts those texts. FindingsP2-1. Landing #10146 after this PR, taking its side of the conflict, brings back the cycle#10146 ("Limit SSI spousal-deeming child allocations…", open, head Git flags a conflict only in the annual file. The monthly file is new to #10146, so git merges it silently. A resolver who takes #10146's side gets this chain: 209(b) test → countable income → monthly → Witness: merge CI on the second PR would catch this, so it's a hazard, not a defect here. Whichever lands second should carry this PR's reads into the monthly file: part_b_enrolled = person("medicare_part_b_enrolled", period.this_year)
paid_premiums = (
person("medicaid_eligibility_health_insurance_premiums", period.this_year)
/ MONTHS_IN_YEAR
)
paid_part_b = (
person("medicare_part_b_premium_before_buy_in", period.this_year)
/ MONTHS_IN_YEAR
* part_b_enrolled
)
full_part_b = (
person("gross_medicare_part_b_premium", period.this_year)
/ MONTHS_IN_YEAR
* part_b_enrolled
)The same check against #10141, #10631, #10111, #10532 and #10103 merged into this head passes 7/7. P2-2. Two body statements are false
P3-1. The CT spend-down witness doesn't depend on the premium
So the case passes whether or not Medicaid eligibility counts the Part B premium. I tested that with a mutant setting the Part B term in
So the premium is pinned at the unit level, not at the 209(b) decision. The premium decides eligibility when other expenses fall between 11,344 and 13,564. Suggested added case, which passes at this head and fails under that mutant: - name: The Part B premium before the buy-in decides a 209(b) spend-down.
# Countable income 23,580 and limit 10,016. 23,580 - 12,000 = 11,580 is over
# the limit; 23,580 - 12,000 - 2,220 = 9,360 is under it.
period: 2025
input:
age: 70
taxable_interest_income: 30_000
other_medical_expenses: 12_000
receives_ssi: true
state_code: CT
output:
medicaid_optional_senior_or_disabled_countable_income: 23_580
medicaid_medically_needy_medical_expenses: 14_220
is_209b_ssi_recipient_for_medicaid: true
medicaid_part_b_buy_in_premium_coverage: 2_220
medicare_part_b_premium: 0P3-2. The annual SSI read in the Medicaid tests (follow-up, same on main)The 209(b) branch of the buy-in reads
So the CT January-only recipient gets no buy-in month. That's the same result as main, and the brief told the author to leave both variables alone, so it's the hand-off's follow-up, not this PR's defect. The TX January-only row shows the follow-up's other face: the buy-in counts January, but P3-3. The
|
| Mutant | Killed by |
|---|---|
| M3 sum instead of max | premium YAML 2, Python 1 (test_medicare_part_b_premium_preserves_only_irmaa_above_msp_support); the property test no longer kills it, as the hand-off says |
| M8 SSI receipt ignored | buy-in 4, premium 12, CA 2, Idaho 1, Python 1 |
M13 reported receives_ssi ignored |
buy-in 5 (CA full year, both CT, TX December and January), premium 1 |
Year's receives_ssi read in the loop |
buy-in 3: CT December-only, TX December-only, TX January-only |
| 209(b) countable income reads the after-buy-in premium | CycleError (counts above) |
| (mine) 209(b) branch dropped | buy-in 2: both CT cases |
| (mine) medically needy arm reads the after-buy-in premium | CycleError (counts above) |
| (mine) Medicaid premiums drop Part B | medically needy 1, CA 2; survives the buy-in file (P3-1) |
All worktrees were removed, and git status is clean.
The property test (test_part_b_msp_offset.py:422-466) keeps the three bounds and no longer restates the formula. It runs one 200-person simulation.
Readers.
medicare_part_b_premium: 25 variables, including SPM premiums, the premium aggregate, NH FAP and 22 LIHEAP/EAP income definitions.medical_expense_health_insurance_premiums: 12, including HUD, Schedule A and its excluded premiums, the self-employed ALD exclusion, SNAP, PA CCW, UT HEAT, OH, ID and three MT readers.medicare_part_b_premium_before_buy_inandmedicaid_eligibility_health_insurance_premiums: only the two Medicaid variables.medicaid_part_b_buy_in_premium_coverage: only the premium.gross_medicare_part_b_premium_if_enrolled: onlymedicare_cost.
Every after-buy-in reader sees a premium that is equal or lower, and lower only for buy-in months, so none is worse than main except as P3-2's follow-up describes.
Docs. Each added documentation line and comment matches the code read here: the buy-in, premium, before-buy-in and Medicaid-premiums docs, the countable-income comment, and the WA and OK comments. The changelog fragment is a top-level changelog.d/medicare-part-b-payers.fixed.md.
Scope. Nothing changes under .github/ or the partner tests.
- Open PRs naming the changed variables: Add California LIHEAP regular heating assistance #10607, Project Medicare premiums and IRMAA past the last announced year #10103, Add Idaho LIHEAP regular heating assistance #10613, Add Connecticut CEAP regular heating assistance #10611, Add Delaware LIHEAP regular heating assistance #10612, Count only filer-paid premiums in Schedule A medical expenses #10270, Apply 416.1163(e)(2) to deemed SSI and identify SSI couples by marriage, not tax roles #10141, Count eligible long-term care premiums in Schedule A medical expenses #10265, Exclude employer-plan-eligible premiums from the self-employed health insurance deduction #10122, Exclude people otherwise eligible for Medicaid from Illinois HBWD and use Illinois's income rules for its disability pathway #10631, Limit SSI spousal-deeming child allocations to the couple's co-resident children #10146, Include farm and partnership earnings in SSI and correct loss netting #10532, Subtract the expected Part D premium from medicare_cost #10111.
git merge-treeagainst this head is clean for all but three: Project Medicare premiums and IRMAA past the last announced year #10103 (conflict inmedicare_part_b_premium.yaml), Count only filer-paid premiums in Schedule A medical expenses #10270 (conflict intest_medical_expense_premium_conservation.py) and Limit SSI spousal-deeming child allocations to the couple's co-resident children #10146 (P2-1).
Impact. The impact: line exists and lists the buy-in, premium, aggregates, SPM, tax, SNAP, HUD, LIHEAP, medicaid_enrolled and is_medically_needy_for_medicaid. The diff moves outputs at baseline through the buy-in alone. Suggested population checks:
- buy-in sum and count, split by 1634/SSI-criteria versus 209(b) states;
- the count of people with buy-in in fewer than 12 months;
- that
is_medically_needy_for_medicaiddoesn't change, and that anymedicaid_enrolledchange traces to the SNAP work-requirement path.
What I couldn't check
- Any statute or regulation text: eCFR, the U.S. Code sites, govinfo and Cornell's LII were all unreachable from this VM. The rulings rest on the hub's quotes.
- The 2025 and 2026 standard premiums against CMS.
- Baseline movement on population data, including how many SSI recipients gain a buy-in and how many 209(b) recipients are newly covered.
- The full 105-file sweep: I ran 5 of its files plus the 7 changed files, and leave the rest to CI, which passed.
Generated by Claude Code
|
Picking this up for the US hub. I'll post a hand-off comment here when it's ready. Generated by Claude Code |
In the existing Connecticut case, $40,000 of medical expenses clears the spend-down on its own, so the case passed even with the Part B premium left out of Medicaid eligibility. With $12,000 of other expenses, countable income of 23,580 less 12,000 is 11,580, over the 10,016 limit, and less the 2,220 premium too it is 9,360, under it. Dropping the Part B term from medicaid_eligibility_health_insurance_premiums now fails the case: the person is no longer a 209(b) recipient and gets no buy-in. Claude-Session: https://claude.ai/code/session_01QpcqEDZvsBp213aZFaj3ty Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Ready for hub review Head: Built on ItemsItem 14 (P3-1), the 209(b) spend-down case.
Item 15 (P2-2), the two false statements.
Item 16 (P2-1), the overlap with #10146. I added "Overlaps with open PRs" with the brief's bullet. It sits just above the
Test counts in the body.
Item 17, runs at this head, one file per process:
Hand computationsThe new case:
I took the 10,016 limit from the review. No case asserts it, and I didn't trace its parameter. CIPull request run 41868367787 at
Only the job and run records lag. #10094's run showed the same pattern: its run record concluded Judgment calls
Follow-upsNone new. The review's P3-2 follow-up on the annual SSI read in the Medicaid tests stays with the hub. Generated by Claude Code |
|
Hub review in progress The final review is posted: #10634 (comment). It supersedes this interim note. Generated by Claude Code |
|
Ready for hub review Round 3 delta review of #10634. The head is still What changed since Verdict. The new case asserts what it claims and kills the review's mutant. The two corrected statements match the code at main and at the head. CI is green. Nothing here is a P1.
METHODOLOGY_CHOICE: yes carries over from round 2:
This round adds no new reading. Sources. From this VM, ecfr.gov and aspe.hhs.gov failed at DNS. ecfr.gov, govinfo.gov, uscode.house.gov, law.cornell.edu, aspe.hhs.gov and portal.ct.gov all returned 403 at the proxy's CONNECT. I could read no statute, regulation, poverty guideline or Connecticut source, and I quote none. The values below are traced to the repository's parameters, not to the law. FindingsP2-1. The #10146 bullet leaves out the Part B enrollment gate, so the merge it describes still fails a testThe body's "Overlaps with open PRs" bullet tells whoever lands second to carry two reads into #10146's new monthly file:
Failure scenario. I merged #10146 into the head with Then I also replaced CI on the second PR would catch this, because this PR's Part A-only case would fail. But the bullet is the hand-off a resolver will follow. The round 2 review's code block had the gate. The body's bullet dropped it. Replacement for the bullet in "Overlaps with open PRs":
That resolution should also drop the monthly file's "medicare_enrolled … stands in for Part B enrollment" note, which would then be false. P3-1. #10112 now conflicts with this PR, and the body doesn't list it#10112 ("Add 2015-2023 Medicare IRMAA brackets and 2015-2020 Part B premiums", open at
The resolution is comment-only:
With that resolution, the merged tree passes:
Add to "Overlaps with open PRs":
P3-2. No test pins the 209(b) spend-down at exactly the limit (same on main)The spend-down test in
The new case sits at 9,360, well inside the window, so it can't tell the two apart. Optional case for the buy-in file, after line 64. It passes at the head and fails under the mutant ( - name: A 209(b) spend-down that lands exactly on the limit qualifies.
# Countable income 23,580 and limit 0.64 x 15,650 = 10,016.
# 23,580 - 11,344 - 2,220 = 10,016, at the limit; 11,343 would leave 10,017.
period: 2025
input:
age: 70
taxable_interest_income: 30_000
other_medical_expenses: 11_344
receives_ssi: true
state_code: CT
output:
medicaid_medically_needy_medical_expenses: 13_564
is_209b_ssi_recipient_for_medicaid: true
medicaid_part_b_buy_in_premium_coverage: 2_220
medicare_part_b_premium: 0I couldn't read 42 CFR 435.121 to confirm that "at the limit" qualifies, so the case pins the code's reading, not the regulation's. Carried from round 2 (hub actions, unchanged)
Checked and sound
What I couldn't check
Generated by Claude Code |
PR Review: Charge the Medicare Part B premium only to people who pay itSummaryThe PR makes I checked the law first. The approach matches it:
The readers. I grepped every reader. None nets the buy-in or MSP twice, and none adds back an amount it shouldn't, except the two Medicaid eligibility readers, which deliberately read the premium before the buy-in. Every reader that wants "the premium the person pays" or "the premium withheld from the check" now gets the right amount. That covers the LIHEAP/EAP income definitions, SNAP, HUD, the federal Schedule A, the state premium deductions and SPM MOOP. No partner test file changed, and the Household API Partners job passes. Open findings. Three should-address items:
There are no critical findings. CI is 36/36 green. CriticalNone. Should address1. The
2. The buy-in's modeled-SSI test is unpinned (
3. The annual
Suggestions
Verified correctWho is charged after the change. A person is charged
A person not in Part B, or not in Medicare, is charged 0 through Readers. The PR body's list matches my grep at the head:
No double-netting and no un-netting.
LIHEAP readers. Their rules count Social Security net of the Medicare premium withheld from the check. A bought-in premium is not withheld, so netting it is correct. Values change only for people covered by the buy-in whom the modeled MSP doesn't already cover: reported SSI above the MSP limits, 209(b) spend-down cases, or MSP forced off. For a modeled SSI recipient, the modeled MSP almost always already pays. Partner tests. The PR changes no file under Hand checks (2025 standard premium $185, 2026 $202.90, both matching CMS):
Probes at the head:
Code checks:
Axiom line assessment
CI status36/36 checks pass at Branch status
Verdict: REQUEST_CHANGES |
DTrim99
left a comment
There was a problem hiding this comment.
Requesting changes: 0 critical, 3 should (the axiom line isn't a valid form and no rulespec-us issue covers Part B enrollment or the SSI buy-in; the modeled-SSI arm of the buy-in is unpinned; the annual max of MSP and buy-in undercounts when the months don't nest, e.g. MSP Jan-Jun plus SSI Jul-Dec charges $1,110 where the law gives $0). The approach matches 42 USC 1395r/1395v, and no reader double-nets. Full report in the comment above.
Keep both new Idaho cases. Drop the two notes in the Medicaid disregard: this branch reads Part B enrollment, and main stores the Part B premium back to 2015. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add buy-in cases for a modeled SSI recipient and a 209(b) spend-down that lands on the limit, and raise the December-only case's interest to $40,000. The buy-in reads eligibility with no take-up step, and it cites SSA's POMS HI 00815.001 for the standard premium. The property test gains a docstring, and the SPM documentation names the netting. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Answered at 6c5d72e29f. Should 1: the axiom line cites rulespec-us#2032 and comments on #2006, #1931, #1933 and #1625. Should 2: a new buy-in case pins the modeled-SSI path, and dropping that term fails it. Should 3: the body lists the annual netting with your witness under "Not in this PR", since the fix touches msp_part_b_premium_coverage, which #9495 and #10632 edit. Suggestion 1: the December-only case now takes $40,000 of interest. Suggestions 2, 3 and 5: "Not in this PR" lists medicare_cost, the MSP enrollment gate and your follow-ups. Suggestion 4: the body and the buy-in's references cite POMS HI 00815.001 and 42 CFR 408.28 and drop the subsection (b) reading. Suggestion 6: the SPM documentation names the netting, and the LIHEAP and EAP comments stay as they read. Suggestion 7: the buy-in's comment, the changelog and the body say "qualifies for Medicaid". Suggestion 8: the property test gives its reason in a docstring.
|
US + core hub merge audit, us#10634 at
🤖 Generated with Claude Code |
Two files conflicted, and both keep both sides. - uprating_extensions.py: this branch's Medicare projection functions and main's long_range_growth_rate (#10119) were added at the same place. - medicare_part_b_premium.yaml: this branch's three projected-year cases and main's Part B payer cases (#10634) were appended at the same place. On the merged tree the three projected-year cases fail, because #10634 nets a state's Part B buy-in for SSI recipients out of the premium. The next commit fixes them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#10634 made medicare_part_b_premium net out medicaid_part_b_buy_in_premium_coverage. In the Section 1634 and SSI-criteria states that buy-in pays the standard premium for every month a person receives SSI. The three projected-year cases give income only for the IRMAA lookback year, so the model found each person an SSI recipient and the buy-in paid the standard premium. Setting ssi to 0, as #10634 did for the file's other cases, restores the premiums the cases test: 5,028, 8,547.60 and 10,560. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This PR charges the Medicare Part B premium only to the people who pay it, through a new Part B enrollment input and a state buy-in for SSI recipients. The model charged every Medicare enrollee, which overstates premiums in Schedule A, Idaho's premium subtraction and every other reader.
Gaps and witnesses
Each witness takes a single 70-year-old in 2025, when the standard premium runs $185 a month ($2,220 a year), unless the row names 2026.
medicare_enrolledcovers Part A and/or Part B, and the model gated the Part B premium on it, so no input could say a person has Part A only.medicare_part_b_premium2,220medicare_part_b_enrolledinput (defaults tomedicare_enrolled). With it false: premium 0,medical_expense_health_insurance_premiums0,gross_medicare_part_b_premium_if_enrolled0receives_ssi, $30,000 interest (above the 135% FPL MSP limit): Medicaid via SSI,msp_part_b_premium_coverage0, premium 2,220medicaid_part_b_buy_in_premium_coveragepays the standard premium, month by month, for an SSI recipient in a Section 1634 or SSI-criteria state and for a 209(b) SSI recipient who qualifies for Medicaid; premium 0is_209b_ssi_recipient_for_medicaidtrue,medicaid_enrolledtrue), premium 2,220medicare_part_b_premium_before_buy_in), since Congress starts buy-in coverage no earlier than "the first day of the first month in which he is both an eligible individual and a member of a coverage group" (42 U.S.C. 1395v(d)(2)(C)).receives_ssiholds December's value, so an annual SSI read would buy in December-only SSI for all 12 months and January-only SSI for none.ssi> 0 orreceives_ssi): 202.90 buy-in and 2,231.90 premium for bothReaders of the modeled premium
All of these read
medicare_part_b_premium(directly or throughmedical_expense_health_insurance_premiumsorspm_unit_health_insurance_premiums) and inherit both fixes:medical_expense_health_insurance_premiums,spm_unit_health_insurance_premiums, thenspm_unit_medical_out_of_pocket_expenses.itemized_medical_expensesanditemized_medical_expenses_excluded_premiums(Schedule A),self_employed_health_insurance_ald_excluded_premiums.id_qualified_health_insurance_premiums; MTmt_premium_deduction_joint,mt_medical_expense_deduction_joint,mt_eligible_medical_insurance_premiums; OHoh_medical_care_insurance_premiums; WA senior/disabled property tax exemption income deductions.snap_allowable_medical_expenses(and OK LIHEAP through it), HUDhud_medical_expenses, PA CCW, UT HEAT, ME HEAP and NH FAP. The LIHEAP/EAP income definitions read it for AR, AZ, GA, IA, IN, KY, LA, MD, MN, MO, MT, ND, NJ, NV, NY, OH, PA, RI, SD, TN, VA, WA, WI, WY.gross_medicare_part_b_premium_if_enrolledfeedsmedicare_costand the CA disregard of the full Part B premium, and both now take the Part B enrollment gate.Two Medicaid eligibility readers,
medicaid_medically_needy_medical_expensesandmedicaid_optional_senior_or_disabled_countable_income, read the premium before the buy-in (medicaid_eligibility_health_insurance_premiums,medicare_part_b_premium_before_buy_in). They take the Part B enrollment gate but not the buy-in, which starts only once the person qualifies for Medicaid.Changes
medicare_part_b_enrolled(new): the formula returnsmedicare_enrolled; enter false for Part A only.medicare_part_b_premium:defined_forPart B enrollment. It nets the larger of MSP coverage and the SSI buy-in, since both pay the same standard premium, and floors at 0. The enrollee keeps paying IRMAA above the standard premium.medicaid_part_b_buy_in_premium_coverage(new): counts each month the person receives SSI and either passes the Section 1634 or SSI-criteria test or counts as a 209(b) SSI recipient who qualifies for Medicaid. It tests eligibility, with no take-up step. It pays the standard premium only. SSA instructs that "States and territories pay the standard premium for individuals covered under state buy-in" (POMS HI 00815.001). CMS has beneficiaries pay the income-related amount "in addition to the Part B (SMI) standard monthly premium" (42 CFR 408.28).medicare_part_b_premium_before_buy_in(new): the gross premium net of MSP, before the buy-in.medicaid_eligibility_health_insurance_premiums(new):medical_expense_health_insurance_premiumswith the premium before the buy-in. CMS lists "Medicare and other health insurance premiums" among the expenses a 209(b) state deducts (42 CFR 435.121(f)(1)(iii)).medicaid_medically_needy_medical_expensesreadsmedicaid_eligibility_health_insurance_premiums.medicaid_optional_senior_or_disabled_countable_incomereads it andmedicare_part_b_premium_before_buy_inforpaid_premiumsandpaid_part_b.gross_medicare_part_b_premium_if_enrolled:defined_forPart B enrollment.medical_expense_health_insurance_premiumsand the CA optional senior/disabled disregard gate Part B onmedicare_part_b_enrolled.spm_unit_medical_out_of_pocket_expensesand the comments in OK LIHEAP and the WA exemption sources now name the netting.Not in this PR
medicaid_enrolledtrue, premium 2,220.ssiandreceives_ssionly.il_smib_categorical_eligiblereadsis_ssi_eligible, which applies no income test, so an IL 70-year-old with $40,000 of interest getsil_smib2,220. Netting it would zero Part B for nearly every Illinois enrollee.msp_income_eligibletrue January through June,receives_ssitrue July through December: MSP 1,110, buy-in 1,110, premium 1,110, where the state pays all 12 months. No annual input reaches this case, and the fix touchesmsp_part_b_premium_coverage, which Add MSP take-up gate and any-month Kansas CSFP categorical eligibility #9495 and Apply immigration tests to Medicare and Medicare Savings Programs #10632 edit.msp_part_b_premium_coverage. A Part A-only enrollee who qualifies for MSP shows 2,220 of coverage there, and no reader uses it. The gate can follow Add MSP take-up gate and any-month Kansas CSFP categorical eligibility #9495 and Apply immigration tests to Medicare and Medicare Savings Programs #10632.medicare_costfor a Part A-only enrollee. ID, $12,000 Social Security: 17,751 with Part A only against 15,531 with Part B, since the per-capita series includes Part B spending. Only the new input reaches this case.Tests
medicaid_part_b_buy_in_premium_coverage.yaml10,medicare_part_b_premium.yaml19,medicare_part_b_enrolled.yaml4,medicaid_medically_needy_medical_expenses.yaml3. The buy-in file covers CA full-year SSI, modeled SSI, no SSI, Part A only, three CT spend-downs, CT December-only SSI, and TX December-only and January-only SSI. One CT spend-down turns on the premium before the buy-in, and one lands on the limit.ssi: 0to keep testing the uncovered premium.medicare_part_b_premiumand expected Medicaid to read it, and they now entermedicare_part_b_premium_before_buy_inwith the same expected values.test_part_b_msp_offset.py, 15 cases): 200 random draws of gross premium, MSP coverage, buy-in coverage and Part B enrollment in one simulation. The paid premium stays at or above 0 and at or below gross, and reads 0 without Part B.No partner test changed.
Invariants
These hold for every input, and
test_part_b_msp_offset.pychecks them with random draws:medicare_part_b_premium≤ the gross premium.The YAML overlap case pins the netting: a person covered by both MSP and the buy-in counts once.
Overlaps with open PRs
medicaid_optional_senior_or_disabled_countable_income's formula into a new monthly file, which readsmedical_expense_health_insurance_premiumsandmedicare_part_b_premiumand gates both Part B terms onmedicare_enrolled. Limit SSI spousal-deeming child allocations to the couple's co-resident children #10146's branch already conflicts with main in three files: the annual file,ca_state_supplement.pyandca_wdp_ssi_ssp_income_eligible.py. This PR edits only the annual file. Whoever lands second carries three changes from this PR into the monthly file:paid_premiumsreadsmedicaid_eligibility_health_insurance_premiums,paid_part_breadsmedicare_part_b_premium_before_buy_in, and both Part B terms take themedicare_part_b_enrolledgate. Without the two premium reads, the buy-in and the 209(b) test read each other, and the simulation stops with a cycle error. Without the gate, the model disregards the full Part B premium for a California enrollee with Part A only. Whoever lands second also deletes the monthly file's note thatmedicare_enrolledstands in for Part B enrollment.self_employed_health_insurance_ald_excluded_premiumsreadsmedical_expense_health_insurance_premiums, which this PR edits by one gate line.itemized_medical_expenses, which reads the same aggregate, with no shared lines.msp_part_b_premium_coverage, and this PR leaves that file alone.Impact
We estimate that this branch changes none of the outputs we measured in 2026 on the default dataset. We compared main at the merge base
1104c5edb5with this branch at6c5d72e29f.The branch lowers a Part B premium only where the new buy-in would pay more of it than the Medicare Savings Program already pays. No record on the default dataset meets that test in 2026, so no premium, tax or net income moves. The dataset sets no
medicare_part_b_enrolled, so that variable followsmedicare_enrolledfor every record, and the branch's Part B gates match main's. Main lacksmedicaid_eligibility_health_insurance_premiums, which this branch adds, so we couldn't compare it.medicare_part_b_premiummedical_expense_health_insurance_premiumsstate_income_taxincome_taxhousehold_benefitshousehold_net_incomeimpact: no change in 2026 on the default dataset to Part B premiums, health insurance premiums, taxes, benefits or household net income.
axiom: TheAxiomFoundation/rulespec-us#2032 queued (corpus release re-pin and encoder approval); TheAxiomFoundation/rulespec-us#2006, TheAxiomFoundation/rulespec-us#1931, TheAxiomFoundation/rulespec-us#1933 and TheAxiomFoundation/rulespec-us#1625 queued, extended with comments (209(b) premiums, medically needy expenses, California Part B enrollment and the Idaho payer-paid regression).
🤖 Generated with Claude Code