feat(qpp): PY2027 registry + CMS-1848-P proposed changes (refs #613)

This commit is contained in:
kert
2026-08-13 21:55:25 -04:00
parent 8c635024e7
commit 9eb18bb741
2 changed files with 238 additions and 10 deletions

View File

@@ -98,6 +98,89 @@ statement of the Medicare-option figure. Rather than reuse that
number under a different provision's field, ``benchmark_nominal_pct`` number under a different provision's field, ``benchmark_nominal_pct``
is left ``None`` on every entry, with the gap documented in is left ``None`` on every entry, with the gap documented in
``RiskStandards.notes``. ``RiskStandards.notes``.
CMS-1848-P (CY2027 PFS proposed rule) — QPP[2027]
----------------------------------------------------
CMS-1848-P (91 FR 43842, published July 16, 2026, transcribed from
``data/fr_downloads/2026-14327.txt``) is captured on ``QPP[2027]``
(QP Performance Period 2027, payment year 2029). Ingested into Zotero
as :pincite:`5ITGVDJV`. No Final Rule (CMS-1848-F) had been published
as of this transcription, so ``QPP[2027].proposed.changes`` states
proposals only, with no finalized-disposition information available.
QPP[2027] current-law thresholds are transcribed from two sources that
agree: the RIA recital "The thresholds to achieve QP status in the
2027 QP Performance Period (2029 payment year) are set to 75 percent
for the payment amount, and 50 percent for the patient count." (91 FR
44260, line 40311-40313), and the amendatory regulatory text at 42 CFR
414.1430(a)(1)(v)/(a)(3)(v) "2029 and thereafter: 75 percent" /
"50 percent" (91 FR 44285-44286, line 42551/42569) — the same
amendatory text at (a)(2)(v)/(a)(4)(v) gives the Partial QP thresholds
"2029 and thereafter: 50 percent" / "35 percent" (91 FR 44286, line
42559/42576). No amendment to 42 CFR 414.1415 (nominal amount
standard / CEHRT) or 414.1420 (Other Payer Advanced APM standard) is
proposed in this NPRM — the amendatory-text item list runs "44. Sec.
414.1400 ... 45. Sec. 414.1425 ..." (line 42368, 42504), skipping both
sections — so ``risk_standards`` and ``cehrt_required`` are carried
forward unchanged, corroborated indirectly by this NPRM's own
statement that the Shared Savings Program ENHANCED track Level E loss
recoupment limit — independently stated as "shall not exceed 8
percent of total Medicare Parts A and B FFS revenue" (91 FR 44069,
line 23890-23891) — equals "the revenue-based nominal amount standard
under the Quality Payment Program (QPP) (42 CFR 414.1415(c)(3)(i)(A))"
(line 23894-23896), consistent with the existing 8% figure.
``qp_cf_applies`` is True: "eligible clinicians who are QPs for the
2024 performance year/2026 payment year and beyond will receive an
increased physician fee schedule update of 0.75 percent qualifying
APM conversion factor" (91 FR 44217, line 30603-30606) confirms the
split-CF policy is not time-limited and persists through payment year
2029. ``apm_incentive_pct`` is None: the amendatory text at 42 CFR
414.1450(b)(1) (91 FR 44286, line 42629-42632) lists applicable
percentages only for payment years 2019-2024, 2025, 2026, and 2028 —
no entry for payment year 2027 or 2029 — so under current law as
restated by this NPRM, no lump-sum APM Incentive Payment is payable
for payment year 2029 (the sunset already captured on QPP[2025]/
QPP[2026] has a gap, not a clean cutoff — see next section).
CMS-1848-P's substantive Advanced-APM-relevant proposals (see
``QPP[2027].proposed.changes`` for full sourcing) are: (1) applying QP
(and, by conforming amendment, Partial QP) status strictly at the
TIN/NPI level rather than to the clinician across all TIN
reassignments, beginning with the 2027 QP Performance Period (91 FR
44215-44217, 44285); (2) a clerical fix to 42 CFR 414.1425(c)(5)(ii)
removing an erroneously-included clause; (3) a clarification for APMs
without a Participation List; (4) a restructuring/condensing of 42
CFR 414.1430(a)/(b) to conform the regulation text to already-enacted
statutory threshold levels (not a new CMS-set threshold change); and
(5) codifying the CAA 2026's 3.1% APM Incentive Payment extension for
payment year 2028 and restructuring 414.1450(b)(1) into a per-year
list.
**Concern — PY2026 (QPP[2026], payment year 2028) restatement
discrepancy, NOT corrected here:** this NPRM's own amendatory text for
42 CFR 414.1430(a)/(b) (91 FR 44285-44286) states, for payment year
2028: QP payment amount threshold 50% (a)(1)(iv), QP patient count
threshold 35% (a)(3)(iv), Partial QP payment amount threshold 40%
(a)(2)(iv), Partial QP patient count threshold 25% (a)(4)(iv) — and
for payment years 2021 through 2026 (covering QPP[2023]'s payment
year 2025 and QPP[2024]'s payment year 2026): QP payment amount
threshold 50% (a)(1)(ii), QP patient count threshold 35% (a)(3)(ii).
These figures directly **contradict** the values currently coded on
``QPP[2023]``, ``QPP[2024]``, and ``QPP[2026]`` (75%/50% QP,
50%/35% Partial QP, uniformly), which were sourced from the CY2026
Final Rule quote in this module's docstring ("The thresholds to
achieve QP status in the 2026 QP Performance Period (2028 payment
year) are set to 75 percent for the payment amount, and 50 percent
for the patient count.", 90 FR 49980). This NPRM's amendatory text
also directly states, for payment year 2028, an APM Incentive Payment
of 3.1% (42 CFR 414.1450(b)(1)(iv), 91 FR 44286) — contradicting
``QPP[2026].apm_incentive_pct = None``. Per task scope, these PY2023/
PY2024/PY2026 values are **not modified** by this transcription; see
task-7-report.md for the full cross-check and a recommendation that a
follow-up task re-verify ``QPP[2023]``, ``QPP[2024]``, and
``QPP[2026]`` directly against 42 CFR 414.1430/414.1450 (eCFR) rather
than the FR-corpus narrative quotes.
""" """
from __future__ import annotations from __future__ import annotations
@@ -432,6 +515,109 @@ QPP: dict[int, QppYear] = {
), ),
), ),
), ),
2027: QppYear(
# QP Performance Period 2027 / payment year 2029. Current-law
# thresholds transcribed from data/fr_downloads/2026-14327.txt
# (91 FR 43842, CMS-1848-P) -- see module docstring "CMS-1848-P
# (CY2027 PFS proposed rule) - QPP[2027]" for full sourcing:
# - RIA recital, 91 FR 44260 (line 40311-40313): "The
# thresholds to achieve QP status in the 2027 QP
# Performance Period (2029 payment year) are set to 75
# percent for the payment amount, and 50 percent for the
# patient count."
# - Amendatory text, 42 CFR 414.1430(a)(1)(v)/(a)(3)(v), 91 FR
# 44285-44286 (line 42551, 42569): "2029 and thereafter: 75
# percent" / "50 percent" (QP); (a)(2)(v)/(a)(4)(v), 91 FR
# 44286 (line 42559, 42576): "2029 and thereafter: 50
# percent" / "35 percent" (Partial QP).
# Risk standards / CEHRT: no amendment to 42 CFR 414.1415 or
# 414.1420 in this NPRM (amendatory-text item list skips both,
# 91 FR 44284-44285) -- carried forward unchanged; see
# module docstring for the indirect Shared Savings Program
# Level E cross-check (91 FR 44069).
# apm_incentive_pct: no payment-year-2029 entry in the
# amendatory text at 42 CFR 414.1450(b)(1), 91 FR 44286 (line
# 42629-42632) -- no APM Incentive Payment for this payment
# year under current law as restated by this NPRM.
# qp_cf_applies: "eligible clinicians who are QPs for the 2024
# performance year/2026 payment year and beyond will receive an
# increased physician fee schedule update of 0.75 percent
# qualifying APM conversion factor" (91 FR 44217, line
# 30603-30606) -- split CF persists through payment year 2029.
performance_year=2027,
payment_year=2029,
qp_thresholds=_qp_thresholds(),
partial_qp_thresholds=_partial_qp_thresholds(),
risk_standards=_risk_standards(),
apm_incentive_pct=None,
qp_cf_applies=True,
citation="91 FR 44260, 44285-44286",
# NPRM proposals per :pincite:`5ITGVDJV` -- CMS-1848-P, 91 FR
# 43842, transcribed from data/fr_downloads/2026-14327.txt. No
# Final Rule (CMS-1848-F) published as of this transcription --
# proposals only, no finalized disposition available.
proposed=QppProposed(
cms_rule_id="CMS-1848-P",
federal_register_citation="91 FR 43842",
changes=(
"TIN/NPI-level QP and Partial QP status determination: "
"proposed to apply QP status (and, via a conforming "
"amendment, Partial QP status) strictly to the "
"eligible clinician as a TIN/NPI combination, rather "
"than to the clinician (NPI) across all of their TIN "
"reassignments as under current policy, beginning with "
"the 2027 QP Performance Period (NPRM 91 FR "
"44215-44217, section 'Advanced APMs' > 'QP "
"Determination' > '(2) Applying QP Determinations at "
"the TIN/NPI Level'; amendatory text adding Sec. "
"414.1425(c)(8) and (d)(5), 91 FR 44285). "
"APM Entity Termination clerical fix: proposed to "
"remove an erroneously-included clause ('even if such "
"termination date occurs within such QP Performance "
"Period') from 42 CFR 414.1425(c)(5)(ii), correcting a "
"CY2020-PFS-final-rule clerical error that misaligned "
"the QP-status termination text from its Partial-QP "
"counterpart at 414.1425(d)(3)(ii) (NPRM 91 FR "
"44217-44218). "
"Participation List clarification: proposed to clarify "
"that APMs without a Participation List are not "
"thereby excluded from QP determinations or MIPS APM "
"scoring, addressing an interpretive gap for future "
"episode-based/mandatory APM designs (NPRM 91 FR "
"44218). "
"QP/Partial QP threshold regulatory-text conformance: "
"proposed to restructure and condense 42 CFR "
"414.1430(a)/(b) into a consolidated payment-year "
"schedule, conforming the regulation text to "
"already-enacted statutory changes (CAA 2024's "
"extension of payment-year-2025 thresholds through "
"payment year 2026, and subsequently legislated "
"payment-year 2027/2028/2029+ levels) rather than "
"proposing new CMS-set thresholds (NPRM 91 FR "
"44219-44220; amendatory text 91 FR 44285-44286). See "
"QPP[2027].qp_thresholds/partial_qp_thresholds for the "
"values as restated for payment year 2029. "
"APM Incentive Payment: proposed to codify the "
"Consolidated Appropriations Act, 2026's extension of "
"a 3.1 percent lump-sum APM Incentive Payment to "
"payment year 2028 (2026 QP Performance Period), and "
"to restructure 42 CFR 414.1450(b)(1) into a per-year "
"subparagraph list for readability, with no "
"substantive change to any other year's percentage "
"(NPRM 91 FR 44218-44219; RIA 91 FR 44260; amendatory "
"text 91 FR 44286). CONCERN: this amendatory text lists "
"no applicable percentage for payment years 2027 or "
"2029 (i.e., no incentive payment in those years) and "
"3.1 percent for payment year 2028 -- the latter "
"directly bears on QPP[2026].apm_incentive_pct "
"(payment year 2028), which is currently coded as "
"None; this transcription task is scoped not to "
"silently correct that entry -- see module docstring "
"'Concern - PY2026 ... restatement discrepancy' and "
"task-7-report.md."
),
),
),
} }

View File

@@ -3,12 +3,13 @@
Covers src/qpp/__init__.py: Covers src/qpp/__init__.py:
- QpThresholds / RiskStandards / QppProposed model construction - QpThresholds / RiskStandards / QppProposed model construction
- QppYear model construction with required and default fields - QppYear model construction with required and default fields
- QPP dict: performance years 2023-2026, payment_year = performance_year + 2 - QPP dict: performance years 2023-2027, payment_year = performance_year + 2
- qp_cf_applies: False before performance year 2024, True from 2024 onward - qp_cf_applies: False before performance year 2024, True from 2024 onward
- Every entry has a non-empty citation - Every entry has a non-empty citation
- QPP[2026].proposed is CMS-1832-P - QPP[2026].proposed is CMS-1832-P; QPP[2027].proposed is CMS-1848-P
- for_payment_year(year) lookup, including KeyError on miss - for_payment_year(year) lookup, including KeyError on miss
- Exact-value asserts for transcribed thresholds (see task-6-report.md) - Exact-value asserts for transcribed thresholds (see task-6-report.md,
task-7-report.md)
""" """
from __future__ import annotations from __future__ import annotations
@@ -110,10 +111,10 @@ class TestQppYear:
class TestQppDict: class TestQppDict:
EXPECTED_YEARS = [2023, 2024, 2025, 2026] EXPECTED_YEARS = [2023, 2024, 2025, 2026, 2027]
def test_count(self): def test_count(self):
assert len(QPP) == 4 assert len(QPP) == 5
def test_keys(self): def test_keys(self):
assert sorted(QPP.keys()) == self.EXPECTED_YEARS assert sorted(QPP.keys()) == self.EXPECTED_YEARS
@@ -150,6 +151,9 @@ class TestQpCfApplies:
def test_2026_true(self): def test_2026_true(self):
assert QPP[2026].qp_cf_applies is True assert QPP[2026].qp_cf_applies is True
def test_2027_true(self):
assert QPP[2027].qp_cf_applies is True
class TestApmIncentivePct: class TestApmIncentivePct:
"""Lump-sum APM Incentive Payment sunsets after payment year 2026.""" """Lump-sum APM Incentive Payment sunsets after payment year 2026."""
@@ -166,6 +170,13 @@ class TestApmIncentivePct:
def test_2026_no_incentive(self): def test_2026_no_incentive(self):
assert QPP[2026].apm_incentive_pct is None assert QPP[2026].apm_incentive_pct is None
def test_2027_no_incentive(self):
# Payment year 2029: 42 CFR 414.1450(b)(1) (as amended by
# CMS-1848-P, 91 FR 44286) lists applicable percentages only
# for payment years 2019-2024, 2025, 2026, and 2028 — no entry
# for 2029.
assert QPP[2027].apm_incentive_pct is None
# ── QPP[2026].proposed — CMS-1832-P ────────────────────────────── # ── QPP[2026].proposed — CMS-1832-P ──────────────────────────────
@@ -186,25 +197,53 @@ class TestProposed:
assert QPP[2025].proposed is None assert QPP[2025].proposed is None
# ── QPP[2027].proposed — CMS-1848-P ──────────────────────────────
class TestProposed2027:
def test_2027_has_proposed(self):
p = QPP[2027].proposed
assert p is not None
assert p.cms_rule_id == "CMS-1848-P"
assert p.federal_register_citation == "91 FR 43842"
def test_2027_changes_non_empty(self):
assert len(QPP[2027].proposed.changes) > 0
def test_2027_no_numeric_change_blocks(self):
# CMS-1848-P's threshold/incentive amendments conform the
# regulation text to already-enacted statutory levels rather
# than proposing new CMS-set numeric values — see
# QppProposed.qp_thresholds docstring.
p = QPP[2027].proposed
assert p.qp_thresholds is None
assert p.partial_qp_thresholds is None
assert p.risk_standards is None
# ── Exact transcribed threshold values ─────────────────────────── # ── Exact transcribed threshold values ───────────────────────────
class TestSpecificValues: class TestSpecificValues:
"""Verify transcribed QP/Partial QP thresholds and risk standards. """Verify transcribed QP/Partial QP thresholds and risk standards.
See task-6-report.md transcription table for sourcing per value.""" See task-6-report.md / task-7-report.md transcription tables for
sourcing per value. QPP[2027] (payment year 2029) values are
sourced from CMS-1848-P (91 FR 44260, 44285-44286) rather than the
CY2026-cycle documents underlying 2023-2026 — see module
docstring "CMS-1848-P (CY2027 PFS proposed rule) — QPP[2027]"."""
@pytest.mark.parametrize("year", [2023, 2024, 2025, 2026]) @pytest.mark.parametrize("year", [2023, 2024, 2025, 2026, 2027])
def test_qp_thresholds(self, year): def test_qp_thresholds(self, year):
assert QPP[year].qp_thresholds.payment_amount_pct == 75.0 assert QPP[year].qp_thresholds.payment_amount_pct == 75.0
assert QPP[year].qp_thresholds.patient_count_pct == 50.0 assert QPP[year].qp_thresholds.patient_count_pct == 50.0
@pytest.mark.parametrize("year", [2023, 2024, 2025, 2026]) @pytest.mark.parametrize("year", [2023, 2024, 2025, 2026, 2027])
def test_partial_qp_thresholds(self, year): def test_partial_qp_thresholds(self, year):
assert QPP[year].partial_qp_thresholds.payment_amount_pct == 50.0 assert QPP[year].partial_qp_thresholds.payment_amount_pct == 50.0
assert QPP[year].partial_qp_thresholds.patient_count_pct == 35.0 assert QPP[year].partial_qp_thresholds.patient_count_pct == 35.0
@pytest.mark.parametrize("year", [2023, 2024, 2025, 2026]) @pytest.mark.parametrize("year", [2023, 2024, 2025, 2026, 2027])
def test_risk_standards(self, year): def test_risk_standards(self, year):
# Revenue-based standard (42 CFR 414.1415(c)(3)(i)(A)) is # Revenue-based standard (42 CFR 414.1415(c)(3)(i)(A)) is
# transcribed (8%); the benchmark-based standard (42 CFR # transcribed (8%); the benchmark-based standard (42 CFR
@@ -214,7 +253,7 @@ class TestSpecificValues:
assert QPP[year].risk_standards.revenue_nominal_pct == 8.0 assert QPP[year].risk_standards.revenue_nominal_pct == 8.0
assert QPP[year].risk_standards.benchmark_nominal_pct is None assert QPP[year].risk_standards.benchmark_nominal_pct is None
@pytest.mark.parametrize("year", [2023, 2024, 2025, 2026]) @pytest.mark.parametrize("year", [2023, 2024, 2025, 2026, 2027])
def test_cehrt_required(self, year): def test_cehrt_required(self, year):
assert QPP[year].cehrt_required is True assert QPP[year].cehrt_required is True
@@ -235,6 +274,9 @@ class TestForPaymentYear:
def test_2028_maps_to_performance_2026(self): def test_2028_maps_to_performance_2026(self):
assert for_payment_year(2028) is QPP[2026] assert for_payment_year(2028) is QPP[2026]
def test_2029_maps_to_performance_2027(self):
assert for_payment_year(2029) is QPP[2027]
def test_unknown_payment_year_raises_keyerror(self): def test_unknown_payment_year_raises_keyerror(self):
with pytest.raises(KeyError): with pytest.raises(KeyError):
for_payment_year(1999) for_payment_year(1999)