Over the past year I have designed, built, tested and deployed six complete systems — web crawlers and retrieval
pipelines, a WhatsApp product on Meta’s Cloud API, a WordPress plugin now in review at wordpress.org, a
7,125-page public reference site, and an automated back-office that reads and triages my own mail. Every one runs
on real infrastructure with real tests, not as a demo.
Two of them I stopped on purpose, and this portfolio says exactly why. I would rather show you a real cause of
death than a screenshot of something that never had users. What I actually do well is verification: I build the
instrument that checks the work, and I have caught myself being wrong more often than anyone has caught me.
None of this is coursework. I read space sciences, not computer science — every system on this page was
built outside a syllabus, on a schedule I set, against problems nobody assigned me.
114,283wage classifications parsed and published
7,125pages generated, live and indexed
244automated tests across three products, all green
4,009government PDFs parsed, zero failures
0documents dropped by the parser once faults were fixed
Selected work
What I built, what it cost, what broke
Live
Davis–Bacon Rate Lookup
2026 · Python, static site generation · public, free, no sign-up
Every current US federal construction wage determination, parsed from SAM.gov and republished as a
county-level reference anyone can search. The government publishes these as PDFs that are almost unusable
in practice; a contractor looking up the fringe rate for a single trade in a single county has to read a
60-page document. This turns that into one page per county per construction type.
I fetched all 4,009 determinations with two concurrent workers and zero failed documents, parsed each into
structured rows, and generated the site. Then I submitted all 7,125 URLs through IndexNow and Search
Console so the pages were actually findable rather than merely published.
QueueWatch — Past-Due Monitor for Action Scheduler
2026 · PHP, WordPress plugin · submitted to the WordPress Plugin Directory
WooCommerce runs its background work through Action Scheduler. When that queue stalls, orders stop
emailing, subscriptions stop renewing, and nothing announces it — the site looks fine. QueueWatch
watches for actions that are past due and tells the site owner before a customer does.
It shipped with 112 automated assertions run against a real WordPress and WooCommerce install rather than
mocks. The review team returned it with three items — a naming conflict, function prefixes one
character short of the guideline, and an ownership question — and I fixed all three in one pass,
including a data migration that moves nine stored options by explicit name rather than by prefix sweep,
because a sweep would have moved rows belonging to any other plugin using the same prefix.
2026 · Python, FastAPI, Meta WhatsApp Cloud API, Modal · deployed and working
Businesses that quote over WhatsApp lose money in a specific, boring way: a customer asks for a price and
nobody replies. QuoteRadar sat on a company’s WhatsApp number, tracked every conversation’s
state, and surfaced the ones waiting on a reply.
It ran live on Meta’s real infrastructure, not a sandbox — verified end to end with an actual
message from my own phone arriving through the webhook, entering the state engine, and appearing on the
dashboard. Authentication used signed HttpOnly session cookies with login throttling; the webhook stayed
open to Meta and authenticated by X-Hub-Signature-256 instead, because Meta cannot log in.
Why it stopped
Connecting a real client’s existing WhatsApp number requires Meta’s Coexistence flow, and
Coexistence requires Tech Provider status, which requires business verification, which requires a
registered company. I do not have one. The only alternative was fully migrating a client’s number
to the Cloud API, which permanently removes the WhatsApp Business app their staff work in every day. No
real business accepts that. The product worked; the paperwork gate did not move, so I stopped rather
than keep building against it.
A support and product-discovery bot embedded in online stores, answering from the store’s own
catalogue with live price and stock rather than a stale index. It crawled each store behind quality gates,
served a per-tenant embeddable widget with per-store branding, and included a CSS-only variant for pages
that could not run JavaScript.
The part I am most pleased with is not the bot. It is the adversarial evaluation harness I wrote to attack
it — deliberately hostile questions per store, scored automatically. Stores entered at 66% and I
fixed engine bugs until most sat at 100%. It also generated its own demo videos by driving a headless
browser and capturing real typing and streaming to MP4. Generation ran across three
model providers with automatic failover, because a single provider deprecating a model mid-project had
already taken the whole system down once.
Why it stopped
Over 100 stores and roughly 100 agencies contacted. Openers drew about 20% engagement, well above
benchmark — and then every single conversation died at the moment I explained who I was. The
diagnosis was trust, not wording: an unknown individual with no registered company asking a shop to put
a script tag on their live storefront. Rewriting the message many times changed nothing, so I stopped
rewriting and accepted the finding.
Generates the US Department of Labor’s WH-347 certified payroll form from an existing payroll
register, then verifies it: that each worker’s classification actually appears on the wage
determination governing that contract, that hours split across classifications are reported per class per
day rather than averaged, that fringe is tested per hour per classification, and that overtime across two
classifications uses the weighted average regular rate — the calculation that most often fails audit.
Thirty automated checks, written from the regulation and the DOL’s own form instructions rather than
from a blog post, with the separate certified-payroll requirements of all 50 states recorded alongside.
The scraping and verification layer underneath the outreach work. It finds companies, derives and checks
their real domains, fetches every candidate page, and rejects the ones that do not hold up — then
sends, with retries, and can never double-send because state is only written after a send returns.
The verification half exists because the naive version was confidently wrong. Guessing a domain from a
company name produced other companies’ websites: a door-repair firm mapped to Automattic, a painting
contractor to an online casino, a construction company to a foreign-exchange broker. Checking that a page
merely contains a company word does not catch this. The domain has to be built from the
company’s words in order, and then the live page has to be fetched and read.
Pythonasyncioconcurrent fetchingHTML parsingIMAP/SMTPretry with backoff
Running
AI Employee Vault
2026 · Python · agentic back-office with a human approval gate
An automated back office that runs on my own machine. Three watchers poll mail, an approvals folder and
the filesystem; incoming email is classified by an LLM and routed; a planner drafts a reply and files it
for approval. Nothing is ever sent by the system on its own — every outbound action waits on an
explicit human approval, and the entry points refuse to run without a passing preflight check.
It is the system my MCP servers expose to Claude, which is why the assistant can operate my mail pipeline
rather than describe what I should do in it. The approval gate is the part I would defend hardest: an
agent that can act unsupervised on a real mailbox is a liability, and the correct design is one that
drafts confidently and sends only on permission.
Claude is the environment I build in, not a tool I open
Everything above was built in Claude Code across roughly six months of daily use. Over that time I have built
the scaffolding around it that makes long-running work possible — persistent memory, a house style, two
agents that do not collide, and rules derived from my own mistakes rather than from advice.
A persistent, file-based memory
An indexed set of memory files — one per session or topic, with a lean index loaded at the start of
every conversation. Decisions, measured numbers and pending steps survive between sessions, so a project
picked up three weeks later starts from evidence instead of from my recollection.
A house style that overrides defaults
A CLAUDE.md that sets a plan / execute / revise loop, a hard output budget, banned filler
words, and required preflight checks before any action that sends or posts anything. It is short on purpose,
because a long one is not followed.
Two agents, one repository
A shared status file that Claude and Gemini both read before touching anything, listing which files are
being modified. It exists because concurrent writes to the same JSON silently destroyed work — each
process held a stale snapshot and deleted the other’s finished rows.
MCP servers for my own systems
Local MCP servers exposing my mail pipeline and accounting database as tools, so the assistant operates
the systems I actually run rather than describing what I should do in them.
Rules written from real failures
A working-rules file that grows only when something goes wrong: never trust a marketplace search count
without relevance-filtering it, never quote a deadline from a job that is serial rather than slow, never
read a bounce rate from the inbox alone because bounces land in spam.
Render before done
Visual work is not finished until it has been rendered, captured and looked at. That rule earned itself
— it caught a blank page, a progress bar pushing its own label onto a second line, and a settings row
still describing behaviour the code had changed.
What the failures taught
Five products died in distribution, none in construction
I think this is the most useful thing I can tell you about myself, and it is the reason I would be a good
ambassador rather than just an enthusiastic user. I have been wrong publicly and in writing, and I have kept
the receipts.
01Nothing I built failed because it did not work.Every one shipped, ran and was tested. They failed at the point where a stranger had to
decide to trust an unknown individual with no company behind him. That is a distribution problem, and no
amount of additional engineering touches it.
02A green test suite is not evidence if the assertions cannot fail.I have written a tautological assertion and watched it pass while the system underneath
it was completely down. Now I check that a test can fail before I trust that it passed.
03Hypothetical interest is worth nothing.“That sounds useful” has never once become money. Eight people told me a
product was interesting and none of them bought it. Only a request for commitment reveals anything.
04Measure the instrument before believing the measurement.Marketplace search engines inflated counts by factors of ten to ten thousand; one
reported a billion downloads for a term whose real figure was 72,050. Every count I now publish has been
relevance-filtered first.
05When the research converges, more research is procrastination.Five rounds of adversarial review across two different models produced one instruction:
finish what you already built. Knowing when analysis has stopped adding information is a skill I learned
the expensive way.