Investigation Review Hub — production gap analysis
These tasks share one shape: a legal team wants a normalized JSON assessment of
what is wrong with a rolling production for one matter. The prose, the client
name, and the output field names change; the underlying data model and the
reasoning do not. Solve it by pulling the matter's records from the hub,
separating the few material records from a large field of look‑alike
distractors, deriving exact counts, classifying each with domain rules, and
emitting JSON that conforms exactly to the task's answer_template.json.
What the task hands you
- A prompt naming a
matter_id and the deliverable.
input/payloads/answer_template.json — the output contract: required top‑level
keys, per‑item required keys, the allowed enum values for every field,
ordering rules, and numeric precision. This defines the answer; it does not
contain it.
input/payloads/<context>.json (e.g. request_context / review_scope /
matter_context) — client‑facing labels and category titles only. Never a
source of evidence facts; use it just for the matter_id and category codes.
- An environment access file describing a read‑only hub (per‑record read
endpoints plus a read‑only SQL query endpoint) and the credentials to send.
Read that file at task time to learn the base location and credential to use —
do not assume any particular address or key.
Hard rules
- The hub is the only source of business evidence. Do not read local env
files, database files, seeds, generated data, manifests, setup/source code, or
any answer/evaluation file — the prompts forbid it and those are traps.
- Filter every query by your
matter_id. The hub holds many matters; issue
labels and record shapes repeat across them, so unfiltered data is misleading.
- Return only the JSON object the template specifies — no prose around it.
Procedure
1. Load the schema and pull the matter
Learn the hub's data model, then pull every relevant table filtered to your
matter. See references/hub-data-model.md for the tables and the columns that
matter. Prefer the SQL query endpoint for one bulk pull per table; save the raw
rows and work from them. Always also pull the matter row itself to get the
hold_date — several classifications depend on comparing dates to it.
2. Identify the MATERIAL set — the crux of the task
Most rows are realistic noise. The escalated, material records are few. Find them
with three mutually‑reinforcing signals (see
references/material-vs-distractor.md):
remediation_actions is authoritative. Keep only the non‑noise actions
(drop any whose id/description marks it as operational noise, and any whose
target is a bare category code rather than a record id). Each remaining
action's target_ref is a material anchor record.
- Distinctive IDs. Material records use a short, human token in the id
(e.g.
SRC-<TOKEN>-<NAME>, PRIV-<TOKEN>-<TAG>, QC-<TOKEN>-<TAG>,
RET-<TOKEN>-<TAG>). Distractors use long sequential ids
(…-<MATTERSLUG>-0NN) and carry give‑away notes (see the reference).
- Cross‑check. The set of non‑noise action targets should equal the set of
distinctive‑id records. If they agree, that is your material set. Everything
else is out — even rows whose
status looks alarming (their notes will say
"no production‑impacting issue escalated", "remediated by archive collection",
"ordinary review variance", etc.).
3. Derive per‑record facts and counts
Counts come straight from the anchor records — never estimate:
- privilege entries →
withheld_count, logged_count, and
unlogged = withheld − logged.
- qc findings →
doc_count; note the coding issue (miscoded responsive vs
miscoded privileged vs zero‑claim contradiction) and its affected_category.
- retention events →
volume_count/volume_unit; split destroyed volume by
pre‑hold vs post‑hold using event_date vs the matter hold_date.
- custodian sources → count lost / not‑collected sources, keyed by source type
(personal device/email/messaging, board site, archive, …).
- Roll these up into the template's named metric fields exactly. Booleans like
production_ready / rolling_production_ready are false whenever any open
gap remains.
4. Classify with domain rules
See references/classification-and-enum-mapping.md. Highlights that generalize:
- Severity/risk is domain‑driven, not copied from the action's severity:
a policy‑compliant destruction before the hold is low; a loss after the
hold (spoliation) is high; a large unlogged‑privilege or zero‑claim
contradiction is high/critical.
- Route each record to the right output section by its nature: records/box
retention losses vs messaging‑system losses; privilege corrections vs QC/coding
issues; sources that are gaps (lost / not collected) go in the risk/finding
lists, while sources that are available archives or retained systems go in the
"available/retained sources" list and are a remediation path, not a risk.
- A category's status/impact summarizes all material records touching it; when the
template offers a "multiple blockers"/"mixed" value and a category has more than
one kind of issue, prefer it, otherwise use the single dominant issue.
5. Normalize to the template's enums
The hub's raw vocabulary is not the template's. For every enum field, map the raw
value to the closest allowed enum member by meaning (e.g. a system‑loss becomes
an active‑system‑loss; an incomplete log becomes a log‑gap / supplement‑log;
an over‑designation becomes a downgrade/recode; a forward to an outsider becomes a
third‑party waiver / waiver‑assessment). Derive action_type from the underlying
issue, not from the hub action's verb. For owner, normalize the hub action's
owner string to snake_case and use it if an enum member matches, otherwise map to
the nearest enum member. The reference lists the recurring mappings.
6. Assemble and order the JSON
- Include exactly the
required_top_level_keys; give every list item exactly its
item_required_keys.
- Apply every ordering rule (sort findings/events by id, categories by code,
actions by priority/rank; sort category‑code lists ascending and uppercase).
- Use whole integers for all counts; use the template's null/
not_applicable
conventions when a field does not apply.
- Anchor list items on the hub's own stable record ids.
- Emit the single JSON object and nothing else.
Checklist before finishing
1---2name: investigation-hub-production-gap-analysis3description: Produce a structured-JSON litigation e-discovery gap / production-readiness / remediation analysis for an investigation matter whose evidence lives in a read-only "Investigation Review Hub". Use when a task gives a matter_id, points at a review hub as the source of record, and asks for a JSON object conforming to a provided answer_template.json (critical findings, category statuses, retention/communication gaps, privilege corrections, top risks, metrics, prioritized actions, etc.). Covers subpoena/grand-jury/SEC/DOJ production reviews across custodian collection, preservation/retention loss, privilege logging, third-party waiver, and QC/responsiveness coding.4---56# Investigation Review Hub — production gap analysis78These tasks share one shape: a legal team wants a normalized JSON assessment of9what is wrong with a rolling production for one matter. The prose, the client10name, and the output field names change; the underlying data model and the11reasoning do not. Solve it by pulling the matter's records from the hub,12separating the few **material** records from a large field of look‑alike13**distractors**, deriving exact counts, classifying each with domain rules, and14emitting JSON that conforms exactly to the task's `answer_template.json`.1516## What the task hands you1718- A **prompt** naming a `matter_id` and the deliverable.19- `input/payloads/answer_template.json` — the output contract: required top‑level20 keys, per‑item required keys, the allowed **enum** values for every field,21 **ordering rules**, and numeric precision. This defines the answer; it does not22 contain it.23- `input/payloads/<context>.json` (e.g. `request_context` / `review_scope` /24 `matter_context`) — client‑facing labels and category titles **only**. Never a25 source of evidence facts; use it just for the matter_id and category codes.26- An **environment access file** describing a read‑only hub (per‑record read27 endpoints plus a read‑only SQL query endpoint) and the credentials to send.28 Read that file at task time to learn the base location and credential to use —29 do not assume any particular address or key.3031## Hard rules3233- **The hub is the only source of business evidence.** Do not read local env34 files, database files, seeds, generated data, manifests, setup/source code, or35 any answer/evaluation file — the prompts forbid it and those are traps.36- **Filter every query by your `matter_id`.** The hub holds many matters; issue37 labels and record shapes repeat across them, so unfiltered data is misleading.38- **Return only the JSON object** the template specifies — no prose around it.3940## Procedure4142### 1. Load the schema and pull the matter43Learn the hub's data model, then pull every relevant table filtered to your44matter. See `references/hub-data-model.md` for the tables and the columns that45matter. Prefer the SQL query endpoint for one bulk pull per table; save the raw46rows and work from them. Always also pull the matter row itself to get the47`hold_date` — several classifications depend on comparing dates to it.4849### 2. Identify the MATERIAL set — the crux of the task50Most rows are realistic noise. The escalated, material records are few. Find them51with three mutually‑reinforcing signals (see52`references/material-vs-distractor.md`):53541. **`remediation_actions` is authoritative.** Keep only the *non‑noise* actions55 (drop any whose id/description marks it as operational noise, and any whose56 target is a bare category code rather than a record id). Each remaining57 action's `target_ref` is a material **anchor record**.582. **Distinctive IDs.** Material records use a short, human token in the id59 (e.g. `SRC-<TOKEN>-<NAME>`, `PRIV-<TOKEN>-<TAG>`, `QC-<TOKEN>-<TAG>`,60 `RET-<TOKEN>-<TAG>`). Distractors use long sequential ids61 (`…-<MATTERSLUG>-0NN`) and carry give‑away notes (see the reference).623. **Cross‑check.** The set of non‑noise action targets should equal the set of63 distinctive‑id records. If they agree, that is your material set. Everything64 else is out — even rows whose `status` looks alarming (their notes will say65 "no production‑impacting issue escalated", "remediated by archive collection",66 "ordinary review variance", etc.).6768### 3. Derive per‑record facts and counts69Counts come straight from the anchor records — never estimate:70- privilege entries → `withheld_count`, `logged_count`, and71 `unlogged = withheld − logged`.72- qc findings → `doc_count`; note the coding issue (miscoded responsive vs73 miscoded privileged vs zero‑claim contradiction) and its `affected_category`.74- retention events → `volume_count`/`volume_unit`; split destroyed volume by75 pre‑hold vs post‑hold using `event_date` vs the matter `hold_date`.76- custodian sources → count lost / not‑collected sources, keyed by source type77 (personal device/email/messaging, board site, archive, …).78- Roll these up into the template's named metric fields exactly. Booleans like79 `production_ready` / `rolling_production_ready` are **false** whenever any open80 gap remains.8182### 4. Classify with domain rules83See `references/classification-and-enum-mapping.md`. Highlights that generalize:84- **Severity/risk is domain‑driven, not copied from the action's severity:**85 a policy‑compliant destruction *before* the hold is **low**; a loss *after* the86 hold (spoliation) is **high**; a large unlogged‑privilege or zero‑claim87 contradiction is **high/critical**.88- **Route each record to the right output section by its nature:** records/box89 retention losses vs messaging‑system losses; privilege corrections vs QC/coding90 issues; sources that are *gaps* (lost / not collected) go in the risk/finding91 lists, while sources that are *available archives or retained systems* go in the92 "available/retained sources" list and are a remediation path, not a risk.93- A category's status/impact summarizes all material records touching it; when the94 template offers a "multiple blockers"/"mixed" value and a category has more than95 one kind of issue, prefer it, otherwise use the single dominant issue.9697### 5. Normalize to the template's enums98The hub's raw vocabulary is not the template's. For every enum field, map the raw99value to the closest allowed enum member *by meaning* (e.g. a system‑loss becomes100an active‑system‑loss; an incomplete log becomes a log‑gap / supplement‑log;101an over‑designation becomes a downgrade/recode; a forward to an outsider becomes a102third‑party waiver / waiver‑assessment). Derive `action_type` from the underlying103**issue**, not from the hub action's verb. For `owner`, normalize the hub action's104owner string to snake_case and use it if an enum member matches, otherwise map to105the nearest enum member. The reference lists the recurring mappings.106107### 6. Assemble and order the JSON108- Include exactly the `required_top_level_keys`; give every list item exactly its109 `item_required_keys`.110- Apply every **ordering rule** (sort findings/events by id, categories by code,111 actions by priority/rank; sort category‑code lists ascending and uppercase).112- Use whole integers for all counts; use the template's null/`not_applicable`113 conventions when a field does not apply.114- Anchor list items on the hub's own stable record ids.115- Emit the single JSON object and nothing else.116117## Checklist before finishing118- [ ] Every query filtered to the matter_id; no local/DB/source files touched.119- [ ] Material set = non‑noise remediation targets = distinctive‑id records; all120 sequential‑id / "noise‑note" distractors excluded.121- [ ] Counts taken verbatim from anchor records; `unlogged = withheld − logged`;122 box volumes split pre/post hold.123- [ ] Pre‑hold loss = low risk, post‑hold loss = high risk applied.124- [ ] Each record routed to the correct output section (gap lists vs125 available/retained‑source list; retention vs communication; privilege vs QC).126- [ ] Every field value is a member of that field's template enum.127- [ ] Ordering, required keys, integer precision, uppercase‑sorted category codes.128- [ ] Output is only the JSON object conforming to `answer_template.json`.