The diagnostic you run on a case before opening the physical file. Pulls everything Merus knows in parallel, computes the staleness and exposure flags from data — not from prompting — and tells you what is broken, what is missing, and what is about to bite you.
At the prompt:
aaicase> health check on Doe
Or by case ID:
aaicase> health check on case [CASE-ID]
Sixty seconds later you have a one-screen report: who the applicant is, who is handling the case, what the case is about, what is wrong, and what you should chase next. It is the single skill an attorney runs before a client call, before a status conference, and before reassigning a case.
It is intentionally shorter and faster than audit [case]. The health check uses data Merus already exposes via API. The audit reads every document on the case. Health check is the screening test. Audit is the workup.
If you give it a name, the first thing it does is resolve to a case ID:
node bin/merus-search.mjs "Doe" → list matches, pick one
Then a single bash block fires six parallel fetches:
/caseFiles/view/[CASE-ID] → case header, applicant, staff
/tasks/index → open tasks (filtered to this case)
/events/index → future events (filtered to this case)
/activities/index/[CASE-ID] → ALL activities on this case
/parties/view/[CASE-ID] → parties count
/injuries/view/[CASE-ID] → DOI list
Two of those six (parties, injuries) are optional — if they fail, the report still runs with a small note. The other four are required; if any fails, the skill stops and tells you which endpoint died.
All six results land in a per-run temp directory created with mktemp -d and locked to owner-only permissions (chmod 700). The directory is deleted at the end. Nothing about the case lives on disk after the check completes.
Six sections, in this order:
Name, file number, status, opened date, venue, jurisdiction, principal claim number, and the first 500 characters of the case comments. The comments field is treated as the canonical case summary — the attorney’s own note on what the case is about — so it gets shown verbatim, not paraphrased.
Name, phone, email, language, interpreter flag, date of birth. If the language is not English and interpreter is unset, that becomes one of the flags below.
Attorney responsible and paralegal handling, looked up against the firm’s actual user list — not raw user IDs. If a paralegal seat is empty, the skill flags it.
Open real tasks, total real tasks, overdue tasks, uploads, future events, total activities, parties. “Real” means after the noise filter removes REVIEW (auto…), VERIFY (auto…), and the “Review filed orphan” auto-generated chatter — the kind of task volume that makes every case look busy when it isn’t.
The last 3 activities by date, with the description stripped of HTML. This is the “is this case moving” smell test.
The exposure picture (described below), then the pre-computed LC 5405 SOL and LC 5410 reopener deadlines for every DOI on the case — rendered verbatim from the same DEADLINE-line schema as the standalone deadlines skill.
Every flag is computed in JavaScript, in the same bash block as the fetch — no second LLM pass, no string matching against AI output. The numbers are facts. The presentation is the only interpretation step.
| Flag | What triggers it | What it tells you |
|---|---|---|
| Days since client contact | > 30 days since any activity tagged as client contact OR client-contact event | “HIGH: No client contact in X days — CALL [phone]” |
| Days since client contact — NOTE_FALLBACK override | If no canonical contact tags matched but the firm logs client calls under tag 101 (Note), the model reads the 3 most-recent NOTE entries and overrides daysSinceContact from “never” to the date of the most recent that describes communication WITH THE APPLICANT | Same “HIGH: No client contact in X days” flag, but accurate on firms that don’t use tag 111 |
| Days since any activity | > 30 days since the most recent activity of any kind | “Case going cold — X days since last activity” |
| Defense activity (30 days) | Activities in the last 30 days tagged as defense correspondence / pleadings | “Defense filed X items in last 30 days — check for responses needed” |
| UR / IMR (60 days) | Activities in the last 60 days tagged UR/IMR | “X UR/IMR decisions in last 60 days — check for appeal deadlines” |
| No upcoming events | Zero future events on the calendar | “No upcoming events — case may be stalled. File DOR?” |
| Recent QME | QME report in the last 30 days | “QME report received — 30-day objection window (8 CCR 31.5(a))” |
| Administrative gaps | No paralegal, no claim number, no comments, no email, or language ≠ English without interpreter | One line per missing item |
The flags are derived from tag IDs in the activities feed (client-contact tags, defense tags, UR/IMR tags, QME-report tags) plus the events feed. No regex on free-text descriptions. When canonical contact tags (111, 32263, 32265) return zero matches, the skill emits the top 3 tag-101 Note entries as data and the model classifies them — preserving “no regex” while still catching firms that log calls as Notes.
The flags above are short-window (30 / 60 days). The milestone checks compare the case’s age against what should have happened by now:
/caseStatuses/index; no hard-coded values.These are the situations attorneys notice after they bite, not before. The health check flips that order.
Three ethics-anchored flags, tied to Cal. Rule of Prof. Conduct 1.4 (duty to keep the client reasonably informed) and 8 CCR 10607 (obligation to communicate material developments):
These are not nag flags. Each one is the kind of gap that shows up in a State Bar complaint timeline.
Every health check ends with a deadlines block, one structured line per DOI on the case, rendered verbatim from the same pre-compute pipeline as the standalone deadlines skill:
DEADLINE LC5405 doi=2022-07-14 deadline=2023-07-14 days=-1059 status=SATISFIED
DEADLINE LC5410 doi=2022-07-14 deadline=2027-07-14 days=402 status=ACTIVE
The status enum tells the attorney where the case sits at a glance:
The script computes; Claude renders verbatim. No model calendar math, no editorializing. All dates are computed in America/Los_Angeles regardless of the attorney’s OS time zone.
If the attorney needs the full per-case deadline table including QME-objection, IMR-appeal, and DOR-response windows, that’s the deadlines skill.
| Health check | Audit | |
|---|---|---|
| Time | ~2 minutes | ~4 minutes |
| Source data | Merus API (header, tasks, events, activities, parties, injuries) | Every PDF on the case, read natively (no text extraction) |
| Finds | Staleness, exposure, ethics gaps, milestone misses | Misfiles, body-part mismatches, wrong tags, missing money, wrong filenames |
| Run before | A client call, a status conference, reassigning a case | Taking over a case, preparing for trial, large settlement push |
If a health check surfaces something serious — a possible misfile, an inconsistent body-part history, a value that doesn’t feel right — the natural next step is an audit on the same case.
The name didn’t match anything. Try a partial last name, or try the case file number directly. If you have it open in Merus, the case ID is in the URL.
The skill lists them with file numbers and asks you to pick one. It will not guess.
Those two endpoints are optional. If they fail, the report still runs with a one-line NOTE explaining what data is missing. The rest of the check is unaffected.
Every flag derives from a specific Merus tag ID or event type. If the firm is using a custom tag that the skill doesn’t recognize, the corresponding flag may under-report. The fix is to add the tag ID to the skill’s recognized lists — not to add free-text matching, which is what the skill is deliberately built to avoid.
The check looks for activities with the QME/AME report tag. If the report was uploaded but never tagged, it won’t register. Run audit [case] — the audit reads PDFs directly and will find it regardless of tagging.
Part of AAI for MerusCase — code-guarded AI case intelligence for California Workers’ Comp attorneys.