Shell Heuristics · application docs

publisher · enricher-v2 · corpus

postcrime document taxonomy — matter class / enforcement / scheme type

Derived 2026-06-08 from live postcrimedb (33,801 docs). Answers: how to group PR vs complaints vs rule-change PRs, and tag civil/criminal + scheme type.

Key finding

The grouping you want is already latent in source + kind. Only press_release + pdf is genuinely mixed. Don't reshuffle kind — add 3 derived fields.

Dimension 1 — Civil vs Criminal = AGENCY (sources.name), 100% clean

agency matter_class docs authority
doj-sdny criminal 5,951 US Attorney SDNY — indictment/information/superseding_indictment/criminal complaint/plea/sentence
sec-litreleases civil 16,026 SEC Enforcement — litigation releases (always a real case)
sec-pr civil / administrative 11,824 SEC press office — enforcement AND rule-making/notices

SEC has no criminal authority → every SEC doc is civil or administrative. DOJ-SDNY is criminal. That one column gives civil-vs-criminal for free.

Dimension 2 — Enforcement vs non-enforcement (document type)

Always enforcement (no classifier needed) — 15,795 docs: litigation_release, complaint, indictment, information, superseding_indictment, judgment (14,270 sec-litrel + 907 sec-pr + 618 doj). These ARE the matters.

Mixed — need a classifier — 18,006 docs (press_release + pdf):

agency PR total enforcement (title verbs) admin (rule/meeting/appoint) neither
doj-sdny 5,017 4,678 (93%) 35 311
sec-pr 7,095 2,812 (40%) 907 (13%) 3,397 (48%)
  • DOJ PRs ≈ 94% enforcement — trivial.
  • sec-pr is the real ambiguous bucket the user flagged: ~13% are clearly rule adoptions / open meetings / personnel appointments / whistleblower awards / speeches (the "PR which are rule changes or something else"), ~40% clearly enforcement, ~48% need an LLM read.

Strongest existing enforcement signal = case_facts.monetary_amount > 0 (3,410 sec-pr + 3,010 doj PRs carry a penalty/disgorgement). defendants_json is currently sparse (62/288) because that's exactly the field the false-skip drain is repopulating — it will become a strong signal post-drain.

Dimension 3 — Scheme type (NOT in any column — needs new enrichment)

No column holds this. Derive via a new LLM classify pass over body + case_facts.notes + triples, only on is_enforcement=true docs. Proposed securities-fraud enum:

insider_trading, ponzi, pump_and_dump, market_manipulation, accounting_disclosure_fraud, offering_fraud_unregistered, misappropriation, fcpa_bribery, broker_dealer_compliance, crypto_digital_asset, microcap_shell, affinity_fraud, other

Recommended schema add (3 derived fields, no kind change)

  1. matter_class ∈ {criminal, civil, administrative} — rule: doj-sdny → criminal; sec-* → civil, downgraded to administrative when is_enforcement=false.
  2. is_enforcement booleankind ∈ always-enforcement set OR (kind ∈ {press_release,pdf} AND (defendants non-empty OR monetary_amount>0 OR title matches enforcement verbs)). Else admin.
  3. scheme_type enum — new LLM pass (parallel to extract-case-facts), gated on is_enforcement=true.

matter_class + is_enforcement are pure-SQL (run now, zero LLM). scheme_type is the only one needing a model pass.