The log, and the sentence that holds it together
In July 2026 I started keeping a dev log — a personal knowledge base, one folder per project, each with a timeline, a decisions record, a running list of problems, and a set of notes on specific techniques. This website is generated from it. Not copied from it — generated, with a script, so the site and the source can't drift apart.
Why it exists is the thesis of everything here.
Working alone is different, and not just in workload
Being the only developer on a project is a genuinely different job from being one developer on a team. It's not mainly about the hours. It's that there's no second reviewer to catch a bad call before it ships, and no one else's mental model of the system to cross-check your assumptions against.
That absence is what turned things I used to treat as nice-to-haves into load-bearing infrastructure. Automated error monitoring. Schema-drift checks in CI. Targeted regression tests for bugs I'd already hit once. A verification ledger. Those aren't polish — they're doing part of the job a second developer would otherwise do just by noticing things in passing. When there's nobody to notice, you have to build the noticing.
The verification ledger
The core practice is simple.
Every user-facing flow in a project is a row in a table. Each row has a status. A flow is only marked verified when it has been driven end to end, by me, as the actual user role that flow exists for, in the real running application — with the specific thing I clicked and the specific thing that appeared on screen written down, against a date. Compiling doesn't count. Tests passing doesn't count. "I read the code and it looks right" definitely doesn't count — that was my old bar, and the first time I replaced it with this one, a single pass turned up eleven-plus real bugs in a slice I'd have bet money on.
There's an auto-downgrade rule: touch a piece of shared code and every flow that depends on it drops back to unverified, because a fix in a shared place has a way of quietly breaking something adjacent. And the ledger is explicitly the single source of truth for what works — not the codebase, not the test suite, not what "should" work because the code exists.
Two findings I keep coming back to:
"Not yet re-tested" and "was never built past the API" are completely different statuses, and collapsing them hides a product gap behind what looks like backlog. I found a feature sitting in a ledger as "prior evidence stands, not re-tested this pass" — full backend CRUD, a fully-typed client — and went looking for the button to click, and there was no button. Anywhere. It had never been built past the API layer. "The code looks done" will never tell you that. Going to look for the button will.
Accepting a consequence and measuring it are different actions, and only one of them changes anything. The most expensive class of mistake I've made wasn't a wrong decision. It was a decision whose consequence was correctly identified, written down, and formally agreed to — and then never enumerated. "Some old records will stop resolving" and "these fifteen named businesses cannot take a single order as of today" are the same fact at two resolutions, and only the second one makes anybody act.
The notes
Alongside the ledger there are about forty-five notes — one self-contained idea each. How a transactional outbox actually guarantees a side effect isn't silently lost. Why connection pooling becomes necessary and the exact search_path bug that bit me. Sequence numbers and event replay for a realtime system that can't afford a silent gap. Why I picked one tool over another and what it cost.
They're written to be useful to someone else, not as a highlight reel, which means a fair number of them are about mistakes. That's on purpose. The notes section is the closest thing I have to a body of work, and I'd rather it be honest than impressive.
The sentence
If I could keep only one line from the whole log, it's this one:
Nothing is done until it's been watched working.
Everything else — the ledger, the notes, the "test as every real role," the "read the response body not the status code," the "a migration reporting 27 rows written is evidence about the migration, not the feature" — all of it is just that sentence, applied.
And underneath that is the drum kit. The first thing I ever built existed because a tool I wanted didn't exist and didn't satisfy me, and I built a bad version rather than wait until I was qualified. The most recent thing I've built is a peer-to-peer daemon in Rust with cryptographic invariants, and it exists for the same reason.
The tools got much harder. The reason never changed. That's the story.
This site is a living document; it changes as I do. If something here is out of date, I haven't gotten to it yet.