Document lab
Drop any file and see what is actually inside it. A PDF's pages and the files stapled into it, a workbook's hidden third sheet, a Word file's footer and the sentence someone deleted, an email's attachment, an archive's members — each part with the stage that has to read it next and whether that stage exists.
Drop one file here
Any type. It is not written into a case — testing what a container holds is not the same decision as filing it as evidence, so this reads it in a scratch directory and forgets it.
Readers on this machine — 10 of 10 ready, up to 8.4 MB per file.
tesseract is not installed, so scanned pages can be found but not read
One fixture per reader, decomposed before deployment. Each was built to carry a case the readers have to get right.
mixed-evidence-pdf.pdf — A PDF carrying every component class one can carry: a text page, a hybrid page with a captioned photograph, two page-filling scans, and three files stapled inside the container.
Typed by its bytes as pdf (PDF), read by the pdf reader — which uses pdfinfo, pdftohtml, pdfdetach, ffmpeg.
- sha-256
- 512594a27ec96be9
- nesting depth
- 1 level
- pages
- 4
- produced by
- whoisjson pdf-parts fixture
- creator
- —
- pdf version
- 1.3
- fonts declared
- 3
- acroform
- none
- javascript
- no
- encrypted
- no
- page size
- 595.276 x 841.89 pts (A4)
Identifiers with a fixed shape, and — where one exists — the check digit run against them. These are the keys that join a CDR to a bank statement to an FIR; a name does not, because the same person is spelled four ways.
No identifier value matched anywhere in this artifact. For a masked export that is the expected answer — the header still says what the column holds, below.
Columns that hold one
A header that says msisdn is a claim about what the column holds even when the export is masked, and it is what tells the next stage which join key it is.
- msisdn → Indian mobile number (c015)
- imei → IMEI (c015)
- cell_id → Cell tower id (c015)
distinct counts are summed per component, so one number appearing in two components counts twice. Deduplicating across components is entity resolution's job, not this one's
The routing is real, and every route below is a key in rules/routes.json. Most of the stages it routes to are not built — this is the list of what the file just asked for.
- text_ready4 components
Readable as text already. No model needed.
not builtentity extraction
- image_analysis2 components
A photograph of a place or a person. Goes to face detection and clustering — never to OCR, and never to identification.
not builtface detection and clustering, never identification
- not_evidence1 component
Nothing reads it: a blank page, an empty file, or a raster under the page-furniture floor — a crest, a rule, a stamp edge.
builtnothing — not evidence
- ocr2 components
Pixels of a page and no text for them. Needs character recognition before anything can read it.
builtOCR
- page_raster2 components
This raster is the page. The page's own recognition reads it, so it is not read twice.
builtnothing — the page's own OCR reads it
- classify3 components
A file inside the file. Goes back through the classifier as its own artifact.
builtthe classifier, on the extracted child
- table_ready1 component
Rows and columns already parsed out. Goes to column mapping.
not builtcolumn mapping and row ingestion
4 of 5 images fingerprinted, 1 not — c005: smaller than 1% of the page — logo, rule or stamp.
c004 ~ c013 identical bytes
the content hashes match
the same file twice. The exact-duplicate collapse already accounts for this; it is listed so the two kinds of duplicate are not confused.
every group is a proposal. Nothing here is merged, and a perceptual hash off a 48x48 thumbnail can put two different pages of dense text in the same group.
Indented by where it was found. A file stapled inside this one is opened in turn, up to 2 levels here — and anything past the limit is listed with the depth as its reason rather than left out.
- c001mixed-evidence-pdf.pdfcontainertext_readynot built
document metadata, readable without a model
- Author
- Naharpur Police Station
- CreationDate
- Wed Apr 1 10:30:00 2026 IST
- Encrypted
- no
- Form
- none
- JavaScript
- no
- Keywords
- fixture, decomposer, synthetic
- ModDate
- Wed Apr 1 10:30:00 2026 IST
- PDF version
- 1.3
- Page size
- 595.276 x 841.89 pts (A4)
- Pages
- 4
- Producer
- whoisjson pdf-parts fixture
- Subject
- Mixed-component evidence PDF
- Tagged
- no
- Title
- Case file extract - Naharpur 214/2026
- c002page 1pagepage 1text pagetext_readynot built
a text layer and no significant raster
582 characters in 10 runs · 6% text · 0% raster · 0 rasters
FIRST INFORMATION REPORT (EXTRACT) FIR No.: 214 of 2026 Police Station: Naharpur District: Mohanwadi Date of report: 01 April 2026 Sections: 420, 468, 471 read with 120B Informant states that a consignment was removed from the godown on Dock Road on the night of 01 April 2026 against a delivery challan that does not appear in the warehouse register. The challan book, the register and one mobile ha
- c003page 2pagepage 2hybrid pagetext_readynot built
a text layer and raster regions on the same page; each raster carries its own route
179 characters in 4 runs · 2% text · 5% raster · 2 rasters
ANNEXURE B - PHOTOGRAPH Photograph produced by the informant on 02 April 2026. Not identified by any witness at the time of this report. Photograph, 48 x 62 mm, produced in original.
c004page 2exhibitpage 2scene photographimage_analysisnot builtmatched scene_photograph
exhibit: An artifact in its own right. The route says who reads it. · 5% of the page · rule score 3.5
caption (below): Photograph, 48 x 62 mm, produced in original.
no ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN is set, so nothing here can call a model
rasters/p002-000.jpg · 9 kB
- c005page 2exhibitpage 2not_evidencenot attempted
smaller than 1% of the page — logo, rule or stamp
no raster was written
furniture: Under the floor — a crest, a rule, a stamp edge. · 0% of the page
- c006page 3pagepage 3scanned pageocr
a raster covers the page and there is no text layer
0 characters in 0 runs · 0% text · 100% raster · 1 raster
recognitionfound536 characterstesseract, engGENERAL DIARY ENTRY Naharpur Police Station Entry No. 214 of 2026 Date: 01.April 2026 At about 2140 hours the undersigned received information by: telephone that a consignment. had been moved from the warehouse on Dock Road without the required transport documents. Ateam-was constituted and proceeded tothe spot. The godown. keeper was present and produced a delivery challan which:did not match the
c007page 3exhibitpage 3document scanpage_rasterthis raster is the page; the page's own OCR reads it
page: The page's own read already covers these pixels. · 100% of the page · rule score 10
rasters/p003-000.png · 59 kB
- c008page 4pagepage 4scanned pageocr
a raster covers the page and there is no text layer
0 characters in 0 runs · 0% text · 100% raster · 1 raster
recognitionfound202 characterstesseract, engSEIZURE MEMO Annexure C to Panchnama 1. Ledger, hardbound, 240 pages 2. Delivery challan book, part used 3. Mobile handset, IMEI recorded separately 4. Cash, counted and sealed in presence of panchas
c009page 4exhibitpage 4document scanpage_rasterthis raster is the page; the page's own OCR reads it
page: The page's own read already covers these pixels. · 100% of the page · rule score 8.5
rasters/p004-000.jpg · 48 kB
- c010accused-photograph.jpgattachmentclassify
opened here; its own parts are listed below it
image · JPEG
- c013accused-photograph.jpgexhibitscene photographimage_analysisnot built
matched scene_photograph
exhibit: An artifact in its own right. The route says who reads it. · rule score 3.5
JPEG 480×620 · 0.3 MP · no metadata in the header, which is a fact rather than a silence
- c011keeper-statement.txtattachmentclassify
opened here; its own parts are listed below it
document · Plain text
- c014keeper-statement.txtsectiontext_readynot built
text already in hand
168 characters
Statement of the godown keeper, recorded at the spot. The consignment was loaded on instruction received by telephone. The challan was handed to me already filled in.
- c012tower-dump-extract.csvattachmentclassify
opened here; its own parts are listed below it
data · CSV
- c015tower-dump-extract.csvtabletable_readynot built
5 columns parsed
3 rows · 5 columns · delimiter ","
msisdn → Indian mobile number · the header name only — no value in the sample matched
imei → IMEI · the header name only — no value in the sample matched
cell_id → Cell tower id · the header name only — no value in the sample matched
msisdn,imei,cell_id,start_time,duration_s 9812xxxx41,35xxxxxxxxxx071,NHP-0417,2026-04-01T21:38:11,64 9812xxxx41,35xxxxxxxxxx071,NHP-0417,2026-04-01T21:52:03,12 9873xxxx08,35xxxxxxxxxx933,NHP-0417,2026-04-01T21:39:47,58