no run in progress

The Digesta decision trees

Read from the code on 4 November 2026 · figures measured against the production PostgreSQL

Diogene is a source of DOCUMENTS; the schede are a source of DATA. Two different things that were living in the same place. Diogene gives us 3.884.843 documents — filings from electronic case files, each with a file — while the 1.091.881 schede are the case-file record cards: no PDF, no pages, nothing to read and nothing to extract. Their job is to hold the documents together and carry their metadata.

As long as the schede sat in documents they inflated every total («11.906.322 documents» included 1,09 million that are not documents at all) — and Diogene, conversely, was invisible: its documents sit under the sources merito_tribunale and merito_gdp, which look like the lower-court database and are not. The source column names the register, not who gave them to us.

Who gave them to usdocumentsdownloaded
Diogene · electronic case files3.884.8433.686.242
lower-court database3.531.2601.408.712
administrative justice (TAR, Council of State)2.499.6912.499.616
Court of Cassation642.093642.082
legislation114.143114.133
other142.411—
DOCUMENTS10.814.4418.493.052

Diogene by register: dgn:cc 2.357.766, dgn:gdp 1.443.430, dgn:esm 83.647.

And separately — the DATA, which are not documentsrows
case record cards (one per Diogene case file)1.091.881
fascicoli · the table that binds90.867
documents attached to a case file2.879.435

Four decisions in a row. Each has exactly one job, and the output of one is the input of the next:

 What it decidesfromto
1 · choicein or outthe catalogue
10.814.441
the SUBCORPUS
2.934.278
2 · cataloguingwhat TYPE it is — and so whether it is PRIMARYthe subcorpus
2.934.278
the PERIMETER
the primary ones
1.623.869*
by class 1.185.653
by type 438.216
3 · readinghow to read it, page by pagethe perimeter
1.623.869
the text
4 · extractionwhich fields to ask forthe textthe fields

* the perimeter is not closed yet: 1.623.869 is what cataloguing carries away as done so far. 737.931 invisibles remain, and until they have a type there is no telling whether they are primary — that is tree 2's job.

Tree 1 · the CHOICEWhich documents we look at — and no others

It decides one thing only: in or out. Out of 10.814.441 catalogued documents it takes 2.934.278 by four rules — and that is the subcorpus, what this alpha version works on. It does not decide what they are, nor how to read them: that is where it ends.

branchdocuments
Diogene — the classes that carry fields + all the invisibles1.971.565
justice of the peace (all)1.179.759
Cassation, civil division242.327
database — tort liability195.435
the SUBCORPUS, no duplicates2.934.278

You cannot exclude by class something that has no class. Keeping the invisibles out would mean never finding out what they are: they would not enter, so they would not be read, so they would never get a type. They come in, and tree 2 will say whether they are primary. Also in are spese, altro and veicolo, which looked like procedural paperwork and in fact carry invoices, payment demands, attachment orders and vehicle registry extracts.

the catalogue — the DOCUMENTS 10.814.441 documents · 8.493.052 downloaded WHO GAVE THEM TO US (documents · downloaded) Diogene 3.884.843 · 3.686.242 lower-court db 3.531.260 · 1.408.712 administrative 2.499.691 Cassation 642.093 legislation 114.143 other 142.411 four rules, not a list Diogene the classes that carry fields + ALL the invisibles no class is no reason to exclude 1.971.565 lower-court db subject = tort liability 195.435 Cassation, civil division all of it 242.327 justice of the peace every document, envelopes included 1.179.759 HOW THE CHOICE IS MADE, INSIDE DIOGENE (3.676.765 classified) in · classes that carry fields 1.107.212 out · procedural paperwork 1.828.467 invisible · no class 741.086 the union, no duplicates 2.934.278 documents the SUBCORPUS · 2.934.278 what the alpha works on — what they are is not yet known
The perimeter is not a list: it is the union of four rules, and rebuilding it is idempotent (tools/perimetro_costruisci.py). The Diogene branch selects by class — and this is where the circularity comes from: the 741.086 without a class do not enter, and without entering they will never be read, so they will never have a class.

Tree 2 · CATALOGUINGWhat type each document is — and which are PRIMARY

It decides the TYPE of every document in the subcorpus, and out of that comes the PERIMETER: the primary documents. A hearing record, a power of attorney, a certified email carry none of the fields we extract — they are the paperwork of procedure, not of the case. Cataloguing them is precisely how we keep them out of the perimeter, and therefore out of pre-OCR. In come the 2.934.278 of the subcorpus, out comes a type for each, and the type says which are primary.

2.934.278 in · out split three ways
 documentswhat becomes of them
THE PERIMETER — the primary ones1.623.869go to pre-OCR
└ by our classification1.185.653the Diogene bridge
└ only by the TYPE the source declares438.216database and Cassation — 30.654 also have a class, counted above
discarded — low 89.984 + invisible 737.931827.915they end there: no type to decide on
not passed — procedural paperwork482.494they stop here
the subcorpus2.934.278 

The perimeter — who passes (1.185.653 by class): memoria 345.008, provvedimento 267.633, introduttivo 132.217, ctu_perizia 119.111, spese 77.735, assicurativo 71.372, comparsa 67.924, medica 56.394, sinistro 24.657, veicolo 16.251, altro 7.351 — plus the 438.216 that pass only by the type the source declares (sentenze 206.789, ordinanze 182.023, decreti 42.154). The two routes make 1.623.869, which is exactly what sits in lavoro_ocr today.

Of these, 1.269.602 already have text and 354.267 do not. The real work is the second figure: the source's rulings almost all have text (0 ordinanze and 0 decreti without), whereas medica (42.979 of 56.394) and sinistro (16.313 of 24.657) are almost all still to be read.

Who does not pass (482.494): tecnico 135.676 (envelopes, certifications, filing notes), procura 88.031, corrispondenza 80.531, hearing records 70.834, notifica 44.933, F24 tax forms 27.840, photographs 27.180, registry data 6.490. Reading them would cost money and yield not one field.

The type can come from us or from the source — and for a while we looked only at ours

Classification covers only the Diogene bridge. The lower-court database and the Court of Cassation never went through it, so they have no class — but the source declares the type: Sentenza, Ordinanza, Decreto. A judgment is a primary document, and knowing that takes no model.

As long as the filter looked only at classification, 438.230 primary documents stayed out — 206.796 judgments, 182.023 orders, 42.154 decrees — and 99% of them already have their text. It was the part of the perimeter that costs not one minute of GPU, and it was exactly the part that was missing.

From now on primary means: our classification says so or the source declares it — one single definition, in app/primari.py, for whoever builds the perimeter, whoever surveys it and whoever measures it.

The 275.666 without a type are neither in nor out: until they are catalogued, the perimeter is not closed. Nearly all of them are waiting for text — and text is what pre-OCR produces, which is the next tree. It is the one point where the two chase each other.

From here the journey is a single one: the primary documents enter pre-OCR, from there the ones that need it go to OCR, and the text that comes out goes to extraction.

The first question is not «is it an envelope?»: it is «do we already know it?». A document that has a class, an envelope or a name that speaks is read as it is, and the five sources vote. A document we know nothing about goes first to discovery: we find out what the file really is, we split off the text layer that already exists, we unwrap wherever there is an envelope, and only over the pages that remain does tesseract run. At that point text exists — and that document is catalogued from its text like every other, entering through the testo source and from there to the vote. It skips nothing: it arrives late at the same table.

Five independent sources, each proposing a class with a strength; then they vote. Text is one of the five, and that is why 1,4 million documents have a class despite never having had a single character of text.

DISCOVERY — for the documents we do not know the first 16 bytes envelope, or PDF? envelope unwrap · 0 opened ZIP, XML, CAdES · RAR 0: no tool the loop: what comes out re-enters the 16 bytes PDF is there a text layer? does the PDF carry one? no TESSERACT the first page · CPU, no GPU yes — the text is already there XML: the schema is the text still not readable → discarded no text found → discarded · 0 now text exists: catalogued from the TEXT 667.953 documents to catalogue do we already know it? a class, an envelope, a name that speaks no · needs discovery yes · read as it is diogene its own classification across the whole corpus: envelope the XML schema of the PCT 782.862 293.933 filename the REAL name of the file 805.174 text first 3.500 chars (+ tail, for 281-sexies) 785.544 filing type the tail too (281-sexies) the vote • a FAMILY votes once only: Diogene-on-the-name and our own filename are one evidence — they confirm (+0,5), they do not add up • a tie goes to the most reliable family: envelope > text > event high two independent families agreeing, none strongly against 842.668 · +0 this run medium a single source and no contradiction 825.749 · +0 this run DISCARDED no text 0 — tesseract vote failed 0 — no type 827.915 — they end here — from the vote: 1.668.417 (high and medium, with a class) + 437.946 from the SOURCE's type database and Cassation: no classification row, but «Sentenza» is what the source says skips the vote THE FILTER — does this type carry our fields? memoria, provvedimento, introduttivo, ctu_perizia, assicurativo, comparsa, medica, sinistro → YES yes · 77% no · 23% PASSED · the PERIMETER 0 +0 this run · to pre-OCR by OUR class: 0 only by the SOURCE's type: 0 NOT PASSED procedural paperwork 482.494 · +0 this run 2.106.363 in · 2.106.363 out — none lost
From the five sources to the perimeter. The decidi() vote gives the type; the type decides who is primary; the 2.934.278 of the subcorpus come out split three ways. 1.405.450 documents have a type without anyone having read a single character of text — 647.149 from the filename, 544.224 from the envelope, 106.208 from Diogene's own classification. Of those still without a type, 91% have no text: for them the other four sources have already failed and the only one left does not exist.

Discovery: four steps, and back in line with everyone else

The filename, the envelope and Diogene's own label are read as they come. For a document with none of the three, text has to be brought into existence, and that takes four steps. The 16-byte guardian says what the file really is, because anything at all can arrive behind a .pdf name. The PDF's text layer is split off: the pages that already have text cost nothing. Unwrapping opens the envelopes where there are any — and it is a loop, not a step, because what comes out can itself be an envelope. And tesseract reads only the pages left over, on CPU we already own: cataloguing needs 3.500 characters, which is to say the first page.

Once the four steps are done text exists, and from there on that document is no longer a special case: it enters through the testo source like any document that had text from the start, and the vote treats it identically. That is why testo is no longer the «expensive» source in the drawing: in discovery the price is paid by the CPU, not the GPU.

And after the vote, low confidence is discarded

The 89.984 at low confidence end there: they do not enter the filter and they go no further. A contradicted class, or one resting on a weak clue, mapping onto the empty tuple would not get a field wrong — it would lose the whole document. They are left out deliberately, not by oversight.

Level 2 — the Qwen model (197.235 documents) and the CPU classifier (69.656) — is not a step after the vote: it is one of the ways a class gets decided, and once it has spoken its verdict is already inside the high or the medium band.

Text is not free the way the other three sources are

The filename, the envelope and Diogene's label are read as they come. Text is not: first the file has to actually be a PDF. The 16-byte guardian runs ALWAYS, not only when the type is missing — anything at all arrives behind a .pdf name, and the stored type can be wrong: 7.716 documents out of 97.783 were recorded as scanned and were PCT XML envelopes, JPEG photographs, zips, mail messages. As long as the check ran only on an empty type, those files left for the GPU as scans and came back without a character.

And a container — certified email, ZIP, XML envelope, CAdES — is not a document: it gets unwrapped, the main document that comes out is re-typed and re-enters from the beginning. It is a loop, not a step: unwrapping can itself produce something to unwrap.

The two hand-written disambiguations

Between the text and the filing-type recogniser there are two cases the vote alone would get wrong, and they sit in the code as explicit exceptions: a judgment delivered orally into the record (art. 281-sexies) is a ruling even though the header says «hearing record», and a party's filing that cites a decree is not a decree.

Tree 3 · READINGHow to read the primary documents

Every primary document enters: the whole Alpha 2 Perimeter, as tree 2 passes it. There is no choosing by type here any more — the filter of tree 2 has already decided what is primary.

Alpha 2 Perimeter 0
already readable, zero GPU 0
still to be read 0
estimated pages 0
pages to the GPU (53%) 0
hours at 17 pods · cost 0

The estimate uses figures measured on the perimeter: 11,9 pages per document to be read, 52% of pages escalating to the GPU after the tesseract gate, 0,59 pages/s per pod and 0,59 $/h per pod. A document that already has text costs nothing: it just goes into extraction.

Pre-OCR does not read: it decides. First it discards what is not a document, then it looks page by page for text that is already there, and only what is left goes to the GPU. It costs tenths of a second of CPU.

Whatever already has text does not come in here: there is nothing to read
 documents 
already have text1.269.60278% — they skip the tree and go to extraction
INCOMING — without text354.26722% — this is the tree's work
└ already surveyed37.159not done again
└ still to survey317.108 

The 354.267 without text are this tree's work. They have no text anywhere: without this pass they stay documents that can be neither catalogued better nor extracted. The other 1.269.602 already have text and can go to extraction without spending a minute of GPU.

The four modes, over the 37.159 WITHOUT TEXT already surveyed
modedocumentspages cut
intero — all scan34.665 · 99%412.552
ridotto — mixed891.374
figure — photographs only20
strato — the text was already there0—
surveyed37.159413.926

In here there is nothing left to settle on the text layer: 99% is genuine scan, and obviously so — these are precisely the documents that have no text. The pages go to the tesseract gate, and only those tesseract cannot read well enough escalate to the GPU:

The pages of the text-less, at the gate
 pages
through the tesseract gate381.775
ESCALATED — to the GPU200.437 · 52%
pages per document, measured here11,9
ALPHA 2 PERIMETER entered from tree 2: 0 0 still to compute is there a PDF on disk? store.doc_pdf_file no no PDF · 0 → FAILED is it a known placeholder? sha256, impronte.riconosci yes · 0 discarded: source lacks it guardian: 16 bytes the name says .pdf, the file does not is it a container? PEC, ZIP, XML envelope, CAdES yes unwrap the main one back in: another layer? no · a PDF pages · 0 documents · 0 the PDF is cut, one page per file for EVERY page: must it be read? • the text layer is thin — fewer than 200 characters • or image covers ≥15% and text is <1200 • or there is text but it is the font talking from tree 5 the text was only the signature stamp read again · 0 how many pages are left? strato none text already there 0 pages passing figure photographs only waiting for vision 0 pages waiting ridotto mixed: some pages yes, others no 0 pages being sorted intero all scan, or not analysable 0 pages passing sorted page by page, by kind text saved AT ONCE, no GPU post_ocr(res) · full or partial tesseract reads the cut pages the text is saved: it is the second opinion ESCALATION — is tesseract not enough? confidence under 90, a table, original under 150 dpi, or empty chandra, on the single page 0 pages queued never sees a GPU at all not a PDF, not an envelope · 0 nothing readable → FAILED text already there → PASSED no: tesseract is enough VISION · general VLM photographs + what chandra missed 0 queued · 0 read unreadable or uncuttable → FAILED · 0 CUT THE PAGE, if missing this run only · alpha3/beta1: in tree 3 uncuttable → FAILED no text → vision · 0 read: 0 pages no text from any page → FAILED · 0 RECONCILIATION 0 pages waiting · 0 out as documents PASSED · the text is there 0 of 0 entered · to trees 4 and 5 had text already: 0 · text layer: 0 reconciled: 0 on CPU · 0 after the GPU FAILED · no text to be had 0 no PDF, not a PDF, too many pages, or nothing even chandra could read still in the tree · 0
Only what has no text comes in: 354.267. The four modes and the page counts are measured on the 37.159 of them already surveyed — and there `strato` does not exist, because a document that settles on its text layer has text and would not have entered.

Tree 4 · EXTRACTIONWhich fields to ask for, given the type

to be extracted · this run 0
extracted 0
passed by tree 3 0

Fed by what tree 3 PASSED: every primary document it has read. The same output feeds tree 5, and the two run side by side. Running now: the pilot, 2,000 documents from tree 3's PASSED, stratified by kind of document, on the base qwen38 model with no adapter — it measures the prompt before it is frozen for tree 6. The boxes below count this run.

Here the class really earns its keep: it decides which fields to ask for. You do not ask a medico-legal report for the operative part of a judgment, and you do not ask a hearing record how the accident happened. Asking everything of everyone is what produced 89% empty values in the 3 November pass — and you pay for it twice, in prompt and in empty answers written up as though the model had failed.

to be extracted · pilot, 2,000 of tree 3 0 is there text? no waiting does not count as an attempt what kind of document is it? 1. class/subtype, from the classification (high, medium) 2. the source's type (sentenza, ordinanza…) · category 3. ordinanza: decisive or not, from the text · CTU ≠ CTP which fields can it carry? — catalogue albero4.v2 249 fields · 20 kinds of document · judgment and filing readings only the fields that fit the case: no plate outside RC-auto zero fields done, calling nobody · 0 a receipt, a service notice a subset DIOGENE FIRST — already answered high/medium, non-empty: saved as PRIMARY, never asked 0 values reused · both kept if they differ · 1% audit nothing left to ask 0 docs, no model RULES second, because they are free PCT envelope: valore_causa and oggetto at confidence 1,0 computable fields computed and asked · 0 values the text, page by page each page from its best reading: layer, OCR, chandra photos: [FOTO p.N — description] + the text on them the window: 8.500 characters · 0 read 2/3 head + 1/3 tail · the middle via the sliding window → digesta-extraction (pilot) · GPU value · confidence · page · PASSAGE · a NOTE 0 values · 0 tokens a document the full run: digesta-alpha-a4v1, once tree 6 has trained it window full? retry at 60% SLIDING WINDOW worth going on? only long prose with readable text · stop after 2 empty next 8.500 chars of the middle, 1.000 overlap, ONLY the missing at most 8 · the first value wins unless a later one is surer 0 windows on 0 documents which fields do we still ask? not determinable, or low confidence none left → the write EXTRACTED 0 documents · 0 fields found each field: source (diogene · rules · model · vision), page, box, window · Diogene primary, conflicts flagged not determinable: a list on the document's row 3rd time FAILED · 0 unreadable answers · 0 to retry CASE SUMMARY · side job a queue per case folder: when its documents are done, one summary from their notes and key fields
Extracting a document. Three things save money: the fields are narrowed by the kind of document before the prompt is written; what Diogene has already answered, and what a rule knows for certain, is never asked of the model; and the sliding window walks the middle of a long document only when that document is worth it, asking only for what is still missing. Every value keeps where it came from, so the workstations can show it on the page.

The catalogue albero4.v1 merges three lists into one: the judgment catalogue (sib.v4, 167 fields), the 27 case-file questions and Diogene's 127 fields, of which 55 had no counterpart in ours. The draft had 225 fields across 18 kinds; after the review of 08/11/2026 it was frozen as albero4.v1 and then albero4.v2: 249 fields across 20 kinds of document. Each field carries a judgment reading and a filing reading, and the kinds of document that can contain it. In v2 a missing value is null, and −1 on a liquidated amount means the claim was rejected.

Tree 5 · CHUNKS AND VECTORSCutting the text into pieces, and turning each piece into a vector

text to vectorize 0
vectorised 0
passed by tree 3 0

Fed by what tree 3 PASSED, the same output that feeds tree 4. Tree 5 runs beside extraction, not after it — neither waits for the other.

A small tree with one job: make the text searchable by meaning. The text is cut into pieces, every piece becomes a vector, and the vectors go to Qdrant. Two gates come first, because a vector is hard to take back once someone has searched with it: a text that turns out to be in fase di oscuramento must not be indexed at all, and a page that holds only a signature is not text — it goes back to be read again.

text to vectorize · tree 3 PASSED, every 2 min 0 obscured? «in fase di oscuramento», found in the text yes STOP · 0 flagged; its pieces and vectors are deleted no only a signature page? the text is a signature, not a document yes back to OCR read again · tree 3 · 0 no CHUNK · always from scratch old pieces and vectors replaced · chunk_pipeline empty DISCARDED · 0 no pieces, nothing to index EMBED · bge-m3 · GPU 0 in · 0 waiting (no answer or write failed) DENSE + SPARSE FOR EVERY PIECE? 0 in · 0 waiting (short or broken answer) 3rd time FAILED · 0 3 broken answers from bge-m3 WRITE · QDRANT digesta_ibrido 0 waiting to be written · pieces replaced in chunks old vectors out, new in · payload: kind, class, category indexing paused · searches scan the newest points VECTORISED 0 in this run · 0 vectors in Qdrant, whole corpus the model is written on the pieces only AFTER the upload
Vectorising a document. The order matters at the end: the model is written on the pieces after the vectors are in Qdrant, so «done» can never be true of a document whose vectors are missing. A short or broken answer from the embedder — fewer vectors than pieces, a piece with text and no sparse vector, a dense vector that is not 1,024 long — is refused rather than stored: pieces and vectors are paired by position, and a missing vector would otherwise leave a piece that looks finished and can never be found. The GPU never waits for the database: writing is a stage of its own, with its own queue.

Every document is chunked and embedded again, from scratch, even when it already has pieces and vectors: on 4,000 documents sampled on 07/11, 2.7% had pieces older than their current text, and cutting is cheap (about 2 ms a document against 313 ms of embedding). The new pieces replace the old ones and the new vectors replace the old points in Qdrant. A document whose write fails halfway has no «done» mark in this run and is simply done again.

Tree 6 · TRAININGTeaching digesta-alpha the extraction tree 4 will ask of it

training examples 0
blind gate 0
to beat 71.8%
labels collected 0

Not training yet. It starts once the catalogue and tree 4's prompt are frozen after the 2,000-document pilot: every example must look exactly like what tree 4 will send. Steps 1–2 are done: 0 labels on 0 documents collected, the gate frozen. The pilot is running now, and every answer it gets back is kept in tree 4's exact prompt format: 0 so far. No training example exists yet, so that counter stays at zero.

The data to teach from exists already; nothing here waits for tree 4 to run. What changes is its shape: every source is rewritten as one tree 4 call — the fields that kind of document can carry, the window, the photo blocks — and the answer tree 4 expects back: value, confidence and verbatim passage for each field, plus the note on the document. The blind half of the gold set is never shown to the model: it is the gate.

GOLD SET · human 405 docs · 52,422 labels the jurists' labels · weight 3 CORRECTIONS Sibilla, Vitruvio, Omnia, insurer desks users fixing a field · weight 3 MODEL AGREEMENT alpha run · 5,215 docs · ~593k three models agree · weight 1 DIOGENE · weak 1.5M answers · ~82k documents weak weight · self-contradictions out PILOT + EXPERT SHEETS 26 filings · 9 case sheets half to train, half to the gate NOTES · teacher Opus writes the notes on a limited set · at most $40 BLIND GOLD SET 151 blind · 0 gate documents in all NEVER trained · it is the gate TREE 4'S PROMPT, EXACTLY albero4_dati.py: the fields of that kind of document (albero4.v1), the window, the [FOTO] blocks → value · confidence · PASSAGE for each field, plus the NOTE · 0 pilot answers kept WHAT IS TAUGHT, AND WHAT IS MASKED a passage only if it is verbatim in the window outcome only from the jurists · Diogene vs the trio: masked «not determinable» masked in later windows confidence target by source: human 0.95 · trio 0.9/0.7 · Diogene 0.7 QLoRA · on A40 pods 4-bit base · rank 16 · 8,192 tokens · local SGD every 40 steps 8 pods × 1–2 days ≈ $110–230 UPLOAD TO CODERAI · digesta-alpha-a4v1 a new name, never reused · at temperature 0 it must differ from the base THE GATE blind gold set ≥ 71.8%, no drop on outcome or amounts case documents: the held-out half of pilot + expert sheets calibration: accuracy by confidence → tree 4's low-confidence line only to measure fails → back to the data THE MODEL FOR TREE 4 registered under the name tree 4 calls · its sha saved on every value
Training the extraction adapter. Human labels weigh most, model agreement less, Diogene's answers least; the blind half of the gold set is only ever used to measure. An adapter that does not beat today's 71.8% on it, or that loses on outcome and amounts, goes back to the data instead of to tree 4.

The thresholds, and why they are what they are

ConstantValueWhat it decides
SOGLIA_CARATTERI200 below this the page's text layer is «thin» and the page must be read
COPERTURA_IMMAGINE0,15 how much of the area must be image for the page to be suspect
TESTO_RICCO1.200 beyond this the text is plentiful and the image no longer counts: this is the clause that saves a scanned body with a digital header on top
CARATTERI_PER_GIUDIZIO200 below this we do not judge whether the text is genuine: in doubt we keep it, because re-reading what was already readable costs GPU for nothing
TESTA3.500 the characters of the first page the classifier reads. Knowing what a document is does not require reading all of it

Three things the tree does that its name does not reveal

The text layer of mixed documents is saved regardless. In ridotto mode the pages that do not go to the engine have text, and that text is written straight away as a partial reading: quality forced to «failed» and pagine_fallite telling the next tier which pages are missing. Without this the document would leave the queue and its text would be re-extracted every time — measured on 31 October, 81.314 pages across 2.930 documents.

Photographs do not go to OCR. Since 25 October: on figure-pages 46,7% of requests came back 5xx against 1,7% for normal pages, and of the 83% that did come back the reading was rejected. They stay recorded under figure, and that is the vision queue.

A document sent whole «as a fallback» is distinguishable. When the PDF will not open or exceeds the page ceiling, the mode is intero but per_pagina is false and motivo says why. Without that distinction it was indistinguishable from a document that genuinely is all scan — and they are 8%.