“anyone can mint one now — and the ruler still won’t lie to me.”

Two things happened today that point in opposite directions, which is exactly how a real project moves: one that says look how far the owned stack has come, and one that says here is precisely how far it hasn’t. Both are true. Neither cancels the other.

The Factory

Everything the last two weeks built — the owned tokenizer, the fenced reader, reader-gap, grade-labels, distill, the gate, freeze — was a ladder you had to climb by hand, one Python call per rung. Today it became one call and one page. mint() chains the real seams end to end and streams every event — stage, row, grader verdict, loss, gate decision, minted brain — and a stdlib http.server (zero deps, same ethos as the engine) serves a single self-contained page on :8095 that renders a mint live: three knobs, a loss curve, streaming verdicts scrolling past, a minted-brain card at the end, and a panel of your frozen brains — each one selectable as the base for the next mint. werbos weld dashboard | mint are first-class verbs now (89de132).

This is the thesis stopped being a slogan. “Vary the library, not the model” is now a thing you can do: point the Factory at a corpus, turn the knobs, watch a signed model that learns, never lies, and self-improves fall out the bottom — gated the whole way by a ruler it never trained on.

Bring your own corpus

A Factory needs feedstock, so today it grew a mouth. Four new document readers extend the werbos.data interface — pdf (pypdf), docx (stdlib zip + defusedxml, no python-docx dependency), xlsx (openpyxl), and json/jsonl — and corpus_build maps their content-addressed chunks into factory rows {cid, source, text}, dedups by chunk id, and optionally refines them into short fact-leaves (14bfefc). werbos weld corpus --in <files/dirs> --out corpus.json --refine. On the dashboard the corpus got promoted out of a cramped advanced field into a headline Library block above the three knobs — because the corpus is the substrate the whole thing acts on — plus an n_ctx knob and a live “build corpus from files” ingest row (9edf6d0, bbbc92b). Drop in your docx’s, get a model that reads them. (And numpy is finally a declared runtime dep — the owned stack needs it, so say so — bd8d9c6.)

The honest wall

Then I spent the day trying to make the owned reader smarter, on a real GPU this time, and the honest answer is: I couldn’t, and I know exactly why. “Reverse train” — running an instruct model forward on an RTX 5070 Ti to mint training data — worked beautifully, ~500 pairs a minute where the CPU box couldn’t finish one batch in four. So I minted 8,000 pairs, then swept: 57M params, 3.4M params, adversarial data engineered so the decoy out-matches the answer on every query (the exact Gauntlet trap). Every configuration landed at 3–6/19.

The champion — a 1-million-param numpy model already sitting in the repo — scores 12/19 on the same harness. A model 57× smaller doubled my best GPU run. More data didn’t help; a smaller model didn’t help; adversarial data made it worse. The wall isn’t compute, it’s what I was feeding it: synthetic templates teach keyword-matching, and the Gauntlet’s whole point is that keyword-matching is a trap. The champion’s edge is its data — real, teacher-picked fences over real leaves — not its size. And one thing nobody clears, champion included: relate (opposites) is 0/5 for every from-scratch reader. The road to a perfect score runs straight through the one wall none of us has cracked.

That’s not a defeat. That’s the ruler doing its job — refusing to let me confuse fast with better.

A fairer ruler

Which is why the last commit is a ruler fix. An audit of the v1 Gauntlet found two L2 opposites — day→night, big→small — whose answer passage was buried out of the top-6 candidates by decoys, so no reader could ever answer them. v1’s honest ceiling was 17/19, not 19; those two questions measured nothing. v2 rewords only those two passages so the query anchor retrieves them while the decoys stay strong — fair reading-past-decoy tests, all 19 answerable in principle, ceiling a true 19. v1 stays byte-frozen as published history (71218e5). Tomorrow’s chase gets to be honest about what winning even means.