pfs: derive code families from elements and CMS's own "code family" language; hand registry becomes the fixture #687
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Spec docs/superpowers/specs/2026-09-09-code-family-longitudinal-design.md (
pfs/families.py).What.
pfs.code_family(key, code, role, since, until, item_key, p_id): a family is a set of codes sharing a descriptor stem and differing only intime/actor/populationelements, unioned with (a)relationelements (add-on-of, replaces, defined-by-reference-to) and (b) CMS's explicit family phrases in the FR — e.g. "The Chronic Care Management code family will be resurveyed during CY 2020" (YBM4IZUS¶1578, 85 FR 84639). Roles: base, add-on, predecessor, successor, RHC/FQHC bundle (G0511 averages 99484/99487/99490/99491 + PCM,JE7KYBW3¶1100).API stays.
FAMILIES,detect_codes,family_ofkeep their signatures (P48 chat depends on them);FAMILIESloads from the replica when present and falls back to the current hand list (ACP, CCM, PCM, TCM, APCM — 17 codes) which becomes the regression fixture.Done when the derived families reproduce the five hand families exactly, add their predecessors (G2058, G2064/G2065, the CY2013–14 CCM G-code) with
since/until, and produce at least 20 further families across the 8,572 payable codes without human seeding (spot-check: E/M office visits 99202–99215 + G2211; RPM 99453–99458; audio-only 98008–98016).Implemented on branch
worktree-p49-code-family-foundation(Task 8 + final review):src/pfs/families.pykeeps the P48 API (FAMILIES,detect_codes,family_of,find_codes); the literal is nowHAND_FAMILIES,FAMILIESis refreshed in place byrefresh_from(con)frompfs.code_family(hand families are a minimum — never dropped).derive_families= connected components over:addon-of/defined-by-reference-torelation elements, single-targetreplaces/replaced_byevents, and stem-token Jaccard ≥ 0.5 with a non-empty identical activity set (not-with,crosswalk, multi-code lists excluded — they collapsed ACP+CCM+PCM into one component on the first live run). Components spanning two hand families are split by BFS from each hand seed with a warning. Derived keys keep description word order and are made unique on collision; non-code members are rejected. CLI:stack pfs families [--write].Live run: 17,202 rows / 17,187 keys; the five hand families:
ACP/TCM/APCM/PCM equal the hand lists; CCM = hand list + G2058 as intended, plus G0502/G0503 — a false merge caused by a long background paragraph absorbed as G0502's descriptor (new issue filed; not a family-rule defect). Roles come from events/elements (99424 shows
predecessorbecause tworeplaced_by-shaped FR events exist for it — membership is right, the role label needs the same earliest-event rule as #686).Not yet wired into the chat: #699.
Update 2026-09-09 evening — families now come from the CPT manual's own hierarchy (branch
worktree-p49-slice2-anchors, plandocs/superpowers/plans/2026-09-09-cpt-organizing-principles.md, schema reviewdocs/superpowers/specs/2026-09-09-cpt-canonical-schema-design.md).The AMA CPT editions in Zotero (2019, 2021, 2022, 2024 EPUBs) were imported into bib (
stack bib import-zotero), parsed (pfs/cpt_epub.py: sections with code spans, code entries with symbols and required-elements lists, parenthetical instructions, CPT Changes years, Appendix D/M/N/P/T lists) intopfs.cpt_*tables (stack pfs cpt-ingest --all; 12,056 code entries in 2024; guideline reprints and resequenced placeholders resolved intopfs.cpt_code_alt).derive_familiesnow assigns every CPT code to the lowest CPT heading that groups ≥ 2 codes (grouped by heading path, not section id), keyed by the heading title, with the heading path in the newcode_family.note; add-on/parent/replacement edges attach only codes without a heading of their own;since/untilcome from edition presence across all ingested editions.Live result (
stack pfs families --write): 8,518 keys, 816 families with ≥ 2 codes, 856 CPT-named, 5 hand families kept as a minimum, 7,657 singletons (mostly HCPCS codes awaiting element extraction, plus CPT codes deleted since 2019 and unlisted codes alone under a parent heading).Every non-hand family maps to exactly one heading (CCM spans the chronic and complex-chronic headings by design). 99490:
since 2019, noteEvaluation and Management > Care Management Services > Chronic Care Management Services.Still to land in this slice: CPT Changes years as lineage events and CPT elements as an extraction source (#685/#686), the explainer notebook's CPT sections, then a re-run of
stack llm restamp --collection allso chunkfamiliesanchors use the new registry (today they only carry the five old families).Delivered in P49 slices 1–2a (
edc128e,d016f70): pfs.code_family derived from CPT headings + elements + CMS 'code family' language, hand registry as the fixture (8,489 keys, 805 multi-code, 843 CPT-named); refresh_from feeds the chat (#699). Closing.