fix(notebooks): route CY2027 NPRM citations through bib.frlink/cfrlink (closes #642)
All checks were successful
CI / lint (push) Successful in 29s
CI / notebooks-smoke (push) Successful in 1m25s
Deploy / notebooks (push) Has been skipped
Deploy / zotero (push) Has been skipped
Deploy / docs (push) Has been skipped
Deploy / api (push) Has been skipped
Deploy / llm (push) Has been skipped
Deploy / mc (push) Has been skipped
Infra CI / notebooks (push) Successful in 1m9s
Infra CI / zotero (push) Successful in 24s
Infra CI / docs (push) Successful in 16s
Infra CI / api (push) Successful in 2m13s
Infra CI / llm (push) Successful in 1m12s
Infra CI / mc (push) Successful in 19s
Deploy / report (push) Successful in 12s
CI / test (push) Successful in 13m29s

The CY2027 notebook defined the fr_md/cfr_md jump-link wrappers (P40
#638, P41 #641) but only used them in four spots — every other FR
citation rendered as plain text. All simple 'NN FR NNNNN' cites (intro,
CF-walk sources, BN-decomposition narrative, RVU-delta and GPCI
sources, cross-NPRM cell, QPP proposal, QP-differential sources,
comment-period callout) and interpolated registry citations now go
through fr_md(), and the bare 42 CFR 414.1430(a) cite through cfr_md().
Compound qpp citations ('91 FR 44260, 44285-44286') stay plain — the
resolver grammar takes one locator. All six page cites verified against
the bib anchor maps via stack bib fr-jump; headless re-run renders 18
federalregister.gov + 4 ecfr.gov links.
This commit is contained in:
kert
2026-08-18 10:08:19 -04:00
parent 73017081ef
commit c429a29cdd

View File

@@ -12,11 +12,11 @@ def _():
@app.cell(hide_code=True)
def _(mo):
mo.md("""
def _(fr_md, mo):
mo.md(f"""
# CY2027 PFS Proposed Rule — Financial Changes & Advanced APM
CMS's CY2027 Physician Fee Schedule NPRM (CMS-1848-P, 91 FR 43842,
CMS's CY2027 Physician Fee Schedule NPRM (CMS-1848-P, {fr_md("91 FR 43842")},
published July 16, 2026; docket CMS-2026-2377) is a **proposed rule
only** — there is no CY2027 Final Rule (CMS-1848-F) yet, and every
"CY2027" figure below is a proposal, not a finalized payment
@@ -184,8 +184,8 @@ def _(alt, cf_walk, fr_md, mo):
No CY2027-final bars appear anywhere in this notebook — the
Final Rule (CMS-1848-F) has not been published.*
**Sources:** CY2026 Final Rule — 90 FR 49266. CY2027 NPRM —
{fr_md("91 FR 43842")} (CMS-1848-P).
**Sources:** CY2026 Final Rule — {fr_md("90 FR 49266")}.
CY2027 NPRM — {fr_md("91 FR 43842")} (CMS-1848-P).
"""),
]
)
@@ -193,11 +193,11 @@ def _(alt, cf_walk, fr_md, mo):
@app.cell(hide_code=True)
def _(mo):
mo.md("""
def _(fr_md, mo):
mo.md(f"""
### Budget-neutrality adjustor decomposition
CMS's own NPRM narrative (91 FR 44242) describes the CY2027 CF
CMS's own NPRM narrative ({fr_md("91 FR 44242")}) describes the CY2027 CF
derivation explicitly: start from the **CY2026 conversion factors
with the one-time 2.50% statutory increase backed out**, multiply
by the 0.53% budget-neutrality adjustment, then multiply by the
@@ -207,15 +207,15 @@ def _(mo):
cross-check that the registry's transcription is internally
consistent with CMS's narrative — for the **standard** CF only;
the anesthesia CFs reflect "the same overall PFS adjustments with
the addition of anesthesia-specific PE and MP adjustments" (91 FR
44242) that are not modeled as separate registry fields, so they
the addition of anesthesia-specific PE and MP adjustments"
({fr_md("91 FR 44242")}) that are not modeled as separate registry fields, so they
are excluded from this reconstruction rather than approximated.
""")
return
@app.cell(hide_code=True)
def _(RULES, mo, pl, proposed_for):
def _(RULES, fr_md, mo, pl, proposed_for):
_cy26 = RULES[2026]
_prop = proposed_for(2027)
@@ -281,7 +281,7 @@ def _(RULES, mo, pl, proposed_for):
({_ONE_TIME_BACKOUT}) and `annual_update_mult`
({_ANNUAL_UPDATE_MULT["Non-QP"]} non-QP /
{_ANNUAL_UPDATE_MULT["QP"]} QP) are **cited transcriptions
of CMS's NPRM narrative (91 FR 44242,
of CMS's NPRM narrative ({fr_md("91 FR 44242")},
`data/fr_downloads/2026-14327.txt:39088-39106`)**, not
registry fields — no field in `pfs.rules` or `qpp` models
the 2.50%/0.53%/0.25%/0.75% components individually, only
@@ -382,7 +382,7 @@ def _(RULES, pl, proposed_for, rvu_delta_raw):
@app.cell(hide_code=True)
def _(AMBER, RULES, TEAL, alt, mo, proposed_for, rvu_delta):
def _(AMBER, RULES, TEAL, alt, fr_md, mo, proposed_for, rvu_delta):
_n = 20
_winners = rvu_delta.sort("delta_vs_2026final", descending=True).head(_n)
@@ -419,8 +419,8 @@ def _(AMBER, RULES, TEAL, alt, mo, proposed_for, rvu_delta):
winners_losers_chart,
mo.md(f"""
**Sources:** `pfs.rvu_proposed` (`CMS-1848-P`) — CY2027 NPRM,
{proposed_for(2027).federal_register_citation}. Baseline —
`pfs.rvu` CY2026 Final ({RULES[2026].federal_register_citation}).
{fr_md(proposed_for(2027).federal_register_citation)}. Baseline —
`pfs.rvu` CY2026 Final ({fr_md(RULES[2026].federal_register_citation)}).
Both sides priced with each vintage's own non-QP standard CF
— this delta blends RVU-table changes with the proposed CF
change, it is not an RVU-only comparison.
@@ -450,7 +450,7 @@ def _(mo, proposed_for, rvu_delta):
@app.cell(hide_code=True)
def _(con, mo, proposed_for):
def _(con, fr_md, mo, proposed_for):
_new = con.execute("""
SELECT count(*) FROM pfs.rvu_proposed p
WHERE p.cms_rule_id = 'CMS-1848-P' AND (p.mod IS NULL OR p.mod='') AND p.status_code='A' AND p.non_fac_pe_rvu IS NOT NULL
@@ -471,7 +471,7 @@ def _(con, mo, proposed_for):
> baseline.
**Source:** `pfs.rvu_proposed` — CMS-1848-P Addendum B,
{proposed_for(2027).federal_register_citation}. `pfs.rvu` — CY2026
{fr_md(proposed_for(2027).federal_register_citation)}. `pfs.rvu` — CY2026
PFS Final Rule Addendum B.
""")
return
@@ -523,13 +523,13 @@ def _(q):
@app.cell(hide_code=True)
def _(cross_nprm, mo):
def _(cross_nprm, fr_md, mo):
mo.vstack(
[
cross_nprm,
mo.md("""
**Sources:** `pfs.rvu_proposed` — `CMS-1832-P` (90 FR 32352)
and `CMS-1848-P` (91 FR 43842) partitions of the same table.
mo.md(f"""
**Sources:** `pfs.rvu_proposed` — `CMS-1832-P` ({fr_md("90 FR 32352")})
and `CMS-1848-P` ({fr_md("91 FR 43842")}) partitions of the same table.
Total non-facility RVUs only — no dollar conversion, since
the two NPRMs' CFs are not directly comparable across a
one-year gap without also re-basing for the RVU-neutral
@@ -605,7 +605,7 @@ def _(q):
@app.cell(hide_code=True)
def _(AMBER, TEAL, alt, gpci_2027p, mo, pl, proposed_for):
def _(AMBER, TEAL, alt, fr_md, gpci_2027p, mo, pl, proposed_for):
_n = 15
_up = (gpci_2027p["d_mean"] > 0).sum()
_down = (gpci_2027p["d_mean"] < 0).sum()
@@ -662,7 +662,7 @@ def _(AMBER, TEAL, alt, gpci_2027p, mo, pl, proposed_for):
**Sources:** `pfs.gpci_proposed` (`CMS-1848-P`, gpci_year
2027) — CY2027 NPRM Addendum E,
{proposed_for(2027).federal_register_citation}. Baseline —
{fr_md(proposed_for(2027).federal_register_citation)}. Baseline —
`pfs.gpci` year 2026 (CY2026 Final).
"""),
]
@@ -1371,13 +1371,13 @@ def _(QPP, pl, plain_years):
@app.cell(hide_code=True)
def _(QPP, mo):
def _(QPP, cfr_md, mo):
mo.md(f"""
Columns are labeled `qp_performance_period` (the year Advanced-APM
participation is measured) and `payment_year` (the year the
resulting QP status is applied) explicitly and separately — every
threshold in this table governs by **`payment_year`**, per 42 CFR
414.1430(a) and section 1833(z)(2) of the Act. `QPP[2027]`
threshold in this table governs by **`payment_year`**, per
{cfr_md("42 CFR 414.1430(a)")} and section 1833(z)(2) of the Act. `QPP[2027]`
(payment year {QPP[2027].payment_year}) is the entry this
notebook's CF walk (Section 1) corresponds to.
""")
@@ -1436,14 +1436,14 @@ def _(alt, apm_thresholds, cfr_md, fr_md, mo):
@app.cell(hide_code=True)
def _(QPP, mo):
def _(QPP, fr_md, mo):
_prop = QPP[2027].proposed
mo.vstack(
[
mo.md(f"""
### CMS-1848-P proposed QPP changes — proposals only, no Final Rule disposition yet
`qpp.QPP[2027].proposed.changes` ({_prop.federal_register_citation},
`qpp.QPP[2027].proposed.changes` ({fr_md(_prop.federal_register_citation)},
{_prop.cms_rule_id}) is the single source of truth for the
narrative below — quoted live, not retyped. Unlike the
CY2026 notebook's disposition table, there is **no**
@@ -1506,7 +1506,7 @@ def _(pl, proposed_for, q):
@app.cell(hide_code=True)
def _(alt, mo, proposed_for, qp_differential):
def _(alt, fr_md, mo, proposed_for, qp_differential):
differential_chart = (
alt.Chart(qp_differential.to_pandas())
.mark_bar()
@@ -1522,9 +1522,9 @@ def _(alt, mo, proposed_for, qp_differential):
[
differential_chart,
mo.md(f"""
**Sources:** RVUs — `pfs.rvu`, CY2026 Final (90 FR 49266).
**Sources:** RVUs — `pfs.rvu`, CY2026 Final ({fr_md("90 FR 49266")}).
CFs — `proposed_for(2027)`, CY2027 NPRM
({proposed_for(2027).federal_register_citation},
({fr_md(proposed_for(2027).federal_register_citation)},
{proposed_for(2027).cms_rule_id}) — final rule pending.
National unadjusted means GPCI = 1.0 — actual payment
varies by locality.
@@ -1556,7 +1556,7 @@ def _(cfr_md, mo):
@app.cell(hide_code=True)
def _(mo, proposed_for):
def _(fr_md, mo, proposed_for):
from datetime import date
_prop = proposed_for(2027)
@@ -1567,7 +1567,7 @@ def _(mo, proposed_for):
mo.callout(
mo.md(f"""
**Comment period: {_status}** — {_prop.cms_rule_id} ({_prop.federal_register_citation})
**Comment period: {_status}** — {_prop.cms_rule_id} ({fr_md(_prop.federal_register_citation)})
published {_prop.published.isoformat()}, comment period closes
**{_close.isoformat()}** (`proposed_for(2027).comment_close`,
read live from the registry; today is {_today.isoformat()}).