EHR governance packet builder
You are given a task folder that contains a prompt.txt, a input/payloads/answer_template.json, sometimes
extra request payloads, and an environment_access.md. Your job is to query a read-only EHR
"quality-governance" API and emit one normalized JSON object that conforms exactly to the answer template.
No prose, no SOP/narrative text — JSON only.
Every task in this family is the same shape: read the contract, gather evidence from the API, normalize it,
classify a disposition/readiness, and assemble stable IDs into the template's structure. The templates and
case objects change; the operating rules below do not.
1. Read the contract before touching the API
prompt.txt — extract the case objects (the IDs you must center on): patient_id(s), duplicate
candidate_id, referral_id, ServiceRequest id, batch_id, recipient provider id, and the required
task_id. Note the service line (cardiology / orthopedics / …) and what deliverables are requested.
input/payloads/answer_template.json — this is the authoritative contract. Enumerate its
top-level required keys, every field, every enum's allowed_values, and every ordering rule. Your
output must contain exactly these keys with these types. Never invent enum values — pick only from the
template's allowed list. If the template states a required_value for task_id, emit it verbatim.
- Any other payload (e.g. a
*_request.json) — it restates the case objects and the requested outputs;
use it to confirm scope, not as a data source.
environment_access.md — read the base URL and the allow-listed endpoints from here. Do not assume
a URL; use the one in the file. Credentials are typically none. This file is only for network access.
Read references/api_reference.md for the endpoint families and response conventions, and
references/normalization_rules.md for the field-by-field normalization and classification ladders. Read
references/task_archetypes.md to see how the five recurring deliverables map onto the same procedure.
2. Gather evidence from the API (read-only GET)
- Use detail endpoints for named objects (
/api/patients/{id}, /api/duplicates/{candidate_id},
/api/referrals/{referral_id}, /api/icd10/{code}, /api/providers/{id}, /api/service-codes/{code}).
- For a patient's clinical picture, pull the per-patient list endpoints you actually need:
conditions,
medications, allergies, encounters, immunizations, documents, disclosures, service-requests.
- Query-string filters are ignored by this API.
GET /api/referrals?batch_id=X returns the whole
collection, not the batch. To scope a batch (or find records by name/insurance/etc.), fetch the full
collection and filter client-side on the field. Same for /api/patients.
- Unknown IDs return HTTP 404 with
{"error":..., "status":404}. Treat a 404 on a code lookup as
"unknown/invalid code" evidence, not as a crash.
- Response bodies wrap lists under a named key (
{"conditions":[...]}, {"referrals":[...]},
{"duplicate_candidates":[...]}); a few (audit-logs) come back as bare arrays. Handle both.
3. Normalize (the reusable rules)
These rules recur across every task; apply the ones the template asks for.
- Active-only lists. For condition/medication/allergy unions, keep only records with
status == "active".
Drop inactive, resolved, entered-in-error. This is the primary distractor filter.
normalized_key is the canonical identity. Build clinical "key unions" from the normalized_key
field, deduped across duplicate rows and across both patients in a merge. Emit as a set: unique +
sorted per the template (usually alphabetical/ascending).
- Patient endpoints beat any preview. When a duplicate candidate carries a
merge_preview of active
keys, the per-patient active-list endpoints are authoritative. Reconcile: any active key present in the
patient endpoints but missing from the preview must be added; report it if the template has a
reconciliation/"added_from_active_endpoints" section.
- Signals: map to the template's vocabulary. Take
match_signals / conflict_signals from the duplicate
candidate. If the template gives an allowed_values enum for signals, emit only values from that enum
(mapping raw labels to it); if it just says "signal labels sorted alphabetically", emit the raw labels sorted.
- Evidence = stable IDs, never prose. Cite
document_id, audit_id, encounter_id, immunization_id,
disclosure_id. Select documents by status (prefer final; exclude preliminary/cancelled) and by
the packet's document policy (e.g. identity/external-continuity docs only → include
identity_verification and external notes, exclude internal chart_summary; a referral packet wants the
echocardiogram + office_note). List unrelated docs/audit rows under an "excluded_distractors" section if
the template has one.
- Providers by id. Resolve the receiving/specialist/owner provider from the id on the referral /
ServiceRequest / disclosure, then copy the directory record's exact fields (
name, role, service_line,
facility, phone, fax). Confirm the service_line matches the requested specialty.
- Codes. Validate a diagnosis
code via /api/icd10/{code}: compare chapter to the expected service
chapter, and if requires_laterality check the narrative against expected_terms (→ laterality_mismatch
/ narrative_mismatch / missing_laterality). Validate a service_code via /api/service-codes/{code}:
it must exist, be active, and its service_line match the performer.
- Dispositions & readiness are decided from the evidence, then mapped onto the template's enum ladder
(blocking conflicts,
null merge target/source, missing docs, missing/pending authorization, incomplete
allergy, disclosure not permitted, invalid code all push toward "review"/"hold"/"do_not_merge"). The exact
ladders per archetype are in references/normalization_rules.md.
- Counts are integers, dates are
YYYY-MM-DD, booleans are real booleans, and use null only where the
template's type union allows it.
4. Assemble & validate output
- Build the object in the template's key order; include every required top-level key.
- Apply each array's stated ordering (sets → dedupe + sort as specified; object arrays → sort by the named
field; "newest→oldest" where stated). Default to ascending/alphabetical when a set has no explicit rule.
- Re-check every enum value against the template's
allowed_values; re-check task_id's required value.
- Confirm no narrative/SOP text leaked into any field, and that the whole payload is a single valid JSON
object. Output JSON only.
5. Common distractors to exclude
Inactive/resolved/entered-in-error clinical rows · duplicate patients who merely share a name · unrelated
merge/audit log rows for other charts · internal chart_summary documents when an identity/continuity policy
applies · preview key-lists that disagree with the active endpoints · cross-patient laterality conflicts
(e.g. right-knee vs left-knee) that mean "not a true duplicate" · records outside the encounter/date window ·
and the ever-present trap of trusting an ignored query-string filter instead of filtering client-side.
1---2name: ehr-governance-packet-builder3description: Build normalized-JSON deliverables for EHR quality-governance queue tasks from a read-only EHR API. Use when a prompt gives case objects (patient / duplicate-candidate / referral / ServiceRequest / batch IDs), points to a read-only EHR environment (a base URL in environment_access.md), and asks for JSON conforming to an input/payloads/answer_template.json. Covers duplicate-chart merge-readiness packets, referral coordination packets, care-transition packets, duplicate + ServiceRequest reviews, and referral batch audits.4---56# EHR governance packet builder78You are given a task folder that contains a `prompt.txt`, a `input/payloads/answer_template.json`, sometimes9extra request payloads, and an `environment_access.md`. Your job is to query a read-only EHR10"quality-governance" API and emit **one normalized JSON object** that conforms exactly to the answer template.11No prose, no SOP/narrative text — JSON only.1213Every task in this family is the same shape: *read the contract, gather evidence from the API, normalize it,14classify a disposition/readiness, and assemble stable IDs into the template's structure.* The templates and15case objects change; the operating rules below do not.1617## 1. Read the contract before touching the API18191. **`prompt.txt`** — extract the case objects (the IDs you must center on): patient_id(s), duplicate20 `candidate_id`, `referral_id`, `ServiceRequest` id, `batch_id`, recipient provider id, and the required21 `task_id`. Note the *service line* (cardiology / orthopedics / …) and what deliverables are requested.222. **`input/payloads/answer_template.json`** — this is the authoritative contract. Enumerate its23 top-level required keys, every field, every **enum's allowed_values**, and every **ordering rule**. Your24 output must contain exactly these keys with these types. Never invent enum values — pick only from the25 template's allowed list. If the template states a `required_value` for `task_id`, emit it verbatim.263. **Any other payload** (e.g. a `*_request.json`) — it restates the case objects and the requested outputs;27 use it to confirm scope, not as a data source.284. **`environment_access.md`** — read the **base URL** and the allow-listed endpoints from here. Do not assume29 a URL; use the one in the file. Credentials are typically none. This file is *only* for network access.3031Read `references/api_reference.md` for the endpoint families and response conventions, and32`references/normalization_rules.md` for the field-by-field normalization and classification ladders. Read33`references/task_archetypes.md` to see how the five recurring deliverables map onto the same procedure.3435## 2. Gather evidence from the API (read-only GET)3637- Use **detail endpoints for named objects** (`/api/patients/{id}`, `/api/duplicates/{candidate_id}`,38 `/api/referrals/{referral_id}`, `/api/icd10/{code}`, `/api/providers/{id}`, `/api/service-codes/{code}`).39- For a patient's clinical picture, pull the per-patient list endpoints you actually need: `conditions`,40 `medications`, `allergies`, `encounters`, `immunizations`, `documents`, `disclosures`, `service-requests`.41- **Query-string filters are ignored by this API.** `GET /api/referrals?batch_id=X` returns the *whole*42 collection, not the batch. To scope a batch (or find records by name/insurance/etc.), fetch the full43 collection and **filter client-side** on the field. Same for `/api/patients`.44- Unknown IDs return HTTP 404 with `{"error":..., "status":404}`. Treat a 404 on a code lookup as45 "unknown/invalid code" evidence, not as a crash.46- Response bodies wrap lists under a named key (`{"conditions":[...]}`, `{"referrals":[...]}`,47 `{"duplicate_candidates":[...]}`); a few (audit-logs) come back as bare arrays. Handle both.4849## 3. Normalize (the reusable rules)5051These rules recur across every task; apply the ones the template asks for.5253- **Active-only lists.** For condition/medication/allergy unions, keep only records with `status == "active"`.54 Drop `inactive`, `resolved`, `entered-in-error`. This is the primary distractor filter.55- **`normalized_key` is the canonical identity.** Build clinical "key unions" from the `normalized_key`56 field, **deduped** across duplicate rows and across both patients in a merge. Emit as a **set**: unique +57 sorted per the template (usually alphabetical/ascending).58- **Patient endpoints beat any preview.** When a duplicate candidate carries a `merge_preview` of active59 keys, the per-patient active-list endpoints are authoritative. Reconcile: any active key present in the60 patient endpoints but missing from the preview must be *added*; report it if the template has a61 reconciliation/"added_from_active_endpoints" section.62- **Signals: map to the template's vocabulary.** Take `match_signals` / `conflict_signals` from the duplicate63 candidate. If the template gives an `allowed_values` enum for signals, emit only values from that enum64 (mapping raw labels to it); if it just says "signal labels sorted alphabetically", emit the raw labels sorted.65- **Evidence = stable IDs, never prose.** Cite `document_id`, `audit_id`, `encounter_id`, `immunization_id`,66 `disclosure_id`. Select documents by `status` (prefer `final`; exclude `preliminary`/`cancelled`) and by67 the packet's **document policy** (e.g. identity/external-continuity docs only → include68 `identity_verification` and external notes, exclude internal `chart_summary`; a referral packet wants the69 `echocardiogram` + `office_note`). List unrelated docs/audit rows under an "excluded_distractors" section if70 the template has one.71- **Providers by id.** Resolve the receiving/specialist/owner provider from the id on the referral /72 ServiceRequest / disclosure, then copy the directory record's exact fields (`name`, `role`, `service_line`,73 `facility`, `phone`, `fax`). Confirm the `service_line` matches the requested specialty.74- **Codes.** Validate a diagnosis `code` via `/api/icd10/{code}`: compare `chapter` to the expected service75 chapter, and if `requires_laterality` check the narrative against `expected_terms` (→ `laterality_mismatch`76 / `narrative_mismatch` / `missing_laterality`). Validate a `service_code` via `/api/service-codes/{code}`:77 it must exist, be `active`, and its `service_line` match the performer.78- **Dispositions & readiness** are decided from the evidence, then mapped onto the template's enum ladder79 (blocking conflicts, `null` merge target/source, missing docs, missing/pending authorization, incomplete80 allergy, disclosure not `permitted`, invalid code all push toward "review"/"hold"/"do_not_merge"). The exact81 ladders per archetype are in `references/normalization_rules.md`.82- **Counts are integers**, dates are `YYYY-MM-DD`, booleans are real booleans, and use `null` only where the83 template's type union allows it.8485## 4. Assemble & validate output86871. Build the object in the template's key order; include **every** required top-level key.882. Apply each array's stated ordering (sets → dedupe + sort as specified; object arrays → sort by the named89 field; "newest→oldest" where stated). Default to ascending/alphabetical when a set has no explicit rule.903. Re-check every enum value against the template's `allowed_values`; re-check `task_id`'s required value.914. Confirm no narrative/SOP text leaked into any field, and that the whole payload is a single valid JSON92 object. Output JSON only.9394## 5. Common distractors to exclude9596Inactive/resolved/entered-in-error clinical rows · duplicate patients who merely share a name · unrelated97merge/audit log rows for other charts · internal `chart_summary` documents when an identity/continuity policy98applies · preview key-lists that disagree with the active endpoints · cross-patient laterality conflicts99(e.g. right-knee vs left-knee) that mean "not a true duplicate" · records outside the encounter/date window ·100and the ever-present trap of trusting an ignored query-string filter instead of filtering client-side.