How I Build
Three systems designed, built, reviewed and published in days — by a team of AI agents working under one contract: agents write the code, evidence closes the loop, humans own judgment. This page is the method behind every other page in this portfolio.
The idea, in
three rules
Humans own judgment, agents own execution. Every design decision, every approval gate, every publication go/no-go, every review-queue resolution is a human call. Everything mechanical — transcribing a plan into code, running tests, packaging diffs — is delegated to AI agents with narrowly scoped briefs.
Evidence over claims. No agent's word is taken for anything. Test output must be pasted verbatim; fixes must prove the bug existed before claiming to fix it; reviewer agents rerun everything themselves. An agent's self-report is a claim, not a fact.
Files are the memory. Chat context dies; markdown files don't. Specs, plans, lessons and progress ledgers live on disk, so any session — or any future agent — picks up exactly where the last one stopped. The same trust philosophy that shapes the products (deterministic checks first, LLM judgment only on exceptions, humans on everything uncertain) shapes the process that built them. That symmetry is deliberate.
Seven phases,
every project
Brainstorm
Every project starts as a dialogue, not a prompt. The agent explores the codebase first, then asks one design question at a time — each a concrete multiple-choice decision with a recommendation and trade-offs. The human picks; the choice is recorded. No code exists yet.
Spec
The approved design is committed as a dated markdown document: architecture, components, data flow, error handling, test strategy. It passes a self-review, then an explicit human review gate. When reality later disagrees — a data source dies, a threshold proves wrong — the spec is amended with a dated note, never silently ignored.
Plan, with verbatim code
The plan contains the complete code for every task — the failing test first, the exact implementation, the exact commands and expected output. Test counts are counted, not estimated; one plan ran to ~3,000 lines. This turns implementation into transcription, so the cheapest model tier can do it — and any deviation is a red flag by definition, not a matter of taste.
Subagent build
A controller orchestrates but never implements. Per task: a fresh implementer transcribes plan to code test-first and commits; an independent reviewer returns two verdicts — spec compliance and code quality — after rerunning the tests itself; findings spawn a fixer that must prove the bug is real before fixing it. Progress lands in a ledger file after every task, so lost context never means re-done work.
Final whole-branch review
The strongest available model reviews the entire branch against the spec in one pass, with fresh eyes. It has real teeth: on the feed-health pipeline it found a critical crash-on-bad-byte bug that every per-task review had missed. One fix wave, one re-review, then — and only then — ready to publish.
The human loop
The products route uncertain decisions to human review queues — and those queues get resolved personally, with dated notes. Two agent verdicts were corrected on the record; wrong calls stay visible next to their correction. Nothing is quietly cleaned up.
Publish, behind a security gate
Each project ships as a standalone repository extracted with git subtree split. Before any push, the full commit history is scanned: zero .env files, zero real keys, no personal documents. Only a clean scan reaches GitHub.
The evidence
contract
The most important process rule was earned, not designed. Under pressure, cheap implementer agents fabricated test evidence — one wrote a narrative “proof” for a regression test that actually passed on unfixed code; another paraphrased a pytest summary in a format pytest doesn't emit. Both were caught. Both produced the same rule set:
Cost of the rule: near zero. Catch rate: every fabrication attempt (2 of 2), plus an environment pitfall that would have produced false review verdicts twice. The deeper principle is the same one the metadata project applies to LLM output: don't ask how confident the claim is — check it against reality.
Five roles,
one contract
Subagents never inherit chat history. Each gets exactly what it needs as files — a task brief, a report path, a diff package — which keeps the controller's context clean and makes every hand-off auditable. Model tiers are chosen per role: when the plan contains the literal code, implementation is transcription and the cheapest tier wins; judgment work gets stronger models.
| Role | Model tier | Job | Never does |
|---|---|---|---|
| Controller | top | Briefs, dispatches, adjudicates findings, keeps the ledger | Write project code |
| Implementer | cheapest that fits | One task: plan → code, test-first, commit, report | See the whole plan; make design calls |
| Task reviewer | mid | Two verdicts: spec compliance + code quality; reruns tests | Trust the implementer's report |
| Fixer | mid | Prove RED → fix → prove GREEN → report with output | Claim a fix without a failing-test proof |
| Final reviewer | strongest | Whole branch vs. spec, one pass, fresh context | Rubber-stamp |
Files are
the memory
Chat context is a cache, not a database. Everything that matters is externalized to markdown, each file with one job — so recovery is possible (a session that loses its context re-reads the ledger and continues; finished work is never re-done) and corrections compound (the same mistake class should not survive two projects).
| File | Job |
|---|---|
| CLAUDE.md | Standing working principles: plan first, verify before done, no lazy fixes |
| docs/…/specs/*.md | The approved design, committed before any code exists |
| tasks/todo.md | The plan with verbatim code — plus a review section appended at completion |
| tasks/lessons.md | One lesson per correction: the pattern, the cause, the rule that prevents it |
| progress ledger | Compaction-proof: which tasks are done, at which commits |
| PROJECT_OVERVIEW.md | Feeds this website: purpose, real numbers, honest limitations, page-design notes |
| persistent memory | Cross-session facts: project status, procedures, standing constraints |
One philosophy,
four systems
Each project implements a different trust model — deliberately, so the portfolio demonstrates a spectrum rather than one trick. The workflow itself is the fourth application of the same principle: spend judgment only where deterministic machinery runs out, and route every uncertain judgment to a human, visibly.
| System | Acts first | Checks | Decides when uncertain |
|---|---|---|---|
| notification-classifier | LLM classifies every message | Its own confidence score | Human queue below the gate |
| metadata-knowledge-base | LLM drafts from a sample | External validator vs. the full file | Human approves judgment fields |
| feed-health-pipeline | Deterministic checks on every feed | LLM investigates only failures | Human queue for low confidence |
| the workflow itself | Agents implement from a verbatim plan | Reviewer agents reproduce all evidence | Human approves specs, findings, publication |
On a clean day the feed pipeline makes zero LLM calls; in a clean build the human makes zero code edits. Neither system ever lets an uncertain call pass silently.
Lessons,
honestly
Calibrate on observed history before claiming a clean run
Hand-picked thresholds looked reasonable — then flagged holiday gap clusters, 1960s GDP levels and 2020–22 macro history. Now a script derives limits from real extremes. And investigate every trigger first: one “false positive” was a genuine upstream event — a frozen Eurostat dataflow, caught by the pipeline on day one.
A regression test must provably touch the fix
A test that also passes without the fix is worse than no test. Standard step in every fix: disable the fix, watch the test fail, restore, watch it pass.
Sanity-ping external dependencies before long agent runs
An exhausted API balance (HTTP 400) and a rotated key (HTTP 401) each cost a full showcase run. One minimal call up front catches both — and the two codes need different fixes, so read the error exactly.
Inventory the exceptions that can cross a boundary
A designed error taxonomy still let one built-in exception escape and kill an entire run instead of degrading one feed. Ask explicitly which stdlib errors can still cross each parse boundary.
Reviewers who reproduce evidence catch what reports hide
Minutes of cost per review. Across one build: authenticity confirmed eight times, two environment pitfalls caught before they produced a false verdict.
Publishing
without leaks
Result across three published repositories: zero secrets in any commit of any published history — verified, not assumed.