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.
“werbos-0.0.1.”
Day 29 closed at midnight with the first ratchet click — a 1B LoRA trained on the operator’s own dogfood corpus produced a +39.6% composite delta over baseline. The trainer worked. Day 30 was making the result visible enough to ship.
The 3B run
Same script, bigger numbers. BASE=mlx-community/Llama-3.2-3B-Instruct-4bit ITERS=500 EVAL_N=100 scripts/train-werbos-self.sh. Backgrounded;
about 2 hours wall time end-to-end:
- Ingest: 1424 files / 7664 rows / 19 secrets filtered
- Split: 7281 train / 383 eval (then sampled to 100)
- Baseline (3B): composite 0.0795 (slightly lower than 1B’s baseline; within noise)
- Train: 500 iters batch-size 2 on Llama-3.2-3B-Instruct-4bit
- Candidate (3B + werbos-0.0.1 LoRA): composite 0.1201
Delta +0.0406, 1.51× baseline. Bigger absolute and bigger
relative than the 1B run. The 27 MB adapter sits at
/tmp/werbos-0.0.1-3b/.
TR.1 — dashboard backend (edf872d)
The operator wanted the eval loop visible somewhere richer than
CLI tail. TR.1 is the data layer for the future
/dashboard/training/ React surface. Three endpoints:
GET /api/training/cycles?limit=N
GET /api/training/baseline
GET /api/training/cycles/{name}/eval?side=candidate&limit=N
A convention locked for v1:
~/werbos/adapters/<name>/
training_meta.json # SE.7.1 writes
adapters.safetensors # mlx-lm writes
eval/
baseline.json # werbos data score --out
candidate.json # same
noise.json # --runs N --out
promoted.json # touched on promote
The reader is tolerant: a cycle that finished training but
hasn’t been scored is a valid CycleSummary with null score
fields. Pre-SE.7.1 adapter directories from older mlx-lm runs
(v1, v2-coder, v5-ttt-bf16 — 13 of them) sit in the operator’s
~/werbos/adapters/ and get silently skipped. The dashboard
shows zero of them; only werbos-0.0.1.
Schema: tr/1, camelCase wire format (observe-aligned, matches
the existing /api/budget + /api/activity convention). Forty
one tests pin the wire format, the discovery layer’s tolerance
of partial state, and the HTTP route boundaries.
Promotion
werbos-0.0.1 moved from /tmp/ to its proper home:
mkdir -p ~/werbos/adapters
cp -r /tmp/werbos-0.0.1-3b ~/werbos/adapters/werbos-0.0.1
mkdir -p ~/werbos/adapters/werbos-0.0.1/eval
cp /tmp/werbos-self-work/baseline.json …/eval/baseline.json
cp /tmp/werbos-self-work/candidate.json …/eval/candidate.json
echo '{"promoted_at_iso":"2026-06-01T21:15:00Z","reason":…}' \
> ~/werbos/adapters/werbos-0.0.1/promoted.json
Live HTTP test against ~/werbos/adapters/:
GET /api/training/cycles
→ werbos-0.0.1 composite=0.1201 delta=+0.0406 promoted=True
GET /api/training/baseline
→ {
"schemaVersion": "tr/1",
"name": "werbos-0.0.1",
"baseModel": "mlx-community/Llama-3.2-3B-Instruct-4bit",
"composite": 0.12008,
"threshold25Sigma": 0.12008,
"promotedAt": "2026-06-02T05:46:59.830385+00:00",
"adapterPath": "/Users/jasonsutter/werbos/adapters/werbos-0.0.1"
}
The ratchet is engaged. Subsequent cycles have to beat werbos-0.0.1’s threshold, not raw llama3.1:8b’s.
Polish: werbos chat --model <adapter-dir> Just Works (9e737a5)
The launch-video command sequence used to be:
werbos chat --backend mlx \
--model mlx-community/Llama-3.2-3B-Instruct-4bit \
--adapter ~/werbos/adapters/werbos-0.0.1
Three flags, one of which the operator has to copy-paste correctly. After this commit:
werbos chat --model ~/werbos/adapters/werbos-0.0.1
One flag. build_backend_from_args runs _detect_trained_adapter
on the model identifier; when it points at a directory with
training_meta.json, the backend upgrades ollama → mlx, the
base model gets pulled from the meta, the adapter path gets
filled in. Explicit operator-provided values always win.
Same auto-detect contract as werbos data score already uses
(both read config.base_model from the same JSON). Single
sourced.
Eleven new tests cover the detect matrix + the integration into
build_backend_from_args. The args mutation keeps everything
in sync downstream (logging, telemetry, debug surfaces).
Numbers worth keeping
- Day 30 commits: 3 (TR.1 backend + werbos-0.0.1 1B milestone + UX polish)
- werbos-0.0.1: 27 MB at
~/werbos/adapters/werbos-0.0.1/ - Composite: 0.1201 vs baseline 0.0795 (+0.0406, 1.51×)
- 3B run: ~2 hours wall, 500 iters, batch-size 2, max-seq-length 1024
- Tests: 41 new for TR.1 + 11 for auto-detect = 52 Day-30 tests, 5370 broad-suite green
- Promote marker:
promoted.jsonin the adapter dir - Dashboard: three endpoints live, returning structured JSON for a real adapter
The launch demo, end-to-end
# 1. Build the corpus
werbos data ingest ~/Documents/Companies/werbosLLM \
--include '*.md' --include '*.py' \
--strategy heuristic \
--out me.jsonl
# → 7664 rows from your own work
# 2. Split + baseline
werbos data split me.jsonl --eval-fraction 0.05 --out-prefix me
werbos data score me.eval.jsonl --backend mlx \
--base mlx-community/Llama-3.2-3B-Instruct-4bit \
--model mlx-community/Llama-3.2-3B-Instruct-4bit \
--out baseline.json
# → baseline composite
# 3. Train
werbos train --corpus me.train.jsonl \
--base mlx-community/Llama-3.2-3B-Instruct-4bit \
--out werbos-0.0.1 \
--iters 500
# → 22 MB LoRA adapter
# 4. Score + promote
werbos data score me.eval.jsonl --model werbos-0.0.1
# → candidate > baseline + 2.5σ ⟹ promote
# 5. Use it
werbos chat --model werbos-0.0.1
# → terse, declarative, knows your stuff
Five lines. Different corpus produces different model. Same engine. This is the homepage video.
AHAs
- “werbos-0.0.1.” The first werbos-trained model exists. On the operator’s M1. Trained on the operator’s own corpus. Composite delta clears noise. The ratchet is engaged.
- The UX has to match the engineering. The one-flag
werbos chat --model <adapter-dir>polish is what separates “we built a thing” from “we built a thing anyone can use.” - The dashboard convention is also a public commitment. Once
~/werbos/adapters/<name>/{training_meta,eval/*,promoted}.jsonis the locked shape, every future tool consumes it the same way. TR.1 today, TR.2 (React) next, whatever comes after.
Tomorrow
The plan from here splits clean:
- TR.2 — React surface over TR.1. The cards + sparkline
- per-row table sketched in Day 28’s “known gaps.” ~1 day.
- Launch video. The five-line demo works end-to-end now. Cut it, push to werbos.ai, ship.
- werbos.ai domain + org repo. The launch surface itself.
- NX.1 npm publish. Still gated on A.5 PyPI.
The ratchet click happened. Everything after is distribution.
“werbos-0.0.1.”