EHR / Referral Quality-Governance Packet Skill
When to use
Use this skill whenever a task asks you to produce a normalized JSON packet from a read-only
EHR/referral environment and supplies an answer_template.json describing the required shape.
The task families this covers:
- Duplicate-chart merge readiness packets — verify a duplicate candidate, pick canonical
target/source, compute active clinical-list unions, capture identity match/conflict signals,
and gather document/audit/provider contact evidence.
- Referral coordination packets — reconcile a referral with the patient's active chart,
validate the ICD-10 code against the narrative, check allergy/document/authorization readiness,
and choose normalized referral-letter field values.
- Care-transition packets — select the most relevant recent handoff encounters for a service
line, attach the latest immunization, applicable disclosure, and risk flags.
- Duplicate + ServiceRequest reviews — decide a duplicate-review disposition and validate a
draft ServiceRequest's codes, provider routing, and SBAR coverage.
- Batch referral audits — over a referral batch, flag invalid/out-of-range codes, laterality
or narrative mismatches, duplicate groups, insurance anomalies, follow-up queues, tiered
action plans, and summary counts.
Core procedure (every task)
1. Read the prompt, the answer template, and any request payload
- The prompt names the case objects (candidate IDs, patient IDs, referral IDs, batch IDs,
provider IDs) and the goal. Copy these IDs verbatim — they are the join keys for every fetch.
- The answer template is the contract. Read every field's type and
enum/allowed_values
before fetching anything. Note which arrays are sets (set_semantics: true or "evaluation
treats as a set") vs. ordered, and the required ordering ("sort ascending", "newest to oldest").
- Where a request payload exists (e.g.
merge_packet_request.json), use its requested_outputs
as a checklist of sections to populate.
2. Pull only what the prompt names, then fan out by the template's sections
Fetch the named object first, then the patient/provider/condition/etc. records the template's
fields imply. Do not fetch unrelated patients "in case" — the prompts are scoped, and the
environment contains distractor records deliberately planted to test filtering.
Common fan-out per patient: conditions, medications, allergies, encounters,
immunizations, documents, disclosures, service-requests. Per referral/duplicate/service
request: the object itself plus the referenced patient and provider. For codes: the ICD-10 and
service-code lookup endpoints.
Cache the raw JSON locally while working so re-classification rounds don't re-hit the API.
3. Filter by status, then normalize to keys
- Active-list unions use only records with
status: "active". Records with status: "inactive" (often a legacy_import/external_note of the other laterality) are
excluded distractors, not part of the union — list them in the excluded_distractors block
when the template asks for it.
- Use the record's
normalized_key (not the free-text name or code) as the set element. A
condition appearing twice (e.g. on problem_list and pcp_note) contributes one key.
- Duplicate-candidate
merge_preview lists are usually a subset of the true active union.
Reconcile against the per-patient active endpoints and record the keys present in the endpoints
but missing from the preview in any active_list_reconciliation / "added from active endpoints"
field. The authoritative source is the patient active-list endpoints, not the preview.
4. Classify identity / duplicate signals
match_signals and conflict_signals come straight from the duplicate-candidate record —
copy them, do not re-derive or relabel.
- A
name_variant signal is a match, not a conflict — do not list name variation under
conflicts. Treat only the candidate's listed conflict signals (e.g. address_abbreviation,
different_given_name, opposite_laterality_problem) as conflicts.
- Disposition mapping (the single highest-value judgment call):
confirmed_duplicate / merge → set merge_target/merge_source to the canonical pair and
emit merge_ready.
needs_review / mixed match+conflict signals (including an opposite_laterality_problem) →
needs_review + review_hold, and leave merge_target/merge_source null (no merge is
committed during a hold). Do not auto-reject to do_not_merge on the strength of an
opposite-laterality conflict alone, and do not populate a tentative target during a hold.
- A single minor conflict (e.g.
address_abbreviation) on an otherwise strong match does not
flip a merge_ready disposition to merge_ready_with_conflict_review — keep it plain
merge_ready/ready with manual_review_required: false. Escalating a minor conflict to a
review-note disposition is incorrect; only the candidate's own needs_review status warrants
a hold.
- Canonical target = the record with
canonical_status: "active" and canonical_patient_id: null;
source = the record with canonical_status: "duplicate" (its canonical_patient_id points back
to the target).
5. Validate codes against the ICD-10 directory
For each diagnosis/service code in scope, call the lookup endpoint and read chapter,
expected_terms, and requires_laterality. Then classify (this is the second highest-value
judgment call):
- Code not in the directory →
unknown_code (invalid).
- Code valid but its
chapter is outside the service line's expected chapters (e.g. a
Respiratory J-code on an orthopedic batch; orthopedic = Musculoskeletal + Injury) →
out_of_range_chapter.
- Code valid and in-chapter: compare the referral narrative to the directory
expected_terms
and to the code's laterality:
- narrative laterality token (
left/right) conflicts with the code's laterality token →
laterality_mismatch.
- none of the
expected_terms appear in the narrative → narrative_mismatch.
- code
requires_laterality: true but the narrative carries no laterality token and is the
same anatomical condition → missing_laterality. Do not append missing_laterality when
the narrative is about a different body region entirely (that is a narrative_mismatch only).
matches_patient_evidence / referral_relevant: true only when the patient's own active
conditions/encounters contain that code or a same-site condition. For a code-vs-narrative
mismatch on a narrative field (e.g. "HFpEF" vs a "diastolic HF" code), prefer the literal
directory text: if the term does not appear, valid_but_narrative_mismatch with
narrative_match: false is the safer classification than forcing a match.
6. Map clinical records to risk flags and readiness enums
- Risk flags and readiness enums are closed lists. Only emit a flag/enum value that appears in
the template's
allowed_values/enum. If nothing fits, prefer the enum whose name most
literally matches the environment signal over an invented other.
- Drive readiness from the most specific environment signal available: a
coordination_note
like "confirm … details before letter" means that readiness dimension is
incomplete_needs_clarification regardless of whether the sub-records look complete. Document
"received" lists on a referral are authoritative for received booleans.
- Keep the readiness story internally consistent: the
overall_readiness, the
blocking_issues set, and any letter-field *_choice must all point at the same blocker. Don't
emit hold_for_allergy_clarification in one place and ready_to_send in another.
7. Encounter / referral selection
- "Most relevant recent handoff encounters" for a service line: prefer the encounters on the
surgical-workup / care-transition trajectory for the operated joint — the linked series of
visits that track that joint's osteoarthritis and the preoperative plan — newest to oldest,
capped at the requested count. Exclude clearly non-handoff visits (geriatric/memory, unrelated
telehealth) and stale out-of-window follow-ups. Recency alone is not sufficient — a fresher
unrelated visit should not displace a relevant older workup visit. Selecting the N newest visits
while excluding only an obviously off-topic one is the wrong rule; the joint-workup trajectory
is the right one.
- Record both
selected_encounter_ids (in display order) and excluded_encounter_ids (all
reviewed-but-excluded, sorted ascending) when the template asks.
8. Batch audits — classify every referral, then aggregate
- Build one classification record per referral (chapter validity, mismatch types, document
presence, authorization status, urgency, receiving provider) before assembling any section.
Derive every count and queue from those records programmatically so counts and arrays cannot
drift apart.
- Tiering rule that fit the data:
- Tier 1
urgent_coding_or_duplicate_blocker: urgent urgency, OR the duplicate-resubmission
row, OR an invalid/out-of-range code.
- Tier 3
administrative_document_completion: routine, clinically validated (no mismatch,
not invalid), authorization approved, but missing a document (office note or imaging).
- Tier 2
routine_coding_auth_or_document_blocker: all other routine referrals (mismatch,
auth-missing, or other document blocker).
- Duplicate groups: same
patient_id with >1 referral → one same_patient_resubmission group,
consolidated under the original; the resubmission row (often an ID ending -DUP or flagged
"duplicate resubmission") is the Tier-1 duplicate blocker; the original stays a separate
clinical review.
- Insurance anomalies: a shared
insurance_id across different patients is a
shared_insurance_different_patients anomaly with disposition verify…_do_not_merge. The
same-patient separate-clinical-referrals case belongs to duplicate tiering, not the insurance
anomaly list — don't double-count.
- Follow-up queues are keyed by referral_id, sorted ascending.
authorization_missing and
authorization_pending come from the referral's authorization_status
(missing/pending). records_request = referrals missing the office-note document.
imaging_follow_up = referrals missing imaging or flagged "imaging pending" in a
coordination note — check both signals.
9. Emit normalized JSON only
- Output exactly one JSON object conforming to the template, with every required top-level key.
No prose outside the object.
- Sort all set/ID arrays as the template specifies (usually ascending; encounters often newest to
oldest; objects in arrays sorted by their ID unless stated).
- Use
null (not omitted, not empty string) for nullable fields the template marks
string | null — e.g. merge target/source during a review hold, or a missing document's
document_id.
- Dates as
YYYY-MM-DD. Booleans as JSON true/false.
Cross-task pitfalls observed
- Do not escalate minor conflicts. A single address-abbreviation or name-variant signal on a
strong match keeps
merge_ready; only the candidate's own status: needs_review justifies a
review_hold.
- Do not auto-populate merge target/source on a hold. Review-hold means no merge is decided;
both stay
null.
- Do not trust the duplicate
merge_preview as the full clinical picture. Re-derive active
unions from the per-patient endpoints and reconcile the delta.
- Do not mix readiness stories. Pick one dominant blocker and align every readiness/choice
field to it.
- Do not over-flag
missing_laterality when the narrative is about a different body region —
that is narrative_mismatch only.
- Do not let counts drift from arrays. Aggregate counts from the same classification records
that produce the arrays.
- Prefer the literal, template-aligned enum value. When a classification is genuinely
ambiguous, choose the allowed value whose name most literally matches the environment's explicit
signals (status fields, coordination notes, resubmission ID markers) over a reasonable-but-invented
classification. Closed-enum and selection fields are where internally-consistent candidates most
often diverge from the intended answer, so be strict and literal there.
Scope note
This skill describes how to read the prompt, gather and filter environment data, classify it, and
shape the normalized JSON output. It is instance-independent: it carries no specific task IDs,
answer values, or environment addresses, and it applies to any EHR-quality or referral-coordination
packet task that provides an answer template.
1---2name: ehr-referral-quality-packets3description: Produce normalized JSON "quality-governance packets" from a read-only EHR/referral API — duplicate-chart merge packets, referral coordination packets, care-transition packets, duplicate+service-request reviews, and batch referral audits. Read BEFORE producing any answer JSON for an EHR-quality or referral-coordination task that supplies an answer_template.json.4---56# EHR / Referral Quality-Governance Packet Skill78## When to use910Use this skill whenever a task asks you to produce a **normalized JSON packet** from a read-only11EHR/referral environment and supplies an `answer_template.json` describing the required shape.12The task families this covers:1314- **Duplicate-chart merge readiness packets** — verify a duplicate candidate, pick canonical15 target/source, compute active clinical-list unions, capture identity match/conflict signals,16 and gather document/audit/provider contact evidence.17- **Referral coordination packets** — reconcile a referral with the patient's active chart,18 validate the ICD-10 code against the narrative, check allergy/document/authorization readiness,19 and choose normalized referral-letter field values.20- **Care-transition packets** — select the most relevant recent handoff encounters for a service21 line, attach the latest immunization, applicable disclosure, and risk flags.22- **Duplicate + ServiceRequest reviews** — decide a duplicate-review disposition and validate a23 draft ServiceRequest's codes, provider routing, and SBAR coverage.24- **Batch referral audits** — over a referral batch, flag invalid/out-of-range codes, laterality25 or narrative mismatches, duplicate groups, insurance anomalies, follow-up queues, tiered26 action plans, and summary counts.2728## Core procedure (every task)2930### 1. Read the prompt, the answer template, and any request payload31- The **prompt** names the case objects (candidate IDs, patient IDs, referral IDs, batch IDs,32 provider IDs) and the goal. Copy these IDs verbatim — they are the join keys for every fetch.33- The **answer template** is the contract. Read every field's type and `enum`/`allowed_values`34 before fetching anything. Note which arrays are **sets** (`set_semantics: true` or "evaluation35 treats as a set") vs. ordered, and the required ordering ("sort ascending", "newest to oldest").36- Where a request payload exists (e.g. `merge_packet_request.json`), use its `requested_outputs`37 as a checklist of sections to populate.3839### 2. Pull only what the prompt names, then fan out by the template's sections40Fetch the named object first, then the patient/provider/condition/etc. records the template's41fields imply. Do **not** fetch unrelated patients "in case" — the prompts are scoped, and the42environment contains distractor records deliberately planted to test filtering.4344Common fan-out per patient: `conditions`, `medications`, `allergies`, `encounters`,45`immunizations`, `documents`, `disclosures`, `service-requests`. Per referral/duplicate/service46request: the object itself plus the referenced patient and provider. For codes: the ICD-10 and47service-code lookup endpoints.4849Cache the raw JSON locally while working so re-classification rounds don't re-hit the API.5051### 3. Filter by status, then normalize to keys52- **Active-list unions** use only records with `status: "active"`. Records with `status:53 "inactive"` (often a `legacy_import`/`external_note` of the *other* laterality) are54 **excluded distractors**, not part of the union — list them in the `excluded_distractors` block55 when the template asks for it.56- Use the record's `normalized_key` (not the free-text name or code) as the set element. A57 condition appearing twice (e.g. on `problem_list` and `pcp_note`) contributes **one** key.58- Duplicate-candidate `merge_preview` lists are usually a **subset** of the true active union.59 Reconcile against the per-patient active endpoints and record the keys present in the endpoints60 but missing from the preview in any `active_list_reconciliation` / "added from active endpoints"61 field. The authoritative source is the patient active-list endpoints, not the preview.6263### 4. Classify identity / duplicate signals64- `match_signals` and `conflict_signals` come **straight from the duplicate-candidate record** —65 copy them, do not re-derive or relabel.66- A `name_variant` signal is a **match**, not a conflict — do not list name variation under67 conflicts. Treat only the candidate's listed conflict signals (e.g. `address_abbreviation`,68 `different_given_name`, `opposite_laterality_problem`) as conflicts.69- **Disposition mapping** (the single highest-value judgment call):70 - `confirmed_duplicate` / `merge` → set `merge_target`/`merge_source` to the canonical pair and71 emit `merge_ready`.72 - `needs_review` / mixed match+conflict signals (including an `opposite_laterality_problem`) →73 `needs_review` + `review_hold`, and leave `merge_target`/`merge_source` **null** (no merge is74 committed during a hold). Do **not** auto-reject to `do_not_merge` on the strength of an75 opposite-laterality conflict alone, and do **not** populate a tentative target during a hold.76 - A single minor conflict (e.g. `address_abbreviation`) on an otherwise strong match does **not**77 flip a `merge_ready` disposition to `merge_ready_with_conflict_review` — keep it plain78 `merge_ready`/`ready` with `manual_review_required: false`. Escalating a minor conflict to a79 review-note disposition is incorrect; only the candidate's own `needs_review` status warrants80 a hold.81- Canonical target = the record with `canonical_status: "active"` and `canonical_patient_id: null`;82 source = the record with `canonical_status: "duplicate"` (its `canonical_patient_id` points back83 to the target).8485### 5. Validate codes against the ICD-10 directory86For each diagnosis/service code in scope, call the lookup endpoint and read `chapter`,87`expected_terms`, and `requires_laterality`. Then classify (this is the second highest-value88judgment call):89- Code not in the directory → `unknown_code` (invalid).90- Code valid but its `chapter` is outside the service line's expected chapters (e.g. a91 `Respiratory` J-code on an orthopedic batch; orthopedic = `Musculoskeletal` + `Injury`) →92 `out_of_range_chapter`.93- Code valid and in-chapter: compare the **referral narrative** to the directory `expected_terms`94 and to the code's laterality:95 - narrative laterality token (`left`/`right`) **conflicts** with the code's laterality token →96 `laterality_mismatch`.97 - none of the `expected_terms` appear in the narrative → `narrative_mismatch`.98 - code `requires_laterality: true` but the narrative carries no laterality token **and** is the99 same anatomical condition → `missing_laterality`. Do **not** append `missing_laterality` when100 the narrative is about a different body region entirely (that is a `narrative_mismatch` only).101- `matches_patient_evidence` / `referral_relevant`: true only when the patient's own active102 conditions/encounters contain that code or a same-site condition. For a code-vs-narrative103 mismatch on a *narrative* field (e.g. "HFpEF" vs a "diastolic HF" code), prefer the literal104 directory text: if the term does not appear, `valid_but_narrative_mismatch` with105 `narrative_match: false` is the safer classification than forcing a match.106107### 6. Map clinical records to risk flags and readiness enums108- Risk flags and readiness enums are **closed lists**. Only emit a flag/enum value that appears in109 the template's `allowed_values`/`enum`. If nothing fits, prefer the enum whose name most110 literally matches the environment signal over an invented `other`.111- Drive readiness from the **most specific** environment signal available: a `coordination_note`112 like "confirm … details before letter" means that readiness dimension is113 `incomplete_needs_clarification` regardless of whether the sub-records look complete. Document114 "received" lists on a referral are authoritative for `received` booleans.115- Keep the readiness story **internally consistent**: the `overall_readiness`, the116 `blocking_issues` set, and any letter-field `*_choice` must all point at the same blocker. Don't117 emit `hold_for_allergy_clarification` in one place and `ready_to_send` in another.118119### 7. Encounter / referral selection120- "Most relevant recent handoff encounters" for a service line: prefer the encounters on the121 **surgical-workup / care-transition trajectory** for the operated joint — the linked series of122 visits that track that joint's osteoarthritis and the preoperative plan — newest to oldest,123 capped at the requested count. Exclude clearly non-handoff visits (geriatric/memory, unrelated124 telehealth) and stale out-of-window follow-ups. Recency alone is **not** sufficient — a fresher125 unrelated visit should not displace a relevant older workup visit. Selecting the N newest visits126 while excluding only an obviously off-topic one is the wrong rule; the joint-workup trajectory127 is the right one.128- Record both `selected_encounter_ids` (in display order) and `excluded_encounter_ids` (all129 reviewed-but-excluded, sorted ascending) when the template asks.130131### 8. Batch audits — classify every referral, then aggregate132- Build one classification record per referral (chapter validity, mismatch types, document133 presence, authorization status, urgency, receiving provider) **before** assembling any section.134 Derive every count and queue from those records programmatically so counts and arrays cannot135 drift apart.136- Tiering rule that fit the data:137 - **Tier 1** `urgent_coding_or_duplicate_blocker`: urgent urgency, OR the duplicate-resubmission138 row, OR an invalid/out-of-range code.139 - **Tier 3** `administrative_document_completion`: routine, clinically validated (no mismatch,140 not invalid), authorization approved, but missing a document (office note or imaging).141 - **Tier 2** `routine_coding_auth_or_document_blocker`: all other routine referrals (mismatch,142 auth-missing, or other document blocker).143- Duplicate groups: same `patient_id` with >1 referral → one `same_patient_resubmission` group,144 consolidated under the original; the resubmission row (often an ID ending `-DUP` or flagged145 "duplicate resubmission") is the Tier-1 duplicate blocker; the original stays a separate146 clinical review.147- Insurance anomalies: a shared `insurance_id` across *different* patients is a148 `shared_insurance_different_patients` anomaly with disposition `verify…_do_not_merge`. The149 same-patient separate-clinical-referrals case belongs to duplicate tiering, not the insurance150 anomaly list — don't double-count.151- Follow-up queues are keyed by **referral_id**, sorted ascending. `authorization_missing` and152 `authorization_pending` come from the referral's `authorization_status`153 (`missing`/`pending`). `records_request` = referrals missing the office-note document.154 `imaging_follow_up` = referrals missing imaging **or** flagged "imaging pending" in a155 coordination note — check both signals.156157### 9. Emit normalized JSON only158- Output exactly one JSON object conforming to the template, with every required top-level key.159 No prose outside the object.160- Sort all set/ID arrays as the template specifies (usually ascending; encounters often newest to161 oldest; objects in arrays sorted by their ID unless stated).162- Use `null` (not omitted, not empty string) for nullable fields the template marks163 `string | null` — e.g. merge target/source during a review hold, or a missing document's164 `document_id`.165- Dates as `YYYY-MM-DD`. Booleans as JSON `true`/`false`.166167## Cross-task pitfalls observed168- **Do not escalate minor conflicts.** A single address-abbreviation or name-variant signal on a169 strong match keeps `merge_ready`; only the candidate's own `status: needs_review` justifies a170 `review_hold`.171- **Do not auto-populate merge target/source on a hold.** Review-hold means no merge is decided;172 both stay `null`.173- **Do not trust the duplicate `merge_preview` as the full clinical picture.** Re-derive active174 unions from the per-patient endpoints and reconcile the delta.175- **Do not mix readiness stories.** Pick one dominant blocker and align every readiness/choice176 field to it.177- **Do not over-flag `missing_laterality`** when the narrative is about a different body region —178 that is `narrative_mismatch` only.179- **Do not let counts drift from arrays.** Aggregate counts from the same classification records180 that produce the arrays.181- **Prefer the literal, template-aligned enum value.** When a classification is genuinely182 ambiguous, choose the allowed value whose name most literally matches the environment's explicit183 signals (status fields, coordination notes, resubmission ID markers) over a reasonable-but-invented184 classification. Closed-enum and selection fields are where internally-consistent candidates most185 often diverge from the intended answer, so be strict and literal there.186187## Scope note188This skill describes how to read the prompt, gather and filter environment data, classify it, and189shape the normalized JSON output. It is instance-independent: it carries no specific task IDs,190answer values, or environment addresses, and it applies to any EHR-quality or referral-coordination191packet task that provides an answer template.