Repository navigation
Charge the Part D income-related premium only to Part D enrollees - #10115
Merged
Merged
Conversation
income_adjusted_part_d_premium_surcharge was defined for medicare_enrolled (Part A and/or Part B), so every Medicare enrollee above the IRMAA thresholds paid it, including people whose drug coverage is not Part D (retiree drug subsidy plans, FEHB, TRICARE for Life, VA) and people with no drug coverage. 42 U.S.C. 1395w-113(a)(7) raises the Part D beneficiary premium, which only Part D enrollees pay. Adds takes_up_medicare_part_d_if_eligible (input, default true) and medicare_part_d_enrolled (Medicare enrollees who take up Part D; 42 U.S.C. 1395w-101(a)(3)(A)), and gates the surcharge on the latter. With the default, results are unchanged until microdata supply the input. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…case Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 11, 2026
MaxGhenis
marked this pull request as ready for review
October 11, 2026 19:35
Contributor
Author
|
US + core hub merge audit, us#10115 at
|
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.
Problem
income_adjusted_part_d_premium_surchargewasdefined_for = "medicare_enrolled", andmedicare_enrolledcovers Part A and/or Part B. So every Medicare enrollee above the IRMAA thresholds paid the Part D surcharge. That includes people whose drug coverage is not Part D (retiree drug subsidy plans, FEHB, TRICARE for Life, the VA) and people with no drug coverage. 42 U.S.C. 1395w-113(a)(7)(A) increases "the monthly amount of the beneficiary premium applicable under this section", and (a)(1)(A) defines that premium "for a prescription drug plan". Only Part D enrollees pay it.Measured on the certified dataset. The run used the
us-6.2.6bundle (populace-us-2024-spm-20260915) on pe-us 2.2.1 with #10106 backported, through policyengine.py's managed microsimulation. Every figure below is a weighted MicroSeries sum. The model's Part D IRMAA payer count equals its Part B count by construction:The Part B payer count matches. The Part D count is 14% high, because 1 in 8 Part B payers has no Part D income-related premium. The rest of both dollar gaps is a top-heavy tier mix, which comes from the dataset's AGI distribution (PolicyEngine/microcosm#958). That is a data issue and is out of scope here.
Change
takes_up_medicare_part_d_if_eligible(Person, bool input, defaulttrue): whether a Medicare enrollee takes up Part D. Microdata assign it, like the other take-up inputs.medicare_part_d_enrolled(Person, bool):defined_for = "medicare_enrolled",addsthe take-up input. 42 U.S.C. 1395w-101(a)(3)(A) limits Part D to individuals entitled to Part A or enrolled in Part B.income_adjusted_part_d_premium_surchargeis nowdefined_for = "medicare_part_d_enrolled".Impact: none until microdata set the input. On the certified h5, base (
ae3782f4d7) and this PR give identical results. Each side ran as a frozengit archivesnapshot throughpolicyengine_us.Microsimulation, and the dataset sha256 begins6496cc4393d4.medicare_part_d_enrolled=medicare_enrolledThe data step is a Microcosm Part D take-up input (PolicyEngine/microcosm#1206), queued for Max as decision d1372. Program take-up is assigned in microdata, not at simulation time. The full diagnosis covers tiers, filing status, the AGI tail against SOI Tables 1.1 and 1.6, and prototype reweightings. It is in
~/PolicyEngine/crfb-m4a/research/irmaa-run/diagnosis/REPORT.md.Invariants (Hypothesis,
test_part_d_enrollment.py)For every drawn set of people (ages 55–95, Medicare and Part D take-up, filing status, float32 MAGI from $0 to $1.5M, 2024–2026):
medicare_part_d_enrolledequalsmedicare_enrolledAND take-up. Part D enrollment implies Medicare enrollment, which implies eligibility.gross_medicare_part_b_premiumunchanged.Mutation check. With the old
medicare_enrolledgate restored, the property test fails on invariant 1, and so do YAML cases 4a and 4b.Cost. One test of 25 examples, each building two small simulations on the shared model system. No extra
CountryTaxBenefitSystemstays resident. Locally (macOS, not Linux CI) the call took 3.3 s, and the process peaked at 1.15 GB, mostly model import. It falls in the Restpolicygroup.Tests
medicare_part_d_enrolled.yaml: default take-up, no take-up, not Medicare-enrolled, under 65 without disability entitlement, and SSDI entitlement under 65.income_adjusted_part_d_premium_surcharge.yaml:Interactions
medicare_costsubtractspart_d.enrollment_share × (premiums_per_enrollee + surcharge)): that expected-value formula assumes the surcharge is charged to every Medicare enrollee. Once microdata set Part D take-up, multiplying byenrollment_sharewould count non-enrollment twice. Flagged on Subtract the expected Part D premium from medicare_cost #10111 (Subtract the expected Part D premium from medicare_cost #10111 (comment)).git merge-treeagainst each head is clean. The new YAML cases sit beside the related case, so they don't collide with the cases those PRs append.Plan
axiom: TheAxiomFoundation/rulespec-us#1677 queued (extended with the 1395w-113(a)(1)/(a)(7) enrollment gate and 1395w-101(a)(3)(A))
🤖 Generated with Claude Code