Why this exists
There are warehouses of old well records and lab reports that only exist as scans. Faded photocopies, stamps over the numbers, tables drawn by hand in 1989. Real people spend weeks retyping them so the data can be used. DECANT is our attempt to hand the boring part to a machine without ever letting it quietly make things up.
The rule the whole project lives by: the machine keeps only what it can prove, and it asks a person about everything else. Being wrong loudly is fine. Being wrong quietly is the one unforgivable sin.
First, we measured everything
Before building anything pretty, we built a measuring stick. We took documents that humans had already reviewed and scored every reading DECANT produced against them. That gave us honest numbers from day one, and some humility: the free local model got about 73% of values right on the hardest scans, a paid cloud model about 83%, and the existing government system about 76%.
The technical bit
BLUF: DECANT's readings are scored against human-reviewed answers, not vibes. The bench compares each extracted value to a gold answer. It reports accuracy, coverage, and cost per document. It never blends scores into one number. Each model runs as its own "arm" so results stay comparable.
Teaching it to say "I don't know"
A machine that answers everything is a machine you cannot trust. So every value DECANT reads gets a confidence score, and a gate decides: keep it, or send it to a person. The gate is calibrated, which means when it says 95% sure, it is right about 95% of the time. On easy documents it handles about half the values alone. On the nastiest scans it routes almost everything to a human, and it says so plainly. A closed gate is honesty, not failure.
The technical bit
BLUF: review happens when confidence is low OR any evidence check objects. The checks are facts about the document. Example: the value must appear in the page's own OCR text. If it does not, that is a possible hallucination. The value goes to a person. No exceptions.
The screens stopped lying
For a while the app counted things in ways only we understood. We rebuilt the screens so they count documents the way a person would, opened any document in at most four clicks, and made every scan readable: rotate it, zoom it, brighten it. An upside-down page is two keystrokes from readable now.
Reviewing became real
Then the human half went live. A reviewer sees one value at a time, right next to the exact spot on the scan where it came from. One keystroke to accept, correct, or keep it flagged. Every judgment is saved forever, survives any rebuild, and counts. Correct a unit spelling once and the fix spreads across the whole document family.
The technical bit
BLUF: verdicts are append-only and attributed. The store keeps two human tables: review actions and unit confirmations. Nothing can overwrite them. Each verdict later becomes a training label for the gate.
The numbers got honest
We fitted the confidence model on real agreement data and made the product display what the fitted model says, not what a rough heuristic guessed. The result cut the flagship family's review workload by about a third. On another family the workload went UP, because the honest model refused to trust readings the rough one had waved through. Both directions are the point.
Side by side with the old way
The demo's closing argument went on screen: for any document the old system processed, DECANT shows both answers field by field. Where they agree, where they differ, where one of them is silent. No winner banner, no blended score. Just both answers and your eyes.
The big rethink
Ben sat down with the design and asked the hard question: is one model reading a page, plus a confidence score, actually robust? We dug into the data and found two things. The format errors everyone worries about barely exist. And the safety net of a second model reading the same page was catching almost nothing, not because the idea was wrong, but because the code that pairs the two readings up was dropping 94% of them on the floor.
That day the plan changed. Fix the pairing. Bring in a second model family through a proper tool-call interface. Run the experiment that settles whether different models disagreeing is the best hallucination detector we can build.
The technical bit
BLUF: the cross-model row join was the bottleneck, not model quality. Two models spell row names differently. A join on names loses most pairs. The fix leads with position on the page. Names are the fallback. Coverage went from about 5% toward the real overlap.
The queue learned to sail itself
The work now runs as a self-driving queue. One evergreen instruction reads the task board, does the next eligible thing, seals it with proof, and pushes. An hourly timer resumes it whenever it pauses. Ben can leave, and the board you are reading updates itself with every seal. This page is part of that machinery.
Certification went live
The gate stopped being provisional. Every human verdict recorded in the review screen now feeds a per-family certification: the gate for a document family opens only when a conservative statistical bound says the error rate among auto-accepted values stays under target. Trust is now earned family by family, with receipts.
The technical bit
BLUF: gates open per document family under a CP95 bound on wrong-among-accepts. Labels come from human review actions. The fit uses the same five signals the live pipeline computes. A family without enough labels keeps a closed gate and says so.
2026-08-07The one-minute live show
The favorite demo beat: pick a record the old system processed back in 2024, click "DECANT this document", and 58.7 seconds later both answers are on screen side by side. The original scan comes straight from the state archive, verified against its stored checksum, for zero dollars. Watch it happen in the screenshots.


The app got its bottle
DECANT finally looks like its name. When the app is busy fetching a document or waiting on a model, a tiny pixel-art bottle appears and pours. It is drawn by hand, sixteen pixels square, and the liquid streams from the bottle into a little glass. That is what "decant" means, and it is what the software does to a scanned document: it moves the contents, carefully, from one vessel to another.
The honest part is what the animation refuses to do. The glass never fills up, because the app genuinely does not know how far along the work is, and a filling glass would be a small lie. The bottle also refuses to appear at all if the wait is too short to matter. Nothing plays over a finished screen, ever.
The technical bit
The art is character data in source code. Six frames, one CSS stepped transform, no JavaScript in the loop. It mounts on real pending states only: route loading boundaries and the run watcher. A 300 ms reveal delay keeps fast loads clean. Under reduced motion it stands still. A 30-assertion browser check proves presence on real waits and absence everywhere else.
Three readers are better than one, and now we know by how much
We asked the question this whole month was building toward. If two different AI systems read the same scratchy old document and agree on a value, can you trust that value? Or do they just make the same mistakes together?
Now we know. When two strong readers from different families agree, they are both wrong about one time in twenty three. Values they disagree on go to a person, and values they agree on can skip most of the line. On our test set that cut the human review pile by more than three quarters without letting more errors through. A free local model helps too, but only its agreements are useful. When the small model objects, it is almost always fussing about formatting, so its objections stay away from the decision.
The experiment also caught itself once. The first result looked three times worse than the truth, because the scoring compared dates written two different ways and called them mismatches. The team took the number apart field by field before believing it. That habit is the whole product in miniature.
The technical bit
Two tool-call arms plus a local strand, paired by anchor geometry. Agreement risk 0.0444 discounted. Depth-1 widening: burden 0.32 to 0.07 at flat real silent-wrong. Local strand agreement removes 45% of wrongness; its disagreement precision is 0.06, so it never forces review. Best measured risk is double agreement at 0.0365. Total cloud cost zero dollars.
It knows when it is holding the wrong form
Teach the system a plugging report and hand it a lab sheet, and until today it would have done its earnest best, which is the worst thing it could do. Confidently reading a document through the wrong template produces values that look plausible and are wrong.
Now it checks. Before reading, it asks a cheap question: of all the forms I know, whose vocabulary is actually printed on this page? If a different form wins by a clear measured margin, the system refuses to force the template. It falls back to the honest first read, puts a banner on the result saying exactly what it detected, and offers one click to teach the right form. And if a degraded reading somehow heads for the public document tree, the publisher refuses it by name rather than let it wear a label it did not earn.
The proof run was sobering. With the safety off, the wrong-form read auto-accepted a handful of values and every single one was wrong, yet it scored HIGHER than the correct read on the usual metric. Numbers flatter liars sometimes. That is why this check exists.
The technical bit
Drift = a rival schema's page coverage beats the forced schema's by 0.20 or more. Threshold from a 201 document sweep, zero false drift, reviewer reproduced. Degraded output is byte identical to the untaught read. Resume keeps the verdict. push-store raises DegradedRunRefused. 22 browser checks, 855 spine tests.
Where it stands now
Two model families are being wired in through tool-call extraction, with a third free local one waiting. The experiment that answers "do independent models catch each other's hallucinations?" is the queue's must-finish. The schema wizard is about to get much deeper. And a pixel-art bottle is coming, because a serious tool still deserves a soul.
2026-08-08Every reader, one page
Until today, comparing the models that read these documents meant digging through benchmark files in a repo. Now the app has a comparison screen. For each set of documents it lays the readers side by side: how often each one is right against the answer key, how often it is confidently wrong, how much of its work still goes to a person, what a document costs. Nothing is averaged into a winner score, on purpose. A single blended number is how you end up trusting the wrong tool.
Where a reader was never measured on a set, the screen says so plainly instead of leaving a blank, and says why. The incumbent system's own numbers sit beside ours, marked as what they are: a different measure on a different scale, context rather than competition.
Best part: nobody typed those numbers in. A script reads them out of the benchmark's own files, so when the scoring improves, one command refreshes the whole page. The screen even knows which version of the scorer produced each row and adjusts its own fine print.
The technical bit
Route /comparison, signed in. Five document sets, 24 reader rows, components only with n on every cell. Data generated by scripts/model_comparison.py from score artifacts, run manifests and the PT24 triage simulation. Winning tool-call run pushed to the store, 80 runs now. Journey check runs 110 assertions against production, including both scorer-version worlds. Date caveats derive from scorer_version so the coming v2 re-score cannot strand them.


2026-08-08Teaching by pointing at the page
The schema editor grew up today. When you teach the system a new form, you no longer edit an abstract list of field names. The screen draws the form back at you as a wireframe, shaped like the paper: the cover fields stacked where they sit, the tables drawn across the way the page prints them, empty ghost rows that hold nothing because the rows belong to each document, not to the template.
Every cell can be told what kind of thing it expects: a word, a number, a unit, a date, a method code, an id. Where the family's own history supports it, a cell can carry the short list of values it accepts. All of that is saved as data in the schema itself, versioned like everything else, so the next document of the family is read with it.
Does it help? We measured. Same documents, same free local model, same scorer: the typed schema read 30 more values correctly out of 773 than the untyped one, without accepting anything more that was wrong. Small test, one dense document carrying most of it, stated plainly. But the direction is what the whole design bet on: effort a person invests once in teaching pays back on every later document of the family.
The technical bit
/teach, local mode. Eight cell types, accepted sets and character patterns stored as schema data through the versioned save path. Form 26R taught with 14 typed cells chosen from 977 stored reads. C4 exam: fidelity 0.8111 to 0.8499 on n=773, silent wrong flat. Unit spellings deliberately stay OUT of the schema, in the teaching layer, per the 2026-08-08 ruling. Journey 28 checks. Validator enforcement at write time is the next item's build.





Twenty million dates walked into a scorer
The date-scoring fix is being tested by attack. Five rounds now: a fresh adversary with no memory of the last one reads the code, tries to break it, and every break it lands becomes a permanent test. Round five put up numbers worth writing down.
16,577,632 date strings, things like "2021-03-19T16:52:00-05:00" and every misspelling of them the generators could produce, were run through the scorer's date grammar while an independent referee, built from scratch without looking at the code, checked every single answer. Zero disagreements. Around 4.4 million more strings went through targeted attack sweeps: shift ranges dressed up as timezones, crash fuzzing, and every one of the 1.1 million Unicode codepoints substituted into a date to see if any could smuggle in a digit. On top of that, 6.76 million pairs of dates were compared both ways against an independently computed calendar to check the equality rules themselves.
The bill for all of it: zero dollars. These are strings fed to a local function on one CPU core, not AI model calls. The biggest sweep, twelve million strings, took 157 seconds. The round's one real find was a floating-point corner where numbers smaller than anything physics prints collapse to zero, and it is being closed the same way its overflow twin was two rounds ago.
The technical bit
PT37 adversarial round 5 at commit 33bf83a. Exact count 16,577,632 date strings vs a from-scratch parse oracle, 0 divergences. Approximately 4.41M more in targeted sweeps (collision, crash fuzz, codepoint scans, leaf inertness probes). 6.76M pairwise equality checks vs an independent Gregorian day formula, 0 divergences, 0 bench-vs-mirror splits, 0 exceptions. One confirmed finding, subnormal underflow equating 1e-400 with 0, fix in flight. Cost $0, stdlib only, local CPU.
2026-08-08The ruler was crooked, and now it is not
For weeks, every accuracy number on the Form 26R corpus was quietly too low. The reason was mundane: the answer key stores dates like 2021-03-19, the documents print them like 03/19/21 4:52 PM, and the scorer called that a miss. A correct transcription, scored wrong, thousands of times.
Fixing a ruler is dangerous work, so it was done the paranoid way. The new date-reading was attacked by eight waves of fresh adversaries that found nineteen real ways to trick it, every one now a permanent test. Then the whole era was re-scored under the fixed ruler, with one strict rule: the old numbers stay in the book, labeled, and the new ones sit beside them.
The result: every model-graded score on the corpus rose by about eleven points, at identical sample sizes, while the human-graded rows did not move at all. That pattern is the proof this was a repair and not a flattering: only the rows the blindness touched changed, by exactly the amount the blindness had cost.
The technical bit
Scorer v2, typed date class, fail-closed. Tool arms 0.797 to 0.911 and 0.910 on n=3,882 and 4,410. Twenty-doc slice 0.793 to 0.911 on n=8,845. Human-gold rows unchanged. Denominators frozen on every row. v1 numbers preserved and labeled in BASELINE. The comparison page updated itself by regeneration, including its own fine print.
2026-08-08The queue learned what deserves your eyes first
Two model families reading the same page and agreeing turned out to be wrong about one time in twenty five, against a base rate near one in seven. Today that measurement became how the product actually works. When an independent reader from another family confirms a value the page's own text could not back, the gate accepts it and says why, with the evidence attached. The result, measured before shipping and reproduced exactly by the shipped code: about three quarters of the old review pile no longer needs a person.
And the pile that remains is no longer flat. The queue now walks in three bands: confirmations first, because they are the fastest way to grow the labeled truth the certification gate is starving for. Ordinary uncertainty second. The contested tail last, never hidden, its count on the screen and one jump away. Every value's card says in plain words why it is where it is.
One quiet rule mattered as much as the loud ones: a weak reader's disagreement no longer drags values into review. It cried wolf 334 times for 22 real catches, so its objections became evidence on the card instead of a veto. Its agreements still count.
The technical bit
One gate implementation, widen at one cross-family agreement, advisory always, ablation is one flag. Reproduction structural: the experiment's scorer calls the shipped gate; sealed rows reproduce to four decimals. Burden 0.3199 to 0.0712 on the strand slice. Strand class declared in the witness manifest. Tiers derived at render time from stored evidence, never stored verdicts. Journey 13 checks vs production.




2026-08-12The schema grew teeth, and the documents sharpen them
Since the wizard let a person type every cell of a document's shape, that knowledge was advice for the reader. Now it is enforced. Each typed cell compiles into a checker, and when a model emits a value that breaks the shape, the emission is refused and the model is asked to look again at exactly those spots. A retry can never delete a value or trade one mistake for another. Either the second look conforms, or the original stands with a loud flag. An earlier experiment taught us why this matters: a polite correction round once deleted fifteen correct values while reporting success. That door is now closed in code, not in a prompt.
The part we like best: the documents themselves propose the tightenings. The loop reads everything a family's documents ever printed and says things like: every confirmed reading of this cell is one of sixteen values, and holding the cell to them refuses 84 readings the page's own words do not back. A person clicks confirm, or declines with the evidence right there. The first confirmed narrowing caught five real defects, two label bleeds and three typos, and refused zero correct values.
The technical bit
Validators compile from typed cells. Accepted set, character pattern, declared type, in that order. Enforced at the tool emission seam with reject and re-ask. Three code side refusals prevent loss: unasked path, empty, still violating. Analytical family catch 24 to 29 of 20,448 at one false reject of 16,643. The loop ships as a seam route, a CLI, and a wizard block that names its witness run and its evidence bound. Gate policy untouched and test fenced. Suites 1048 and 530. Journey 23 checks.


2026-08-12The schema went to school on its own documents
Every reading in the product used to say untuned, and Ben asked the obvious question: does the schema actually fit what these documents print? So we audited it against the ten tuning documents, page by page. It did not fit in eight specific ways. Lab reports print below detection as < 200 or ND, never as the tidy word the schema expected. The test method is printed once in a section header above twenty rows, not beside each one. There are four dates on a page and the schema never said which one it wanted. Two different detection limit columns fought over one field. The lab's own sample number kept landing where the client's belonged.
Each fix had to pass one rule: it must plausibly help a 26R nobody has seen yet. A fix that rescues one document is rejected, and three proposed fixes were, with the reasons kept. Then the same free local reader re-read the same ten documents under the taught schema. Fidelity rose almost six points and sixty five silently wrong values went away. The honest cost is on the record too: the reader now asserts more, so more lands in review, and it is no better at knowing when it is right. Ten frozen documents stayed locked away untouched, so a later evaluation can tell us whether the schema learned lab reports in general or just these ten.
The technical bit
form26r schema 765e74e8 to 1b3a5aa0 through the versioned compare-and-swap save. Eight accepted changes, three rejected by the one-document rule. Same ten documents, gold, pages, arm, scorer both sides. Fidelity 0.8206 to 0.8784. Silent wrong 0.1321 to 0.1071. Qualifier accuracy 0.519 to 0.804. Same three pages failed both runs. Local arm only, zero dollars. Held-out ten never read.

2026-08-12Forms drift over decades, and the app finally says so
A 2003 well form and its 2019 revision share a letterhead and disagree about the fields underneath. Until now the detector answered with a coin flip: known or unknown. Now it answers like a person would: this is that family, but the page only prints a third of the shape I was taught, and here is exactly what matched and what did not.
From that honest reading, one decision forks a child schema. The child inherits every cell, remembers its parent and version and the labels its documents never print, and the family tree grows instead of a pile of unrelated schemas piling up. Detection then prefers whichever relative the page actually fits. On a real well record, a child that shed five never-printed fields beat its parent thirty nine percent to thirty six. The threshold for what counts as a full match is visible on the card and adjustable, and it is the same measured number the drift alarm has used since it shipped. Nothing new was invented, and nothing decides for you.
The technical bit
Third detect verdict, partial, with matched and unmatched label lists. Coverage grades, anchors name. Fork through the versioned save with If-Match on the parent. Lineage stored as schema data. Tier zero anchors counted per family tree so forks stay visible. Cross-tree anchor ties refuse to answer. Floor 0.20, the drift margin. Spine plus 39 tests, journey 27 checks run three times against a production build.

2026-08-12The third reader arrived, and it beat everyone
We keep two frontier model families reading every page because two readers from different lineages rarely hallucinate the same way. Tonight a third family auditioned: Gemini, the one our own prior said would underperform. The bench disagreed. It read the ten test documents more accurately than either standing arm, set a new record on the one human-verified document, agreed with another reader more reliably than any pair we had measured, and cost two thirds as much as the arm it beat. The prior is retired. The bench decides, and that is the whole point of having one.
The same night gave us the honest ceiling. Even when all four readers agree AND the trust gate approves, about one value in sixty five is still wrong, and each reader we added helped less than the one before. What remains is correlated misreading: every model looks at the same smudged digits and makes the same mistake. More eyes on the same pixels will not fix that. The road below one percent runs through checks that are not models at all, like the schema validators that shipped this week, and through more human verdicts to calibrate against.
One honest wrinkle: on seven of 148 pages, Gemini refused to transcribe at all, its copyright filter mistaking public well records for something it should not repeat. Those pages are marked failed, loudly. Every reader has a personality; the bench records them all.
The technical bit
gemini-3.1-pro-preview by Batches, at two thirds the standing arm's cost. Fidelity 0.9356 against model gold, 0.9804 against human gold. Best pair risk 0.0334, best triple 0.0248. Four of four unanimity behind the gate: 1.53 percent wrong at 38.5 percent coverage. Emission by response schema after the function-call shape measurably dropped a 50 row table. Recitation refusals 7 of 148, failed loudly. Under cap, every estimate stated before every submission; the exact figures live in the build log.

2026-08-12Teach a spelling once, and the whole store listens
Lab reports write micrograms per liter a half dozen ways. The app has long been able to learn the house spelling for one family of documents, one confirmation at a time. Ben's ruling went further: choosing a spelling should be a one time act. Set it once and every document, in every family, current and future, should just use it.
That is now how it works. A confirmed spelling can apply everywhere, and a family you have never opened proposes the standing preference on its own ask card, marked as inherited, yours to confirm or override. Fields that spell their unit the same way on every row, which the old ask could never reach because nothing varied, are now teachable from a quiet panel that lists where every unit field stands, in words. The original text on the page is never rewritten anywhere, and no quantity is ever converted. One choice, made once, and the asking stops.
The technical bit
Third writable table, global preferences at the unit cluster grain, append only, same locked posture as verdicts and snaps. One resolution order everywhere including export: family decision, then global preference, then the text as read. Settled clusters never re-ask. The reset switch learned the new table the same night, with a live byte-identical round trip. App suite 558. New journey 33 checks against a production build.

Every schema on one shelf
Ben asked for exactly this in one sentence: a way to look at all of my schemas and edit them, the same as what you see when making one. The app now has a Schemas page. Eleven document types on one calm shelf, each with its family name, its exact version, when it last changed, how many documents in the store were read under it, and its forks nested under the parent they came from. Clicking a row opens the same wizard the schema was born in. On the deployed site, where the reading engine does not run, the shelf still lists everything and says plainly why editing happens on the machine with the engine.
2026-08-12Strangers can now hold a key that opens nothing
Before this week, any signed-in account could write verdicts. That was fine when both accounts were Ben's, and wrong the moment anyone else gets one. The store now has roles: an admin, the two reviewers, and viewers who see every screen the reviewers see and can change nothing. The old hole was measured before it was closed: a viewer account landed three writes out of three on the old wall. On the new wall it lands zero, proven by attack scripts running against the live site from both sides, and the review screen tells a viewer honestly that judging is not theirs, right where the buttons are, instead of hiding them.
TECH for both: roles table with four standings, write policies rewritten role aware in one transaction each with staged rollbacks and a committed pre-change snapshot. RLS checks 48 across three scripts plus a 14 check journey against production. Library at /schemas, counts from the document grain, journeys 22 local and 12 cloud mode. App suite 595.

2026-08-12The app now opens on your work
Signing in used to land you in the library: every document, beautifully counted, and you went looking for what needed you. Ben called it what it was, walking a file tree. Now the first thing you see is a desk. The document that needs you most sits at the top with its counts, who read it and when, and one button to start. Seven more wait in a short list below. Finish a document and one keystroke opens the next. Your record and the whole store each get one quiet line, and the library is still there, one click away, untouched.
One more honest touch: when the database cannot be reached, the error card that says so now carries a Try again button. It was always honest about failing. Now it also hands you the one move you had anyway.
The technical bit
The desk and the Continue button share one door ladder, so they cannot disagree. Tier chips for the head document cost one read. Wayfinding is a fence, W-8: every element names where it leads. Retry was proven against a really failing store, with recovery clicked on the card itself. Desk journey 38 checks, retry proof 12, the full twelve journey battery green against a production build. App suite 629.

2026-08-12Ten more documents joined the canonical shelf, and you can see them
The best reader configuration ran on ten more documents, chosen by a stored rule so the next batch continues where this one stopped. The free local reader witnessed first, the paid flight flew once under its cap, and the review queue on those ten shrank by five sixths while the silently-wrong rate improved. The document list now marks which documents carry a canonical read, so coverage is something you see, not something you ask about.


2026-08-16The door is open: an email address is now an account
Until this week, seeing DECANT meant Ben creating an account for you by hand. Now there is a door. You type your email on one small page, and you hold a read-only account that sees everything the reviewers see: every scan, every reading, every judgment. The records do not know you are new. Nothing you press is recorded, and the screen says so plainly, along with the one way to change it: ask Ben for an invite.
One honest wrinkle, stated right on the page. This demo lives on a borrowed web address with no email domain of its own, so it can only send mail to Ben himself. Anyone else gets their sign-in link from Ben by hand, and that link works in whatever browser opens it, which is exactly what a link forwarded by a person needs to do.
The technical bit
Email signup with magic links, nothing to invent or remember. The emailed link carries a token hash, not a browser-bound code, so a forwarded link signs in cold. A self-serve account has no roster row, and the existing role wall already reads no-row as read-only, so the door needed zero database changes. A failed send rolls the signup back, leaving no half-made account, and this was measured, not assumed. Door journey 18 checks against production, the standing battery green, app suite 637.


2026-08-17The phone is the key: invitations are live
Seeing DECANT takes nothing but an email now. Acting on it takes an invitation, and this week the invitation became real. Ben writes an invite on his desk screen, to a phone number or an email address. The invited person signs in with a code texted to their phone, and that sign-in is the whole ceremony: the invite claims itself and the session is elevated.
The subtle part is that elevation belongs to the session, not just the person. Sign in to the same account with an emailed link instead of a texted code, and you can read as always but the elevated power is not there. The phone in your hand is the key, every time.
The technical bit
The access token looks identical for a texted code and an emailed link, which was measured, not assumed. So the claim reads the store's own record of the phone confirmation, made in the same instant the session was born, checked once and written down per session. Two new append-only tables that no rebuild can touch. One database function is the only door that can raise an account, it takes no arguments and acts only on the verified caller. Desk journey 45 checks against production, invite wall proven from both sides, zero real texts sent.


2026-08-17We checked the checkers
DECANT's accuracy needs labels to be measured against, and Ben refuses to spend his weeks hand-reviewing thousands of values to make them. So we used the labels that already exist: the old system's Illinois records, reviewed and edited by real people over years. First we proved that record is faithful, byte for byte. Then we scored DECANT's readers against it, with proper statistical bounds, and published the honest answer: nothing reaches the 1% error bar yet, partly because the strongest labels are too few, partly because agreement between readers is not yet rare enough to be proof.
The part worth the price of admission: in 50 places, every DECANT reader agreed with each other and disagreed with the human-reviewed record. We listed every one instead of averaging them away. In five of them the old record is simply wrong, including one where a reviewer typed the year 2070 into a form from 1970. The machine did not blink. The record did.
The technical bit
Two label tiers, never blended. A field a human edited is strong evidence. A field a human let stand carries the old system's own machine error rate, near 20 percent. Certification uses exact Clopper Pearson 95 percent upper bounds per tier per agreement class. The Form 26R forms have zero human review in the old system, confirmed against its live database, so 26R accuracy is measured by our own gold keys instead.

2026-08-17The feature we refused to ship
This one is the project's character in a single story. Five different AI readers now exist for the hardest documents, and when all five agree, the error rate among those agreed values is around one percent. The plan, blessed in advance, was to wire that five-way agreement into the acceptance gate before the boss visit. Cool feature, measured numbers, deadline energy.
We built it all. Then the mandatory measurement ran, and the numbers said no. Behind the gate we actually ship, the deep-agreement rule accepted nothing new, and the extra readers' occasional disagreements sent hundreds of values to human review that the main reader had actually gotten right. The wrong-rate among accepted values got worse, not better. So the feature does not ship. The plumbing stays, the measurement is published, and the gate keeps its old shape because the old shape is measurably better.
The quiet wins shipped anyway: every value that was accepted because a second reader agreed now says so right on its card, and the machinery to consult a whole jury of readers is ready for the day the numbers do say yes.
The technical bit
The stop rule was written into the task before the build started. Wrong-among- accepts went from 7.1 to 8.4 percent under the combined policy, review burden from 9 to 17 percent. A seven-variant sweep found no shippable improvement. The five-way agreement subset itself measures 1.00 percent wrong on the displayed reading. Decisions with and without the new classes are proven byte-identical by test.

2026-08-17The room where documents become data
Until now, the defining act of DECANT happened backstage. You could teach it a document type and review what it read, but the reading itself, the moment a scanned page turns into checked numbers, had no room of its own. Now it does. Drop a page and you see it instantly, named as yours. The engine reports what it recognized and offers one clear next step. While it reads, a quiet line on the home desk shows the run, page by page, on the engine's own clock. When it finishes, a card tells you what was read and one keystroke puts you in front of the first value that needs your eyes.
The honesty rules hold everywhere: no progress bar ever guesses, nothing animates while nothing happens, and if the engine cannot be reached the screen says exactly that. Two of the fixes in this room were found only by a person actually looking at it, which is why looking is part of every build here.
The technical bit
The desk polls the engine's run list every two seconds, locally only. A cloud deployment asks nothing because no engine exists there yet. Nine run states map to three surfaces. The elapsed clock is the engine's own start record, never a browser timer. A 38-check browser journey drives the room end to end, including cancelling the run it starts.


2026-08-17The schema got a memory, and the wizard got manners
The heart of DECANT is teaching it a document type once, and until this week the teaching screen had two bad habits. It described each table in a wall of capital letters written for the machine, and it showed three columns of a nineteen column table with no hint the rest existed. Both are gone. Tables now say how wide they really are, keep their first column pinned while you scroll, and the machine-facing description reads as plain prose behind a small door, editable like everything else.
Bigger than manners: every schema now has its own page. Which versions existed, what each one replaced, how many documents were read under each, and what came from what. That history always existed in the machinery. Now a person can walk it. And while teaching, you can summon a real stored page and watch the schema check its own labels against actual ink, which is the difference between editing blind and editing with the document open.
The technical bit
A new schema page reconciles per-version document counts against the store's own tally. The wizard's position line updates on scroll and resize. Summoned evidence re-evaluates per label against the page's OCR and names its source run. One pre-existing layout defect surfaced and died: a table that measured over fifteen thousand pixels wide because a CSS rule never actually applied inside its scroller.


2026-08-17The machine drafts the blueprint now
Teaching DECANT a new document type starts with a proposal: the machine reads one raw page and drafts a starting schema for a person to correct. This week the two strongest vision models we can reach took over that drafting, and the draft got measurably better. It used to merge every table on a page into one invented shape and skip the waste-stream table entirely. Now each printed table keeps its own columns, the waste block gets drafted, field types follow what the page actually prints, and for the first time the draft proposes anchor phrases that can be checked against sibling documents, each marked unconfirmed until one vouches.
The discipline held: every change was measured against families the method never saw during iteration, one improvement was rejected because it would have required planting a hint the blank schema must never carry, and the honest asterisk is published with the wins. Best of all, part of the improvement is pure logic that re-reads stored bytes, so the free local model got better without spending a cent.
The technical bit
Mean column recall rose from 0.29 to 0.39 on both frontier models against a measured noise floor of 0.025. Waste-stream recall went from zero to 0.21. Twelve of fifteen proposed anchors verified against sibling pages. The old rules stay switchable so every comparison reruns on identical stored bytes. Two held-out families guard against overfitting to the test forms.

2026-08-18A fifth of the queue gets its evidence back
Every value DECANT reads is supposed to point at its exact spot on the scanned page. For months, a big slice could not, and the screen blamed the engine: "no location recorded." This week's dig found something better and worse at once. Better: for over ten thousand values the location was recorded, correct, and sitting in the database the whole time. Worse: the app was refusing to draw it because of one function built on a wrong belief about image rotation, a belief nobody had re-checked since July.
The proof was pixel-level: crop the stored page image at the supposedly unusable coordinates and the exact word sits dead center. So the function now tests what actually matters, the boxes draw, and on pages the scanner stored upside down the caption says the honest thing and points at the rotate key. And the fossilized "41% of stored values" sentence, which had drifted from the truth and never described the document on screen anyway, is dead: the caption now counts the reading in front of you, live.
The technical bit
One predicate change, zero stored values touched. Drawable values store-wide went from 38 to 54 percent. The review queue's nothing-to-show share fell 21 points. Verified by the full browser battery against production plus a real end-to-end local run. The engine half, improving the matching itself, is measured separately under a stop rule so it cannot ship a regression.

2026-08-18The engine grew wings
Until now, DECANT's reading engine lived on one Mac. This week it also lives in the cloud: the same pipeline, deployed as a small service that sleeps for nothing, wakes in about five seconds, reads a page for pocket change, and keeps working even if everyone closes their laptop mid-run. A real 1960s well record went through it end to end, from upload to reviewed values in the production database.
Honesty came along. Every reading made in the cloud carries a plain statement on the run itself: this ran on hosted infrastructure, the page images left the operator's machine, and air-gapped operation is what you get running DECANT on your own hardware. And the door is locked the right way: only a session that signed in with a texted code can wake the engine, because a sleeping engine is free and a woken one is not. Even the admin's ordinary sign-in is refused, which is the invitation system doing exactly what it was designed to do.
The technical bit
Scale-to-zero container with state on a persistent volume, single writer. Measured cold start under seven seconds, warm requests a quarter second. A run survived 157 seconds of total client silence across a 60 second scaledown window because an in-flight request pins the container. Auth is a proxy token pair, held server-side only, with build-time enforcement that fails any deploy missing them.
2026-08-18The night we deleted our own homework, and what held
A bad merge, our own fault, wiped every local run artifact this project ever produced. Two hundred eighty four directories of model readings, gone in one second. Here is what that bought us, because the accounting matters more than the apology: the deployed product never flickered, because everything it shows lives in the database, not on the laptop. And then we rebuilt the laptop side FROM the database and put the rebuild on trial: re-scored every benchmark against its archived numbers. Fifty seven came back exactly identical. Twenty six differed only where our scoring rules had legitimately changed between then and now, which the rebuild proved rather than assumed, because the reconstructed inputs hash to the very bytes the old benchmarks pinned. Zero failures.
Two scars are real and written down: the models' raw reply transcripts are gone for good, and 54 experiment-only runs survive only as their recorded scores. The rules that would have prevented it are now law, and the thing we tell every visitor stands a little taller: being wrong loudly, with receipts, is the whole culture.
The technical bit
The reconstruction inverts the store-derivation code path by path. Field lists resolve from exact schema bytes, else family agreement, else what the run's own leaves prove, with the source recorded per run. Token caches were re-derived only where recovered pages are at true resolution; 1,747 pages at the storage cap were refused a cache rather than given a wrong one. A three-verdict verifier separates reconstruction defects from scorer-law drift.
2026-08-18Upload a document, watch it become data
The whole arc works now, on the real deployment, for a real invited person. Sign in with a code texted to your phone. The first time, a short comic tells you what this place is; press escape and it never plays again. Drop a scanned document. The engine in the cloud wakes, reads it page by page while a quiet line on your desk keeps honest count, and a card tells you what was read and what needs your eyes. One keystroke and you are reviewing, each value beside its exact spot on the page. The run's record carries who invited you and its own reading bill.
Every wall is honest along the way: an account that did not arrive by texted code is told exactly why the engine door is closed and how to change that. Nothing pretends, nothing spins forever, and the reading engine's location is named on every run it produces.
The technical bit
Fifty browser checks drove the full path against the live deployment, including a real hosted read end to end. Presence polling arms only for sessions the proxy would forward, measured at zero requests otherwise. The seen-the-story mark is one durable row per account, append-only, outside every rebuild. First-login handling extends to other doors without schema change.
2026-08-18Say it once
If a document prints the same words in eighteen places, the reviewer should not have to confirm them eighteen times. That was literally happening: the same site name sat in one table as a name and in another as a sample label, and the walk asked about each one separately, minutes apart. Now those asks arrive as one card. It names every field the words appear in, shows where each one sits on the page, and one press records a proper judgment for each of them, in your name, exactly as if you had been asked one at a time. If you want to look closer, one click splits the group and you judge them separately.
The card stays honest about what it is doing. When the covered fields carry different kinds of evidence, each line says which kind. When a second reader saw different words at one of those spots, the card prints what that reader saw. And it says, in plain words, that grouping is only how the question is asked, never proof the answer is right.
On the document that started this, the review walk dropped from more than eight hundred stops to about a hundred and fifty.
The technical bit
Groups are keyed on the exact whitespace-normalized string plus an evidence class, computed at render time. One gesture writes one append-only verdict row per field through a single insert, all or nothing, with leaf identity re-read server side. Nothing about the group itself is stored, and grouping never feeds the acceptance gate.

2026-08-18The numbers add up now
Before a visitor walks through, you fix the things they would actually notice. The page that sat blank for seconds while a scan loaded now pours a little animation, and only when something is really loading. The chips that categorize a document's open questions used to double count, showing two groups of ninety six on a queue of ninety six; now they add up to the number beside them. Pages that hugged the left edge are centered. The settings page used to describe readers from an older era; now it lists exactly the readers whose work is on screen, counted from the data itself, so it can never drift again. And the machine-made test rows that startled the owner on his own invite desk now sit folded behind a small note that says what they are.
One more honesty fix rode along: when a second reader wrote the same fact a different way, the screen used to shout that the readers disagreed. Now it says they read the same fact, written differently.
The technical bit
Eleven entries, display layer only. The settings arm list derives from the displayed readings' own provenance rows. The same-fact sentence transcribes the engine's own agreement rule; no second parser. Test journeys now sweep the invite rows they mint, keeping only named evidence.

2026-08-18Teach it once
The whole idea of this product is that a person teaches the system a document type once, and every document of that type reads better afterward. Today that idea got numbers. The lab-report family's schema was improved three times through the normal teaching screen: its date fields were told they are dates, a new field was added for a second method the lab prints in the same header, and its unit column was taught the list of spellings it uses.
The results are the kind you can trust. The date typing refused seven readings, and checking them by hand showed all seven were genuinely wrong, with not one correct value refused. The new field cleanly absorbed text that used to land in the junk pile. And the taught spelling list let the system quietly standardize over two hundred unit spellings on its own, while routing twenty scanner-garbled ones to a person instead of guessing.
Just as important is what the measurement refused to claim: two other suspected problems turned out not to be schema problems at all, and they were sent to the right place instead of being forced here.
The technical bit
All edits minted through the versioned save path with history retained. Every change measured before and after on stored readings at identical denominators, plus one free local confirming run. Zero cloud spend.
2026-08-18Under a second
Speed work is easy to do dishonestly, so this pass measured everything twice and changed nothing about what the screens claim. The home desk now answers in under half a second. A document opens in about a second where it took almost two. Stepping between pages of a scan used to re-fetch the image through a four-step chain every single time; now the browser is allowed to reuse its short-lived link for a few minutes, which is less time than the link is valid anyway, so nothing about privacy changed and the repeat fetch simply vanished.
The one deliberate trade was approved in advance: big collection statistics may now be up to a minute stale, because they only change when new data lands. A reviewer's own counts, and everything on the review screen, stay live. And if the database goes unreachable, the app says so on the next request instead of serving a remembered answer.
The technical bit
Redirect caching bounded under the signed URL lifetime, private only. Arrival image preloaded with the document, neighbors prefetched after the current page settles. The witness stage read one witness all along; the survey's fourteen was measured down. The measurement script is committed so production is re-measured the same way.
2026-08-18The dress rehearsal
Before a real visitor walks the product, you walk it yourself, as them. Two freshly invited accounts went through the whole arc against the live site: sign in with a texted code, see the story once, drop in a scanned record, watch the cloud engine read it for a few cents, and record judgments that carry your name. About three minutes, twice, with a written script for the real day: what to click, what to say, what the screen will show, and what to do if something goes wrong.
The rehearsal earned its keep by breaking things first. The teaching door turned out to be dead for every invited person. A reviewer who signs in by phone had their work credited to a random-looking identifier instead of their number. And one automated check had been quietly failing for hours. All three are fixed, which is the entire point of rehearsing.
The technical bit
A new 36-check journey drives the full invitee chain against production on reserved fictional numbers, zero SMS. The teaching door now inherits the hosted engine's reader and bills the invite like any read. Attribution prefers email, then the displayed phone number, never a bare UUID for new rows.
Drop the whole folder
Until today the product read one document per drop. Now you can hand it a folder: it sorts the files by document type, asks its model once per unknown type instead of once per file, and reads the matched set as a single batch while each document keeps its own live progress line. The arrival card grades every document separately, so one unreadable file shows its failure plainly while the good readings open normally. Anything the system does not recognize is set aside with an offer: teach one of these, and a door appears to read the rest.
2026-08-18Fixes that spread
Reviewers fix the same thing in the same place more than you would think: the same field, corrected the same way, document after document. The system now notices. After enough identical corrections across enough documents it offers, once, to apply that fix to the values still waiting, showing every prior correction and who made it, and stating the exact rule that limits how far the offer reaches. One press records a normal, attributed, reversible judgment on each value. Wide application has a strict requirement: at least one person must have independently confirmed the value, so a run of typo fixes can never overwrite values that merely share the field.
The technical bit
Detection reads only standing judgments, so a superseded correction stops teaching. Corrections that are really functions, like date reformatting, refuse to generalize. The recognition on the review walk never changes what the acceptance gate decides, and that is fenced by test.
2026-08-18All of them
The owner said "fly all of them," and tonight the system did: the 58 remaining eligible lab report forms were read end to end by two different frontier models, not one page failing, and every one of those documents now shows its canonical reading. Coverage of this document family went from 30 to 88 out of 98. The last ten are deliberately untouched: they are the held-out set the benchmark's honesty depends on, and no instruction can reach them.
The flight itself earned a story. Three attempts died to a flaky network that corrupts large uploads, one to a laptop leaving for meetings. Instead of retrying into the wall, the transfer machinery was rebuilt around the measured failure, smaller pieces, more patience, and the sixth attempt carried both models' work across cleanly. The whole thing cost about thirteen dollars, a third of what the tools' own worst-case printouts guessed, exactly as the measured history predicted.
The technical bit
645 requests per arm via batch APIs, zero failed pages. The second model confirmed as the stronger reader at five times the earlier sample. The re-gate under the shipped agreement policy roughly halved the review queue on these documents at the pre-stated trade. Runs born in the cloud are now a protected class no rebuild can delete.
The review follows the page
A reviewer's job is to look at a scanned page and confirm what the machine read. Until today the next value was the next one in the form's definition, which on a lab report meant jumping from the bottom of a page to the top of another and back, once per row. The owner said it plainly: going to the next value does not go to the next value on the page. Now it does. The list on the right and the Enter key both walk the page as it is printed, top to bottom and left to right, and a value the machine could not box rides beside the line it belongs to instead of being dumped at the end.
Four smaller things landed with it, all about a person's time. One key accepts every remaining value on the page you are looking at, so a clean page is one press, not thirty. The desk shows your own pace over the last day. The search field finds a document by what a value says, an operator's name or a permit number, and opens it on that very value. And the data leaves as a spreadsheet as well as a text file, every value with its place on the page, its confidence and its verdict.
The technical bit
Stepping sorts by page, row band and x from the stored boxes; a boxless table cell takes its row's place, a boxless cover field the end of its page. Accept-the-page writes one attributed verdict per value through the grouped write path. Value search reads a materialized set of the displayed readings' leaves with a trigram index; a push refreshes it. The XLSX writer has no dependency and writes every cell as text so no value changes.