Design the evidence-review screen before automating the decision
I wanted staff to inspect a manual page without accidentally starting another model attempt—or accepting a generated value as fact.
That sounds like a screen-design problem, but it is really an authority problem. A document can provide evidence. An extractor can propose a value. A person can accept that proposal for use in a workflow. If the interface collapses those actions into one “analyze” button that both spends compute and writes a business value, the operator cannot tell what happened, who approved it or which source supports the result.
I separate the journey into four explicit actions: inspect the retained document; request a bounded extraction; compare the proposal and its provenance with competing evidence; accept or reject it. Inspection stays available even when extraction is off. Proposing is an explicit operation with a budget. Acceptance is a separate staff-authorized action.
Put evidence next to the proposal
A number without its source context is just a plausible string. The review surface needs to keep the proposed value attached to the retained document identity and hash, selected page, parser or extraction method, confidence, model/extractor identity and revision, and any conflict or prior attempt. A reviewer should be able to open the cited page without initiating another extraction. When a second proposal disagrees, show both values and their source locations rather than overwriting the first answer.
That layout supports an important distinction: a manual can say that a part has a certain size, while a physical installation can still fail because the manual is for a different revision or the surrounding installation has changed. Document review tells me what evidence was read and what value was proposed. It does not establish that the part fits in the actual space.
The user experience can make the state machine visible without turning it into a wall of implementation detail. For example:
Retained manual → selected page → extracted evidence
↓
reviewable proposal
↓ explicit staff action
accepted business value
The arrow from proposal to accepted value is deliberately not automatic. A confidence score can prioritize a queue or explain uncertainty, but it cannot grant the staff member’s acceptance authority.
Bound the expensive path
The implementation tries text extraction before OCR and lets staff select a page when OCR is needed. The page selector accepts one unambiguous integer from 1 through 80; repeated or coerced query values are rejected rather than silently choosing one. OCR work is bounded by explicit limits: pages, characters, time, image pixels, temporary bytes, process memory and a confidence floor. Concurrent OCR is refused instead of accumulating an unbounded queue of buffered documents.
The pinned source gives this configuration:
export const OCR_LIMITS = Object.freeze({
pages: 80,
characters: 200000,
milliseconds: 300000,
pixelsPerPage: 2_000_000,
totalPixels: 100_000_000,
temporaryBytes: 256 * 1024 * 1024,
rssBytes: 512 * 1024 * 1024,
confidence: 50,
scale: 2,
});
These are configured caps, not observations of a normal document or a promise that every cap is enforced by the operating system. The product’s controls should tell the user when extraction was skipped, refused, timed out or returned uncertain evidence. An empty proposal list should not be mistaken for a document that contains no relevant information.
The OCR worker also installs application-level denials for fetch, HTTP/HTTPS and network sockets before loading the OCR engine, including in its worker isolate. This closes the application routes the code explicitly covers. It is not an OS sandbox for arbitrary native code, and it does not replace a process boundary if the threat model includes hostile native components. Saying exactly what the control blocks helps the team choose the right deployment boundary instead of trusting a broad “offline” label.
The permission model follows the same separation. Reading an already-retained manual is not the same capability as asking a model or OCR worker to process it, and neither should implicitly accept a field into the operational record. A reviewer can inspect while extraction is disabled; a proposal request is attributable and budgeted; acceptance records the human decision and the evidence version it applies to.
Keep the evidence states honest
I keep three evidence cohorts separate because they answer different questions. The live UI acceptance made 13 GET requests across 1,280-pixel and 375-pixel layouts and recorded no horizontal overflow. That live manual library contained zero documents. The joined CLI, database, API and UI qualification used a synthetic fixture and completed in 11.113 seconds. Its corruption control changed stored bytes, failed in 4.288 seconds, and the exact restoration passed in 11.036 seconds. Those are useful checks of layout, integration and integrity behavior; they do not demonstrate extraction of a real retained PDF or a correct physical fit.
That distinction should appear in the product’s own evidence model. A test against an empty live library can show that the empty state renders. A synthetic joined test can show that a composed workflow moves a fixture through importer, database, API and UI. A real retained document example would answer whether the selected-page extraction is useful on actual manuals. Each test has value, but substituting one cohort for another creates a story the evidence cannot support.
A small proposal record should make review reproducible. The exact schema depends on the application, but the review contract should bind at least: the retained document identity and content hash; page and source span; extraction method and version; proposal value and units; confidence or uncertainty; the reviewer; and the decision timestamp. If the underlying document changes, the old acceptance should remain tied to the old hash rather than silently following a new revision.
The review screen should also make conflicts durable. If one extraction says 4.2 mm and another says 4.8 mm, a new attempt should not erase the earlier proposal. Show both, preserve each attempt’s provenance, and let the reviewer choose the accepted value or leave the field unresolved. A retry budget is part of this workflow: otherwise a button that looks like “try again” can create unbounded model or OCR work while the reviewer thinks they are only refreshing the page.
Review the decision, not only the extraction
I start an interface review by asking what every button can cause. Does opening the PDF trigger OCR? Does pagination spend another attempt? Does choosing a new page erase the prior proposal? Does acceptance have a distinct permission and an auditable record? What happens when extraction fails or times out? Can the user still inspect the source? Can a changed manual invalidate a prior proposal without destroying the history?
Then I inspect the failure paths. Repeated page parameters should fail clearly. A page outside 1–80 should be rejected. A busy OCR worker should refuse rather than queue an unknown amount of work. A low-confidence result should remain uncertain. A conflict should not be auto-resolved by whichever attempt finished last. A network request from the worker should be denied through the covered application routes. Finally, I verify that the accepted value references the same retained-document version the reviewer saw.
The broader product lesson is that a good AI interface does not automate every step adjacent to the model. It makes the evidence inspectable, the proposal attributable, and the consequential action explicit. That often reduces reviewer noise more effectively than a more confident extraction model, because it lets a human spend attention on the real disagreement instead of reconstructing what the system did.
The practical test is straightforward: start with a retained document, inspect one page without running extraction, create a bounded proposal, introduce a conflicting value, and accept only after the UI shows both provenance trails. Then change the document hash and prove the prior decision does not silently attach to the new revision.
How this was verified
The source dossier pins the API, OCR budget, worker, joined qualification and live UI acceptance versions. It records a live UI check of 13 GETs at 1,280 px and 375 px with no overflow but zero manuals; a separate synthetic joined workflow at 11.113 seconds; and a storage-byte corruption control that failed in 4.288 seconds before exact restoration passed in 11.036 seconds. No real retained-PDF extraction, provider/model result or physical-fit acceptance is established. The pinned timbar-fit checkout is not present in this workspace, so the source hashes and excerpts are taken from the dossier’s source catalogue rather than independently read from those Git objects in this pass.
