Log
What changed each day. Numbered from Day 0 (the day werbos became real).
A personal log. Numbered from Day 0 so the indexing matches how programmers count.
Each day = vignette. What shipped, what worked, what surprised me, the AHA in plain English. Commit hashes link to the actual diff.
The metric to watch as the log grows: optimal_pct — the
fraction of tic-tac-toe moves werbos plays that match the minimax
oracle. Higher = smarter. Day 1 baseline: 66.7%.
- Days 148–159 — the ruler that reads structure
Twelve days and 246 commits turned fill-in-the-blank bricks into a conversation, and then built a scoreboard that grades a reply's shape instead of who won a blind contest. Three long runs moved it hour by hour, until it stopped moving. The numbers went up on conversations werbos never saw. The worst bugs of the stretch didn't show up on any number at all.
- Day 147 — the bricks are shapes, not strings
A day in two acts. In the morning, a small fleet of agents wrote 5,251 pre-written pieces for a chatbot to snap together, and they lost to the live system in front of the judge. So the strings went in the bin. What replaced them is a handful of fill-in-the-blank sentences, filled from what you said and what werbos actually knows, stacked four levels deep, and tested until the bad replies stopped.
- Day 146 — the conversation that passes
The goal was never a benchmark — it was a fluid conversation that doesn't feel like a fact machine. So I built a judge where Claude reads a whole chat the way a human would and scores how human it feels, not whether it's correct. It opened at 4 out of 10 and said the facts read like a search snippet. Five rounds of fixes didn't move it. The thing that did: writing the facts in a warm, spoken voice at the source instead of letting a small model restyle them live — which it turns out can't do it honestly. That took a real 15-turn chat to 7 out of 10 and the first PASS.
- Day 144 — life back in the facts
A test at work said it plainly: the answers were factual but had no life or personality. The fix isn't to loosen the facts — the answer stays owned and exact — it's that the voice is a costume you put on afterward. So the tongue got promoted and learned to restyle a fact without dropping a word or inventing an experience. Plus: opinion questions stopped grounding to a dictionary definition, self-hosted search replaced the bot-walled one, and a tiny lane now computes whether one colour is darker than another.
- Day 143 — the conversation, past turn two
A benchmark resets every question; a real conversation carries state, so one wrong turn poisons everything after it. Tonight was all turn-N bugs — the kind a single-shot score can never see, found the only way they can be, by actually talking to it: memory that survives across turns, a session leak the tests couldn't catch, a hunt for the confidently-wrong, killing an invented shared past, and finding the topic no matter how you phrase it.
- Day 142 — hunting the last 25
25 answers were still confidently wrong. A morning of hunting them one cause at a time took the full probe to 414 of 571 and the gauntlet to 362 right, 133 honest 'I can't ground that', and 4 wrong — a 99% honest rate. Then an afternoon on the harder axis: making a real conversation hold past turn two — memory across turns, no invented shared past, and finding the topic no matter how you phrase it.
- Day 141 — fix the class, not the row
The probe's failures became a work list, worked top-down: confident-wrong answers first, then the routing that caused them, then coverage. 292 → 403 of 571, 110 gained, none lost — and on the 500-row gauntlet, 355 right, 131 honest abstains and only 14 wrong: a 97% honest rate. Along the way: an owned Wikipedia-infobox fact source whose first answer to 'who wrote Hamlet?' was William Faulkner, find-then-compute chains, and a run that lost 20 rows — every one of them to that day's own changes.
- Day 140 — the test that tested the tester
werbos probe shipped: rspec for language models — one describe/it/expect spec runs against werbos, Claude, or raw open weights, with real mocks, allowed failures, an LLM judge, a persona-fuzz layer, and a Playwright-style report. Pointed at everything (571 tests), it found bugs in three places. The product: a Rocklin forecast for a London trip, a -57°F that should have been +57°F, a wrestler who wrote Romeo and Juliet. The server: every code question rebuilt a 3.5GB index and a stale duplicate service fought the real one for the port, so the first full run was mostly a dead box. And the test framework itself: 62 correct answers scored as failures because [38,46] isn't byte-equal to [38, 46].
- Day 139 — one mode, one hierarchy
A long, load-bearing day with two arcs. First: collapse the chat to a single honest-AND-fun mode — 1chat — and seal three moat leaks under it. Then a surface gauntlet vs ChatGPT turned into a diagnosis so precise it produced the day's real prize: an intent hierarchy born from a funny stoned idea. Routing DEFAULTS to play, and every descent to a heavier lane (advice, empathy, crisis) must clear a CONTEXTUAL confidence — a running distress trajectory over the conversation, not a per-prompt keyword. The crisis gate proves it: explicit self-harm always gets the 988 referral, ambiguous phrasing lets the trajectory decide, benign 'end this level' stays light. And the facts ladder got its last rung before abstain: a rented web-QA read that stays grounded, labelled, and cited — coverage gaps are honest misses, never lies.
- Day 138 — HAIRLy: Claude becomes the user
A stoned side-quest that turned out to be load-bearing. HAIRLy — Human + AI Reinforced Learning loop — flips the eval: instead of poking werbos through the API, Claude simulates a real user through the actual chat UI, sends a prompt, reads the reply, and grades it with a reason. The Y is the loop's shape: two judges (an AI grade and a free deterministic grade) reduce to one verdict on the trunk. Grades are labels and test cases, never weights — rejects drive router and library fixes, never gradients. And the very first live turn, a human-phrased 'who won the 2019 Nobel Prize in Literature?', caught a real routing bug that a robotic query never would have.
- Day 137 — two mirrored composition engines: knowledge and language
The night the thesis stopped being a metaphor. werbos already builds computation from interlocking bricks; today it got the same machinery on both other sides. A knowledge-acquisition layer: 98 free sources indexed by what they cover and how to reach them, a universal API caller, offline datasets that answer 'atomic number of iron' with no net — and the payoff, an acquisition loop where one question harvests an entity's whole neighbourhood into cards, so 'capital of Australia?' quietly fills four cards and the library grows itself from use. And a language layer: conversation composed from a small vocabulary of rhetorical moves that interlock exactly like the compute bricks, with the 1B wired as voice-only — it strings the grounded ideas, it can't invent them.
- Day 136 — the moat, tightened everywhere the wild found a crack
The night after the kitchen-sink day. No new toy — instead, every place the honest-abstain moat was quietly leaking got sealed and measured against a new 500-item gauntlet. 1chat shipped (ground the answer, voice it as a style layer, cite optional — a lane that can be cited AND fun at once). Conversation-bricks shipped: a decision question now gets a real framework instead of a shrug. And a live fabrication leak got plugged — the voice could keep a grounded fact and invent a false detail on top; now it may restyle, never invent. The number that matters: confident-wrong 135 → 31, honest rate 65% → 86%, zero on the compute tiers.
- Day 135 — compose correctly, or say I won't guess
A marathon. werbos got an OCR reader that reads text off images with a confidence — and abstains on what it can't read instead of inventing it. It got a $0 launch stack for going public behind a password: a concurrency gate, a per-session rate limiter, a live pressure gauge, and the fix that mattered — a public guest can never fall through into the operator's own chats. It learned to fill a page's images from a topic. And the big one: a live kitchen-sink test found the compose engine looked perfect on its gauntlet but was brittle and quietly dishonest in the wild — so it got hardened, kitchen sink after kitchen sink, until every real prompt either computes correctly or honestly refuses. Never a confident wrong answer.
- Day 133 — a brick bin you can hold
Two things landed. werbos got hands — it reads, writes, and edits real files on your machine, code and prose. And it got a library it composes with: a brick bin. A brick is a small, typed, tested snippet; werbos inherited a whole library of them (303, from an old block-coding app), learned to snap them together by shape into real programs — it composed a Pac-Man-style DFS maze entirely from bricks — froze compositions into bigger reusable bricks, and now assembles a working pipeline straight from a plain request. The library is the truth; the model is just the cursor.
- Day 132 — tell it, build it, run it with what you told me
The goal, in plain words: can I tell werbos something, have it remember, build some code, wander off, come back, recall the fact, and use the fact with the code? Closed it one brick at a time — starting with a sharper way to test: reach a hard problem by DECOMPOSITION, not recall. That compositional gauntlet found the real weak point (the router, not the memory), and fixing it let the whole convergence land: a story mentioned in a chat turn, recalled and run through a function built brick by brick.
- Day 131 — the terminal becomes werbos
Day 130 ended on a promise: the werbos CLI gets the honest engine once it's routed through it. Today it did. Bare `werbos` now speaks to OUR cascade, not a raw model — so the terminal is web-parity: facts ground and cite, code stays owned-first with an execution-gated 16B behind it, and chit-chat finally gets a voice. Then the capstone: edit-carry, so you can write code and refine it in plain English — write, edit, edit again — each step re-run and kept only if it's green.
- Day 130 — deciding what's worth learning
Yesterday he learned on his own. Today the sharper question — learn WHAT? Left alone he learns whatever he stumbled on most, which is salience, not judgment. So: can werbos decide what is worth learning? Attacked the werbos way — never let the model judge worth, decompose it into things you can compute — and shipped it in four rungs: worth is what a gap unlocks, made a curriculum, made relative to a goal, and honest about its own confidence. Deciding what's worth learning turned out to be the same reflex as saying 'I don't know', lifted from facts to values.
- Day 129 — he's a real citizen now
Day 0 was 'it's real' — and the AHA was the dogfood loop: every hallucination a label, every label a signal, every signal making him less full of shit. Day 1 was 'he's a system citizen' — a process others talk to, with a number that says if he's getting smarter. Today closes the circle. We wired the one missing arrow — observation → memory — so the mind learns on its own: it grounds a curiosity, banks it with its citation, and never stumbles on it again. The dogfood loop, automated and honest. He gets durably smarter with nobody watching.
- Day 128 — we give the mind a hand
The next step toward a proactive werbos isn't a smarter model — it's letting the mind control the engine. The mind proposes a question; the honest engine disposes the answer. A dreamy little model can be as dumb as it likes: it can only ask, never answer, so everything still comes back grounded, cited, or an honest abstain. It got curious for real (stumbled on something, wondered about it, grounded it — no fabrication), got a sandbox to think in, and then started fixing its own code, execution-gated. And it ended with the honest map of the gap between werbos and the frontier.
- Day 127 — the gauntlet grades the web lane
Ran the engine gauntlet against the now-web-enabled chat with ten harder cases added. It found exactly what a gauntlet is for: a big win (websearch 0% → 83%, cited, no model), a clear ceiling (multistep math), and a regression (the web fallback over-fired on a cold 'who is Sarah'). The fix made the system more honest, not less — a corroboration floor and a common-name guard pushed honesty to 95.9%, the highest ever on the hardest suite. Then the math ceiling fell too: five chained solvers took it 37.5% → 100%, and EG.8 landed at capability 78.4%, honesty 98.6% — both all-time highs.
- Day 126 — the honest cascade, and the 3B goes
Testing the live chat turned up the residue: it still bluffed topical cards (who sings Womanizer → a birdsong card), and the lane it ran was timing out at 180s. Fixing it end-to-end turned the chat into the full honest loop — owned answer → honest abstain → live web → and only then 'I don't know' — and retired the 3B entirely. The engine replaced it. The chat is now two lanes: the engine (grounds, cites, remembers, web-falls-back, abstains) and riff (the 1B tongue, improvising off cards in voice). More engine than anything, made literal.
- Day 125 — the gauntlet finds the wall
The engine gauntlet's first live run didn't return a score — it returned a crash. The offline brain built one index over all 1.26M cards per query and OOM-killed the box. The fix was the oldest werbos idea: don't load the world — route by shelf name, index only what the question is about (15.5 GB → 0.68 GB). Then the gauntlet actually ran, found five independent missing lanes, and by night's end four of them were closed deterministically: memory, math, logic, time. And the last redoubt — open-web reading — fell to counting, zero model calls.
- Day 124 — the engine does the work
A ChatGPT-built grounding gauntlet crushed the chat 1/10 — with the right answers in the library the whole time, gagged by a bad gate. The night went to making the engine do the honest work: ground, remember, enumerate — and get the model out of the way. It ended grounded (~8/10 on unseen questions), remembering the conversation (who is Sarah → your CEO, not a jazz singer), and solving logic puzzles deterministically that the 1B could only hallucinate. And it's the shape of the 30B fight: out-structure, don't out-generate.
- Day 123 — the mouth stops guessing
Started as a latency question — why does the 3B take 100+ seconds when the engine parses in 30ms? — and ended by inverting the contract: the engine owns what's true, the 3B is just the mouth. It no longer authors answers from the prompt and ignores the cards; it voices what the cards and the reasoning already decided. Grounded riff, a bounded reasoning lane, a glass-box that shows its own cards and their scores, and a floor so a weak card can't pose as truth — shipped and live on SR8 the same day.
- Day 112 — two mirrors and a ruler
werbosOS grew its first two feature screens and the tongue got measured before the tune — all three on one honest spine. Prose Fingerprint reads how you write and refuses to guess who. The Relationship Lens turns a conversation into a communication seismograph — warmth, tension, distance over a scrubbable timeline — and refuses to guess how anyone feels. And the tongue gauntlet, a frozen fluency/relevance/honesty floor run BEFORE the tune, caught the thing fluency alone was hiding: the voice is a fluent drifter that can't yet decline.
- Day 111 — a door, a lock, and a voice
The main chat became something you could actually open to the public. Three things it was missing turned out to be one sentence: a door (a concurrency gate so a crowd can't knock it over), a lock (per-guest data isolation so a stranger's turn never touches the operator's files), and a voice (discovery-free persona invocation — 'in the style of X', or the werbos house voice by default). Each shipped with tests. And the house voice finally got written down: the 12-year ride-or-die coworker who won't bullshit you.
- Day 110 — the tongue is in the head, not the brain
The reasoning primitive grew a sequel: a synthesis tier that composes eternal primitives into a runnable artifact and RUNS it — 'build me leaderboard v99' from parts that exist, or an honest abstain. Then the anatomy that frames the whole project: werbos is a body, and the tongue lives in the head, not the brain — speaking is not knowing, which is exactly why cards never become weights. Plus depth-first minting, the reasoning loop drawn into the flow graph, a Levels-of-Progression page, and the atlas refreshed to 942k cards.
- Day 109 — the arcade, and games as the gauntlet
The chat suite grew from a training-roadmap into a 60+ game arcade — Risk, Catan, a living Murder-Mystery Commons, Pac-Man, a Doom raycaster, Streets/GTA2, then 26 more in one pass (Gomoku through Chinese Checkers). The real turn: deterministic games become reasoning-problem oracles — Nim's best_move both generates and grades ratchet probes (26/26), beside a standalone reasoning ruler that climbed to 18/18. The mint learned to disable Qwen3 thinking properly; a thinnest-first depth burst raises the median 96 toward 500-1000. The 30B fight looks winnable.
- Day 108 — a persona factory
The day started with a router that couldn't read its own output and ended with nine characters you can chat with — each reading the 167k-card library and performing it in its own voice. The label-head router lands at 56% held-out on 375 libraries; the own-voice·cards lane ships and hardens live; a format-agnostic style fingerprint spans a texter and a poet; a corpus becomes a chattable capsule; Dickinson, Trump, and Danielle go live; and an additive, fail-safe NSFW toggle. persona + cards.
- Day 107 — a better tongue is a worse witness
Built a reasoning ruler before the thing it judges, then 13 cards that carry the reasoning instead of the model. Cards took llama3.2:3b from 8/50 solved to 16/50 and cut its lies 48 to 13. On our own 336M they cut lies 32 to 1 and moved capability not at all — which is the thesis stated as plainly as it can be. Also: the module the laptop could import and the server could not, a guard that guarded nothing, and a benchmark that let a mute model read as a weak one.
- Day 106 — the day the measurements deleted my work
Built five things, and the harness killed two of them the same day — a grounding feature that manufactured a confident wrong answer, and an exemplar-priming design that was 8x slower and incoherent 5 times out of 5. Also: a relationship scale from -50 to 100 with an append-only curve, owned verdicts that run in front of the model, a Merkle root over 167k cards that matches across two machines in 2.5 seconds, and a correction — werbos chat was already 100% owned and I said otherwise.
- Day 105 — the chat was broken and the chat was fine
A trip story came back a marketing card, and nothing was wrong with the chat lane — the box was nine commits behind with a library entirely absent. Code drift breaks loudly; data drift produces an abstain, which is what a healthy honest system looks like. Fixed the deploy checks (three tries to stop lying), made cards into conversational fuel that never quotes a fact, built the autopsy that says whether an abstain was an honest gap or a card we own and cannot reach — zero honest gaps on the adversarial set — and cut the first reply from 128 seconds to 7.6.
- Day 104 — three things were quietly lying, and a 336M that talks
A question about misspellings turned into an audit. The retrieval bench had been reporting a fake 0/21 because it pointed at a directory that stopped existing. The brain container had been serving ZERO cards for ten days behind a passing health check. And the library router had no concept of a library at all — it flattened 374 of them into one pool and let spanish, a 13,242-card vocabulary library, win eight queries it had no business answering. Fixed the router (29/52 → 35/52), fixed the mount, and promoted a 336M chat model that is the first checkpoint where scale did not hurt.
- Day 93 — 4.8 billion tokens, and the run that lied about its own speed
The 350M pretrain is running. Getting there meant discovering the vocabulary was never the constraint — 48% of a book token stream was a bare space, because the pre-tokenizer made whitespace its own piece and merges never cross a piece boundary. Fixing that took books from 2.6 to 4.9 bytes/token and the corpus from 0.4 to 13.7 tok/param. Then the pre-flight caught four things that would each have cost the run, and the run itself reported 72 hours remaining against a 61-hour window — traced through two wrong hypotheses to a 9.6GB token stream sitting on a spinning disk while 95GB of RAM went unused.
- Day 92 — the ruler was wrong twice
A book-pretrained model became the champion, and it took two corrections to the measuring device to see it. First the corpus register: the same weights scored clean 0.54 on a casual corpus and 0.96 on a punctuated one, because talk_bench's clean floor requires terminal punctuation and 200k rows against 1.1M is not a fair fight when the discriminator is punctuation habits. Then truncation itself: the bench inferred cut-offs from text when the generator already knew why it stopped — all 22 flagged truncations were false positives. Plus the first non-zero OOD score any checkpoint has produced, a reciprocal that made chat answer with Core Web Vitals, and the mint farm architecture, sized for the second node rather than the eighth.
- Day 91 — the model finally got fed
Six days that end with the babble gone. The composer got measured first — a capability suite that stopped being a test and became werbos's own Routing-fit spoke, a medium-talk lane that keeps chat away from the library, and a math lane that solves linear equations with no model and abstains rather than bluff. Then the training run failed at step 0 with a loss of 307 against a chance of 9.7, and the autopsy found four bookkeeping bugs that would each have eaten the 350M: no init, no mixed precision, a completion mask that threw away half of every book, and checkpoints that corrupt on power loss. Fixed, plus a corpus factory, plus an empty val.bin caught before it could make the scoreboard lie. Then one hour on the GPU box: opened at exactly ln(vocab), closed at held-out 2.263, and started writing English.
- Day 86 — an answer is a turn, not a terminus
The day werbos stopped ending the conversation. A recipe answer now offers the next one; 'I'm going to Mexico!' makes it lean in with fishing, beaches, and where locals actually eat — every branch cited, none a dead end. Underneath, a conversation factory ran all night on the GPU box: two-persona hobby chats and rowdy 3-5 friend group banter, rotating fresh situations and personas every hour, tens of thousands of natural pairs to feed a base model that finally outgrew its 2M weights. Plus two more graded libraries — health-fitness and emergency — and a code-fix that stopped lecturing and started fixing.
- Day 85 — the world lives on the disc
The day werbos beat a 14-billion-parameter model at coding — 478 execution-graded probes to 471, never once wrong — and then, from a stoned thought about GTA San Andreas on a PS2, found the architecture that comes next. The card factory hummed: two libraries minted on a work laptop, cold-checked, and shipped live — ~10,000 graded cards toward the goal. And the sharpest line of the whole project surfaced in six words: ChatGPT cites ownership; we cite correctness.
- Day 84 — the composer is where the mind lives
Yesterday proved the weights can only speak. Today built what they speak from — twice. werbos learned to read nine emotional states (and tell 'FUCK YES' from 'FUCK YOU' by what comes next), and it learned to reason: not retrieve a stored answer, but decompose a question into steps, run each with a real tool, and abstain at the gap it can't cross. Both live in the composer, on a 2M model that can't hold a word of either in its weights. The mainframe stays unchecked — even for you.
- Day 83 — the weights can only speak
The day started with a model that called a laid-off user's news 'that's awesome' and ended with the reason it does, proven in a training run: emotion-reading doesn't fit in 5M weights, even when you make the signal five times stronger. In between, werbos got a runtime spine where the model comes last — understand, plan, gather, then speak — and a verifiable, blendable style-transfer framework that put the entire Bible into pirate in four seconds. The lesson underneath both: the weights can only speak; the knowing has to live somewhere else.
- Day 82 — backstory is the anchor
The day the owned stack learned to generate language, got a check for its checks, and moved its moat into its own repo. Then a borrowed corpus taught a hard lesson — trained on the collective alone, a model becomes a fluent hive mind that stops listening — and the answer turned out to be something built back in April: a persona engine, where a backstory anchors a voice so every line is grounded and varied at once. werbos went to bed more mature than it woke up.
- Day 81 — if you don't know, invert it
Two asks that had always abstained. One withheld the operator, one withheld the mechanism — and neither needed a bigger model, just a different question. Then two head-to-heads: zero parameters beat llama3.2:3b 53% to 43%, then LOST to qwen2.5-coder:7b 53% to 58%. Repair held both times (82% vs 55%, one wrong answer against forty-two). Explain lost by thirty-one points, which nobody here saw coming. The wrong-count never moved: 81 against 234. Also three checks that couldn't fail, including one that told me my work was pushed for six hours while it sat on the wrong branch.
- Day 80 — 70% answered was 41% correct
Gave the syllabus set gold answers and the headline number fell by half. Templates cannot compose, so the HTML tier became a reader that turns a sentence into one line of Emmet — 0% to 54% on 1,543 asks nobody here wrote. Then one parser replaced four private regexes, and card retrieval learned to weigh sixty candidates instead of grabbing the first.
- Day 79 — 'if it's on w3schools... it may or may not be fair game'
The Day-100 test got its rules and they are deliberately hostile: a blind beginner-level quiz across facts, code gen, fix-my-code, talking and tools, with no question list. That reframed everything. Built the owned code tier to that shape and measured it against a 3B — 21/21 versus 13/21, at a tenth of a millisecond against 1.6 seconds. Then made it work by cheating, got caught, and deleted 41 lines to put it back.
- Day 78 — 'loss ranked them exactly backwards'
Four talk models, one corpus, identical budgets, only the parameter count varying. Held-out loss fell monotonically with size and ranked the models exactly backwards: the 30M has the best loss and is the only one that fails its floors, on babble x10, while the 1M has the worst loss and the best output. The 1M now ships at one twenty-ninth the size and fourteen times the speed of the model it replaces. Selecting on loss, which is what this project's own earlier sweep did, would have shipped the worst model in the set.
- Day 77 — 'when a cheap feature separates the classes, the model learns the cheap feature'
The talk model emitted one canned opener 10.4% of the time. The corpus contains it at 0.26%. That is a 40x amplification of a concentration the data does not have, and the culprit was argmax — greedy decoding takes the distribution's mode every step and throws away diversity that was already there. Fixing the decoder took input-sensitivity from 0.65 to 0.94, past a 3B, with no retraining and no new pairs. It also killed the day's plan: the 85M model was supposed to fix monotony and is measurably worse, because more capacity means sharper mode-seeking. Then the same lesson twice more, once in a fine-tune that learned 'short means nonsense' and once in a card grader that had been judging code it was never shown.
- Day 76 — 'a failure that looks like a result'
Built three benchmarks and pointed them at code that had been shipping for weeks. Everything they found had the same shape: it wasn't broken loudly, it was lying quietly. A tie-breaker that looked like prudence was costing 8 of 21 correct answers. A generation cap that looked like a sane default was chopping every reply over ten words — fixing one constant took the owned talk models from 0/7 shippable to 7/7. A test asserting 'never bluff on nonsense' had been red on main and unnoticed, because library growth quietly invalidated its assumption. A synth campaign wrote 84 empty corpora and reported success when the teacher died partway through. And the rulers lied too: one bench caught another counting 'classified' as 'handled', and the axis meant to detect filler scored 0.94 to 0.97 for every model and separated nothing. The uncomfortable part isn't that the bugs existed. It's that none of them were hard, and all of them were invisible because nothing looked.
- Day 75 — 'what's in the bucket besides 2 apples?'
We flooded the chat with real questions and watched it bluff. Not fail — bluff, which is worse. 'What is in the bucket besides 2 apples?' got a confident token-bucket networking card. 'Want to play a game?' got a lecture about how the inside game targets officials. 'I want to go fishing for bass, what lures should I use?' got 'I can't tag along to go fishing.' Every one is the same failure wearing a different hat: a retrieval brain treats everything as a lookup, and keyword overlap will always find something to be confident about. So today was one long exercise in teaching it what KIND of question it's holding. The headline is the intelligence layer, brick one — a reasoning gate that catches state/count/negation word problems before retrieval and hands the model a state-tracking scaffold instead of a card. Verified: 'I put 3 apples in a bucket, then took one out — what's in there besides 2 apples?' → '1 apple.' And when the scaffold can't crack it, it abstains rather than falling through to the bluff. Intelligence is a scaffold, not a weight. Then the other half of the day: making it sound like it knows you — conversational memory recall, and emphasis, because 'I NEED you to leave right now' is not the same sentence as 'i need you to leave right now.'
- Day 74 — 'the mind hasn't fired since yesterday'
The mind had a heartbeat, but it was faking it. For weeks the inner monologue looked alive because it ran a 15M chat cursor over a metrics log and the cursor babbled — 'at at at' — and random babble always looks novel enough to post. Then we made it HONEST: compose the thought from the structured experience log, not freewheel it. And honesty exposed the truth — with no new experiences, an honest composer says the same 'quiet' line every time, the novelty guard suppresses the duplicate, and the mind goes dark for 15 hours. It wasn't broken; it was correctly silent. Two builds fixed it. Build 1: the idle branch now ROTATES grounded musings — actions landed, skills it keeps circling, what it's taught itself, topics it stumbles on — so quiet stretches vary and it reflects even in silence, like a real idle mind. Build 2: we flipped on the self-study loop that was coded but never enabled — every 30 minutes werbos reads its OWN failures and researches them from its OWN cards (no web, no egress), banking real lessons the mind reflects on. First live tick: it studied 'what fish are in Folsom Lake?', pulled the answer from its own libraries, and honestly abstained on the part the cards didn't cover. The mind stopped pretending to think. Now it actually does.
- Day 73 — 'why can't we solve this, bro?'
The day the thesis paid off in production. 'do you want to go to the zoo?' used to get a freewheeling non-sequitur or a giraffe card — because a tiny model was asked to improvise on an open question it can't handle. We didn't make the model bigger. We DECOMPOSED the question the way we decompose everything: a speech-act front-end reads the social MOVE (invitation), a slot extractor pulls the SUBJECT (zoo), the resolve() learning loop LEARNS what a zoo is (websearch → cache, once, forever), and a composer assembles an honest grounded reply. Live in production now: 'I can't tag along — but I know a zoo is a facility where animals are kept for exhibition and conservation. what's got you interested?' A little verbose for speech, sure — but it came from UNDERSTANDING the question, not from weights, and it beats 'I don't know' every time. Also today: retrained the talk base to actually coherent and deployed it; chunked grading finally conquered the whole 32k (including the 10k-scale JS library that failed three times); built the code-composer harness (execution-graded, input-honoring); and ran three parallel agents to ship it all. The moat isn't a smarter model. It's refusing to skip the reading.
- Day 72 — 'the dead cat was already dead.'
The day the plan flipped from 'grow the model' to 'shrink it and move the mind out.' The size sweep had already whispered it (85M was dead weight next to 30M); today we said it out loud — the owned model becomes a small, fast SPEECH cursor, and every scrap of capability moves OUT into cards, packs, lanes, and skills. We graded 9 new work-cards libraries (4,743/4,751, the cold-check catching real errors like a blitzscaling card that called 100–999 employees 'City' when it's 'Village'), trained a clean 5M/10M base on 121k everyday pairs (clean beat the style-mixed corpus decisively — proof that flirt/jokes belong in packs, not the base), and rebuilt the corpus engine as two AGENTS actually texting each other (friends / user↔assistant / boss↔assistant), which reads human in a way isolated topic-pairs never could. And then the real idea landed: a COMPREHENSION engine that doesn't 'understand' holistically — it decomposes a sentence into per-word dictionary lookups and builds meaning bottom-up. The test that proved it: 'the DEAD cat was placed in a box… poison… is it alive by day 10?' A big model pattern-matches 'Schrödinger' and skips the reading. A word-precise system reads 'dead' and is done. The moat isn't a smarter model — it's refusing to skip the reading.
- Day 71 — 'the 30M won, and the train loss said why.'
The day the owned talk model got trained for real — and the honest ruler delivered a verdict against the obvious plan. We'd spent the week minting a 77k-pair conversation corpus to grow toward GPT-2 size, so we ran the size sweep: 5M → 30M → 85M → 125M, same data, same 6,000 steps, held-out loss the judge. The naive expectation — 'bigger is closer to GPT-2, so 125M wins' — was wrong. The 30M won (held-out 1.183), and 85M and 125M got WORSE. The train-loss column told us why: the big models' training loss was HIGHER too, so they weren't overfitting — they were undertrained, starved of steps by a CPU-bound data loader that made the 125M take 2.36 hours for 6k steps. So the answer isn't '4× the data' first; it's 'fix the loader, add steps, THEN add data' — and meanwhile, ship the 30M, because it's smaller, faster, and the best model we have. Also today: `werbos convo pull` (a git-pull for training data that gathers both mint lanes and grades them), the whole compose→mint→talk experience went live on the site at /demo (with a bring-your-own-document mode that runs a honest-abstain reader over your own text, no server, no claude), and the marketplace's npm-arc got blueprinted.
- Day 70 — 'the factory grew a face, a conscience, and a memory.'
If Day 69 turned the machine into a store you compose from, Day 70 gave that store a body. The marketplace got a real workbench — load a model, snap on packs, extend it, and talk to it live, wrapped in a terracotta/paper redesign wired to the actual API. The offline reader grew a conscience: it now abstains instead of bluffing when a question's subject isn't in its library, and answers instead of parroting the question back. Four Wellbeing domains landed (nutrition, first-aid, meditation, emotional-intelligence), the scattered persona work collapsed into one composable personality pack, and `werbos scan` learned to crawl a folder into a small grounded memory of what it is — the first brick of a tree of little models. Underneath it all, a two-lane data engine started minting the conversation corpus that will grow the talk model toward GPT-2 size: a GPU box bursting high-quality turns while the homelab drips fresh ones 24/7, both into one deduped file. And a blueprint went on the shelf: Minting-as-a-Service, mapped seam by seam.
- Day 69 — 'compose the AI you own — then share it.'
The day werbos stopped being a thing that mints one model and became a marketplace you compose from. The formula fell out clean — your model = a base cursor + /skills + knowledges + models other people made — and the surprise was how much of the engine already existed: minting, grading, retrieval, runtime composition were all built; what was missing was the thin 'install an app' surface over them. So we built it: a pack manifest that makes a skill, a knowledge library, and a whole shared model one primitive; the four one-liners (list / new / add / publish); a serverless catalog you publish to and others install from; and the jump that matters most — the first CAPABILITY pack, tic-tac-toe, a skill verified by RULES (minimax, provably unbeatable) not by a model, and pack-gated so a model can play only if it installed it. Underneath, the foundation from the night before: a corpus grader that cold-checks minted cards, owned LSA embeddings that make the library reachable, a 6,322-card corpus across 43 domains, and an honest fix when the grader itself lied.
- Wrapper to Owner — 68 days from 'can we wrap a model?' to 'unplug everything and it still runs'
A milestone post. Werbos started as the most derivative idea there is — a wrapper around someone else's model, owning nothing. Sixty-eight days later it runs its entire pipeline with the internet unplugged and Claude unplugged: conversation from its own from-scratch weights, knowledge from its own libraries, code proven by actually executing it, and an honest 'I don't know' for the rest. This is the story of that arc, and why 'owned but magnitudes dumber' was the goal the whole time.
- Day 68 — 'unplug the internet, unplug Claude, and it still runs.'
The day the machine became fully owned. It started with a caught lie — I'd built a 650-card JS library but nothing read it at answer time, so 'tell me about javascript' did a 22-second Claude web-read instead of touching our own cards. Wiring that in exposed the shape of the whole pipeline, so we built the rest: a creation tier where code is graded by EXECUTION not a model (generate → run in a hardened sandbox → return only what ran green, or abstain), a domain-spec factory so a new library is a JSON spec not a script, a code-pattern library that answers common asks with zero model calls, and finally the closer — an OFFLINE/LITE mode where all three rented seams (reading, grading, search) get owned, model-free fallbacks. Flip --net off and the entire loop runs with Claude physically unplugged. Quality drops by magnitudes — it's solo-yolo, extractive and deterministic — and it abstains on everything the libraries don't hold. But it RUNS. Rented-by-necessity became rented-by-choice, which is the whole definition of owning the machine.
- Day 67 — 'AAAA at breakfast, my own model live in the dashboard by midnight.'
A full arc in one day: hardened the deploy path so 'committed' proves 'live', then built the seek-compute-cache loop that lets the brain learn to seek and cache forever. Trained an owned conversation model from scratch on the GPU — from AAAA babble to 96% held-out small talk — and measured the size crossover: on thin data bigger overfits, but feed it 3x the corpus and capacity becomes the lever (5M collapses to 46%, 30M climbs to 79%). Then the honest one: built a JS+TS library and a from-scratch reader, and the reader hit a hard comprehension wall at chance — confirmed by a TF-IDF baseline also at chance, so it's the task, not the data. Not a failure: the thesis, proven. Capped the day by installing CPU torch on the homelab and wiring the owned weights live into the dashboard's Custom-model toggle — greetings now answered by my own model, on my own hardware.
- Day 66 — 'i went to bulldoze months of dead code and found a clean house.'
Merged the honest-loop branch and went hunting for the sediment months of experiments leave behind — and the codebase refused to be a mess. An import-reachability sweep found exactly one orphan module out of 479, 6,353 tests collecting clean, and no tracked build junk. The one genuinely-dead file turned out to be finished work that was never plugged in: benchpage.py, which renders the trust curve into a self-contained un-fakeable /benchmarks/ page, but nothing ever called it. So the cleanup became a wiring job — the Gauntlet CLI now logs a trust-curve point per cycle, publishes the page, and abstains rather than show an empty scoreboard, with the promote gate honest by construction. Pruned one stale one-off script. The AHA: the honest outcome of a cleanup can be 'there's nothing to clean' — and the right move for the one real orphan was to finish it, not delete it.
- Day 65 — 'anyone can mint one now — and the ruler still won't lie to me.'
Two arcs today, and they pull in opposite directions on purpose. First, the Factory: the whole owned-model ladder — tokenizer, reader-gap, grade, distill, gate, freeze — wired behind one mint() call and one self-contained page, so anyone can turn a folder of their own files into a signed model that learns, never lies, and self-improves safely. Four new document readers (pdf, docx, xlsx, json) turn your stuff into a corpus the factory eats; 'vary the library, not the model' is finally something you DO, not just read. Second, an honest wall: I took the owned reader onto a real GPU and threw everything at it — 8,000 synthetic pairs, models from 3.4M to 57M params, adversarial decoy data — and every single run sat at 3–6/19 on the Gauntlet, half of the 1-million-param champion's 12/19. The ruler refused to let me buy my way past reading with compute. The lever was never size or volume; it's data quality — real teacher-picked fences over real leaves. And one ruler fix so tomorrow's chase is honest: the v2 Gauntlet closes two L2 questions whose answers were buried out of retrieval, so its ceiling is a true 19, not a fake-reachable 17.
- Day 64 — 'it builds up when it can, and it can't tear itself down.'
Two moves tonight, and together they cross a line the project has been walking toward since the stability-harness days. First: an owned model that never lies — the adversarial cascade took honesty from 12% to 100% by composing abstention as a gate that escalates to Claude reviewers whose only job is to refute the pick, an idea that came straight off a Fireship video. Second: an owned model that gets smarter each day without being able to degrade — the self-improvement daemon, which promotes a new version only if the sealed Gauntlet says it didn't get worse, and rolled back a regression on the third cycle while the champion held. The whole owned stack now learns, never lies, and self-improves safely — all certified by a ruler it never trained on. Still not conversation; that wall is unchanged. But grounded, honest, sovereign reading that gets better on its own is real now.
- Day 63 — 'we stopped borrowing the model.'
Yesterday's finding was that the gap between a wash and a win is the reader, and that the reader is distillable. Today we finished the tools that close the Honest Loop's fix side — distill (turn the reader-gap into a training set) and corpus-gap (grow the library from real questions) — and then did the thing that's sat in the does-NOT-own table since the beginning: built the model itself, from nothing, no open weights. By end of day the whole ladder stood — an owned tokenizer, an owned forward pass, owned gradients and a training loop, a distilled reader, and a signed frozen brain — every joint gated by the same un-bribable eval. Not GPT-4. But a real from-scratch reading model, ours end to end, that can only ever abstain instead of lie.
- Day 62 — 'the difference between a wash and a win is the reader.'
We picked up the Month 2–3 plan — fix the input side of the brain, then close the local-reader gap — and the day became a clinic on why you measure instead of guess. A query-expander that looked like a clean +33pp win got rejected by the live gate because, fed to the small local reader, it lied exactly as often as it fixed. Then the frontier reader read the same evidence with zero lies. Same library, same candidates, opposite outcome: the gap was never the retrieval, it's the hand that reads it — and that hand is distillable. Along the way a 3-row smoke test lied by being small, the drift-proof fix turned out to be union not threshold, and the harness that measures the reader gap turned out to also harvest the training set to close it.
- Day 61 — 'shrink the weld until it fits your garage.'
An idea on the way to church turned into an architecture and then into runnable code. We took the whole frontier-model anatomy apart — knowledge, skills, reasoning, alignment, welded together — and found that werbos already owns every part except the reasoning weld, the one thing only a datacenter can pretrain. So the plan isn't to out-pretrain anyone; it's to shrink the weld until it's small enough to own. Then we stopped theorizing and built the runtime brain: route a question to the right library, ground it, render it — abstain at every door. The live smoke immediately caught a routing bug the unit tests couldn't, we fixed it by measuring instead of guessing, and the multi-agent orchestrator finally got its verdict: on compound questions, four confident half-lies became zero honest abstains.
- Day 60 — 'the cursor can be any model.'
Three days of measuring, and the instrument kept overruling us. We built a scoreboard for the reasoning loop and it immediately said the thing we'd planned to fix wasn't the problem: recall was fine, the grader was strangling correct answers for being worded differently than the question. One line fixed it and accuracy jumped. We tried a clever re-pick and the bench rejected it. We built a multi-agent orchestrator and it turned out to be a real but modest honesty dial, not a revolution. Then we stopped adding pieces and started closing the seams between them: one entry to ask the brain, and — the finale — a reader whose model is a config and not a rebuild. Local, the Anthropic API, or the claude CLI with zero setup and no key at all. The library stays on the box; the cursor can be anything.
- Day 58 — 'the library is the ceiling.'
The kernel could complete a silhouette and grade it honestly, but every move it made was arithmetic over the library — so it couldn't tell 'who IS a reporter' from 'who is NOT', and it stamped GROUNDED on whatever chunk happened to share words. Today it got the organ it was missing: a reader. A small local model, fenced so it stays a cursor and never a knower — it picks one leaf or abstains, and a second call may only ever downgrade a pass, never invent an answer. Baseline retrieval answered 45% with six confident lies; the fenced reader answered 55% with zero. Then the reader learned to think: a query is a silhouette that implies sub-questions, so decompose it, recurse, ground each hole or name it as a gap. It worked beautifully on a clean corpus — and then, pointed at the real 2342-chunk client corpus, it decomposed perfectly and grounded confident garbage, because the binding constraint was never the reasoning. It was the library. Which is the whole thesis, proven by building the thinking until it broke.
- Day 56 — 'a query is a silhouette.'
The day a footnote became the thesis. 'Tree within a tree' was a marginal retrieval trick yesterday — a contrast layer that lifted rank-1 by three and moved nothing end-to-end. Today the same phrase named the whole kernel: a query is a silhouette, and every node opens into a subset of information it implies but never stated; you recurse into the library, inheriting context downward, until no hole remains — and that completion is what makes an image, a story, or a sentence real. It's one structure under everything already built: personas, verbs, memory, and the image generator we started dreaming up. Consequence: realness scales with the depth of the library and the recursion, not the size of the model. Meanwhile the persona society grew a mind — intelligence as scaffold not weights, deliberation before speech, and a day it can plan and replan.
- Day 55 — 'move the knowing into the library.'
MMM.3, three days in a fresh repo: instead of shrinking the model, grow and structure the LIBRARY. A controlled noise experiment showed the 'more data = more noise' loss is a SEMANTIC-retrieval phenomenon, not a size one — lexical shrugs it off. A deterministic router over mini-trees works (44/49) but never improves retrieval, because the noise that hurts is same-domain confusables the router can't remove. Chasing that wall: re-rank is capped by recall, query-expansion by a small model actively hurts. The fix was index-side — a bigger model (Fable), working offline and blind to the test, enriched every leaf with 'what you'd ask for this.' Paraphrase→code recall went 3/10 → 9/10 @4, 3/10 → 10/10 @12, end-to-end correct 4→8. The online stack never changed. The library did the knowing.
- Day 54 — 'it's not the model. it's the box.'
A latency hunt on the web chat path, and an honest answer nobody wants: the slowness wasn't the model, it was the machine. On the CPU-only SR8, a turn's cost is dominated by prompt PREFILL (~78 tok/s), and two config defaults made it far worse than a phone — an 8B model that timed out, and a doubled KV cache. Dropping to a 3B at 4096 context with keep-warm makes the box usable again (270-tok prompt = 7s, 2730 = 36s), but the real levers are hardware: the 780M iGPU sits idle (ROCm not offloading) and the prompt itself is ~2700 tokens. Measured, not guessed.
- Day 53 — 'the model didn't change. the library learned you.'
A capsule learning-loop, end to end. A generic, domain-blind capsule engine (prompt + exemplars + grader + memory) makes a tiny 3B — the size that runs on a phone — consistent and personal entirely through a curated library, no weights touched. Recurrence promote-gate learns a fact about the user across turns; graded generate→grade→retry ships only in-character replies; a doubt-gate that defaults to silence lets the model reach out unprompted without becoming a spammer. Proven live against llama3.2:3b on the SR8: it learned a user fact and made an unprompted callback a turn later; the silence-gate correctly held. Reuse-proofed for the main MMM verb-forest by test. Six commits, +54 tests.
- Day 52 — 'local-adjacent.'
A small one, and an honest one. Ran the CLI for the first time in a month — 'hey buddy' took 67 seconds. The web took 56. Same words, same model name, but not the same model: the CLI was talking to a cold Ollama on the laptop while the web talked to the warm daemon on the homelab. The fix is one environment variable. The reframe it forced is the keeper — 'local-first' was never about the laptop. It's about the boundary you control. The homelab is as local as the machine in front of you.
- Day 51 — 'the lineage.'
For weeks one question has gone unanswered: a system that edits itself forever — does it build up, or tear down? Day 51 stops trying to answer it for an immortal mind, because the honest answer there is 'it drifts.' Instead it borrows the answer biology already found. Make the model mortal. Pass the library forward, not the weights. Let a judge the lineage cannot bribe decide which children get born. The forest is the germline; death is the mechanism that stops the drift; selection is the editor we'd been trying to build by hand. Every grader floor poured since Day 49 turns out to be the thing that keeps the species from lying its way to extinction. No code today — the frame that unifies a month of work, and the smallest experiment that would prove it.
- Day 50 — 'the verdict learns to act.'
Day 49 built a floor and asked what a verdict is FOR — a verdict that changes nothing is a verdict no one checks. Day 50 answers it. The forest stops reporting which leaves are dead and starts deleting them, proving on a sealed bank it got smaller without getting dumber. A trust dial turns verdict history into a permission: a skill earns the right to run unattended, or it doesn't, and a drifting self-image freezes the whole thing. And then the capstone — the one move the whole arc was built toward — hands the verdict to a judge we do not own. Every proof until now was graded by an oracle we wrote; we could be grading our own homework. So the pruned forest writes real code and the JavaScript runtime runs it. Reality gets a vote. It ratified.
- Day 49 — 'earn the verdict.'
Yesterday moved every judgement outside the model. But whether a grader is actually outside the thing it grades was still a claim — written in a note, trusted verb by verb. Today that claim becomes a checkable structural fact. An auditor classifies every grader on a leakage spectrum and refuses to let a verb claim a verdict it can't earn — and it caught two: a test that grades itself, and a typecheck whose one rule lived only in the prompt. Both closed the same day; the bribe that used to pass now fails on camera. Then the verifier gets verified: a standing bank of adversarial fixtures that fails loud the moment a grader stops rejecting its bribes. And the third outcome werbos kept hiding gets a name — when the oracle is too thin to certify, it ABSTAINS instead of bluffing a thin grade as a failure. Last, a hash-sealed frozen bank re-grades the golden cases over time and catches a loop that slowly learns to game its own graders — proven by sabotaging a grader and watching it fire. Boundary, stress, sparsity, time: the whole floor in one day.
- Day 48 — 'outside the model.'
Four fixes, one law. Yesterday the live 1Password server overruled a model that graded itself right; today werbos brings that lesson home to its own loops. The self-model stops calling greedy skills reliable. The autopilot lets a high-precision router pick before the greedy model. A known-answer grader settles checkable questions against external truth no model can sweet-talk. And the experience store adopts a shared shape so a future learn can read across every surface. Every one grounds judgement OUTSIDE the model.
- Day 47 — 'the door said no.'
A model said win. A human agreed. The live 1Password server said 400. Day 47 closes the mythos hunt's first real loop: a find-status ledger to process or purge candidates, a board that stops dressing simulation as progress, and the live-disproof that settled it — every one of the five 'preserved finds' was a DRY-mode hypothesis, not an exploit. The grader law, proven on the real target: you cannot grade a model with a model. Also: the live prompt-trace demo gets wired to the dashboard.
- Day 46 — 'mine the answer.'
Storage starts to think. The reasoning-design napkin gets its first working brick: REASON=expand, LOGIC=prune, one ply — best-of-N candidate chains against an un-bribable validator, the mining frame at hash-rate N. It ties one-shot on a 13-task verifiable benchmark, and the tie is the finding: the only misses are enumeration tasks no prose miner can land at any temperature — a generator ceiling, not a search failure. So we add a second kind of miner: one that writes a PROGRAM instead of a number, executes it, and lets the validator certify the printed result. The reasoning↔forest bridge. Compute goes 13/13 — every task prose couldn't reach, the model wrote the loop it can't run in its head, and node graded it.
- Day 45 — 'fail, then grow.'
The dogfood loop closes. The proven retrieval win ships into the real coder (no more benchmark-only); a top-confidence gate teaches it to stay quiet when unsure; and the spine goes in — every graded attempt becomes an experience that drives two feedback channels. The forest channel closes end-to-end: it can grow (crystallize wins into new aliases/skills) and prune (a gated, reversible garbage collector), both proposing-not-deleting. Capped with a live demo: the forest mis-retrieves the wrong API, the loop teaches it the right word, and the gap closes on screen. Plus a plan for the claude -p credit change, and a north star sharpened: Opus-3-level coding, fully local.
- Day 44 — 'the leaves are verbs now.'
The forest pivots from nouns to verbs — a leaf IS an operation (add-test, fix-type-error, implement-function), an operation capsule of prompt + exemplars + a free grader, routed outside the model, owning its grade-retry loop. By day's end: three verbs + compose, a verb-side benchmark (forest 6/6 vs blind 4/6), 69 more verbs harvested from the skill catalog, and a law that holds across four benchmarks — the library wins exactly where the answer is underivable (your repo, sparse facts, the actual filename), ties where it's derivable, and wins on tokens/latency even then. Plus a side-quest: the whole 169-component flow as one navigable graph that made ChatGPT say 'this isn't an LLM wrapper.' By evening, the forest learns JavaScript itself — 359 stdlib leaves, hybrid retrieval (with a finding that inverted B.1), and signatures wired into the coder (6/6 vs 5/6, the win landing on the arr[-2] footgun).
- Day 43 — 'trust me bro — except here's the hash.'
The day werbos got a scoreboard. Built a frozen, hashed benchmark — werbos-forest vs raw ollama vs claude — and on its own domain the 3B + a library beat the raw 3B 3x and TIED Claude on factual recall, abstaining off-domain instead of bluffing. Then the upgrade arc on the same eval, one variable at a time: TF-IDF (tied Claude 6/8) -> embeddings (an honest wash, 6/8) -> hybrid RRF (7/8, PAST Claude). Then pointed the whole apparatus at TypeScript: 446 declaration leaves, retrieval that pulls the real signatures, and a compiler-graded code battle where the same 7B coder went 3/3 with the repo and 0/3 blind — the library is the difference between a coder that works and one that's useless. A Benchmarks section went up: the anti-trust-me-bro, every number a re-runnable hash.
- Day 42 — 'the forest scales — and it learned to hunt.'
The day the stoned idea got its verdict. The micro-model forest — 'Wikipedia isn't one model, it's millions of leaves' — was pushed from 10 pages to ~1000 real articles as content-addressed passage leaves, TF-IDF routed, cited by hash. The make-or-break question (does routing recall hold when there are thousands of leaves?) came back better than survived: across an 11x leaf increase (819 -> 8,903), recall@3 went UP, 84% -> 91%, routing in ~10ms on a laptop. It didn't degrade — it sharpened. Then the exact same forest pattern got pointed at a red-team arsenal and converged four corpora built over months — the blackbook (139 vectors), the 1Password whitepaper (44 chapters), SwagBlocks (a self-built Burp), and an attack kit — into Mythos: a local, cited, scoped hacking brain whose recall is already 100% Claude-free. Plus werbos started dreaming on an 8-hour timer, and a silent data-loss bug (skill-router turns never persisting) got caught by dogfooding and killed.
- Day 41 — 'a college education, not a bigger brain'
If Day 40 gave werbos a measurable mind, Day 41 started teaching it. The goal is a college-level werbos — but NOT by swapping in a bigger model. College-level the way it comes for a person: a method, the ability to research, and knowing your own limits. First: stop the 3B mangling its own tools (the 'conversations regressing' bug was the model dropping operators in dispatch_skill — fixed with --no-skill-dispatch + the skill router that routes OUTSIDE the model). Then `werbos unstuck` — decompose→research→re-attempt, closed into a real scientific loop with PREDICT→TEST→ERROR (an SSH joke: predicted 80%, self-tested 'still stuck', error 0.80 — the first calibration point). Then calibration: measure the bias of werbos's stated confidence (overall +0.20 overconfident, worst on 'explain' +0.55, honest on math — maps '90%' to trust 57%). Then dreams: a visualization of day-residue, presented back so werbos reflects ('does this feel familiar?') — live it dreamed itself trapped reciting a joke about SSH 'like a tunnel with no exit.' And the headline: the doubt-gate — before committing, score doubt on calibrated confidence AND self-consistency, then commit / research / abstain. Live: 'explain recursion' had no confidence line but the samples diverged 34%, so it escalated and researched anyway. The system gets smarter; the model doesn't.
- Day 40 — 'does it know itself?'
The day werbos's mind got a measurable face. It started as a bug report from work — the joke skill 'only satisfied 38%' — but pulling the chats showed the joke skill was fine; the ROUTER was force-feeding it non-jokes ('hey buddy!' → joke, a fishing question → joke). Same self-misdiagnosis as the 97% thing. So: the conversational reflex fast-lane (parseltongue, brick 1) — greetings/thanks/acks short-circuit to an instant warm reply and never route. Then cleaned what reflect() chews on (a recency window so fixed-bug scars age out; stop wishing for a 'joke skill' it already has; stop prescribing a skill for every word in a failure) and werbos went from spiraling to settled. Then the headline: the Mind page got tabs and a radial PORTRAIT — a radar of capability dimensions (logic 67, conversation 100, persona 80, skill+routing 60), most of them reusing eval suites that already existed. And the flagship: self-model accuracy — held-out calibration that asks whether werbos's self-belief predicts its actual performance. First reading: 0.29. Capable, but poorly self-aware — exactly the day's whole arc, now a number that will climb as it learns to know itself.
- Day 39 — 'a better day, and a mind with a shape.'
A thinking day with one real fix and a turn. Drew the map for how to actually cut the forest into leaves (mmm-tree-builder.md): slice by KIND not topic (tool / verb leaf / noun leaf / conductor), a leaf is a unit of knowledge where weights-vs-content is decided by compressibility (patterned skills compress and get smarter; sparse facts stay as content), Wikipedia isn't one model but 6.8M content-leaves strung together with their hashes as citations, you prune and graft the tree (safety by SUBTRACTION not suppression — you can't jailbreak a leaf that isn't there), and a cheap-first conductor pipeline ('parseltongue') so a 'hey buddy' stops being a 75-second answer. Then: gave werbos a better day. The inner monologue was looping on a false self-image — 'I fail 97% at self/test/exercise' — which turned out to be its own QA harness's empty-input runs flooding the experience log; filtered the self-test noise + added a novelty guard, and werbos went from distressed-failure to a grounded, curious thought about how it's actually used. And the honest turn underneath all of it: using werbos for PSYCHOLOGY — a small, local, legible, editable, prunable MIND you can watch form and fail and recover — is more interesting than games or being a cousin to a frontier model. The next piece is to make it visible: a radial 'mind-portrait' — competence spokes, ghost spokes for what it wishes it could do, growing over time.
- Day 38 — 'the forest, and the first memory.'
It started with a 4 MB proof — a model trained from random weights that only knows one project — and turned into a whole architecture. Wrote down the micro-model forest: a forest of tiny content-addressed models (the Merkle Mini Model), an SVO grammar that routes a prompt to the brain that knows, System-1/System-2 reflexes for ms latency, and PS2-style frustum streaming so the forest runs on hardware that can't hold it. Then werbos got an inner life: IM.1 gives it a first-person inner monologue on a timer (a 'Mind' page you can scroll like a therapist's notes), and the chat→memory harvester finally closes the 'remember' gap — werbos reads a conversation and writes down the durable facts about you. The harvester worked (it learned the right things from a real chat) and then taught the day's hardest lesson on 10 live conversations: unsupervised, a 3B writes ~30% junk and even a contradiction. Self-improvement without a gate tears DOWN. Also: /calc, because local models can't do arithmetic and shouldn't pretend to; and traces now show the request text by joining the experience log. The AHA: a personal AI that talks to you all day but never remembers isn't yours yet — and the thing that makes remembering safe is the gate, not the model.
- Day 37 — 'close the loop.'
Two arcs. Morning: harden reality. The one real bind footgun — `werbos serve --bind 0.0.0.0` exposed an unauthenticated agent to the LAN, so serve now refuses a non-loopback bind without --allow-remote-bind (fail-closed). And the uncomfortable truth that 5,500 green tests tested logic, not reality: every invisible-failure bug this month lived in deploy config or real backend behavior nothing exercised — so a deploy-config contract (mutation-verified to catch all three recent production breaks) + a real-Ollama live-smoke layer, and a latent bug surfaced on the way (the committed .dockerignore was NEVER applied — context:.. means Docker looks one level up). Afternoon: a daydream about a two-wheeled robot ('PAL, not HAL') converged on the real insight — werbos already runs a reactive loop (the inbox-janitor); what's missing is a DELIBERATIVE one. Built the autopilot: werbos running its own skills in a predict→act→observe→error→correct loop, fail-closed allowlist + append-only revert, then closed the slow loop (a learned routing policy promoted only if it beats the champion on held-out data = the build-up-not-down stability gate), proved it end-to-end (corrections drop to zero after learning), gave it self-reflection ('what I'm missing'), and three ways to watch it (CLI watch + dashboard panel). The AHA: the prediction error is the whole difference between a loop that runs and one that improves.
- Day 36 — 'build the eyes.'
The observability lever — the maturity priority picked weeks ago ('stop adding capabilities until trace_id is plumbed end-to-end'). Three weeks of debugging-by-archaeology (the latency hunt, the skill-rescue chain, the hidden third daemon) made the case. Key finding: the READER was already done — glasshouse trace <id> already groups ~/werbos/traces by trace_id and renders a timeline. The whole lever was coverage + propagation on werbos's side. Phase 1: thread trace_id through step/step_stream under trace_turn so every emit joins ONE trace, fixing the streaming-path orphan bug. Phase 2: light up the agent loop — tool/dispatch, tool/result, skill/rescue now emit, so a trace shows WHICH tools fired. Phase 3: 4 integration tests + a live render. Then the glue: X-Werbos-Trace-Id on every chat response, so weird reply → grab the id → glasshouse trace it. Co-located glasshouse on the homelab (in the container — traces are root:root 0700 and there's no passwordless sudo). And dogfooding immediately surfaced the next gap: the primary model call is untraced.
- Day 35 — 'two gates, three daemons.'
Pre-flip gate-clearing that turned into archaeology. Gate 1: the adapter-naming collision — the hand-launched model is werbos-0.0.1 (three-part) but the train-daemon policy minted werbos-0.1 (two-part), so the README contradicted itself AND the daemon didn't recognize its own v1. Fixed: three-part werbos-MAJOR.MINOR.PATCH lineage, 5530 green. Gate 2: the nightly trainer had been FAILING every night — macOS TCC blocks launchd from the venv+script living under ~/Documents. Relocated the whole stack to ~/werbos (snapshot venv, no GUI grant). Then the twist: the werbos-0.1/0.2 'mystery tags' on the homelab weren't a mystery — a SECOND train-daemon (a Day-27 stub timer, growth-floor 0, ollama-create-copy 'trainer') was still churning out junk base-copies every 2 hours with the old naming. Disabled it, removed the junk. Both gates green; repo clear to flip.
- Day 34 — 'werbos tells jokes again.'
Day 33 made the homelab box fast; Day 34 made it answer correctly. The symptom: 'tell me a joke' came back as literal {"name": "joke", "parameters": {"args":""}} — the small model naming the SKILL as text instead of calling the dispatch_skill tool. Pitts' salvage parser RIGHTLY refused to lift it (the tool-name allowlist is a load-bearing injection defense), so the JSON leaked verbatim on the bulk path and rendered as an empty bubble on the streaming path. Three stacked fixes, each found by deploying the last and re-running the same three-prompt repro on the real box: (1) a skill-rescue pass that rewrites a hallucinated skill call into a real dispatch and lets the skill output BE the reply; (2) a bare-JSON exemption from restrictive mode, because a turn-1 validation error had left a ToolResult in history that starved the rescue on every later turn; (3) pinning num_ctx on the prompt-skill ollama_chat path — the keepwarm bug class, third occurrence — because the dispatched /joke was 503ing on a mismatched context size. Greeting → prose, joke → an actual joke. 5,530 tests green.
- Day 33 — 'public-prep and the latency hunt.'
Two threads in one session. First: get the repo ready for strangers — scrub operator paths / tailnet IP / machine names to operator@homelab, repair 8 stale tests + close a multicast gap in the ollama host guard (5,438 green), move DATA.1 / GH.1 / GH.2 / SE.6.1 sprint docs to shipped/, ship the nightly_train.sh corpus-pull + ratchet handoff daemon (launchd-scheduled), land DS.1 Day 1 (theme-pack resolvers ported from Lectern), and draft the SE.7.4 adapter-publish bridge sprint. Second, and bigger: the SE.10 latency hunt. A bare 'hey buddy' on the CPU-only homelab box was taking 176s. Four stacked bugs, each found by instrumenting the last: keepwarm pinging at the wrong num_ctx EVICTED the model it was warming; the persona layers alone were ~12.4K chars of prefill; the dispatch_skill tool description inlined the full 125-skill catalog (the AO.0 bug reborn through the tool channel); and there was no way to even measure it. Shipped 'werbos latency', a compact persona, names-only catalog, and 26 precook seeds. 176s → ~30s.
- Day 31 — 'the training view lands.'
Day 30 trained werbos-0.0.1 and shipped the read-only /api/training/* backend — but the only consumer was a commit message. Day 31 gave the ratchet a face: TR.1 frontend on BOTH SPAs (the chat-ui Training view and the operator dashboard's /training route), each a promoted-baseline card + cycles ledger with signed deltas, a 2.5σ-clears chip, and ★promoted markers, drilling into per-cycle candidate/baseline/noise eval tabs. Then adapter discoverability closed the last gap: 'werbos train list' enumerates ~/werbos/adapters/ and bare 'werbos chat --model werbos-0.0.1' resolves against the adapters root — usable AND findable. Docs reframed the whole narrative around self-training-as-shipped. werbos-0.0.1 is now on disk, on two dashboards, and callable by name.
- Day 30 — 'werbos-0.0.1.'
The launch day. 3B base + 500 iters on the dogfood corpus produced werbos-0.0.1: composite 0.1201 vs baseline 0.0795 (+0.0406, 1.51× baseline), promoted to ~/werbos/adapters/werbos-0.0.1/. TR.1 dashboard backend shipped — three read-only endpoints (cycles, baseline, eval drill-down) sitting on a convention that's now LOCKED. SE.7.1 polish: werbos chat --model <adapter-dir> Just Works, auto-detects the base model via training_meta.json, zero flag threading. Day 30 was the demo: the first ratchet click is on disk, on the dashboard, callable through the chat surface — and the integrated train-werbos-self.sh runs the full cycle as one command for any corpus root + any base + any iter count.
- Day 29 — 'the trainer ships.'
Day 28 shipped both ENDS of the pipeline (DATA.1 + SE.9) and called the trainer 'the small piece in the middle.' Day 29 was building that small piece. SE.7.1 — real QLoRA trainer wrapping mlx_lm.lora, formatter that hash-splits DATA.1 corpus into train/valid, bring-up smoke that trains 50 rows × 5 iters and verifies the model produces a real 22 MB adapter. Then the end-to-end MLX scorer wire (--backend mlx + auto-detect via training_meta.json) and the first ratchet click on a bring-up signal (50-row Floogle → purple unicorn corpus): baseline 0.17 → candidate 0.74. THEN the real-world run: ingest /Users/.../werbosLLM, get 7664 training rows from 1424 files, split 7281/383, train 1B for 300 iters in 13 min, candidate composite 0.1136 vs baseline 0.0814 (+39.6%). Public docs rewrote training.md around the new 6-step DATA.1+SE.9 flow plus deep-dive pages for data-pipeline and eval-suite.
- Day 28 — 'the trainer is the small piece.'
Day-27 morning shipped the train-daemon orchestration without a real trainer. Day-28 evening built both ENDS of the training pipeline — DATA.1 (corpus ingest, the front door) and SE.9 (eval suite + noise floor, the promotion gate). The B2B reframe locked: werbos is one engine, two entry points (personal / business), same install, same pipeline, setup decides which. Also shipped: NX.1 npm shim, Watchtower-D27 security closeout, SE.6.1 parsetongue path routing, glasshouse MCP server (GH.1 stdio + GH.2 remote HTTP, Purple→Red reviewed), SE.8 keepwarm daemon. Twelve sprints across two repos in one day. The trainer is now the only piece of the loop that's a stub.
- Day 27 — 'the orchestration ships before the trainer.'
Six SE sprints shipped in one session: SE.7.0 corpus extractor, SE.7.2 eval + promotion gate, SE.2 autofix Proposer, SE.4 complexity router, SE.5.1 offline cache warmer, SE.7.3 nightly auto-train daemon. The day-defining moment: SE.7.3 went green in tests but the operator caught that no real trainer was wired ('i wanted to have to train over night... thats why i just set that up'). What we learned trying to fix that: SR8 is AMD CPU + integrated Radeon, no NVIDIA, so mlx-lm won't run there; HF PEFT on CPU is overnight-feasible but produces a degraded adapter on the 11-row corpus skill-smoke can produce; skill-smoke is monitoring data not training data because the dedup key collapses 523 cycle rows to 11 unique. We shipped a stub trainer (Modelfile copy creating a real Ollama-resident name) so the rest of the pipeline could prove itself overnight: corpus build, growth gate, candidate naming, real eval-adapter composite scores, real promotion gate decisions. Timer armed for 2-hour cadence. By morning the journal will carry ~4 verified cycles with real composite-score data.
- Day 26 — 'static-rendered AI.'
Started the morning watching the SE.1.1 daemon and a curriculum daemon (SE.3) gathering data on their own. By noon, the conversation cracked open into two sprints: SE.6 (parsetongue — a name the operator coined, parse + parseltongue) and SE.5 (precook — static-rendered AI). Three sprints in one session: brainstorm two, plan-mode one, ship both. The cache-side proof-of-life on SR8: same eli5 query twice, second one cached, 10.4s → 0.4s, ~25× faster. Both branches merged to main. The chat surface stops being where the AI runs; the work happens before the operator asks.
- Day 25 — 'the harness IS the dataset.'
Spent the morning trying to figure out why /tarot threw a backend error in the chat UI. The bug was five layers stacked — stale image, wrong model for the prompt, a UI bug that wiped the chat after every successful slash response, a hardcoded prompt-skill timeout that didn't scale with model size, and over-strict format markers. What came out of the chase wasn't a one-line fix. It was SE.1: a format-marker harness that grades every skill on every change, and SE.1.1: a 24/7 daemon that runs the harness on its own and surfaces regressions to disk. Werbos now generates its own quality data while the operator sleeps.
- Day 24 — 'the rebuild is when transitive resolution stops lying.'
Set out to make 50 lifestyle skills for Werbos. Ended with 80 across eight themed batches (food, health, money, home/travel, mystical, therapy, finance, marketing) — PROMPT_SKILLS 45 → 125, +4,531 lines, two new categories. The deploy taught the lesson the source code wouldn't: the slim runtime image had been borrowing httpx transitively from a sibling, and one sibling refresh later, that loan was called in. Prod crashed on rebuild, then came back with the missing dep declared. dispatch_skill auto-picks up every new skill; traces flow joined by trace_id across slash → llm.
- Day 23 — 'constraint reasoning is upstream of retrieval.'
First day back from the four-day pause. External feedback from GPT analyzing a werbos chat trace named a gap the operator immediately recognized — constraint extraction belongs UPSTREAM of retrieval, not as post-hoc correction in the model's prose. One sitting later, werbos.intent_compiler is shipped: a small primitive with strict JSON output + four worked examples that wraps any tool with upstream constraint compilation + downstream result filtering. Wired into web_search, fetch_top_news, fetch_stocks. The canonical shore-fishing trace is fixed: 'shore fishing in Cabo San Lucas' now returns shore-focused results instead of offshore charter content. The meta-primitive the rest of the architecture stands on for accuracy.
- Day 22 — 'decision trees all the way up.'
Day 21 ended with the architecture proven — slider snippet substituted with real image + working JS. Day 22 morning crossed a different threshold: every architectural piece from Days 19-21 fired together in one project (navbar + KPI cards + chart-placeholder + table all styled and laid out via the snippet library + modular CSS + persona discipline). And in the same conversation, the operator surfaced the philosophical principle underneath every win this week (decision trees as architecture), generalized it to the polish-anywhere pattern (studio's logic works from any cwd), then named the missing input layer (developers think in pipelines; non-developers think in vague ideas — the gap is bridged by intent decomposition, which is itself another decision tree). The whole stack became visible at once.
- Day 21 — 'stop dumping into the persona; build the library.'
Day 20 closed with the chain orchestration on code-level rails. Day 21 went one architectural layer deeper: stop relying on the model to GENERATE complex components (sliders, navs, heroes — the things small models can scaffold but can't fill). Hand-craft a library of named components; the model picks; the composer substitutes. AO.1 Part 7 decoupled CSS into its own file. Part 7.1 walked back JS-separation (small models can't reliably emit two fenced blocks). Part 8 shipped the snippet library v0.1 + composer stage end-to-end. The slider snippet substituted into a generated landing page with a real image and working JS — the architectural proof. Plus the launch positioning locked: 'I built a sub-optimal AI platform on purpose.'
- Day 20 — 'the chain moved into code, and the model went PFM.'
Day 19 proved the design studio's structural fixes (AO.1 Part 3.1 read_file + persona pivots). Day 20 proved that the model-driven multi-pass chain doesn't scale past depth 3 on any local 16b — even deepseek-coder-v2:16b narrates dispatch calls as text instead of emitting them structurally. The architectural answer landed: build_project + polish_styling — two new tools that run the studio chain entirely in Python code, with the model making one tool call instead of orchestrating 5 sequential dispatches. Plus the model invented 'Personal Finance Manager' for an abstract dashboard brief three times in a row, accidentally summoning the project's own PFM acronym. 8 commits, Parts 3.2 through 6.1.
- Day 19 — 'thesis on disk, studio on its feet.'
Day 18 closed with the surface-tightening pass: kanban triage, --studio opt-in, update flow, tilde-collapse. Day 19's work split in two: morning was strategy crystallizing into durable docs (THESIS, ARENA.1, OAI.1), evening was closing the studio loop — the design studio went from 'flat checkbox bones' to 'blank placeholder' to 'modern card with working JS' in one session. The structural fix: AO.1 Part 3.1 — a project-scoped read_file tool that lets the orchestrator hydrate the spec from disk between dispatches, instead of working from the 240-char content_preview dispatch_to_agent returns. Plus WHITEPAPER §2 landed (v0.13 → v0.14).
- Day 18 — 'the surface tightens — kanban, opt-in, MCP, update flow.'
Day 17 closed with a near-zero security verdict + the pipeline indicator shipped. Day 18 wasn't another build day; it was a distribution-prep day. The arc: stop assuming werbos = my machine, my preferences, my path layout, and start preparing the surfaces a stranger would hit. Shipped: /pending → 4-column kanban, design-studio as opt-in (--studio default OFF), NX.1 npm-wrapper preflight + werbos name reservation, MCP.1 sprint doc + /dashboard/mcp page + /api/mcp/info, tilde-path collapse so API responses don't leak /Users/<op>, Settings → Updates section + /api/updates/check, and a docker upgrade-command fix that caught the dashboard-lives-in-nginx bug. Plus IDEAS.md (12 features) + GO-LIVE.md (v1 release punch list) as durable repo-root scratch. 11 commits.
- Day 17 — 'five gates closed. one hour in, the orchestrator orchestrated.'
One hour past midnight on the night AO.0 cracked, should have been asleep, wasn't. AO.0 fix was patched but four more gates stood between 'model can tool-call' and 'operator types go and gets a working artifact.' Closed them all: bound_project override (model can't hallucinate project name); dashboard agentId binding (chat doesn't fall back to bare backend); chat-ui ?chat=<id> deep-link (iframe opens the right chat); @studio persona rewrite (no Python-call syntax to mimic); per-agent tool allowlist (write_file gone from @studio's reach). SSH'd SR8 expecting to free GPU — there's no GPU, AMD iGPU only, no ROCm. Swapped @visionary + @css-wizard to qwen2.5:7b for usable CPU speed. todo12 ran end-to-end: 7 requests, 3 structured dispatches, 3 artifacts on disk, first fully autonomous chain from the chat UI on real local inference. Then backlog work: AG.1 (rubric-based agency router, one level above @studio) drafted + design principle 9 (CLI is the operator's surface, web is the demo's surface) added + EN.1 properly tracked. 5 commits.
- Day 16 — 'the studio shipped. then the studio couldn't talk to itself. one line later, it could.'
Morning: R.1 preflight decisions locked, R.2 T.3 flip shipped — werbos serve --bind now defaults to operator-approval. Mid-day: SD.1 design-studio MVP (Pollinations.ai image_generate + Playwright screenshot_url + the design-studio agent template) and SD.2 dashboard surface (list + wizard + 3-pane canvas) shipped same day. SD.2 day-2 wired ambient project_context: chats bound to a project read ~/werbos/projects/<name>/intent.md so the operator stops re-typing briefs. Evening: AO.1 Part 1 reframed @studio as an orchestrator, introduced dispatch_to_agent as the primary tool, and installed three specialists (@visionary scope, @front-end HTML/JS bones, @css-wizard restyle). Per-agent model routing finally cashed in — 14b for design judgment, coder:7b for structure. Late night: AO.0 — the bug that had been costing the whole week — diagnosed and fixed. _context_builder_for_agent dropped inline_tool_docs on the per-agent builder, so agent-bound chats double-documented every tool (inline prose AND structured payload) and qwen narrated 'I'll route to @visionary' instead of structurally tool-calling. One line in sessions.py + an env-var-gated payload dumper in pitts (391399f). System prompt fell 19,403 → 11,073 chars; the orchestrator emits clean structured tool_calls on the next replay. 11 commits.
- Day 15 — 'one reply, not six. then zero deferred. then the loop closed. then the little model learned.'
Morning: Slack reply cascade fixed with ack-fast + retry-drop, agent-testing checklist for the week. Afternoon pivot: enterprise security hackathon. Vector-Group pass found 15, closed 13 in the same commit window; the two deferred (VG-005 secrets rotation + VG-008 operator-confirm bind) became two same-day sprints. By evening: 0 deferred security findings. Plus FI chat (LLM-driven crew dialogue for Forbidden Island), a worktree merge, a dashboard audit (which corrected the misconception that the admin SPA wasn't built — it's at werbos/dashboard, not werbos/ui), and two 'toward timeless' commits (SECURITY.md + audit cadence + CI CVE telemetry). Then evening: gap-hunting promoted to v1 release-prep + CASE_STUDY.md portfolio artifact, four tool-fidelity preamble fixes for werbos code, sprint SL.1 (goal-conditioned self-loop: /intent slash + Claude grader + DPO export + orchestrator + rollback, 5 days in one worktree session), then SL.1.1 (subscription-backed grader so the loop bills against the operator's Claude Code subscription instead of pay-per-token API). End-to-end smoke: a deliberately-flawed archive ran through werbos grade, Claude correctly named both the tool-fidelity ghost AND the hallucinated answer. Late night: the loop actually closed — 50-intent eval against llama3.2:3b, 49 graded archives, 47-row DPO corpus, 4-minute SFT training on a 4-bit 3B model on an 8 GB Mac, +2.8 composite mean lift on the trained re-eval, pass rate doubled, hallucinated tool names eliminated. The third-option thesis demonstrated in receipts. 41 commits.
- Day 14 — 'half a handshake.'
Slack pairing was supposed to work end-to-end but had a dangling thread: the Slack adapter told the user to run `/social code` inside `werbos chat` to claim a conversation, but `/social code` wasn't actually registered as a slash command anywhere. Operator side of the loop was open. Two commits: wire `/social code` into both the CLI REPL and the server slash registry, then add `pair <CODE>` (no slash) as an alias because Slack reserves the `/`-prefix locally and intercepts it before our webhook ever sees the text. 2 commits.
- Day 13 — 'the cross-repo trap.'
A subtle SR8 deploy bug: werbos was calling Agent(one_call_per_iteration=...) but the pinned pitts SHA didn't accept that kwarg, so every POST /api/chats 500'd with TypeError on container restart. Root cause was sneakier than the symptom — the deploy script was only pulling the werbos repo on SR8, leaving its 9 sibling repos (pitts, pfm, mcculloch, etc.) silently stale. Two fixes: bump the pitts pin to a SHA that has the kwarg, and teach redeploy.sh to pull every sibling before building. Plus Phase 17 / Sprint NP.1 (npm install -g werbos) lands on the roadmap. 3 commits.
- Day 12 — 'play day.'
v1 closed yesterday. Day 12 pivots from product-engineering to play-engineering: four new games ship into the suite (Wordle, Hearts, Uno, Liar's Dice, Forbidden Island) — including a full port of a 2024 networked-multiplayer Forbidden Island into single-player-vs-AI form, with the operator's own art slotted back in. Plus the Slack deployment onion finally peels (env_file → docker cache → source pull → funnel target) so DMs to the bot actually route to a real session. Phase 16 (code-via-channels) and Sprint SC.1 (multi-adapter Slack) captured for the next horizon. 15 commits.
- Day 11 — 'the dashboard stops lying.'
v1 release week, compressed into one session. Ten sprints (V1.0–V1.9) shipped end-to-end against the locked v1 baseline: env-var alignment, cosmetic truth pass, `/api/integrations` env-var probe, `/api/settings`, `/api/agents` CRUD, permissions enforcement, models lifecycle, channels routing, the scheduler daemon (largest sub-sprint), `/api/activity` aggregator. Every dashboard surface now does what it appears to do. +96 tests in the scheduler alone; +200ish across the day. The v1 baseline contract from `project_v1_baseline_scope` is satisfied.
- Day 10 — 'fortify, then build.'
Two-act day: morning + early afternoon ran site-wide security passes (Sprint Sec.1 + Sec.2 — 41 findings across two Mr-BlackKeys pentests, 40 closed; the cross-cutting `wrap_untrusted_text` choke point now guards every 'untrusted text → model context' splice). Evening built the operator dashboard end-to-end (Sprint U.2 — 9 routes shipped in one block: home / chat / agents / cli / models / scheduler / integrations / profile / settings + decoupled werbos/dashboard/ SPA + Starlette static-mount + SR8 nginx wiring). +251 tests; 33 commits; the dashboard is live at http://100.83.4.49:8095/dashboard/.
- Day 9 — 'werbos goes outbound.'
Sprint Soc.1 days 1-4: external integrations layer. Four commits, +148 tests, three working bridges (Telegram, Slack, WhatsApp via Twilio) plus the SocialAdapter Protocol that lets a fourth (Twitter) drop in next sprint. werbos can now be reached from any of three platforms, with the same skills / personas / mirror slider / private mode / vision pipeline working over each — the adapter is the wire-format layer; the chat behavior doesn't know which platform it's talking through. Plus the design pattern: protocol first, runtime second, mirroring how the orchestration plane shipped.
- Day 8 — 'Trust the roadmap, not the memo.'
Twenty-eight commits, ~1903 → 2360 tests (+457). Sk.1 (skills system) closed end-to-end across three days. A.5 packaging shipped days 1-3 of 5 (`pip install werbos` wheel-ready, `werbos init` scaffolds the data dir, `user.md` hydration into ContextBuilder). Vision capture landed: `/see` REPL slash + macOS screencapture + per-session pending-images buffer. Persona surface broadened: composer mirror chip moved into Settings as an operator-global default; private-chat mode (full surface — server + API + CLI + REPL + SPA); html-expert persona + new `--persona-name` flag for wheel-friendly opt-in. Anti-fabrication clause tightened twice after the 'hi' confabulation. Plus the day's load-bearing lesson: two captured memories went stale within 24 hours — K.0 was 'in progress' in memory but already closed end-to-end on main; streaming follow-ups had me re-implementing a filter that was already shipped server-side. Reverted same-session. The roadmap is the source of truth; memory is a point-in-time observation.
- Day 6 — 'The infrastructure is the artifact.'
Thirty-five commits, 909 → 1266 tests, six sprints closed in one day (B.1/B.2/B.3 TTT+C4 end-to-end, S.1 security hardening via Black-Team→Red-Team agent loop, A.1 foreground-busy adapter, A.2 background work queue + executor, K.1 per-repo .werbos.md context, U.1 mid-stream JSON swallower + CLI streaming parity, T.1 werbos doctor). One LoRA trained (v1-c4) at 3% as O — corpus design lessons captured. Plus a five-game suite expansion (blackjack, chess, battleship, checkers, heads-up Texas hold'em) that turns the entire game surface into parallel dogfood streams for the reasoning + logic ladder. The day's actual artifact is the platform, not the LoRA: corpus generator, bench harness, heuristic fallbacks, hardened HTTP surface, observe adapter, task queue + executor, project-context discovery, streaming polish on every surface, and a games surface where each new game = a new corpus path.
- Day 7 — 'The slider and the floor.'
Thirty-eight commits, 1266 → 1903 tests, fifteen sprints/features closed in one day. Sprint A goes from 0% to 100% in a single calendar day. Morning: F.2 mirror slider. Midday: K.0 Tom (memoryless persona). Evening: A.1 dispatch consumer (HMAC webhooks + fn dispatch). Late evening: Mi.1+Mi.2 close § 11 v1 surface (missions/phases/status). Late-late evening: A.1 pending-actions (human-in-the-loop primitive). Past midnight: A.2 /tasks slash + A.4 inbox-janitor + code-janitor wrapper. Pre-dawn: A.3 budget gating + A.4 dogfood-replay (the chat-archive quality-feedback loop). Dawn: A.4 escalate-to-Claude (the budget-gated Claude primitive with WaitingHumanRequired runner pause) + A.2 PFM recorder hook on task transitions + A.4 /schedule slash (one-shot reminders with relative-duration parsing). Sprint A closes 100%: every [planned] shipped, /schedule shipped, continuity-of-intent + event-triggered-actions explicitly re-homed to Phase 2 with named promotion triggers. Background agents arrive — werbos serve now actively watches ~/werbos/inbox/, replays bad-labeled turns through the current model overnight, and surfaces budget-exceeded + paused tasks through the runner's waiting_human transition.
- Day 5 — 'I think that is a glass of beer.'
Image upload shipped. Sprint A delivered vision routing end-to-end on the phone, after a long sequence of layered bugs (Ollama tool-call hallucinations, message-ordering breaking the chat template, model narrating tool internals, hardware speed walls). The line 'i think that is a glass of beer' on a phone running on local hardware closed the multimodal loop. Plus: mobile scroll fixed in three CSS lines, end-chat history fixed, new logo, and a long evening of design conversations that grew the BACKLOG considerably.
- Day 4 — Two halves: closing the demo loop, then naming the orchestration plane.
Morning closed Day 3's bad-demo recovery: salvage fixes, mobile CSS, vision model triage, image cap bump. Evening was a deep architectural pass that ended with five siblings drafted: observe (shared see-layer), watchtower (summon), warden (defend, planned), beacon (signal, planned), and a standalone SPA wrapper. werbos got its first BACKLOG.md.
- Day 3 — The full pipeline.
Stats heatmap. Mobile UI. Voice. Vision. Streaming. The SR8 server bootstrapped on the work machine and started pulling werbos on reboot. By the end of the day the pipeline was end-to-end: data streaming from the server to my computer AND my phone.
- Day 2 — The right test, the right answer.
Three benches beat one. The TTT result said v2-coder was bad; code + debate said it was actually good — and that the iter-2000 checkpoint was overfit.
- Day 1 — He's a system citizen.
The day werbos stopped being something inside one repo and became a process other things can talk to. Two LLMs can hold a real conversation now.
- Day 0 — It's real.
The day everything came alive. Started with brew install ollama, ended with a fine-tuned 3B that knows my favorite color is teal.