← Back to AAI for MerusCase

Morning Brief

The first thing you run every day. Two words at the prompt. Seventy-four seconds later you know which client you haven't called in 396 days, which hearing has no prep task, and which case is going to a trial Thursday that hasn't been opened since March.

The case names, doctor names, claim numbers, and dates in this page are fictitious demonstration data. They illustrate how the brief behaves. The actual brief on your install shows your real cases.

On this page

Why this is the most important skill

A typical Workers' Comp attorney is carrying 100 to 250 open cases at any moment. Five hearings tomorrow. Three QMEs the week after. Two trials this month. Forty unfiled uploads waiting in the inbox. Two paralegals processing mail in real time. Defense letters arriving every afternoon. A 5-year jurisdictional reopener clock running on every single case from the day it was filed.

The job is fundamentally triage. Not "do everything." Not "do the most urgent thing." Do the things that, if missed, become irreversible. The other things will wait.

What makes the job hard isn't the volume. It's that the urgent items are silent until they explode. The 5-year reopener doesn't ring an alarm; it just passes. The hearing prep doesn't get marked overdue; the judge just notices you're unprepared. The client you haven't called in 287 days doesn't quit; they file a State Bar complaint the day after the bad result. The 30-day QME objection window doesn't send you a reminder; it expires and the defense advocacy letter becomes the rated medical opinion.

The morning brief exists to make all of that visible at 7 AM, before the day gets away from you.

The whole point of the brief is to ensure that nothing irreversible happens because you didn't know about it. Everything else — the elegant scoring, the parallel fetches, the markdown table — is implementation detail. The thing that matters is: when you read the brief on Monday morning, you cannot truthfully say afterward "I didn't know."

What happens if you skip a morning

Take one realistic Monday. You don't run the brief. You start with the first email in your inbox — a defense advocacy letter on a case you haven't thought about in two months. You spend an hour on it. The clock starts at 9:30 AM.

You don't know:

The brief surfaces all four of these in the first 30 seconds of reading. The first three appear at the top of the DANGER table, ranked by score. The fourth appears in the DEADLINES section with a status verdict. You cannot read the brief and not know.

Why a brief and not a calendar

A calendar tells you when things are scheduled. The brief tells you which scheduled things are dangerous. Those are very different reports.

A calendar entry for "DOE 1:30 PM EXPEDITED HEARING" is information. The brief entry for the same event is:

| 85 | #142 Doe | HEARING | TODAY (0d) | no prep task; 396d no contact |

Same event. Two different reports. The first one you have to interpret; the second one is already triaged. The brief does the interpretation in code and hands you the ranked list. That's the whole skill.

Why running it once is non-negotiable

The brief is not optional. It's not "useful when you have time." If you handle a Workers' Comp caseload above ~60 active cases, running the brief once a day is the difference between knowing your situation and not knowing it. The cost is 74 seconds of your time and roughly $0.30 of Claude API tokens. There is no other check anywhere in the system — manual or automated — that catches the same combination of upcoming proceedings × client-contact age × prep-task absence × statute proximity in one pass.

Attorneys who use AAI typically run the brief twice — once at the start of the day, once after lunch to catch anything filed between morning and afternoon. The afternoon run takes another 74 seconds. By 2 PM you know the same things you knew at 8 AM, plus whatever changed.

What it actually does

You type two words at the prompt:

aaicase> morning brief

About 74 seconds later you have a triaged report. Not a list of events. Not a calendar dump. A ranked report with the most dangerous situations at the top, the supporting context underneath, and a numbered Recommended Actions list at the bottom that names specific cases.

The very first thing you see is the DANGER table:

## DANGER CASES

| Score | Case             | Event       | When         | Why                                          |
|------:|------------------|-------------|--------------|----------------------------------------------|
|   105 | #142 Doe         | AME         | TODAY (0d)   | no prep task; 87d no contact; no open tasks  |
|    85 | #287 Roe         | HEARING     | TODAY (0d)   | no prep task; 396d no contact                |
|    85 | #303 Smith       | HEARING     | TOMORROW (1d)| no prep task; 227d no contact                |
|    45 | #410 Sample      | HEARING     | TODAY (0d)   | 493d no contact                              |
|    25 | #511 Garcia      | AME         | Thu 6/11 (3d)| contact unknown                              |

**Score guide:** 70+ critical, action TODAY | 40-69 attention this week | <40 noted

Five columns: Score, Case (with file # prefix so each row is uniquely identifiable when a firm has multiple cases under the same applicant last name), Event type, When it happens, and Why it's dangerous. Sorted highest score first. This is the headline of every brief. If you read nothing else, you read this.

Danger scoring — the number that ranks your day

Every case going to a formal proceeding this week gets a danger score. The score is the sum of five factors, each of which corresponds to a real reason a case might go badly:

FactorAddsWhy this signal matters
No real prep task on the case+40The biggest single predictor. If a hearing is in 3 days and there's no "call client / case summary / hearing prep" task, the case isn't being worked. The attorney is going to walk in cold.
Last client contact > 30 days ago+30Client doesn't know what's happening. Two failure modes: (1) they show up to the wrong place / wrong time, (2) they file a State Bar complaint when the result disappoints them. Both prevented by a phone call.
Client contact unknown+10The activity fetch found no canonical contact-tag matches. Less urgent than known-stale but more urgent than known-fresh — the +10 is the "we don't know" penalty.
Case has zero open tasks+20Nothing queued means nothing is going to happen. The case is in the dead zone where it'll stay forgotten until the next hearing forces attention.
Formal event within 3 days+15Proximity. A hearing 5 days out can be prepped tomorrow; a hearing today cannot.

The maximum theoretical score is 115 (all five factors at once). In practice the worst-case cases score 85-105 — they have no prep, no contact, no tasks, and the event is imminent. The marketing one-liner is "0 to 100" because that captures the spirit, but yes, a true catastrophe case can score above 100. When you see one, treat it accordingly.

Score interpretation:

The architectural decision underneath the score: the math is deterministic, not editorial. Two runs of the brief on the same data produce the same scores. The model has no input into the number. That makes the score trustworthy — you can rely on the ranking the same way you'd rely on a sort by date.

Score guide: 70+ critical, needs action TODAY | 40-69 attention this week | <40 noted

The first row scored 85 because: no prep task (+40), 287 days no contact (+30), event within 3 days (+15). The attorney scans the Score column and immediately knows where to start. The script computes; Claude renders the table verbatim — no editorializing the score into prose, no hiding it inside a "this week" summary.

Client-contact age — the single most useful signal

If there is one number in the brief that tells you the most about a case, it's how many days since the last client contact. Not the case status, not the recent activity feed, not the number of open tasks. How long since you talked to the human being whose life is on the line.

The number behaves like a compass. A client you called yesterday is going to walk into the hearing with the right expectations, the right documents, the interpreter you arranged, and a calm understanding of what's about to happen. A client you haven't called in 396 days is going to walk in not knowing why they're there, what's being asked, or who you are. The result of the proceeding will be measurably worse in the second case, even if every other variable is identical.

That's why the formula weights contact age more heavily than almost anything else. Stale contact alone is +30. Combined with "no prep task" (+40), a single case can rack up 70 points of danger from communication failures alone, before you account for proximity or task absence.

How the brief computes it

For each danger case, the brief fetches that case's full activity history and scans for activities tagged with one of the three canonical client-contact types:

The most recent date across those tags becomes the last-contact date. The brief takes today minus that date and shows it in the per-case line: 12d no contact, 67d no contact, 200d+ no contact. If no contact activity was found at all — either because the firm uses non-canonical tags or because the case genuinely has zero logged client communication — the brief shows contact unknown and adds +10 to the score.

The NOTE_FALLBACK pattern

If a firm logs client phone calls under the general Note tag (tag 101) instead of the canonical Telephone Call tag (111), the canonical-tag scan returns nothing. To handle that case, the brief emits up to 3 most-recent tag-101 entries for any case that came up contact unknown, and the rendering model reads each note's description. If a note describes communication with the applicant ("called the applicant," "spoke with applicant," "left applicant a voicemail," and Spanish equivalents), the model substitutes that note's date into the Why column for that row — replacing contact unknown with the real number.

The note's score does not change. The +10 unknown penalty stays. This is a display-only correction; the danger ranking is unaffected. A firm using non-standard tagging gets the same accurate contact-age display as a firm using the canonical tags. The score formula remains deterministic.

Real prep-task detection — not "any open task"

Earlier versions of the brief marked a case as "prepared" if it had any open task with a due date before the upcoming event. That gave the wrong answer in practice. A case with 30 routine open tasks all due before next Wednesday counted as "prepared" for Wednesday's hearing — even though none of those tasks were hearing prep. The 30 tasks were medical record review, lien-letter follow-ups, mileage demands, things like that. None of them prepared the case for the hearing. But the brief said "prep=true" anyway.

That was the worst kind of failure mode: a false negative. The brief was telling the attorney "this case is fine" when it wasn't. The attorney trusted the brief. The hearing happened. The case wasn't prepared.

The fix

The current logic only counts a task as prep if its description contains an explicit prep-related token. The token list is intentionally tight:

prep client       call client       case summary
witness prep      hearing prep      MSC prep
mediation prep    pretrial          prep for trial
prep for QME      prep for AME      prep for deposition
prep for depo

If a task's description (lowercased) contains any of these tokens and its due date is before the upcoming event, the case is marked prep=true. Otherwise prep=false, and the case gets +40 to its danger score.

Notice what's excluded: review, brief, and similar generic words. Those match too many non-prep tasks ("review medical records," "settlement brief"). Including them re-introduces the false-negative pattern. The token list is the result of looking at actual prep tasks attorneys write and finding the words that only appear on prep tasks.

This is one of the rare places where the brief makes an editorial judgment: deciding what counts as prep. The judgment is made at the token-list level, encoded in the script, and visible to anyone reading this page. It's not made on the fly by a model interpreting individual tasks. That makes it auditable and stable across runs.

The 8 sections, in order, and what each one is for

The brief always presents sections in the same order. The order is not arbitrary; it's the order in which an attorney's attention should move through the morning. Most-irreversible first, supporting-context next, action-list last.

1. DANGER CASES (the headline)

The 5-column markdown table. Score-ordered, highest first. File # prefix on every Case cell so each row is uniquely identifiable. If the same case has multiple danger events this week — a DEPO + QME on the same day, or an AME + QME both tomorrow — they're merged into one row with combined event types so you don't see the same case twice.

The script computes the score; Claude renders the table verbatim. No editorializing, no hiding the score inside prose. Same architectural pattern as the deadlines skill (script computes the structured lines, Claude renders verbatim).

What to do with it: read every row with score ≥ 70 and act on each one TODAY. The 40-69 rows you schedule for this week. The <40 rows you glance at and move on.

2. DEADLINES WITHIN 14 DAYS

All events of type Statute (SOL), Follow Up, Hearing, QME, AME, Deposition, or Doctor Deposition within the next 14 days. Sorted by date ascending. These carry legal consequence if missed — the 30-day QME objection window, the 25-day DOR response, the 5-year reopener.

What to do with it: for each item, confirm the prep work is queued. If a hearing is on this list but doesn't have a prep task, that case should have shown up in section 1 — go back and look.

3. TODAY'S EVENTS

Everything on the calendar between midnight and 11:59 PM today, with times and locations. The morning-glance section: what's actually happening in the next few hours.

4. THIS WEEK

Remaining events between tomorrow and Sunday, grouped by day. This is the heads-up section: tomorrow has 12 events, Thursday is the trial, Friday is light. Plan accordingly.

5. TASKS — Summary table

A small 3-row table: Overdue / Due today / Due this week, with counts. The Overdue count is the firm-wide total — usually surprisingly large, because most WC firms accumulate years of HIGH-priority overdue 5710 fee-petition tasks that nobody is acting on. Auto-generated "REVIEW (auto..." and "VERIFY (auto..." noise tasks are filtered out of the count; only real attorney work is included.

Don't be alarmed by the Overdue total. A firm-wide count of 700+ overdue is normal for a busy WC practice with multi-year legacy items. The number to watch is "Due today" — that's the call list.

6. TODAY'S TASKS — Itemized

The HIGH and NORM priority tasks actually due today, one bullet each: priority badge, case name, task description. This is the explicit call-list for the day. If the Overdue total in section 5 is high but most of it is stale, this section is where you find what actually needs done today.

7. UNPROCESSED MAIL

Count of upload records with no case_file_id AND no activity_id (true orphans waiting to be filed). The brief offers to run process mail if > 0. If zero, it says "Inbox is clean."

What to do with it: if there are more than a handful, run process mail next. Defense letters get more dangerous the longer they sit unfiled — the response clock starts the day they arrive, not the day you file them.

8. RECOMMENDED ACTIONS TODAY (the bottom line)

A numbered list (max 5) of concrete next moves, drawing from the DANGER table for items with score ≥ 70, the deadlines list for items with imminent statutes, and TODAY'S TASKS for items genuinely due today. Each action names the specific case and gives a one-sentence next step so the attorney can act without scrolling back.

The list is the brief's bottom-line. If you read nothing else after the DANGER table, read this. The two together are the entire actionable surface of the brief: who's in danger at the top, what to do about it at the bottom. The middle six sections are supporting context that explains the top and the bottom.

How it runs under the hood

The brief is a five-phase pipeline. Four of the five phases are deterministic code; only the last phase involves the language model, and even there the model's job is rendering, not computing.

Phase 1: Firm-wide parallel fetch (~10 sec)

Four firm-wide Merus API calls fired in parallel:

node bin/merus-fetch.mjs /events/index    → events for the week
node bin/merus-fetch.mjs /tasks/index     → all open tasks
node bin/merus-fetch.mjs /uploads/index   → for unprocessed-mail count
node bin/merus-fetch.mjs /caseFiles/index → for case-name and file-# lookup

Total wall time is the slowest of the four — usually /uploads/index which is the largest payload (300-800 ms on a healthy connection).

Phase 2: Identify the danger events (~50 ms)

Scan events for the 5 danger event types occurring between today (Pacific-time midnight) and 7 days out. Dedup by case_file_id. Cap at 16 cases for the per-case activity fetch in Phase 3 — the cap keeps total API calls under ~20 and total wall time around 10-12 seconds. (Was 8 pre-4.5.457; raised after telemetry showed 5 of 13 danger cases on a typical busy day were being silently dropped.)

The 5 danger event types:

Type IDWhat it isWhy it's danger-eligible
15403HEARINGCourt appearance — preparation required
15404QME (appointment)Panel QME exam — sets PD evidence
15405AME (appointment)Stipulated medical exam — sets PD evidence
23826DEPO (client deposition)Applicant on the record under oath
28328DR-DEPO (physician deposition)Physician cross-examination

Phase 3: Per-case activity fetch (~1 sec)

For each of the (up to 16) danger cases, fetch its full activity history in parallel:

for cid in $dangerCids; do
  node bin/merus-fetch.mjs /activities/index/$cid > acts-$cid.json &
done
wait

This gives us the client-contact-age signal — the single most useful danger signal. Cases beyond the top-16 cap get contact unknown instead of a real age, with a +10 score penalty. Trade-off: comprehensive triage vs. fast brief. The Phase 3 telemetry on stderr tells you when the cap was hit so you know whether the "contact unknown" rows are "we didn't fetch" vs "we fetched and found nothing."

Phase 4: Score and emit (~200 ms)

For each danger case:

  1. Read its activity file, find last-contact date by tag (canonical tags 111/32263/32265 first, then fallback to tag 101 Note with model classification).
  2. Check the case's open tasks for prep-keyword presence (the token list in the previous section).
  3. Compute the danger score using the five-factor formula.
  4. Sort all danger cases by score descending.
  5. Emit the ready-to-paste markdown ## DANGER CASES section to stdout.

For overdue tasks, the script ranks by priority ascending (HIGH wins), then by date_due descending (newest within priority surfaces first). This was changed in pass 453 from oldest-first; the prior sort always showed the same 5 ancient HIGH-priority 5710 fee-petitions in the top 5, drowning out genuinely actionable items. Newest-first within priority surfaces recent case-assessment reviews, client follow-ups, and prep tasks — items the attorney can actually work on today.

Phase 5: Claude renders (the bulk of the wall time)

Claude reads the bash phase's stdout and writes the final brief. The DANGER CASES section is copied verbatim from Phase 4's output; the other sections are built from the firm-wide data Claude can read in events.json, tasks.json, uploads.json, cases.json.

The architectural decision underneath the brief: do the math in code, let the language model do the presentation. The score is computed by a script that produces the same output for the same input. The presentation is done by a model that can disambiguate case names, surface inline notes about interpreters or in-person locations, and write the closing Recommended Actions in human language.

Performance and cost

The brief runs in about the time it takes to make a coffee and sit down. The scoring is deterministic — same data → same output — so running it twice in the same morning gives the same triage. Run it once at the start of the day; run it again after lunch if you want to catch anything that came in mid-morning.

Schedule it to run automatically

If you want the brief in your inbox at 7 AM:

# Mac / Linux: cron
0 7 * * 1-5 /usr/local/bin/aaicase -p "morning brief" | mail -s "Morning Brief" attorney@aai.dev

# Windows: Task Scheduler with the same command

Or, simpler: run schedule brief from the REPL and follow the prompts. It writes the cron entry for you.

Troubleshooting

"contact=?" on every danger case

This usually means the activity fetches failed silently (API permissions gap on /activities/index/{case_id}). The brief continues with a +10 score penalty per case to flag the unknown. Check your API token's permissions in MerusCase admin.

The brief takes longer than usual

The 4 parallel firm-wide indexes are the floor. If you have a very large caseload (500+ active cases), the /uploads/index response can take 5-10 seconds on its own. That's a Merus-side characteristic; the brief can't do anything about it.

"No danger cases this week" but I know there are hearings

The danger types are HEARING (15403), QME (15404), AME (15405), DEPO (23826), and DR-DEPO (28328). If your firm uses custom event types for these proceedings, they won't be flagged. The fix is to use the standard Merus event types when creating the calendar events.

Brief shows wrong case names

The brief uses field index [1] of each case record as the display name. If your firm renames cases via a custom field, the brief won't see the renamed version. Use the standard "Case Name" field.

Part of AAI for MerusCase — code-guarded AI case intelligence for California Workers' Comp attorneys.