| name | snf-records-review |
| description | Shared reference methodology for the SNF records-review workflow — the five finding tags (APPEAL, LTC-DISPUTE, MEDICAID, QUALITY, TIMELINE), the finding format, dating conventions, OCR and source-location discipline, and the location of the scripts and reviewer prompts used by snf-review, snf-inventory, and snf-document-map. NOT an entry point and NOT a runnable pipeline — to actually review records, use snf-review. Load only when a reviewer, sub-agent, or contributor needs the rubric semantics or a shared script path. |
SNF Records Review
Use this skill when a user is adversarially reviewing Skilled Nursing Facility records — typically after a HIPAA records request in the context of an insurance appeal, quality complaint, Medicaid application dispute, or discharge-planning disagreement. It is designed for large record productions (hundreds to thousands of pages) where a human cannot reasonably read every page.
When to invoke
- User mentions "SNF records," "HIPAA records request to [facility]," "appeal [insurance] denial of rehab," "Medicare SNF benefits terminated," "facility filed Medicaid without my consent," "chart review for [relative]'s nursing home stay."
- Any large PDF production from a skilled nursing facility, rehab, or long-term care facility, including 500-1000+ page PDFs with mixed scanned documents and no reliable internal separators.
- Any situation where the user suspects facility staff documented something that contradicts patient/family stated goals.
Business outcomes this skill serves (work backwards from these)
- Insurance appeal — produce cited, dated evidence of skilled need, therapy progress, and clinical instability.
- LTC vs. home narrative dispute — surface every characterization of patient discharge goal, with authorship and date, to defeat a fabricated LTC predicate.
- Medicaid application withdrawal / dispute — establish when and by whom Medicaid paperwork was signed, and whether the patient was capacitated at the time.
- Quality/harm complaints — identify falls, med errors, missed services, adverse events, and documentation gaps for ODH / Ombudsman / CMS filings.
- Safe discharge evidence package — current functional status, equipment needs, medication list, support services required.
How to use
Step 1 — Inventory
Run scripts/inventory.py on the records directory. It produces:
- Per-PDF JSON sidecar with page count, PDF metadata, inferred section boundaries, and content-date range (in-stay vs. out-of-window).
- A combined
inventory.json consumed by later steps.
The script distinguishes content dates (dates written inside notes, which are what matter) from PDF print/creation dates (which are usually the day the record was exported from the EMR — meaningless for case work).
Step 2 — Build the document map
Run scripts/build_document_map.py immediately after inventory, even if the PDFs appear OCR'd. It produces:
document_map.json — page-level records with source PDF, original page number, text-readability status, likely document type, classification confidence, content-date candidates, and snippet/hash metadata.
document_map.md — human-readable coverage summary, expected-document checklist, contextual segments, OCR remediation actions, and review packet plan.
review_packet_plan.json — source page ranges grouped into reviewer-sized packets while preserving original PDF/page locations.
If the original HIPAA/document request is available, pass it as --request-file. The mapper will add a request comparison section showing requested categories that appear present, possible, not_found, or indeterminate_ocr. Treat this as triage; verify the source request before alleging omission.
When available, the mapper uses local PDF utilities rather than relying on pypdf alone: pdftotext -layout for text/table extraction, pdfinfo for metadata, pdfimages -list for scanned-page indicators, and pdffonts for font/text-layer hints. These signals are recorded in the document map so reviewers know whether a page is text-confirmed, OCR-light, image-only, or needs visual confirmation.
By default, build_document_map.py prefers pdftotext -layout when it is on PATH and skips slower per-page pypdf extraction whenever Poppler returns non-empty text for a page. Use --prefer-pdftotext=false only when you need diagnostic both-engine comparison or are investigating extractor disagreements.
This is the mechanism for disorganized charts. Do not assume a single PDF is one document. Treat it as a sequence of pages that may shift among vitals, MAR/eMAR, TAR, nursing notes, PT/OT/ST, MDS, discharge planning, invoices, admissions paperwork, Medicaid forms, and payer correspondence without obvious separators.
Document-map rules:
- Every page and segment must preserve original location as
<source PDF> p.<page> or <source PDF> pp.<start>-<end>.
- A missing expected document is only a true
not_found when enough pages are text-readable. If OCR is weak, mark it indeterminate_ocr and create an OCR/follow-up action instead of treating absence as evidence.
- Image-only and OCR-light pages are not review failures. They are review-scope constraints that must be routed to OCR remediation or human visual inspection.
- Use the expected-document checklist to drive narrow HIPAA follow-ups: MAR/eMAR, TAR, vitals/pulse ox, therapy, MDS Section Q, care plans, discharge summary/plan of care, incident reports, signed admissions/financial documents, Medicaid/PASSPORT paperwork, itemized billing, and payer/utilization-review correspondence.
Running in time-bounded sandboxes
Some agent shells cap individual command execution (for example, about 45 seconds per bash call). Large 100MB+ charts can exceed that even when the workflow is healthy. In those environments, do not keep retrying one monolithic command. Use one of these bounded patterns:
- Per-file invocation with a symlink staging directory — create a temporary directory containing a symlink to exactly one source PDF, then run
inventory.py and build_document_map.py against that directory. Write outputs under <out>/per-file/<pdf-stem>/ and merge/review the resulting JSON/Markdown afterward. This preserves original filenames while keeping each command short.
- Split first, then map chunks — for a single huge chart, split into page chunks with
qpdf --split-pages or another deterministic PDF splitter, map the chunk directory, and keep a manifest that maps derived chunk page ranges back to the original PDF/page range. Derived packet filenames are allowed, but all findings must still cite original source pages.
- Use progress logs and completion sentinels — write stdout/stderr to
<out>/logs/<step>.<pdf-stem>.log, write completed per-file outputs to <out>/per-file/<pdf-stem>/, and create a small <out>/per-file/<pdf-stem>/DONE.json containing the source filename, SHA-256, page count, script name, and completion timestamp. On resume, skip PDFs whose DONE file matches the current source hash.
- Escalate only when needed — if chunking still exceeds the sandbox limit, dispatch the long-running step to a tool/sub-agent with a longer per-call budget, but keep the same output layout and logs so the run remains auditable.
Keep all staged PDFs, logs, manifests, prompt files, and derived outputs inside the private case output root and out of git.
Step 3 — Read the rubric
RUBRIC.md defines the five tags, the finding format, dating conventions, and scope guardrails. Every reviewer (human or sub-agent) must apply it consistently.
Step 4 — Packetize the large chart
Large consolidated charts (>200 pages) should be packetized before parallel review.
Preferred path: materialize the document-map packet plan. The script uses qpdf when available and falls back to pdfseparate + pdfunite:
python3 ${CLAUDE_PLUGIN_ROOT}/skills/snf-records-review/scripts/materialize_packet_plan.py \
--packet-plan "<out>/document-map/review_packet_plan.json" \
--source-dir "<pdf-dir>" \
--out-dir "<out>/review-packets"
Fallback path: when document-map output is not available, run scripts/split_by_sections.py — it uses the inferred section data from Step 1 and qpdf to cut ~30-60 page sub-packets aligned to clinical section starts (Admission, H&P, Orders, MAR, Nursing Notes, Therapy, Care Plan, MDS, SS, Discharge Planning).
Packetization must preserve original-location metadata. A reviewer packet can be a derived PDF, but citations inside findings still point back to the original PDF/page from the document map or packet manifest.
Step 5 — Dispatch reviewers in parallel
Use REVIEWER_PROMPT.md as the self-contained brief for each reviewer. Works identically for:
- Claude sub-agents (via the Agent tool with subagent_type=general-purpose)
- External CLI tools (Claude CLI, Gemini CLI, Copilot CLI) — the prompt is portable
- Human reviewers
Optional GitHub Copilot CLI offload path: use COPILOT_CLI_DISPATCH.md and scripts/plan_copilot_dispatch.py after the document map and packet plan are complete. This can create per-packet prompt files, a dispatch manifest, a bounded-concurrency launch script, and a /fleet prompt for Copilot CLI. Default to plan-only mode; only run CLI jobs after the user explicitly approves launching them.
Each reviewer writes one findings file per packet using FINDINGS_TEMPLATE.md.
Each reviewer prompt must include the relevant document_map.json / review_packet_plan.json entry for the packet so the reviewer can distinguish:
- Pages reviewed and original source location.
- Likely document types expected in the packet.
- Map OCR statuses (
text, ocr_light, image_or_no_text) and reviewer verification labels (verified, OCR-partial, image-only-needs-OCR).
- Expected-but-absent documents that are true gaps vs. OCR-indeterminate.
- Source records-request delta, when a request file was supplied to the document map.
Step 6 — Aggregate
Run scripts/aggregate_findings.py once findings files exist. It produces:
*_Findings.md — master index grouped by tag, with cross-references.
*_HotItems.md — value-3 findings pre-formatted for appeal narrative.
*_Gaps.md — missing documents, signatures, dates → feeds follow-up records request.
*_Timeline.md — all TIMELINE findings sorted chronologically.
*_Findings.json and *_Summary.json — machine-readable outputs for dashboards, spreadsheets, MCP ingestion, or a case-context evidence register.
Step 7 — Convert gaps into actions
After aggregation, compare three sources before deciding a record is missing:
document_map.md expected-document coverage status.
- Reviewer
Missing / gap observations sections.
*_Gaps.md roll-up from aggregation.
Then route follow-ups as follows:
ocr_remediation / remediate_pdf → request a better copy, run OCR, or assign human visual inspection before relying on absence.
narrow_records_follow_up → feed the exact missing item into hipaa-records-request as a narrow supplement.
- Strategic value-3 findings and true gaps → add to
case-context/evidence_register.md, document_index.md, issue_log.md, and open_questions.md via case-context-ledger.
Inputs required
- Path to folder of PDFs. Optimized/OCR'd is preferred, but the workflow must tolerate mixed scanned documents and explicitly mark OCR-limited areas.
- Context about the patient's situation — enough to set the rubric's "why this matters" framing. The five tags are static but the patient-specific framing goes in the reviewer prompt.
Outputs produced
- Per-packet findings files.
document_map.json, document_map.md, and review_packet_plan.json.
- Four roll-up documents (index, hot items, gaps, timeline).
- Optional: HTML dashboard via
data:build-dashboard skill.
- Optional: Appeal supplement document via
docx skill.
- Optional: durable case-context updates via
case-context-ledger.
Related skills to combine
snf-document-map — for page-level document-type coverage, OCR/readability triage, packet planning, and narrow follow-up actions.
pdf — for any non-trivial PDF operation.
- Local PDF tools —
pdftotext, pdfinfo, pdfimages, pdffonts, pdfseparate, pdfunite, qpdf, pdfcpu, pdfsig, pdftoppm, pdftocairo, pdftohtml, and pdf2json are preferred for deterministic extraction/inspection before custom parsing.
- Adobe Acrobat Pro — local manual OCR, visual confirmation, rotation, redaction, or cleaner-copy export for pages the automated map marks as
ocr_light / image_or_no_text or reviewers mark as OCR-partial.
legal:review-contract — for admission agreements, arbitration clauses, Medicaid paperwork.
legal:legal-risk-assessment — for rating evidence strength.
finance:reconciliation — when a billing ledger is produced.
data:build-dashboard — for visualizing findings.
docx / pdf — for the final appeal supplement.
internal-comms — for follow-up records-request emails.
case-context-ledger — for preserving canonical facts, deadlines, evidence IDs, and open questions across sessions.
What this skill does NOT do
- Does not give medical advice or diagnose.
- Does not produce legal advice (flag items for a lawyer/patient advocate).
- Does not interpret state-specific regulations — always flag state-specific items for human review (e.g., Ohio PASSPORT, Ohio ODH rules).
- Does not replace human review of high-stakes findings — it surfaces candidates with citations so a human can verify.