Files
stack/tests/pfs/test_anchors.py
kert c244cebba1 fix(pfs): code→family index keeps every family so indexed and scan anchors agree (refs #688)
code_family_index kept only the first family per code (setdefault),
while anchor_metadata's un-indexed scan unions every qualifying
family a code belongs to — so stack llm index (no code_index) and
stack llm restamp (always indexed) would write different 'families'
values for the same text once a code belongs to two families, which
the next slice (CPT headings intersecting hand families) will create.

Ruling A6: code_family_index now maps each code to the sorted tuple
of every qualifying (>=2-code) family key, and anchor_metadata unions
those tuples across all matched codes. The indexed and un-indexed
paths are now equivalent by construction. Also drops the dead
`fams = ...` computation in anchor_metadata when code_index is given.

Does not touch the running background comments restamp — the five
live hand families (ACP, CCM, PCM, TCM, APCM) don't share any codes,
so its output is unaffected today.
2026-09-09 16:12:13 -04:00

76 lines
2.9 KiB
Python

"""pfs.anchors — metadata for chunks: codes, families, and element slugs."""
from pfs.anchors import anchor_metadata, code_family_index
from pfs.families import FAMILIES, Family
def test_codes_families_elements():
md = anchor_metadata(
"Use 99439 in conjunction with 99490; consent; per calendar month"
)
assert md["codes"] == "99439 99490"
assert md["families"] == "CCM"
assert (
"activity=consent" in md["elements"].split()
and "period=calendar-month" in md["elements"].split()
)
assert "relation=addon-of" in md["elements"].split() # detail dropped
def test_empty_and_unknown():
assert anchor_metadata("nothing here") == {
"codes": "",
"families": "",
"elements": "",
}
fams = {"X": Family("X", "X fam", ("12345", "23456"), ("x fam",))}
assert anchor_metadata("code 12345", families=fams)["families"] == "X"
def test_code_index_matches_unindexed_scan():
text = "Use 99439 in conjunction with 99490; consent; per calendar month"
index = code_family_index(FAMILIES)
assert anchor_metadata(text, code_index=index) == anchor_metadata(text)
def test_code_index_keeps_every_family_on_collision():
"""Ruling A6: a code shared by two qualifying families must keep
both in the index — a single-winner index made the indexed path
(restamp) disagree with the un-indexed scan the moment two families
shared a code, which the next slice (CPT headings intersecting a
hand family) will create."""
fams = {
"A": Family("A", "A fam", ("12345", "23456"), ("a fam",)),
"B": Family("B", "B fam", ("12345", "34567"), ("b fam",)),
}
index = code_family_index(fams)
assert index["12345"] == ("A", "B")
def test_code_index_matches_unindexed_scan_on_collision():
"""The indexed and un-indexed paths must write identical 'families'
values for the same text once a code belongs to two families."""
fams = {
"A": Family("A", "A fam", ("12345", "23456"), ("a fam",)),
"B": Family("B", "B fam", ("12345", "34567"), ("b fam",)),
}
text = "code 12345"
index = code_family_index(fams)
assert anchor_metadata(text, families=fams, code_index=index) == anchor_metadata(
text, families=fams
)
assert anchor_metadata(text, families=fams)["families"] == "A B"
def test_single_code_family_never_stamped():
"""A stem-derived family of exactly one code (~17,182 of 17,187
derived keys) is not a grouping worth its own anchor — it would just
echo the code already in 'codes' (Ruling A5)."""
fams = {"SOLO": Family("SOLO", "Solo", ("54321",), ("solo",))}
assert "54321" not in code_family_index(fams)
assert anchor_metadata("code 54321", families=fams)["families"] == ""
index = code_family_index(fams)
assert (
anchor_metadata("code 54321", families=fams, code_index=index)["families"] == ""
)