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.

Build progress

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.

ZIP archive · stdlibWord · stdlibEmail · stdlibImageAudio and videoPDFPowerPoint · stdlibCSV, TSV, JSON · stdlibPlain text, HTML, transcripts · stdlibExcel · stdlib

tesseract is not installed, so scanned pages can be found but not read

Or look at one that is already taken apart

One fixture per reader, decomposed before deployment. Each was built to carry a case the readers have to get right.

mixed-evidence-pdf.pdfA 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.

mixed-evidence-pdf.pdfprebuilt fixture · 146 kB

Typed by its bytes as pdf (PDF), read by the pdf reader — which uses pdfinfo, pdftohtml, pdfdetach, ffmpeg.

15components
3files inside the file
2images that are exhibits
4parts needing a model
0held for a person
0found, not opened
3 files inside the file1 the artifact itself5 images4 pages1 text parts1 tables1 hybrid page2 scanned page1 text page
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)
What this artifact carries

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

What has to read each part

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 built

    entity 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 built

    face 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.

    built

    nothing — not evidence

  • ocr2 components

    Pixels of a page and no text for them. Needs character recognition before anything can read it.

    built

    OCR

  • page_raster2 components

    This raster is the page. The page's own recognition reads it, so it is not read twice.

    built

    nothing — the page's own OCR reads it

  • classify3 components

    A file inside the file. Goes back through the classifier as its own artifact.

    built

    the classifier, on the extracted child

  • table_ready1 component

    Rows and columns already parsed out. Goes to column mapping.

    not built

    column mapping and row ingestion

The same picture more than once

4 of 5 images fingerprinted, 1 not — c005: smaller than 1% of the page — logo, rule or stamp.

g001c004 c013 · accused-photograph.jpg

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.

Every part, and what came out of what

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.

  • component c004
    c004page 2exhibitpage 2scene photographimage_analysisnot built

    matched 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, eng

    GENERAL 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

  • component c007
    c007page 3exhibitpage 3document scanpage_raster

    this 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, eng

    SEIZURE 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

  • component c009
    c009page 4exhibitpage 4document scanpage_raster

    this 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

    attachments/001-accused-photograph.jpg · 9 kB

    • 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

    attachments/002-keeper-statement.txt · 168 B

    • 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

    attachments/003-tower-dump-extract.csv · 219 B

    • c015tower-dump-extract.csvtabletable_readynot built

      5 columns parsed

      3 rows · 5 columns · delimiter ","

      msisdnIndian mobile number · the header name only — no value in the sample matched

      imeiIMEI · the header name only — no value in the sample matched

      cell_idCell 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