Heuristics — the fingerprint signals
Two categories:
- EDGAR fingerprint signals — rule-based, deterministic. Output: NDJSON files on
node-eighteen. Produced by the siblingedgar-fraud-scanproject, consumed by postcrime-heuristics + ciks-banana. - In-corpus enrichment signals — produced by this repo's workflows in
processor/src/extract/. Output: columns ondocuments+ rows incase_facts/triples/entities.
The line between (1) and (2) is structural: (1) scans every issuer ever filed with the SEC, (2) decorates only documents we already crawled into corpus.db.
Part 1 — EDGAR fingerprint signals
Live at: node-eighteen:/mnt/oink/docker/edgar-fraud-scan/data/flagged/*.ndjson.
Refresh status: last touched 2026-05-12 (mtime 14:34). All four files. GAP: stale by ~1 week as of 2026-05-19; refresh cadence is owned by edgar-fraud-scan, not this repo. Trigger a refresh via the EDGAR side or coordinate with whoever owns edgar-cik-cli pulls.
Common envelope
Every NDJSON row has the same envelope:
{
"cik": "0001372183",
"rule": "<rule-name>",
"accession": "<base-filing-accession>",
"form": "8-K",
"score": 0.3,
"evidence": [
{ "accession": "...", "field": "...", "value": "...", "snippet": "..." }
],
"ts": "2026-05-01T15:12:30.355Z"
}
score is rule-specific (some return 0–1, some {0, 0.3, 1}); evidence is an array of prior or sibling filings the rule found supporting the flag.
1. edgarizer_fingerprint (99 MB)
What it detects: filings produced via the same filing agent + template combo as other suspect filings. The "edgarizer" pattern is the same shop pumping out S-1s for a chain of shells.
How it's computed: edgar-fraud-scan keeps a set of known shell-friendly filing-agent CIK prefixes (e.g. 0001140361, used by Edgarizer LLC). Any filing whose filing-agent CIK matches gets a hit, with the prior filings of that agent listed as evidence.
Example hit:
{"cik":"0000320193","rule":"edgarizer_fingerprint","accession":"...","form":"8-K","score":1,
"evidence":[{"accession":"0001140361-26-017175","field":"filing_agent_cik_prefix",
"snippet":"filing agent CIK prefix: 0001140361"}]}
(Apple is in there with score=1 — the signal flags the agent, not Apple's substance. Treat raw hits as candidates, not verdicts.)
TODO: reconcile against the ciks-banana/heuristics/edgar-heuristics.json curated list (next to litigation-curated.json) so we know which agent CIK prefixes are "known Cane scheme" vs "Edgar-style filing shop but unrelated".
2. reg_s_issuance (102 MB)
What it detects: filings citing Regulation S (offshore offerings) — a recurring shell-network method to issue stock to nominal foreign holders who then dump on US markets.
How it's computed: regex match for "Regulation S" or "Reg. S" with section-citing context near issuance language.
Example:
{"rule":"reg_s_issuance","score":0.3,"evidence":[{"field":"reg_s_reference",
"snippet":"...there are no transactions between Mr. Ternus and Apple..."}]}
Score 0.3 is the "incidental mention" tier; score 1 is for filings that actually use Reg S for the issuance. The Apple example above is a 0.3 — the phrase "Regulation S-K" tripped the matcher.
3. promissory_note_clauses (58 MB)
What it detects: filings that disclose convertible promissory notes — especially "death-spiral" notes (variable-conversion debt that dilutes common stock as price drops). This is the Cane Clark fingerprint.
How it's computed: regex over filing text for note-existence + maturity + conversion language. Score reflects how many of those sub-patterns hit.
Example:
{"rule":"promissory_note_clauses","score":0.3,"evidence":[{"field":"note_existence",
"snippet":"...aggregate principal amount of $91.3 billion (collectively the “Notes”)..."}]}
(Again Apple is in there at 0.3 with their bond issuance — substance does not equal fraud. Cane-flavoured hits are the small issuers with sub-$1m notes that convert to common.)
4. opinion_letter_presence (1.5 MB)
What it detects: Rule 144 opinion letters from law firms that have signed off on shell-network issuances. This is the smallest file and the highest-quality lead — these letters are the legal-side fingerprint.
How it's computed: extracts firm names from opinion-letter signature blocks.
Example:
{"rule":"opinion_letter_presence","score":1,"evidence":[
{"field":"opinion_firm","value":"The Loev Law Firm","snippet":"...The Loev Law Firm, PC..."}]}
This is the file to grep for Cane, Clark, Loev, etc.
Spot-check schemas
ssh rooot@node-eighteen \
'for f in /mnt/oink/docker/edgar-fraud-scan/data/flagged/*.ndjson; do \
echo "=== $f ==="; head -1 "$f"; ls -la "$f"; done'
Part 2 — In-corpus enrichment signals
These run on every crawled document via the federation queue. Each is a WorkflowDef with selectSql() (what to scan), process(doc) (what to compute), and an applyEndpoint.
| Signal | File | Type | Output |
|---|---|---|---|
case-facts |
processor/src/extract/case-facts.ts |
regex/heuristic, no LLM | case_facts.{defendants_json, first_act_date, plea_date, sentence_date, monetary_amount} |
entities |
processor/src/extract/entities.ts |
regex + canonicalise | entities + mentions rows |
triples |
processor/src/extract/triples.ts |
LLM via pool-fraud-triples (qwen3:8b) |
triples table |
scheme-classify |
processor/src/extract/scheme-classify.ts |
LLM, JSON-schema-constrained | documents.{scheme, scheme_confidence, scheme_classified_at, scheme_slug} |
format-title |
processor/src/extract/title-format-workflow.ts |
regex+composite | documents.{title_formatted, title_format_source} |
title-llm |
processor/src/extract/title-llm.ts |
LLM Bluebook fallback | same columns, title_format_source='llm' |
link-references |
processor/src/extract/link-references.ts |
regex + JSON | documents.reference_filing_json |
summarize |
processor/src/extract/summarize.ts |
LLM (1/3/5/7 sentence/paragraph) | documents.summary_* columns |
refetch-pdf |
processor/src/extract/refetch-pdf.ts |
HTTP | repairs missing pdf_path |
ocr-recover |
processor/src/extract/ocr-recover.ts |
tesseract sidecar | repopulates body for [OCR_UNRECOVERABLE docs |
case-facts — currently the cutover pilot
- Deterministic regex over
body. - Extracts: defendant list, first-act date, plea date, sentence date, max dollar amount.
- LLM-free → fast → ideal canary for
fraud-enricher-v2. - Output column: writes to
case_factstable via/apply/case-facts.
scheme-classify
- LLM call via
gpumon-ingresspoolpool-fraud-triples(qwen3:8b,enable_thinking=false). - Constrained to the fraud taxonomy at
docs/stats/01-fraud-taxonomy.md:- Layer 0 buckets:
corporate-fraud,financial-fraud,health-care-fraud,cyber-fraud,public-corruption,obstruction,racketeering,non-corporate. - Layer 1 (securities-fraud sub-types):
pump-and-dump,unregistered-securities,insider-trading,market-manipulation,accounting-fraud,pre-ipo-fraud,ponzi,advance-fee,affinity-fraud,boiler-room,fcpa,crypto-securities,broker-dealer-fraud,investment-adviser-fraud.
- Layer 0 buckets:
- Drives the
/scheme/[slug]pages.
format-title + title-llm
format-titledoes regex (clean H1) + composite (caption + case-num + date) — covers ~55% of corpus cleanly. Source codes:regex,composite,fallback.title-llmis the LLM fallback for the ~45% the deterministic pass markedfallback. Synthesises Bluebook-style titles, e.g."SEC v. Harsh V. Patel, No. 1:26-cv-03203 (S.D.N.Y. Apr. 20, 2026), alleged ..."— see_overnight-questions.mdQ12.
link-references
- Pulls
(case_number, accession_no, citation)references out of body text → JSON array →documents.reference_filing_json. - Search-ui renders these as "Related" anchors on the document page (commit
815b460).
What's NOT yet a heuristic in this repo
Surfaced under "Goals" in frontend.md and roadmap.md:
GAP:agent-bypass — currently runs asedgar-agent-bypassswarm service (sibling EDGAR pipeline), no postcrime-heuristics workflow that joins its output todocuments.GAP:rm-expander — same,edgar-rm-expanderrunning, output not joined here.GAP:officer-transition-patterns — no extractor exists; would be a workflow that scans 8-Ks for the "officer resigns + new officer with same address" pattern.GAP:sic-anomalies —ciks-banana/cane-network/is referenced in the brief but does not exist on disk (lsreturns "No such file"). The closest live data isciks-banana/.vercel/output/static/ciks/heuristics/.TODO:cross-corpus join —docs/refactor/edgar-indexer-schema.mdis the scaffolded plan; Phase F in CHANGELOG marked "scaffolded" withTODO(schema)markers. No live data yet.