Investigation Review Hub — matter gap / remediation analysis
You are acting as an e-discovery review analyst for outside counsel. A task names
one legal matter (e.g. MTR-<CLIENT>-<GJ|SEC>) and asks for a structured
JSON deliverable about production gaps, preservation/retention losses,
privilege defects, QC/coding defects, and a prioritized remediation plan. The
evidence lives in a read-only Investigation Review Hub HTTP API. Your job is
to pull that evidence, separate the material issues from seeded noise,
normalize each into the enums the task's answer_template.json defines, compute
the numeric metrics, and emit exactly one JSON object.
The output schema is different for every task (different top-level keys,
enums, and field names). Never assume the shape — read the task's
answer_template.json first and let it drive everything. This skill teaches the
reasoning and data access that stay constant across schemas.
0. Inputs you will be handed
For each run, read (do not skip any):
input/prompt.txt — the narrative ask. It names the matter, the deliverable
type, and usually a short list of focus areas (e.g. "off-site bid-file
retention, privilege exceptions, personal messaging sources, deleted
collaboration-channel data, production coding quality"). Treat that list as a
checklist of the material issues you must find.
input/payloads/answer_template.json — the output contract. Field names,
types, ordering rules, numeric precision, and the exact enums/enum_choices
you must choose from. This is authoritative.
input/payloads/*.json (e.g. request_context.json, review_scope.json,
matter_context.json) — client-facing context and category labels only
(a category_synopsis / category-code list). Use these for the matter_id,
category codes, and human labels. Do not treat any evidence numbers here as
fact — event/source/document/metric evidence must come from the hub.
environment_access.md (at the run root) — how to reach the hub: base URL and
the X-API-Key. See §1.
Constraint repeated in every prompt: use only the hub endpoints (plus the
task-local payloads for labels). Never read the environment's source files,
database files, seeds, generated manifests, or any answer/evaluation files, even
if present.
1. Reach the hub
Get the base URL and key from the run context, in this order of preference:
environment_access.md (GDPEVO_ENV_BASE_URL=..., X-API-Key: ...), then any
environment_base_url / query_api_key_header fields in the payloads. Do not
hard-code — different runs may use a different host/key. (Observed default:
base http://task-env:9017/, header X-API-Key: review-key-017.) Always send
the X-API-Key header even if a probe suggests it is not strictly enforced — it
is the documented contract.
Endpoints (all GET unless noted). Every table endpoint accepts a matter_id
query filter — always filter to your matter:
GET / service banner + endpoint list
GET /api/schema table/column definitions
GET /api/matters matters
GET /api/subpoena-categories subpoena_categories (request categories)
GET /api/productions production_stats (per-category batch counts)
GET /api/custodian-sources custodian_sources (custodians, devices, archives)
GET /api/documents/search review_documents (CAPPED at 100 rows)
GET /api/privilege-log privilege_entries
GET /api/qc-findings qc_findings
GET /api/retention-events retention_events
GET /api/remediation-actions remediation_actions ← escalation anchor (§3)
POST /api/query {"sql":"SELECT ..."} read-only SQLite, SELECT-only,
returns {columns,row_count,rows,truncated}
documents/search truncates at 100 rows; for complete/aggregated reads use
POST /api/query. scripts/pull_matter.sh <BASE_URL> <KEY> <MATTER_ID> dumps
every table for one matter to help you work. See reference/hub_data_model.md
for the full column list.
2. Workflow
- Confirm the matter.
GET /api/matters, find your matter_id; note
hold_date (the litigation-hold date — pivotal for retention analysis) and
agency/investigation_type.
- Load category labels from the task payload and/or
/api/subpoena-categories. These are the category_codes you will reference.
- Pull every evidence table for the matter (use
pull_matter.sh or query
each endpoint with ?matter_id=).
- Select the material issues and discard noise — this is the crux; see §3
and
reference/material_vs_noise.md.
- Classify each material record into the template's enums — see §4 and
reference/enum_crosswalks.md.
- Roll up categories — for each affected request category, summarize its
status/impact and the supporting record IDs.
- Compute metrics exactly as each metric's description dictates — see §5 and
reference/metrics_and_action_plan.md.
- Build the prioritized action plan with normalized action types, owners,
priorities, and (if the schema has it)
due_days — see §5.
- Assemble, order, validate, emit — see §6.
3. Material vs. noise — the core discipline
The hub is intentionally salted with realistic-looking noise so a naive dump
fails. The gold deliverable contains only the escalated, material issues.
Primary anchor — remediation_actions. The non-noise rows of
/api/remediation-actions are a curated list of the matter's real escalated
issues; each target_ref points at a material record (a RET-…, SRC-…,
PRIV-…, QC-…, or DOC-… id). Start from this set.
- Noise remediation rows are recognizable:
action_type in
{load_file_cleanup, custodian_followup, sampling_review}, description
literally "Routine action included as realistic operational noise", and
target_ref is a bare category code (e.g. C, F, R11, SEC-1) rather
than a record ID. Drop these.
The anchor is necessary but not sufficient — apply judgment on top of it:
- Some material records are not in
remediation_actions (e.g. a
privilege-log gap or third-party-waiver entry for the matter's privilege-focus
category). Add these when the task's focus areas or a QC finding point to them.
- A remediation-anchored target may still be dropped if it is not material to
this deliverable (e.g. an over-designation cleanup left out of a
preservation-centric dashboard). Let the template's enums and the prompt's
focus list decide.
Telling material from noise on any evidence row:
- IDs: material records usually carry a descriptive id embedding a
custodian/device/topic token (
SRC-<M>-ALDEN-PHONE, RET-<M>-BOX-POST,
QC-<M>-ZERO-CLAIM, PRIV-<M>-WINSLOW). Pure sequential ids
(SRC-<MATTER>-007, QC-<MATTER>-004) are usually noise — but not always, so
confirm with the note and issue type.
- Notes: material notes describe a concrete, specific defect with real
numbers/dates/names ("Personal iPhone erased on after subpoena
issuance", "Privilege log covers N of M withheld … documents", "Two boxes
destroyed after the hold date", "zero-production claim contradicted by two
responsive bid emails"). Noise notes are generic/hedging: "…included as
realistic operational noise", "…create similar labels across matters",
"ordinary review variance", "similar to escalated records in another matter",
"requested re-sampling before escalation", "remediated by archive collection",
"no unresolved production impact", "not dispositive without source comparison".
- Issue type / status / severity: genuine defect signals are material even at
medium severity; ordinary-variance types are noise even at "high" severity.
See the per-table lists in
reference/material_vs_noise.md.
Cross-check the material set against the prompt's focus list: every named focus
area should map to at least one selected record, and you should not have invented
issues outside it.
4. Classify into the template enums
For each material record, populate the item fields using only the enum values
listed in the task's template. The hub's raw vocabulary is richer than any single
template's enum set, so you must map. Full crosswalk in
reference/enum_crosswalks.md; the essentials:
- Retention events (
retention_events.status): post_hold_loss → highest
risk, disclosable; should_exist_missing → locate; policy_destroyed_pre_hold
→ no-fault/low, no action; system_loss/auto_purged on a messaging/voice
system → active-system loss / communication gap (document it). retained /
available → a retained source, not a loss.
- Custodian sources (
custodian_sources.status): lost (esp. a post-hold,
personal device) → preservation failure, critical; not_collected → collection
gap (personal device → collect device; enterprise site → collect source);
available + issue tag archive_available/remediation_source → an available
archive (a remediation path, not a loss); partial_collection → partial.
- Privilege entries (
privilege_entries.issue_type): incomplete_log →
privilege-log gap, unlogged = withheld_count − logged_count, supplement the
log; third_party_waiver (with third_party=1) → waiver exposure, waiver
assessment + disclosure; over_designated → business docs withheld as
privileged, downgrade/QC (include only when material to this deliverable);
clean/family_mismatch → noise.
- QC findings (
qc_findings.issue_type): miscoded_nonresponsive /
zero_claim_contradiction → responsive material coded out / not produced →
recode & produce (its source_ref names the doc(s)); miscoded_privilege →
privileged coded non-privileged → privilege recode. near_duplicate,
metadata_gap, family_break, duplicate_overlay, date_normalization,
family_mismatch → noise.
- Counts come from the anchor record: privilege
withheld_count/
logged_count (unlogged = the difference); QC doc_count; retention
volume_count + volume_unit; a single lost/uncollected source counts as 1
source and 0 documents. Use 0 where a count does not apply, never null (unless
the field explicitly allows null).
affected_categories/category_impacts come from the record's
affected_categories/affected_category/category_impacts/category_code
field. Always uppercase and sort ascending; dedupe.
5. Metrics and the action plan
Metrics — do not guess. Read each metric key's description in the template
and compute it from your selected material set (not the raw tables). Recurring
definitions and worked derivations are in
reference/metrics_and_action_plan.md. Watch for scoped metrics — e.g. a
"destroyed box count" that only sums volume_count where volume_unit == boxes,
or privilege counts drawn "from selected incomplete-log blockers only". A
production_ready / rolling_production_ready boolean is false whenever any
open material gap exists.
Action plan — synthesize a normalized plan; do not copy the hub's
remediation_actions rows verbatim (their owner/priority/action_type use a
different vocabulary). For each material issue (or logical group of issues):
- Choose
action_type from the template enum by the defect: preservation
loss/spoliation → disclose (a lost post-subpoena personal device also warrants a
forensic-recovery action); uncollected source → collect source / personal
device; available archive → collect/search archive; responsiveness miscode →
recode & produce; privilege-log gap → supplement log; waiver → waiver
assessment & disclosure; privileged-miscode / over-designation → privilege
recode / QC remediation; should-exist-missing → locate; active-system loss →
document the gap; pre-hold policy loss → no action.
- Choose
owner from the template enum by the action, not by the hub's owner
(disclosure→outside/litigation counsel; forensic recovery / device or archive
collection→forensics or ediscovery vendor; enterprise collection→client IT;
recode/QC→review vendor/QC; log supplement→privilege team; waiver→privilege
counsel; locate→compliance/audit; system-gap doc→IT messaging; policy-loss→
records management).
- Rank by legal urgency: P0 disclosable post-hold/spoliation losses; P1
uncollected key sources, privilege-log gaps, waiver assessments, responsiveness
recodes, privilege miscoding; P2 over-designation and lower-severity gaps;
P3 monitor-only. Set
priority_rank/rank to a 1-based dense order.
- If the schema has
due_days, assign by action type: disclose ≈ 3, waiver ≈ 3,
recode/supplement-log/privilege-recode ≈ 5, collect personal device ≈ 7, search
archive ≈ 10 (see the reference table).
6. Assemble, order, validate, emit
- Include exactly the
required_top_level_keys, and every
item_required_keys field on every list item — no extra keys, no omissions.
- Apply the template's
ordering_rules precisely (e.g. findings by id ascending;
actions by rank ascending; category lists sorted ascending). Sort every inner
id/category list ascending and deduped.
- Respect
numeric_precision: counts are whole integers; use 0 (not null) for
not-applicable counts unless the field allows null; booleans are real booleans.
- Use stable hub ids exactly as they appear (matter, source, event, QC
finding, document, privilege-entry, category). Do not rename or invent ids;
where the schema uses an
action_id, mint a clean sequential id
(ACT-<TOKEN>-001, …) only if the template expects one.
- Output one JSON object and nothing else — no prose, no code fences, no
trailing commentary.
Self-check before emitting:
- Every prompt focus area is represented; no noise rows leaked in (re-scan ids and
notes).
unlogged = withheld − logged holds everywhere; metric counts equal what the
selected records imply.
- Every enum value used is a member of the corresponding template enum.
- Ordering, required keys, and precision all satisfy the template.
- The object parses as valid JSON.
Reference files
reference/hub_data_model.md — endpoints, tables, columns, query recipes.
reference/material_vs_noise.md — per-table material/noise signal catalog.
reference/enum_crosswalks.md — hub raw value → template enum mappings.
reference/metrics_and_action_plan.md — metric definitions, owner/priority/
due-days derivation, worked (schematic) examples.
scripts/pull_matter.sh — dump all tables for one matter.
1---2name: investigation-review-hub-gap-analysis-53description: Produce a structured-JSON legal e-discovery deliverable (production gap analysis, retention & litigation-hold gap review, cross-system remediation dashboard, or production-readiness review) for a single matter, sourced from a networked "Investigation Review Hub" API and conforming exactly to a provided answer_template.json. Use when a task references an Investigation Review Hub / review hub base URL, an X-API-Key, subpoena/request categories, custodian sources, privilege log, QC findings, retention events, or remediation actions, and asks for a JSON gap/remediation/readiness answer.4---56# Investigation Review Hub — matter gap / remediation analysis78You are acting as an e-discovery review analyst for outside counsel. A task names9one legal **matter** (e.g. `MTR-<CLIENT>-<GJ|SEC>`) and asks for a structured10**JSON** deliverable about production gaps, preservation/retention losses,11privilege defects, QC/coding defects, and a prioritized remediation plan. The12evidence lives in a read-only **Investigation Review Hub** HTTP API. Your job is13to pull that evidence, separate the **material** issues from seeded **noise**,14normalize each into the enums the task's `answer_template.json` defines, compute15the numeric metrics, and emit exactly one JSON object.1617The output schema is **different for every task** (different top-level keys,18enums, and field names). Never assume the shape — read the task's19`answer_template.json` first and let it drive everything. This skill teaches the20*reasoning and data access* that stay constant across schemas.2122## 0. Inputs you will be handed2324For each run, read (do not skip any):2526- `input/prompt.txt` — the narrative ask. It names the matter, the deliverable27 type, and usually a short list of **focus areas** (e.g. "off-site bid-file28 retention, privilege exceptions, personal messaging sources, deleted29 collaboration-channel data, production coding quality"). Treat that list as a30 checklist of the material issues you must find.31- `input/payloads/answer_template.json` — **the output contract.** Field names,32 types, ordering rules, numeric precision, and the exact `enums`/`enum_choices`33 you must choose from. This is authoritative.34- `input/payloads/*.json` (e.g. `request_context.json`, `review_scope.json`,35 `matter_context.json`) — client-facing context and **category labels only**36 (a `category_synopsis` / category-code list). Use these for the `matter_id`,37 category codes, and human labels. Do **not** treat any evidence numbers here as38 fact — event/source/document/metric evidence must come from the hub.39- `environment_access.md` (at the run root) — how to reach the hub: base URL and40 the `X-API-Key`. See §1.4142Constraint repeated in every prompt: use **only** the hub endpoints (plus the43task-local payloads for labels). Never read the environment's source files,44database files, seeds, generated manifests, or any answer/evaluation files, even45if present.4647## 1. Reach the hub4849Get the base URL and key from the run context, in this order of preference:50`environment_access.md` (`GDPEVO_ENV_BASE_URL=...`, `X-API-Key: ...`), then any51`environment_base_url` / `query_api_key_header` fields in the payloads. Do not52hard-code — different runs may use a different host/key. (Observed default:53base `http://task-env:9017/`, header `X-API-Key: review-key-017`.) Always send54the `X-API-Key` header even if a probe suggests it is not strictly enforced — it55is the documented contract.5657Endpoints (all `GET` unless noted). Every table endpoint accepts a `matter_id`58query filter — always filter to your matter:5960```61GET / service banner + endpoint list62GET /api/schema table/column definitions63GET /api/matters matters64GET /api/subpoena-categories subpoena_categories (request categories)65GET /api/productions production_stats (per-category batch counts)66GET /api/custodian-sources custodian_sources (custodians, devices, archives)67GET /api/documents/search review_documents (CAPPED at 100 rows)68GET /api/privilege-log privilege_entries69GET /api/qc-findings qc_findings70GET /api/retention-events retention_events71GET /api/remediation-actions remediation_actions ← escalation anchor (§3)72POST /api/query {"sql":"SELECT ..."} read-only SQLite, SELECT-only,73 returns {columns,row_count,rows,truncated}74```7576`documents/search` truncates at 100 rows; for complete/aggregated reads use77`POST /api/query`. `scripts/pull_matter.sh <BASE_URL> <KEY> <MATTER_ID>` dumps78every table for one matter to help you work. See `reference/hub_data_model.md`79for the full column list.8081## 2. Workflow82831. **Confirm the matter.** `GET /api/matters`, find your `matter_id`; note84 `hold_date` (the litigation-hold date — pivotal for retention analysis) and85 `agency`/`investigation_type`.862. **Load category labels** from the task payload and/or87 `/api/subpoena-categories`. These are the `category_code`s you will reference.883. **Pull every evidence table** for the matter (use `pull_matter.sh` or query89 each endpoint with `?matter_id=`).904. **Select the material issues** and discard noise — this is the crux; see §391 and `reference/material_vs_noise.md`.925. **Classify** each material record into the template's enums — see §4 and93 `reference/enum_crosswalks.md`.946. **Roll up categories** — for each affected request category, summarize its95 status/impact and the supporting record IDs.967. **Compute metrics** exactly as each metric's description dictates — see §5 and97 `reference/metrics_and_action_plan.md`.988. **Build the prioritized action plan** with normalized action types, owners,99 priorities, and (if the schema has it) `due_days` — see §5.1009. **Assemble, order, validate, emit** — see §6.101102## 3. Material vs. noise — the core discipline103104The hub is intentionally salted with realistic-looking **noise** so a naive dump105fails. The gold deliverable contains only the **escalated, material** issues.106107**Primary anchor — `remediation_actions`.** The non-noise rows of108`/api/remediation-actions` are a curated list of the matter's real escalated109issues; each `target_ref` points at a material record (a `RET-…`, `SRC-…`,110`PRIV-…`, `QC-…`, or `DOC-…` id). Start from this set.111- **Noise remediation rows** are recognizable: `action_type` in112 {`load_file_cleanup`, `custodian_followup`, `sampling_review`}, `description`113 literally "Routine action included as realistic operational noise", and114 `target_ref` is a **bare category code** (e.g. `C`, `F`, `R11`, `SEC-1`) rather115 than a record ID. Drop these.116117**The anchor is necessary but not sufficient — apply judgment on top of it:**118- Some material records are **not** in `remediation_actions` (e.g. a119 privilege-log gap or third-party-waiver entry for the matter's privilege-focus120 category). Add these when the task's focus areas or a QC finding point to them.121- A remediation-anchored target may still be **dropped** if it is not material to122 this deliverable (e.g. an over-designation cleanup left out of a123 preservation-centric dashboard). Let the template's enums and the prompt's124 focus list decide.125126**Telling material from noise on any evidence row:**127- **IDs:** material records usually carry a *descriptive* id embedding a128 custodian/device/topic token (`SRC-<M>-ALDEN-PHONE`, `RET-<M>-BOX-POST`,129 `QC-<M>-ZERO-CLAIM`, `PRIV-<M>-WINSLOW`). Pure sequential ids130 (`SRC-<MATTER>-007`, `QC-<MATTER>-004`) are usually noise — but not always, so131 confirm with the note and issue type.132- **Notes:** material notes describe a **concrete, specific** defect with real133 numbers/dates/names ("Personal iPhone erased on <date> after subpoena134 issuance", "Privilege log covers N of M withheld … documents", "Two boxes135 destroyed after the hold date", "zero-production claim contradicted by two136 responsive bid emails"). Noise notes are generic/hedging: "…included as137 realistic operational noise", "…create similar labels across matters",138 "ordinary review variance", "similar to escalated records in another matter",139 "requested re-sampling before escalation", "remediated by archive collection",140 "no unresolved production impact", "not dispositive without source comparison".141- **Issue type / status / severity:** genuine defect signals are material even at142 medium severity; ordinary-variance types are noise even at "high" severity.143 See the per-table lists in `reference/material_vs_noise.md`.144145Cross-check the material set against the prompt's focus list: every named focus146area should map to at least one selected record, and you should not have invented147issues outside it.148149## 4. Classify into the template enums150151For each material record, populate the item fields using **only** the enum values152listed in the task's template. The hub's raw vocabulary is richer than any single153template's enum set, so you must map. Full crosswalk in154`reference/enum_crosswalks.md`; the essentials:155156- **Retention events** (`retention_events.status`): `post_hold_loss` → highest157 risk, disclosable; `should_exist_missing` → locate; `policy_destroyed_pre_hold`158 → no-fault/low, no action; `system_loss`/`auto_purged` on a messaging/voice159 system → active-system loss / communication gap (document it). `retained` /160 `available` → a retained source, not a loss.161- **Custodian sources** (`custodian_sources.status`): `lost` (esp. a post-hold,162 personal device) → preservation failure, critical; `not_collected` → collection163 gap (personal device → collect device; enterprise site → collect source);164 `available` + issue tag `archive_available`/`remediation_source` → an available165 archive (a remediation path, not a loss); `partial_collection` → partial.166- **Privilege entries** (`privilege_entries.issue_type`): `incomplete_log` →167 privilege-log gap, **unlogged = withheld_count − logged_count**, supplement the168 log; `third_party_waiver` (with `third_party=1`) → waiver exposure, waiver169 assessment + disclosure; `over_designated` → business docs withheld as170 privileged, downgrade/QC (include only when material to this deliverable);171 `clean`/`family_mismatch` → noise.172- **QC findings** (`qc_findings.issue_type`): `miscoded_nonresponsive` /173 `zero_claim_contradiction` → responsive material coded out / not produced →174 recode & produce (its `source_ref` names the doc(s)); `miscoded_privilege` →175 privileged coded non-privileged → privilege recode. `near_duplicate`,176 `metadata_gap`, `family_break`, `duplicate_overlay`, `date_normalization`,177 `family_mismatch` → noise.178- **Counts** come from the anchor record: privilege `withheld_count`/179 `logged_count` (unlogged = the difference); QC `doc_count`; retention180 `volume_count` + `volume_unit`; a single lost/uncollected source counts as 1181 source and 0 documents. Use `0` where a count does not apply, never null (unless182 the field explicitly allows null).183- **`affected_categories`/`category_impacts`** come from the record's184 `affected_categories`/`affected_category`/`category_impacts`/`category_code`185 field. Always uppercase and sort ascending; dedupe.186187## 5. Metrics and the action plan188189**Metrics** — do not guess. Read each metric key's description in the template190and compute it from your *selected material set* (not the raw tables). Recurring191definitions and worked derivations are in192`reference/metrics_and_action_plan.md`. Watch for scoped metrics — e.g. a193"destroyed box count" that only sums `volume_count` where `volume_unit == boxes`,194or privilege counts drawn "from selected incomplete-log blockers only". A195`production_ready` / `rolling_production_ready` boolean is `false` whenever any196open material gap exists.197198**Action plan** — synthesize a normalized plan; do **not** copy the hub's199`remediation_actions` rows verbatim (their `owner`/`priority`/`action_type` use a200different vocabulary). For each material issue (or logical group of issues):201- Choose `action_type` from the template enum by the defect: preservation202 loss/spoliation → disclose (a lost post-subpoena personal device also warrants a203 forensic-recovery action); uncollected source → collect source / personal204 device; available archive → collect/search archive; responsiveness miscode →205 recode & produce; privilege-log gap → supplement log; waiver → waiver206 assessment & disclosure; privileged-miscode / over-designation → privilege207 recode / QC remediation; should-exist-missing → locate; active-system loss →208 document the gap; pre-hold policy loss → no action.209- Choose `owner` from the template enum by the action, not by the hub's owner210 (disclosure→outside/litigation counsel; forensic recovery / device or archive211 collection→forensics or ediscovery vendor; enterprise collection→client IT;212 recode/QC→review vendor/QC; log supplement→privilege team; waiver→privilege213 counsel; locate→compliance/audit; system-gap doc→IT messaging; policy-loss→214 records management).215- Rank by legal urgency: **P0** disclosable post-hold/spoliation losses; **P1**216 uncollected key sources, privilege-log gaps, waiver assessments, responsiveness217 recodes, privilege miscoding; **P2** over-designation and lower-severity gaps;218 **P3** monitor-only. Set `priority_rank`/`rank` to a 1-based dense order.219- If the schema has `due_days`, assign by action type: disclose ≈ 3, waiver ≈ 3,220 recode/supplement-log/privilege-recode ≈ 5, collect personal device ≈ 7, search221 archive ≈ 10 (see the reference table).222223## 6. Assemble, order, validate, emit224225- Include **exactly** the `required_top_level_keys`, and every226 `item_required_keys` field on every list item — no extra keys, no omissions.227- Apply the template's `ordering_rules` precisely (e.g. findings by id ascending;228 actions by rank ascending; category lists sorted ascending). Sort every inner229 id/category list ascending and deduped.230- Respect `numeric_precision`: counts are whole integers; use `0` (not null) for231 not-applicable counts unless the field allows null; booleans are real booleans.232- Use **stable hub ids exactly** as they appear (matter, source, event, QC233 finding, document, privilege-entry, category). Do not rename or invent ids;234 where the schema uses an `action_id`, mint a clean sequential id235 (`ACT-<TOKEN>-001`, …) only if the template expects one.236- Output **one JSON object and nothing else** — no prose, no code fences, no237 trailing commentary.238239**Self-check before emitting:**240- Every prompt focus area is represented; no noise rows leaked in (re-scan ids and241 notes).242- `unlogged = withheld − logged` holds everywhere; metric counts equal what the243 selected records imply.244- Every enum value used is a member of the corresponding template enum.245- Ordering, required keys, and precision all satisfy the template.246- The object parses as valid JSON.247248## Reference files249- `reference/hub_data_model.md` — endpoints, tables, columns, query recipes.250- `reference/material_vs_noise.md` — per-table material/noise signal catalog.251- `reference/enum_crosswalks.md` — hub raw value → template enum mappings.252- `reference/metrics_and_action_plan.md` — metric definitions, owner/priority/253 due-days derivation, worked (schematic) examples.254- `scripts/pull_matter.sh` — dump all tables for one matter.