Lessons
Principles earned the hard way.
Not a curriculum — takeaways distilled from real projects. What worked, what failed, and what I'd do differently, written from the scar tissue rather than the textbook.
- [23] Keep Going: Autonomy Inside Rules for a Swarm of Agents An agent that stops to ask at every step isn't careful, it's expensive: you've just made yourself its message bus. The fix isn't more trust. It's standing rules, shared gates and a habit of turning each answer into a rule, so the only questions left are the ones that are really yours.
- [22] Letting Agents Soft-Approve Merges Without Losing the Audit Trail I wanted agents to carry a change right up to the merge button and not one step past it. The trick wasn't a policy. It was making the person's yes a separate act that the pipeline itself refuses to continue without, so the trail of who did what writes itself.
- [21] The Human Is the Race Condition Everyone worries about AI slop. Run enough agents in parallel and the quieter failure is you: a correct answer typed into the wrong session, which the agent then turns into plausible, confident, wrong work. The fix isn't more discipline. It's taking the routing out of your head.
- [20] Creation Rules Must Never Gate Authentication The rules for what a new username may look like are not the rules for what an existing one does look like. Reuse the creation type at login and you lock out every account created under older, looser rules — permanently, and with an error that tells nobody why.
- [19] Caches Outlive the Facts They Hold Every cache is a bet that a fact won't change before the entry dies. The bugs come from caches nobody thinks of as caches — a compiled file, a hash over a server list, a build layer, a credential read at boot — whose keys don't include the thing that changes.
- [18] A Number in Prose Is Not a Measurement Most engineering decisions rest on a number someone typed into a doc. Most of those numbers were derived once, by one method, and never checked. The fix is boring and it works: derive any number that drives a decision twice, by independent methods, before you act on it.
- [17] Gates That Are Red on Day One Get Switched Off An absolute threshold against existing debt is a gate someone will disable by Friday. Ratchets fix that — block only on regression against a stored baseline. But a ratchet's real design work is deciding, in advance, which way every failure mode fails.
- [16] A Default Is a Decision Nobody Made Every unset value in your stack is still set — by whoever wrote the tool, for hardware and workloads that aren't yours. Most defaults are fine. The ones that read their environment are the ones that will quietly size your system for a machine you don't have.
- [15] A Check That Never Ran Looks Exactly Like One That Passed Every team tests that its gates fail on bad code. Almost nobody tests that they fail when they didn't run. Silence is not a green light — and the gates you trust most are the ones most likely to be lying to you by omission.
- [14] A Migration Has Two Halves Renaming a contract that live resources carry isn't a rename — it's a data migration. Honor both names, write the new one, relabel in place. And know that the migration usually has two halves that don't move together: the one you can see, and the one that will delete your data if you call it done too early.
- [13] Putting an AI Reviewer in the Merge Gate It's easy to bolt an LLM onto your pull requests and let it leave comments nobody reads. It's a different thing entirely to make it a blocking check that has to be resolved before code merges. That second version forces you to answer questions the first one lets you dodge — about determinism, cost, and who is actually accountable for the code.
- [12] SvelteKit Is a Node Server That Happens to Render HTML Most teams treat their meta-framework as "the frontend" and reach for a separate backend the moment anything gets serious. But SvelteKit on the Node adapter is a real application server — and the mistakes people make with it almost all come from forgetting that.
- [11] A System That Can Reproduce Itself Is a Different Kind of System Getting uBixOS to compile its own userland on-device wasn't one more feature on the list. It was the moment the OS stopped being a thing my Mac produced and started being a thing that exists on its own. That distinction is bigger than it looks.
- [10] The Second Implementation Is the Test of Your Abstractions uBixOS ran on x86 for twenty years. Porting it to aarch64 didn't just add an architecture — it told me, file by file, which of my abstractions were designed and which had just accreted. The second implementation is the only honest test there is.
- [09] Schema Migrations That Don't Drift A migration system that works is not just a runner that applies SQL files. It's a system that can answer, at any moment: exactly what state is prod in, how did it get there, and what happens if someone deviates from the path? uBix Core's migration standard is built around that question.
- [08] The Monorepo as an Upgrade-Forcing Function Upgrade debt is a structural problem, not a behavioral one. If shared libraries can be ignored, they will be. uBix Core's monorepo makes ignoring them impossible — every PHP API and every SvelteKit frontend upgrade together, in one commit.
- [07] SOLID in Practice — Lessons From a C++ Emulator's Git History SOLID principles are easy to describe and hard to apply. Here's what applying three of them actually looked like in The 8-Bit Machine — with the git history to prove it.
- [06] AI Coding Guidelines Aren't One-Size-Fits-All When AI tools became part of the daily workflow, the first instinct was to write one set of guidelines for everyone. That was wrong. Different engineers need different guardrails — and the difference matters more than you'd expect.
- [05] Know When to Pivot to General — The 8-Bit Machine at v0.8 The 8-Bit Machine started as something specific. At v0.8 a single commit changed the direction entirely: 'Pivot to general-purpose 8-bit machine designer.' Here's why that decision was right, and how to recognize when you're facing the same one.
- [04] Pragmatic Accuracy — Knowing Which Problems Need Precision The 8-Bit Machine emulates the 1541 disk drive with a cycle-accurate IEC serial bus state machine. It also has a warp load trap that bypasses the whole thing. Both exist. Here's why.
- [03] Machine Code Review — The First Line of Defense Human code reviewers should be asking 'is this solving the right problem?' not 'why is this indented wrong?' Machine code review handles the mechanical checks so humans can focus on the things only humans can evaluate.
- [02] What Microservices Actually Cost — Lessons From 13 Services XenTask is a 13-service microservice architecture. Building it taught me three things that no microservices tutorial covers: what shared code costs across repos, how to use the platform for service discovery instead of building your own, and what 13 independent pipelines actually feel like to operate.
- [01] SpherePBX — What I Learned Building a Hosted VoIP Company Five years building a hosted VoIP platform from scratch — architecting the stack, raising $400K, growing to 200+ customers, and what I'd do differently with what I know now.