Commonwealth Payer QA
Data QA · Commonwealth Pain & Spine · Phoenix pre-beta

Commonwealth payer QA

We checked Commonwealth's data end to end after the payer overhaul, then measured the open questions against prod. Payers resolve correctly. What goes wrong is downstream: which claims are in scope, how coverage and contracts are chosen, what pricing is told about each provider, and how money is read from remittances.

QA run 2026-09-28 (pricing fb830978) Follow-up 2026-09-29/30 (pricing eb602efd) Method full scans, read-only; aggregates only Branch cary/data-qa

The short version

Payer resolution is right: it agrees with the legacy system's independent mapping on 99.8% of encounters, is stable across runs, and matches legacy payer mix within 0.8 points. The problems are in the layers after it. The largest, by dollars:

−$7.30MMedicare expected is too high: the mid-level (NP, PA) reduction never applies, because rule sets and pricing name the provider classes differently
$7.4Mbilled on 13,110 claim families that are left out of Phoenix only because an entity isn't set up yet, and would otherwise be priced
−$8.45Mprimary paid missing from gold (−4.0%), because the wrong remittance wins on a line
−$31.4Mof provider-level adjustments (835 PLB) that never reach silver
295,509encounters ($81.4M billed) priced under the wrong contract, because location selectors don't exclude
102,048encounters ($19.1M billed) with real primary coverage dropped by a date filter

Unloaded fee schedules, the known gap, explain the rule sets that price nothing. They don't explain the wrong numbers above. "Expected" dollars are totals over priced candidates, so the effect on reported variance will be smaller.

How the data flows, and where it breaks

Each stage lists the problems that live in it. Ids link to the finding.

athenaSource EHR and billing. Keeps only current policy dates; puts provider-level adjustments on claim-less recordsF3N2F7
BronzeDaily copies of athena tables. Charges start late 2022; claims go back to 2018F7
SilverPayers resolved per insurance package; entities resolved to Phoenix's mastered ones; coverage, remittances, adjustmentsN1F3F2N5N2N6
RoutingEach encounter scored against the contract rule sets; the best score winsF4F4cN4
PricingThe scorer sends each candidate to pricing-service, which applies the rule set's calculationsF1N3F5F6
GoldEncounter and line facts, expected vs actual, scoped for usersF2N7
Omni · PhoenixDashboards and the productO1

Where each check stands

The QA checked seven layers top down; each assumes the one above is right. Status includes the follow-up measurements.

1
Structure
Keys unique, joins intact. Every check returned 0.
Pass
2
Payer resolution
99.79% agreement with legacy; stable; payer mix within 0.8 points. Small lob and rule gaps.
Pass
3
Coverage and scope
A date filter drops real coverage (F3). Unmastered entities drop whole claim families (N1).
Problems
4
Routing
Location selectors never exclude; 11.3% of dated encounters reach the wrong contract (F4).
Problems
5
Pricing
Provider type and procedure category never match (F1). Fee schedules not loaded (known gap).
Problems
6
Money
Billed and patient paid exact. Primary paid 4.0% low (F2). Provider-level adjustments missing (N2).
Problems
7
Presentation (Omni)
SQL totals match the lake; a likely home dashboard is broken; the semantic layer is unchecked (O1).
Partial
—
Guardrails (all layers)
An empty pricing run published (F5); failures carry no reason (F6); drops aren't counted (N1).
Problems
Scope

Which claims are in scope

Background: mastered entities. Customers set up their practices, locations, billing entities (TINs) and providers in Phoenix. The pipeline resolves each athena value to one of these entities. They let customers set canonical values, let several sources (athena, EDI) resolve to one entity, and decide what each user can see. This was wired up on 2026-09-29 (#6154) and is pre-beta. Commonwealth was understood to have one practice and one TIN.

N1Problemmeasured · master data

Unmastered entities drop claim families, silently

encounter.sql inner-joins the mastered-entity mapping, so a claim family whose TIN, department or provider isn't set up has no encounter, and its lines and money go with it. Excluding another business's claims can be correct scoping. But the join treats "not Commonwealth's" and "Commonwealth's, not set up yet" the same way, and reports neither. 82,522 families, $30.3M billed were dropped on the 2026-09-30 run.

What the dropped claim families areBilled dollars; the bar's color says whether they would be priced once included
Commonwealth's, would be pricedNeeds a scope decisionCorrectly excluded from payer pricing
"Would route": the family has a charge from 2023 on and a payer and line of business that some rule set routes. followup.md Q10.
Pay-to TINWhat it looks likeFamiliesBilled
…07241Commonwealth's main TIN, the one set up in Phoenix4.15M–
…49338CCAMP offices in the Carolinas, Feb–Nov 2025; same locations and providers as Commonwealth; 719 families carry both TINs8,016$3.41M
…11762TPI, since Nov 2025, alongside the main TIN at shared hospital and office departments825$0.49M
…97241One digit off the main TIN, at one department for three months of 2026: most likely a typo in athena1,347$0.48M
…9008227 Indiana Medicaid claims at Evansville ASC27$0.06M
…87252AllyMed: 17 offices and 18 providers of its own, none shared; auto and personal-injury payers6,728$16.74M

TINs shown by their last five digits.

Fix. Exclude only on an explicit decision. Left-join the entity mapping and record whether each entity resolved; exclude an encounter only when someone has marked its entity out of scope in Phoenix. Unresolved entities stay visible to admins and in the existing observed_* review tables, and a daily count shows what didn't resolve. Master Good Samaritan Hospital. For providers, fall back to the supervising provider rather than mastering nurses and staff. Ask Commonwealth which TINs are theirs and whether AllyMed is in scope.

F7Problemmeasured · scope

1.49M encounters have no service date

35% of fact_encounter has no service date and $0 billed. These are old, closed claims with no charges: athena's CLAIM table is extracted from 2018, but charges exist in bronze only from late 2022. They carry $2.25M of paid posted later, so deleting them would break the money reconciliation.

No-date encounters by claim creation year99.5% were created before 2023

Fix. Keep them, and filter every encounter count and "routed %" on service_date is not null. What counts as an encounter is a product decision (decision 4).

N7Gapcode · master data

Access scopes cover location and practice only

Each encounter's scopes hold its location and practice. Provider and TIN aren't in it, so a user can't yet be limited to certain providers or billing entities.

Coverage

Coverage

F3Problemverified and re-measured

A date filter on overwritten policy dates drops real coverage

encounter_coverage.sql keeps a coverage row only if the service date falls inside the policy's dates. athena keeps only a policy's current dates, and eligibility refreshes overwrite them. So 102,048 encounters ($19.06M billed) have a payer but no primary coverage row and can never be priced.

Evidence the coverage was realEncounters whose service date is before the policy's issue date
One policy, caught being overwrittenWellCare KY Medicaid; days from the first event (2025-08)
Policy created, issue dateday 0
First encounter (paid by the payer)day +10
Snapshots through Sep 21: no end date–
Sep 22: a refresh sets issue, expiration and cancellation today +416
Encounters now outside the one-day policy42 of 42

Fix. Remove the date predicate (every slot is a policy the claim names), and add a test that a payer on the encounter means a primary coverage row exists. Longer term, keep daily bronze snapshots of tables athena overwrites (decision 5).

Routing

Choosing the contract

F4Problemverified · partly a decision

Location selectors don't exclude, and ties go to the lowest id

Only coverage selectors (payer, line of business, plan) can rule a rule set out. A state or place-of-service selector only adds score, and between two rule sets that both score 1.00 the lower id wins. So a Kentucky-only contract prices Indiana encounters.

Routing verdict for every dated primary encounter2,613,284 encounters, $768.7M billed, checked against the contracts (QA run)
Wrong-contract casesEncounters priced under a contract that doesn't cover them
Not shown: WellCare MA (87,739) and Aetna MA (76,634) route to statutory Medicare, the wrong contract at the same rate.

Fix. Add state excludes to the Humana, Cigna KY, Aetna KY and Aetna Better Health rule sets; correct the Aetna IN, BCBS NC and Humana Medicaid windows; break ties on match score as well as consistency. Anthem MA is a contract question: does Anthem pay MA at its own rate (decision 3)?

F4cProblemmeasured

Medicare-ASC routes claims it can never price

Medicare-ASC is scored on every Medicare encounter and fails on 928k office and lab claims, which bury the real failures. The follow-up found no ASC facility claims in this feed: every claim at an ASC department is professional. It never wins today, so removing it from Commonwealth's routing costs nothing. With it gone, nearly every encounter has one candidate.

N4Problemmeasured · small

An uncalculated row can win

encounter_calculation.sql ranks candidates without regard to whether they calculated. 7,290 winners are uncalculated rows; in 3 encounters ($7,780) one beat a calculated candidate. Fix: rank calculated rows first.

Pricing

What pricing is told

The largest pricing errors come from vocabulary: the pipeline, the rule sets and pricing-service each name the same thing differently, and nothing checks.

F1Problemverified and measured

Provider type and procedure category never match

Effect on expected reimbursementPricing run eb602efd, over priced candidates
  • Mid-level reduction (F1c). All 16 rule sets name classifications the legacy way ("Physician Assistant"); pricing-service compares against "PA". Nothing matches, and since every line now has a provider, the step disappears without a trace. On Medicare, 698,719 NP and PA lines (66%) should take 85%.
  • Physician vs extender (F1b). Rule sets select "MD" and "DO", which are credentials; pricing compares taxonomy codes. Humana MA prices all 156,498 lines at the 76% extender rate; its 54,293 MD/DO lines should be at 95%.
  • Procedure category (F1d). Nothing supplies it, so category rules never fire. Humana MA's lab codes fail outright: 68,891 encounters with no calculation. Code ranges (ProcedureCode Between) already work and need no new data.
  • Undefined dimensions (F1e). Two rule criteria name dimensions pricing doesn't have (KYMedicaidBCCode, BCBSTNNetworkType).

Fix. Short term, an alias map in pricing-service from the long names to PA, NP and so on. Then a derived ProviderClass dimension from taxonomy, and rule sets that select on it. Who owns provider type is decision 2.

N6Problemmeasured · master data

Mastered providers aren't checked against NPPES

All 281 providers have a taxonomy, but some contradict their credential: registered-nurse taxonomies with NP or PA credentials, an "MD" with a student taxonomy. The pipelines can't read the NPPES data to check. Since provider class drives F1's two largest errors, provider data should be reconciled with NPPES when a provider is set up.

G1Known gap

Fee schedules aren't loaded

Every "percent of fees" calculation points at a placeholder schedule that resolves nothing and raises no error. With the Humana MA lab criterion, this is why 192,469 encounters have no calculation at all: every candidate failed. Anthem SC, Aetna IN and KY, Aetna Better Health and Humana Medicaid price little or nothing until schedules load.

Money

Reading money from remittances

F2Problemverified and measured

The wrong remittance wins, and paid is 4% low

For each line, gold keeps one remittance: the latest, then the highest id. Against athena's posted ledger, billed and patient paid match exactly, but primary allowed is 2.9% low (−$7.28M) and primary paid 4.0% low (−$8.45M), every closed month.

Gold minus bronze, by service monthPercent gap, primary payer
Primary allowedPrimary paidStill adjudicating
Show the monthly table
Why the wrong remittance winsLines, all service dates, follow-up run
Two ways to fix the trailing $0 caseLines whose winner is a $0 remittance after a payment
The QA's rule ("drop a $0 remittance after a payment") also restores payments that were really taken back. The codes rule drops a $0 remittance only when all its codes are duplicate or informational.

Fix. Only applied remittances compete; a reversal loses to a replacement in its own batch; a $0 remittance is dropped only when all its codes are duplicate or informational (18, B13, B11, REFUND). Sums over reversal rows must negate them. Also decide what paid, allowed and denied should mean (decision 1).

N5Problemmeasured

Adjustment codes are misread, which inflates and inverts denied

The reason-code parse takes the first digits of any code. Remark code MA18 ("forwarded to supplemental insurer", 464,126 kicks) becomes reason 18, "duplicate". 180 athena codes that wrap a standard code ($12.07M) parse to the wrong reason: OAA1CONTRACT becomes 1, deductible. Separately, when a reversal wins, denied comes out negative (−$4.2M), and a trailing $0 duplicate adds $1.33M of denied on lines that were paid.

Fix. Recognize remark codes first; parse a group and reason only at the start of the code; map athena's money-carrying wrapper codes by hand (their suffixes DENIED, INFORM, CONTRACT, NORC look like athena's own category). No denied on a reversal winner.

N2Problemmeasured

Provider-level adjustments never reach silver

athena writes the 835's provider-level adjustments (overpayment recoveries, forward balances) as "batch exception" records with no claim. Silver drops them, −$31.4M, and remittance_provider_adjustment reads four columns athena leaves empty, so only 6 of its 42,872 rows have an amount. In 23,839 batches the check is $0: the payer reports claims as paid and one adjustment takes it all back.

Fix. Read the amount from payment, keep these as their own fact, and exclude them from the line-level remittance ranking.

Guardrails

Failures nobody saw

F5Problemmeasured

An empty pricing run published, twice

A routing change deployed before the rewritten rule sets landed. Scoring found nothing, reported success, and gold published one all-NULL row. No check is blocking.

fact_encounter_variance rows by saved versionUTC
F6Problemverified

Failed calculations carry no reason

All 1.18M FAILED quarantine rows have errors = []. Pricing-service returns FAILED without an error when no charge has a rate, and the scorer drops the per-charge outcomes.

N3Problemverified in code

One bad request can fail a contract for a whole batch

The scorer sends a contract's rules once per streaming call and refers back to them by label. Pricing-service checks the charge before registering the rules, so if the defining request has a bad charge, every later request for that contract fails: 40 encounters from one missing facility key in the QA run. Fix: register the rules first.

O1Partialmeasured read-only

Omni

SQL through the Commonwealth model matches the lake exactly. But a dashboard that is probably Phoenix's home page fails validation on all 7 tiles, the AI chat topics still describe the old payer field, 12 documents read removed tables, and encounter counts come from lines, which misses encounters with no lines (F7). Omni's semantic layer hasn't been checked as a Commonwealth user.

Kinds of problems

Grouped by how they go wrong, each kind suggests one guard that would have caught the whole class. The first two hold most of the money, and neither shows in totals or row counts.

How it goes wrongProblemsThe guard that catches the class
One field, two vocabularies: sender and receiver spell values differentlyF1b, F1c, F1e, N5, N6, claim_form sent as bill typeChecked vocabularies when a rule set is saved; a contract test per interface
No match treated as a decision: a missing value matches, counts as zero, or excludesF1, null lob in F4, negative denied, N1, F6, G1Make "unknown" a visible outcome; exclude only on an explicit decision
Picking one winner badlyF2, F4 ties, N4Report ties; use explicit priority, not id order
A filter or join that drops real rowsF3, N1, N2Count checks between layers
Related extracts disagree on scopeF7, POS read from different columnsOne stated window and grain per model
Publishing or failing without a traceF5, F6, N3A short list of blocking checks; errors that name their cause
By owner
LayerProblemsOwner
What athena doesF3, F7, N2The pipeline has to model it
Master data and stewardshipN1, N6, N7Phoenix and pipeline together
Pipeline modelingF2, N5, F3, F7, N2, N4Data engineering
Contracts between systemsF1b, F1c, F1e, N3, F6Each interface's owner
Routing designF4Cary
Rule-set contentF1d, F4 rule sets, F4cRule-set author, in payer-monitor
Reference dataG1, procedure categories, 2024 conversion factorData acquisition
GuardrailsF5, F6Platform
PresentationO1Omni

Decisions needed

These turn on what a number should mean or who owns a vocabulary, not on a line of code.

  1. What paid, allowed and denied mean in gold. athena has three notions of paid: what the payer reported, what was posted to the ledger, and cash after provider-level adjustments.

    Recommendation: encounter paid follows the posted ledger; provider-level adjustments get their own fact; denied excludes duplicate and informational codes. For the product team.

  2. Who owns provider type. Phoenix stores a free-text credential; rule sets say "MD" or "Physician Assistant"; pricing classifies by taxonomy.

    Recommendation: NPPES taxonomy is the source of truth, reconciled when a provider is set up; pricing derives a provider class; rule sets select on the class.

  3. How routing chooses a contract. Should location exclude? Explicit priority instead of id order? Anthem MA's rate (250,525 encounters, $65.5M billed), BlueCard, HealthSpring from 2026.

    Recommendation: settle Anthem MA with the contract owner first, then gate-plus-priority. A type-checked selector language such as CEL is one way to catch mistakes when rule sets are saved.

  4. What counts as an encounter. Old no-date claims, dropped claim families and line-based counts each change the denominator.

    Recommendation: one definition ("in scope, with a charge in the extract window"), one flag, used by every count.

  5. Keeping history athena overwrites. Policy dates, package settings and probably provider details change in place.

    Recommendation: keep the daily bronze snapshots from now on; the model that uses them can come later.

  6. Which data problems block publishing. Today every check is non-blocking on purpose.

    Recommendation: block on four things (pricing run not empty, gold keys not null, every in-scope claim family has an encounter, every encounter with a payer has primary coverage) and report the rest daily.

Ready to fix

Clear enough to implement now; each is a few lines. Details and file references are in payer-qa/fixes.md.

FixWhereFor
Accept the legacy classification names (alias map)pricing-serviceF1c, −$7.30M
Remove the policy date predicate; add a coverage testcommonwealth silverF3
Applied-only, same-batch reversal and code-based rules for the winning remittancecommonwealth silverF2
Parse remark and wrapper codes correctly; no denied on a reversalcommonwealth silverN5
Read provider-level adjustment amounts from paymentcommonwealth silverN2
Register rules before validating the chargepricing-serviceN3
Rank calculated rows firstcommonwealth silverN4
Fail the pricing step on an empty run; not-null keys in goldDagster, dbtF5
Fill errors on FAILED; keep per-charge outcomespricing-service, scorerF6
Master Good Samaritan Hospital; add confirmed TINsPhoenix, crosswalkN1
Take Medicare-ASC out of Commonwealth's routing; state excludes; window fixesrule setsF4, F4c
WellCare KY and Passport as Medicaid; Carolina Complete, QualChoice and UHC subsidiariespayer rulespayer resolution
Reference data the fixes need
  • Already available: CMS fee schedules, lab, drug, DME and ASC tables in pricing-service's CMS lake; NPPES and NUCC taxonomy; the RHAIL CARC/RARC list; the legacy CARC rollup; CPT section ranges.
  • Missing: procedure categories (code ranges, CMS's RBCS, or the legacy dimension tree); payer fee schedules (Kentucky Medicaid, commercial contracts); athena's own adjustment codes; NPPES read access for the pipelines.

What passed

Payer resolution was checked against an oracle built independently of the new rules: the legacy system's mapping of the same insurance packages. Where legacy has an answer, the two agree on 99.79% of encounters.

Payer share of encounters, new minus legacyPercentage points by service year; Anthem and BCBS combined because legacy mixes them
New is slightly higher because legacy's mapping stopped being maintained in 2025-08. No payer loses share to "none", which is what a resolution bug would look like.

Open questions and sources

For Commonwealth

  • Are the CCAMP (…49338), TPI (…11762) and Evansville ASC (…90082) TINs theirs?
  • Is …97241 a mistyped …07241?
  • Is AllyMed in scope for Phoenix?
  • Is Good Samaritan Hospital an active location?
  • Their APM status (the 2026 conversion factor depends on it).

For us

  • Do INFORM and REMITRECEIVED count as informational?
  • Where do provider-level adjustments land in gold?
  • How does a steward mark an entity out of scope?
  • Anthem MA's rate, BlueCard, HealthSpring from 2026, Humana's DME rates.

Everything here comes from documents on the branch, under pipelines/projects/commonwealth/docs/: payer-qa-plan.md, payer-qa-results.md, payer-qa-handoff.md, and in payer-qa/: fixes.md, codes.md, followup.md, taxonomy.md, discussion.md, plus the per-workstream files with queries and object pins. All figures are aggregates; no patient-level data appears here.