Investigation Review Hub — Gap & Remediation Dashboard
What this task is
You are given a legal matter (a grand jury / SEC / DOJ subpoena response) and must return exactly one JSON object that summarizes the material production gaps, preservation failures, privilege problems, and QC defects for that matter, plus rollup metrics and a prioritized remediation action plan. All business facts come from a running Investigation Review Hub you reach over the network — never from local files.
Every run varies (different matter, different output schema), but the shape is always:
- Findings list — one row per material gap/defect (may be called
critical_findings,top_risks,issue_ledger,retention_events+communication_gaps, …). - Category coverage — one row per subpoena/request category with a non-complete status.
- Available/retained sources — archives or sources that still limit the loss (may be empty).
- Metrics — a fixed object of integer counters + a readiness boolean.
- Action plan — prioritized, owner-assigned remediation steps.
The hub deliberately buries a handful of material "story" records inside many realistic
distractors. The entire difficulty of the task is separating signal from noise, then
normalizing the signal into the exact enums/keys the answer template demands. Read
reference/materiality_and_mapping.md before you start classifying records.
Inputs you will have
input/prompt.txt— the client ask (which matter, what deliverable).input/payloads/<context>.json— matter context: thematter_id, category labels, and often the base URL placeholder + API key header. (Filename varies:request_context.json,review_scope.json,matter_context.json, …) Use it for the matter id, category codes/titles, and credentials only — it never contains the hub evidence.input/payloads/answer_template.json— the contract for your output: required top-level keys, per-item required keys, ordering rules, numeric precision, and the exact enum choices for every field. This file (not this skill, and not any example) is the source of truth for field names and allowed values. Re-read it for every run; keys and enums change per matter.environment_access.md(repo root) — how to reach the running hub over the network: theGDPEVO_ENV_BASE_URL, the requiredX-API-Key, and the allowed endpoints.
Guardrails (do this, not that)
- Only source of business evidence = the hub over the network. Do NOT read local
environment source files, database/seed files, generated manifests, hidden notes, other tasks'
inputs, or any answer/evaluation files. Use
environment_access.mdonly to obtain the base URL and credentials. - Read the base URL + API key from
environment_access.md/ the matter context payload for the current run; do not assume. (In the environment observed while building this skill the base URL washttp://task-env:9017/and the header wasX-API-Key: review-key-017.) - The hub is read-only; the SQL endpoint permits
SELECTonly. - Output one JSON object and nothing else — no prose, no code fences, no trailing commentary.
- Use stable hub record IDs exactly as they appear (source_id, event_id, entry_id, finding_id,
doc_id, action_id, category_code). Never invent IDs for evidence; the only IDs you may synthesize
are action_ids in the action plan when the template shows synthetic keys (e.g.
ACT-<M>-001).
Workflow
Read the three inputs. From the prompt + context payload get the
matter_idand the category code family. Fromanswer_template.jsonextract:required_top_level_keys, each list'sitem_required_keys, theordering_rules,numeric_precision, and everyenumsblock. Keep the enum lists open in front of you — every field value you emit must be one of them.Reach the hub. Get base URL + key from
environment_access.md. Confirm the matter exists:GET /api/matters?matter_id=<M>(notehold_date,agency,investigation_type). The endpoints and the SQL data model are inreference/hub_api.md.scripts/pull_matter.shdumps every table for one matter and pre-flags material candidates — run it first.Find the material anchor records (the core step — see
reference/materiality_and_mapping.md):- Start from
remediation_actionsfor the matter, excluding NOISE rows (action_id containsNOISE, description == "Routine action included as realistic operational noise.", ortarget_refis a bare category code). The remainingtarget_refs are the authoritative material anchors (retention events, custodian sources, privilege entries, QC findings). - This set is necessary but not complete. Also sweep every table for records that (a) carry a
descriptive slug ID (not a sequential
TYPE-MATTERTOKEN-NNNid) and (b) have a note/ summary stating a concrete, quantified defect, and (c) a material issue type/tag. In particular,documents/searchresponsiveness-miscodes (issue_tagscontainsmiscoded_nonresponsive, coded nonresponsive but responsive) are material even when no remediation action or QC finding points at them. - Discard distractors: sequential ids with boilerplate hedge notes ("ordinary review
variance", "not immediately remediated", "not one of the stable exception records", "realistic
operational noise", "included to create similar labels", "remediated by archive collection", …).
Distractors reuse the same
issue_typevalues as real records — issue_type alone never proves materiality; the slug-id + concrete-note + cross-reference test does. - Pull the linked records for each anchor: a QC finding's
source_ref→ its review document; a privilegeincomplete_logentry → its withheld/logged counts; a retention note may name specific unrecovered volumes or linked docs. Read note text to extract the material count (e.g. a "X of Y withheld docs logged" note → Y withheld / X logged / (Y−X) unlogged; a "N deleted, R recovered, K unrecovered" note → material volume = K unrecovered).
- Start from
Classify & normalize each material record into the template's enums (issue_type, severity/ risk_level, status, source_status, production_impact, category_status, action_type, owner, priority). Use the mapping tables in
reference/materiality_and_mapping.md. When the template lists an enum, pick the closest allowed value — never emit a value outside the enum.Build category coverage. For each request category touched by ≥1 material finding, emit its status (preservation loss / collection gap / privilege log gap / responsiveness gap / archive available / …), production impact, the sorted list of supporting record IDs, a recommended action, and (if required) an open-issue count. Sort category code lists ascending.
Compute metrics. The
metricsobject's required keys differ per template — compute each one literally from your material set (e.g. unlogged = withheld − logged; box counts split pre-hold vs post-hold; counts of lost personal devices, uncollected sources, available archives, miscoded docs, affected categories; the*_ready/production_readyboolean isfalsewhenever any open material gap remains). Every count is a whole integer; use 0 (not null) when not applicable.Build the prioritized action plan. Synthesize one action per material finding (or per related group). Rank by legal exposure and irreversibility, then map action→owner→priority from the template enums (rubric in
reference/materiality_and_mapping.md). Roughly: spoliation / post-hold destruction / lost sources requiring disclosure to the government come first (P0), then privilege waivers, privilege-log supplementation and privilege recodes, confirmed responsiveness recodes, personal-source collection, and archive search (P1), then over- designation downgrades and routine cleanup (P2/P3). Do not copy the hub's ownremediation_actionsowners/action_types verbatim — re-map them to the template's enums.Order, validate, emit. Apply every
ordering_rulesentry (sort findings/categories/actions by the specified key; sort every category-code list ascending; sort everysource_refs/record_refs/issue_refs/target_refslist ascending). Then run the checklist below and print the single JSON object.
Output validation checklist
- Top-level keys ==
required_top_level_keysexactly (no extras, none missing).matter_idmatches the hub. - Every list item has all of its
item_required_keys; every enum field holds an allowed value. - All counts are integers (0, not null, when N/A); booleans are real booleans.
- All ordering rules applied; every id-list sorted ascending.
- Evidence IDs are verbatim hub IDs. No distractor records leaked into findings.
- Output is one JSON object, no prose, no code fence.
See reference/hub_api.md for endpoints + SQL schema and reference/materiality_and_mapping.md
for the signal/noise heuristics and the field→enum mapping and priority rubric.