Signal/python-backend/core/rules.py
Kisa d24340c47a feat: citation rule IDs on every documentation requirement (plan 02, P2)
core/rules.py format-tolerant readers + stable registry (R001-R004 plan-scoped,
R100-R102 universal per LCD L33822). payer_rules.json wrapped in the same
commit as both engine readers (coupling hazard closed). Every DocItem now
cites the rule that decided it; NOT_EVALUATED cites nothing. Independent
audit: SHIP (registry-drift test added per its L2 finding). 138 tests green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 05:10:52 -04:00

52 lines
1.8 KiB
Python

"""
rules.py
Signal — STTIL Solutions
Format-tolerant readers for payer_rules.json plus the stable rule-ID registry
(build plan 02, item P2; design: readiness-model-design-phase2 section 3.1).
A rule value may be FLAT (legacy: `"visit_renewal_days": 180`) or WRAPPED with
its citation (`"visit_renewal_days": {"value": 180, "rule_id": "R001"}`).
Both engines read through these helpers so the JSON format can carry citation
IDs without breaking either reader.
RULE IDS ARE STABLE — never change an ID after shipping. The ID names the rule
KIND; the plan type plus the value together are the citation.
"""
from __future__ import annotations
from typing import Optional
# Universal claim/coverage requirements per LCD L33822, independent of plan
# type. They live in code (no plan-type dependency) but carry rule IDs for
# citation consistency.
UNIVERSAL_RULE_IDS = {"swo": "R100", "visit": "R101", "diagnosis": "R102"}
# Plan-scoped keys in payer_rules.json and their registry IDs.
PLAN_KEY_RULE_IDS = {
"visit_renewal_days": "R001",
"refill_window_days": "R002",
"pa_required": "R003",
"pecos_required": "R004",
}
def rule_value(cfg: Optional[dict], key: str, default=None):
"""Read a rule value, accepting flat (180) and wrapped
({'value': 180, 'rule_id': 'R001'}) formats."""
if not cfg:
return default
raw = cfg.get(key, default)
if isinstance(raw, dict) and "value" in raw:
return raw["value"]
return raw
def rule_id_for(cfg: Optional[dict], key: str) -> Optional[str]:
"""The citation ID for a plan-scoped rule: from the wrapped config when
present, else the registry default for that key."""
raw = cfg.get(key) if cfg else None
if isinstance(raw, dict) and "rule_id" in raw:
return raw["rule_id"]
return PLAN_KEY_RULE_IDS.get(key)