Investigation Review Hub — gap / remediation dashboard
This skill turns raw records in a running Investigation Review Hub into the exact JSON
dashboard a task asks for. Every task in this family follows the same shape:
Read the matter's evidence from the hub over the network → separate material issues from
planted decoys → classify each issue with a fixed legal-review playbook → compute numeric
metrics → emit one JSON object that conforms to the task's answer_template.json.
The output schema, enum names, category codes, and metric names change per task, so the
contract is always the answer_template.json shipped in that task's input/payloads/. The
method below is constant. Read the three reference files for depth:
references/hub_api.md — endpoints, auth, the SQL endpoint, and every table's columns.
references/domain_playbook.md — how each kind of evidence maps to issue type / severity /
status / production impact / action / owner / priority, plus metric-derivation rules.
references/output_contract.md — how to conform to any answer_template.json exactly.
Procedure
1. Read the task, not just the prompt
Read prompt.txt and every file in the task's input/payloads/. From them extract:
matter_id (e.g. MTR-<NAME>-GJ / MTR-<NAME>-SEC) — the filter for everything.
answer_template.json — the output contract (required keys, enums, ordering, precision).
Treat it as authoritative; never guess enum values or keys.
- Any
*context*.json / review_scope.json — client-facing category labels, credentials,
cutoff dates. These give labels only; the evidence must come from the hub.
2. Reach the hub (network only)
Read environment_access.md for the base URL (GDPEVO_ENV_BASE_URL) and the X-API-Key
credential, and send that header on every call. Evidence comes only from the hub API.
Do not read the hub's database/source/seed/manifest files, and never read
train_answers/ or any evaluation/answer file. Sanity-check with GET / and GET /api/schema.
3. Pull all matter-scoped records
For the matter, pull rows from every table (filter by matter_id): matters,
subpoena_categories, production_stats, custodian_sources, review_documents,
privilege_entries, qc_findings, retention_events, remediation_actions. Prefer
POST /api/query with {"sql": "..."} for precise pulls; the REST GET /api/*?matter_id=…
endpoints also work. See references/hub_api.md.
4. Separate material issues from decoys — the key step
The hub seeds each matter with a handful of genuinely material records plus many
plausible decoys. Build your candidate set this way:
- ID convention (primary signal). Material/planted records use the matter's short
abbreviation with a descriptive suffix (schematically
RET-<TOK>-<DESCRIPTOR>,
SRC-<TOK>-<CUSTODIAN>-<DEVICE>, QC-<TOK>-<DEFECT>, PRIV-<TOK>-<DESCRIPTOR>,
DOC-<TOK>-<DESCRIPTOR> — descriptors are words, and may include a year or version like
…-2019 or …-V3, not a bare sequence number). Decoys embed the FULL matter name + a
zero-padded sequence number
(e.g. PRIV-<FULLNAME>-001, RET-<FULLNAME>-007) and carry routine/benign notes. Start from
the short-token records as your material candidates.
- Attribute corroboration. Confirm materiality with the record's own fields, not the ID
alone: retention
status (post_hold_loss, should_exist_missing, system_loss,
auto_purged, post_hold_partial_recovery are material; available and pre-hold
policy-compliant destruction are not); custodian status/issue_tags
(lost, not_collected, available+archive_available are material; routine is not);
qc issue_type (miscoded_*, zero_claim* are material; family_break,
date_normalization, near_duplicate are noise); privilege issue_type
(incomplete_log with a real withheld − logged gap, third_party_waiver,
over_designated); production_stats.status (zero_claim_contradicted is material); and doc
produced_status (not_produced/unrecovered/miscoded-withheld are gaps — already
produced docs are not a gap even if responsive/interesting).
- Ignore the hub's own remediation_actions attributes.
remediation_actions.target_ref
can point at material records, but its owner / priority / action_type are deliberately
wrong and its *-NOISE-* / bare-category rows are decoys. Re-derive everything in step 5.
- Fallback. If a needed dimension has no short-token record (a matter can carry its
privilege story in numbered entries), select analytically: within the flagged category, take
the entries with a genuine defect, one representative per
(category, issue_type) (lowest id).
5. Classify each material issue with the playbook
For every material record, derive its issue_type, severity, status, source_status,
production_impact, affected categories, recommended_action, owner, and priority using
references/domain_playbook.md. Map only to enum values present in this task's template.
Anchor each finding on a stable hub record ID; list all supporting IDs in source_refs
sorted ascending; sort category-code lists ascending.
6. Compute metrics and category coverage
- Derive counts from the material records:
unlogged = withheld − logged; sum boxes/volumes,
split pre- vs post-hold where the template asks; count each issue class and affected sources.
- Fill every metric key the template lists — use
0 / [] / false when the matter has
no such fact. Read each metric's own description for its exact scope (some are "selected
blockers only"). Any material gap ⇒ production_ready / rolling_production_ready = false.
- Category coverage: for each affected category, union the supporting material record IDs
(sorted), pick a representative status / production_impact / recommended_action, and count
open issues.
7. Prioritize the action plan
Order actions by the playbook's ladder (disclosure/preservation → privilege exposure →
recode → collect source → supplement log → search archive → over-designation → no-action) and
number ranks per the template's ordering rule (1 = highest). Assign P0–P3 and owner from
the playbook, targeting stable hub IDs.
8. Emit exactly one JSON object
Conform to the template precisely (see references/output_contract.md): only the required
top-level keys, only template enum values, all lists sorted per ordering_rules, whole-integer
counts, hub IDs verbatim, no prose outside the JSON.
Guardrails
- Evidence only from the hub API; connection details only from
environment_access.md.
- Never read database/seed/source/manifest files or any answer/evaluation file.
- Do not invent record IDs, categories, or enum values — use the hub's and the template's.
- Prefer under-reporting a doubtful decoy to inflating the dashboard with noise.
1---2name: investigation-review-gap-analysis3description: Produce a structured-JSON e-discovery gap / remediation dashboard for a legal-investigation matter by reading evidence from a running "Investigation Review Hub" API. Use when a task asks for a production gap analysis, retention/litigation-hold gap review, cross-system remediation dashboard, or production-readiness review for a subpoena/grand-jury/SEC/DOJ matter, and the answer must be a single JSON object conforming to a provided answer_template.json. Triggers: "Investigation Review Hub", "gap analysis", "remediation dashboard", "production readiness", "retention/litigation-hold gap", "privilege log gap", "custodian sources", matter IDs like MTR-*-GJ / MTR-*-SEC.4---56# Investigation Review Hub — gap / remediation dashboard78This skill turns raw records in a running **Investigation Review Hub** into the exact JSON9dashboard a task asks for. Every task in this family follows the same shape:1011> Read the matter's evidence from the hub over the network → separate material issues from12> planted decoys → classify each issue with a fixed legal-review playbook → compute numeric13> metrics → emit **one** JSON object that conforms to the task's `answer_template.json`.1415The output schema, enum names, category codes, and metric names **change per task**, so the16contract is always the `answer_template.json` shipped in that task's `input/payloads/`. The17*method* below is constant. Read the three reference files for depth:1819- `references/hub_api.md` — endpoints, auth, the SQL endpoint, and every table's columns.20- `references/domain_playbook.md` — how each kind of evidence maps to issue type / severity /21 status / production impact / action / owner / priority, plus metric-derivation rules.22- `references/output_contract.md` — how to conform to any `answer_template.json` exactly.2324## Procedure2526### 1. Read the task, not just the prompt27Read `prompt.txt` and **every** file in the task's `input/payloads/`. From them extract:28- **`matter_id`** (e.g. `MTR-<NAME>-GJ` / `MTR-<NAME>-SEC`) — the filter for everything.29- **`answer_template.json`** — the output contract (required keys, enums, ordering, precision).30 Treat it as authoritative; never guess enum values or keys.31- Any `*context*.json` / `review_scope.json` — client-facing category labels, credentials,32 cutoff dates. These give *labels only*; the evidence must come from the hub.3334### 2. Reach the hub (network only)35Read `environment_access.md` for the base URL (`GDPEVO_ENV_BASE_URL`) and the `X-API-Key`36credential, and send that header on every call. **Evidence comes only from the hub API.**37Do **not** read the hub's database/source/seed/manifest files, and never read38`train_answers/` or any evaluation/answer file. Sanity-check with `GET /` and `GET /api/schema`.3940### 3. Pull all matter-scoped records41For the matter, pull rows from every table (filter by `matter_id`): `matters`,42`subpoena_categories`, `production_stats`, `custodian_sources`, `review_documents`,43`privilege_entries`, `qc_findings`, `retention_events`, `remediation_actions`. Prefer44`POST /api/query` with `{"sql": "..."}` for precise pulls; the REST `GET /api/*?matter_id=…`45endpoints also work. See `references/hub_api.md`.4647### 4. Separate material issues from decoys — the key step48The hub seeds each matter with a **handful of genuinely material records** plus **many49plausible decoys**. Build your candidate set this way:5051- **ID convention (primary signal).** Material/planted records use the matter's **short52 abbreviation** with a *descriptive* suffix (schematically `RET-<TOK>-<DESCRIPTOR>`,53 `SRC-<TOK>-<CUSTODIAN>-<DEVICE>`, `QC-<TOK>-<DEFECT>`, `PRIV-<TOK>-<DESCRIPTOR>`,54 `DOC-<TOK>-<DESCRIPTOR>` — descriptors are words, and may include a year or version like55 `…-2019` or `…-V3`, not a bare sequence number). **Decoys embed the FULL matter name + a56 zero-padded sequence number**57 (e.g. `PRIV-<FULLNAME>-001`, `RET-<FULLNAME>-007`) and carry routine/benign notes. Start from58 the short-token records as your material candidates.59- **Attribute corroboration.** Confirm materiality with the record's own fields, not the ID60 alone: retention `status` (`post_hold_loss`, `should_exist_missing`, `system_loss`,61 `auto_purged`, `post_hold_partial_recovery` are material; `available` and pre-hold62 policy-compliant destruction are not); custodian `status`/`issue_tags`63 (`lost`, `not_collected`, `available`+`archive_available` are material; `routine` is not);64 qc `issue_type` (`miscoded_*`, `zero_claim*` are material; `family_break`,65 `date_normalization`, `near_duplicate` are noise); privilege `issue_type`66 (`incomplete_log` with a real `withheld − logged` gap, `third_party_waiver`,67 `over_designated`); `production_stats.status` (`zero_claim_contradicted` is material); and doc68 `produced_status` (`not_produced`/`unrecovered`/miscoded-`withheld` are gaps — already69 `produced` docs are **not** a gap even if responsive/interesting).70- **Ignore the hub's own remediation_actions attributes.** `remediation_actions.target_ref`71 can point at material records, but its `owner` / `priority` / `action_type` are deliberately72 wrong and its `*-NOISE-*` / bare-category rows are decoys. Re-derive everything in step 5.73- **Fallback.** If a needed dimension has *no* short-token record (a matter can carry its74 privilege story in numbered entries), select analytically: within the flagged category, take75 the entries with a genuine defect, one representative per `(category, issue_type)` (lowest id).7677### 5. Classify each material issue with the playbook78For every material record, derive its `issue_type`, `severity`, `status`, `source_status`,79`production_impact`, affected categories, `recommended_action`, `owner`, and priority using80`references/domain_playbook.md`. Map only to enum values present in *this* task's template.81Anchor each finding on a stable hub record ID; list all supporting IDs in `source_refs`82sorted ascending; sort category-code lists ascending.8384### 6. Compute metrics and category coverage85- Derive counts from the material records: `unlogged = withheld − logged`; sum boxes/volumes,86 split pre- vs post-hold where the template asks; count each issue class and affected sources.87- Fill **every** metric key the template lists — use `0` / `[]` / `false` when the matter has88 no such fact. Read each metric's own description for its exact scope (some are "selected89 blockers only"). Any material gap ⇒ `production_ready` / `rolling_production_ready` = `false`.90- Category coverage: for each affected category, union the supporting material record IDs91 (sorted), pick a representative status / production_impact / recommended_action, and count92 open issues.9394### 7. Prioritize the action plan95Order actions by the playbook's ladder (disclosure/preservation → privilege exposure →96recode → collect source → supplement log → search archive → over-designation → no-action) and97number ranks per the template's ordering rule (1 = highest). Assign `P0–P3` and `owner` from98the playbook, targeting stable hub IDs.99100### 8. Emit exactly one JSON object101Conform to the template precisely (see `references/output_contract.md`): only the required102top-level keys, only template enum values, all lists sorted per `ordering_rules`, whole-integer103counts, hub IDs verbatim, **no prose outside the JSON**.104105## Guardrails106- Evidence only from the hub API; connection details only from `environment_access.md`.107- Never read database/seed/source/manifest files or any answer/evaluation file.108- Do not invent record IDs, categories, or enum values — use the hub's and the template's.109- Prefer under-reporting a doubtful decoy to inflating the dashboard with noise.