Practice
Recent work, and what each one is evidence of. Everything here is checkable: the code is public, or the thing is running, or both.
These are AI-augmented rather than AI-delegated. Every architectural call and every security judgement was mine; the model was the hands. The claim I will defend under questioning is that I direct and review AI-augmented delivery end to end, across security, product and infrastructure.
I direct this work and an AI writes the code. Every design decision and every security call was mine. What I will defend under questioning is that I run AI-assisted delivery end to end, across security, product and infrastructure.
A resident multi-agent fleet
2026-07 → nowFive autonomous roles running unattended on my own hardware, each isolated in its own git worktree, with output confined by construction to a designated write path.
Built usage and cost governance from scratch: live rate-limit metering read directly from provider API headers, which the client library leaves unexposed, plus a pacing dial and quota-guarded scheduling.
Ran a full security audit of the fleet's own write access, self-directed. The documented claim was one gate to main; the practice was six ungated paths. Root cause was capability creep — each addition individually justified, while the count stayed where it was. Fixed with server-side git hooks enforcing a namespace allow-list, ownership and permissions set so the constrained process is unable to edit the control meant to constrain it, and history-rewrite protection. Kill-tested both directions before I trusted it.
I run five automated helpers on my own hardware, unattended. Each one works in its own sealed copy of the files and can only write to one place, so a mistake stays in its own corner.
I built the cost controls from scratch, reading the usage figures the provider sends back in each reply, which their own toolkit leaves out.
Then I audited my own setup off my own bat, and found six ways those helpers could write where the documentation claimed there was one. The cause was ordinary: each addition made sense on its own, while the count stayed where it was. I fixed it so the guard sits out of reach of the thing it guards, and I tried to break it both ways before trusting it.
evidence
Live and operational. The audit pattern — find real gaps in your own system, fix them, prove the fix under test — is the piece I would point at first.
A booking and appointment platform
2026-08Self-hosted, built from a diagnosed failure: a reply left unanswered for three weeks, and deadlines carried in memory.
Full stack with no external dependencies. State as version-controlled plaintext, a commit gate that closes on error — it aborts and alerts where an out-of-scope write would otherwise pass, a slug-authenticated public API on the standard library, reminder scheduling and stale-thread detection over push, and per-client localisation.
Hand-built calendar feed generation to RFC 5545, added after checking whether the target calendar app has a write API. The resulting one-way limit is stated in the product.
Constant-time token comparison, rate limiting, strict CORS, and a runtime identity gate that caught a real gap the build-time check was unable to see.
A booking system, built because I left a reply unanswered for three weeks and was carrying deadlines in my head.
Everything is stored as plain text under version control, so the history is readable and it all stays as files you can open. It refuses and warns where something out of place would otherwise be saved quietly, and it sends reminders by push.
I wrote the calendar feed by hand after checking whether the calendar app I use can accept one the other way. It accepts only one direction, and the app says so plainly on the page.
evidence
In production use. It caught and closed its own privacy leak the same day, before it reached anyone.
A published Android application
2026-08BreathGate, built end to end in Kotlin: interface, custom rendering, real-time audio synthesised on the device sample by sample, and a full signed release pipeline.
Defects diagnosed from plain-language feedback by finding the mechanism each time. A sound described as static traced to a hard amplitude step in an envelope function; described clipping traced to unbudgeted signal summation. Both fixed at the signal level.
Permissions as a product feature: no network permission, the claim readable from the manifest, and a build gate that halts a release that acquires one.
Distribution constraints handled as they appeared, including a hosting platform's terms changing mid-project — found by reading the actual clause. The plan moved; the product held.
BreathGate, an Android app I built end to end: the interface, the animation, and the sound, which is generated on the phone rather than played from a file.
When something felt wrong I looked for the actual cause. A sound described as 'static' turned out to be a sharp jump in volume; described 'clipping' turned out to be layers adding up past what the speaker could take. Both fixed at the source.
It asks for no internet access, you can check that before installing, and the release process stops if a build ever acquires it.
evidence
Public source, published releases, and a signing key you can check against the build.
A self-hosted voice interface
2026-08Speech to a working system and back, with no third party anywhere in the audio path.
Speech recognition, a voice pipeline with activity detection, and synthesis, all running on my own hardware behind an authenticated route.
Measured the network before trusting a framework: two STUN queries from one socket returned different external ports, which is symmetric NAT, and under it peer-to-peer traversal stays out of reach here. The websocket transport is simply the correct answer here, and finding that out cost two build cycles I would rather have spent elsewhere.
Cut spoken-turn latency from about five seconds to under two by sizing the decoder window to the utterance, then verified the transcripts were byte-identical at three lengths so the speed-up cost no accuracy.
A way to talk to my own machine and hear it answer, with no outside company anywhere in the audio.
Speech recognition, the conversation itself, and the voice all run on hardware I own, reached over an authenticated connection.
I measured the network before trusting the software, and found the connection type that rules out direct peer-to-peer here. Better to find that out with a measurement than after two rebuilds. I also cut the delay on short questions from about five seconds to under two, then checked the results were word-for-word identical so the speed cost no accuracy.
evidence
Running. The latency figures were measured live.
A zero-knowledge credentialing system
2026-07Anonymous membership proofs, issued as physical cards and in live use by real participants.
A person proves they belong to a group, and the proof carries which group while leaving which member out of it. A nullifier holds each proof to one use. Lab-proven first — a group of three, a double-cast caught, an outsider locked out — then issued on cards and carried by hand.
Built alongside a governance framework: a charter, a tiered onboarding design, and the screening that decides who a group is for. The cryptography was the easy half.
The limit was named in the build rather than after it: this kind of anonymity is application-level, so it re-leaks the moment it travels over a pipe that leaves metadata exposed. That gap belongs to the field, and it is still open.
evidence
Shipped and in use by early participants. The framework and mechanism are real; the group itself is small by design.
Before that
Built and ran a fifty-member volunteer organisation from zero as founder — recruitment, alignment interviews, training pipelines, rank structures, the whole operating system a volunteer group needs to run on more than goodwill. Plus a decade abroad, several languages, and a practical upbringing that means I am comfortable with tools, engines, animals and dirt.
Start a conversation