| name | investigation-review-hub-answer |
| description | Produce a single-JSON-object answer for an e-discovery / regulatory investigation review task served by the Investigation Review Hub (http://task-env:9017/). Use when a task asks for a production-readiness, retention/preservation, privilege/QC, or cross-system remediation dashboard keyed to a matter ID (MTR-*-GJ / MTR-*-SEC) and an answer_template.json defines the output schema. |
Investigation Review Hub — Structured-JSON Answer Skill
This skill produces the deliverable for tasks built on the shared Investigation Review Hub: a regulatory-investigation / e-discovery review system holding matter metadata, subpoena categories, production stats, custodian sources, review documents, privilege-log entries, QC findings, retention events, and remediation actions. The deliverable is always exactly one JSON object conforming to a task-supplied answer_template.json.
What every task looks like
All tasks on this hub follow the same shape. Recognize it, then run the same playbook:
- A prompt naming a client, a matter ID (
MTR-<CLIENT>-GJ or MTR-<CLIENT>-SEC), and a review workstream (rolling-production gap, retention/hold gap, production-readiness, privilege/QC, cross-system remediation dashboard).
- A context/scope payload (
request_context.json, review_scope.json, or matter_context.json) carrying the matter ID, client, category labels/family, and the base URL.
- An
answer_template.json that is the authoritative output contract: required top-level keys, per-item required keys, enum choices, ordering rules, and numeric precision. The template never contains the answer; it defines field names, types, ordering, and enums.
- The base URL
http://task-env:9017/.
Hard source constraints
- The hub endpoints are the only source of business evidence. Pull matter metadata, categories, production stats, custodian sources, documents, privilege log, QC findings, retention events, and remediation actions from the hub — never from local files.
- Do not inspect environment source files, database/seed files, generation manifests, setup scripts, hidden notes, standard-answer files, or any task answer/evaluation files. If you encounter such material in the working directory, stop and write
contamination_report.txt instead of continuing.
environment_access.md is only for network access (base URL + API key). Treat its contents as access config, not as evidence.
- Use stable record IDs and category codes exactly as they appear in the hub (matter IDs, source IDs, event IDs, finding IDs, entry IDs, action IDs, category codes). Never invent or reformat IDs.
Hub access (see references/hub_endpoints.md for full detail)
Base URL: http://task-env:9017/
SQL endpoint auth header: X-API-Key: review-key-017
Nine resource endpoints return JSON with {count, rows} or a schema object:
GET /api/schema, /api/matters, /api/subpoena-categories, /api/productions, /api/custodian-sources, /api/documents/search, /api/privilege-log, /api/qc-findings, /api/retention-events, /api/remediation-actions.
Read-only SQL: POST /api/query.
Request body uses the sql key (NOT query), with a params array for placeholders:
{"sql": "SELECT ... WHERE matter_id = ?", "params": ["MTR-..."]}
Always send header X-API-Key: review-key-017. Response: {"columns":[...], "row_count":N, "rows":[...], "truncated":bool} — when truncated is true, page or narrow the query.
Playbook (run in order)
- Read all task inputs first. Read the prompt, the context/scope payload, and
answer_template.json completely before querying anything. The template defines the contract you must satisfy.
- Orient on the data model.
GET /api/schema lists every table and its columns (see references/data_model.md). Confirm the exact column names you will select before writing SQL.
- Pin the matter. Pull
/api/matters (or query matters WHERE matter_id = ?) to confirm the matter exists, its hold_date, agency, and investigation type. The hold_date is the pivot for "pre-hold" vs "post-hold" retention loss judgments.
- Pull the category set for that matter.
/api/subpoena-categories?matter_id=... (or SQL). These category codes are the keys you join against in every list field. Most matters use single letters (A, B, C…); SEC matters may use a SEC-* family. Always echo the hub's exact codes.
- Gather evidence per workstream. Query the relevant tables filtered by
matter_id:
- Production gaps / readiness →
production_stats (produced/withheld/responsive counts, zero_claim_reason, status).
- Retention & preservation gaps →
retention_events (status, event_date vs hold_date, policy_section, retention_period_months, volume_count/unit) + custodian_sources (post_hold flag, status).
- Privilege / QC →
privilege_entries (doc_count, withheld_count, logged_count, issue_type, third_party) + qc_findings (issue_type, severity, affected_category) + review_documents (responsiveness, privilege_status, produced_status, issue_tags).
- Remediation / actions →
remediation_actions (action_type, priority, severity, owner, target_ref, due_days).
- Personal-source / archive gaps →
custodian_sources filtered by source_type (personal_phone, personal_messaging, personal_email, *_archive) and status (lost / not_collected / partial / collected).
- Map evidence to template fields. For each finding/risk/issue/category row the template requires, anchor it on a stable hub record ID (
finding_id, event_id, source_id, entry_id, action_id, doc_id). Populate /// with those IDs. Count fields (, , , , volume counts) come from the hub's integer columns; use when a field does not apply.
Cross-cutting judgment rules (distilled from the workstreams)
- Pre-hold vs post-hold: a retention loss with
event_date on or before the matter hold_date (and a valid policy_section) is generally policy-compliant / pre-hold (low or no preservation risk, action no_action_policy_loss-style). A loss after the hold_date, or any loss of a source with no policy basis, is a preservation failure and drives disclosure/forensic-recovery actions. The custodian_sources.post_hold flag is the authoritative marker.
- Privilege log completeness:
withheld − logged = unlogged. Withheld-but-unlogged docs are the privilege_log_gap / withheld_unlogged production impact and trigger supplement_privilege_log. third_party = 1 entries tilt toward waiver assessment; miscoded privilege entries (over-designation, wrong basis) trigger privilege_re_review/privilege_recode_and_log.
- Responsiveness miscoding: documents flagged responsive that should be nonresponsive (or vice versa) appear in
review_documents.responsiveness + issue_tags and in qc_findings with issue_type like responsive_miscoding. These drive recode_and_produce.
- Zero-production claims: a category with
produced_count = 0 and a zero_claim_reason must be tested against the evidence — if responsive docs exist for that category, the zero claim is contradicted (not_ready_zero_claim_contradicted-style status).
- Available archives limit loss: when a destroyed/lost source has a surviving archive of the same
source_type/affected_categories, classify the category as source_gap_with_archive_available (not pure preservation_loss) and route the action to search_archive/restore_from_backup/collect_archive. Only call a loss irretrievable when no archive source covers those categories.
- Personal sources: personal_phone / personal_messaging / personal_email sources that are
not_collected or partial are personal_source_gap; collect via / / .
Output conventions (see references/output_conventions.md)
- Exactly one JSON object; no prose.
- Top-level keys = template's
required_top_level_keys, no extras.
- Every list item includes all
item_required_keys.
- Enums must match template strings character-for-character (including underscores and casing).
- All counts are whole integers;
0 (not null) when a count field is not applicable; use null only where the template explicitly allows it (e.g. dates, third_party, policy_section).
- Dates are
YYYY-MM-DD strings.
- Sort all lists per
ordering_rules before emitting.
Pre-submit checklist