Game · Certified
Sakura Storm
A 6×5 slot game whose payout model holds a 0.97 return across three bet modes, verified over millions of simulated rounds and passed third-party certification.
Slot math is a constrained optimization problem. You are given a target return, a hit frequency, a max win cap and a volatility profile, and the reel set and payout table have to satisfy all four at once. Then it has to survive an audit by someone whose job is to find where you got it wrong.
I specified the game and drove it to certification. The judgement calls were mine: how volatile it should feel, when the numbers coming back were wrong rather than merely surprising, when a cascade animation read as broken instead of dramatic, and when it was actually finished.
Certification is a useful forcing function, because it removes the option of "close enough." A payout distribution is either provably correct across millions of rounds or it does not ship. Getting there meant a lot of runs where the answer was no.
It has passed both front end and math certification. It is now in final platform review ahead of release, and I will link it here the day it goes live.
My part: Specified the game, tuned the model against certification targets, and owned the call on when it was correct. Implementation produced by AI under my direction.
- Return to player
- 0.97 across all 3 bet modes
- Max win
- 25,000×
- Bonus trigger
- 1 in 400 spins
- Certification
- Front end and math passed
- Stake Engine
- Python
- TypeScript
- Svelte
- PixiJS
Certified. In final review ahead of release.
AI automation · Live
The job agent
A pipeline that reads 4,500 job postings a day, narrows them to a few dozen, scores those against my profile, and drafts outreach. It is running on this site right now.
The most honest thing you can build while job hunting is the thing that solves your own job hunt. So this one runs in public, and you can read its output below.
Each morning it polls the public job-board APIs of a watchlist of companies. Cheap deterministic filters run first, checking title, location, and everything already seen, because there is no reason to spend model tokens learning that a Director of Sales role is a bad fit. About 4,500 postings become about 37.
Those go to Claude with a strict schema: a 0 to 100 fit score, the specific reasons, and a draft opener. Anything above the bar lands in a daily digest.
Two decisions I would defend. It drafts but never sends, because auto-applying at volume is how you become spam, and the goal was never to apply to more jobs. It was to only look at the ones that matter. And it is instructed to be harsh about my gaps. An early version rated every single posting exactly 72 and wrote openers claiming experience I do not have. That version was useless, and worse, dishonest. The current one routinely scores roles in the single digits and says why.
My part: Designed the pipeline, caught the scoring model hedging and fabricating, and rewrote the prompt until it told the truth.
- Read per run
- ~4,500 postings
- Survive filtering
- ~37
- Scored by
- Claude, structured output
- Sends on my behalf
- Never. Drafts only.
- Next.js
- TypeScript
- Claude API
- Postgres
- Cron
AI infrastructure
Jarvis
A home assistant whose identity and memory live in a service rather than in any one model, so swapping the model never changes who it is.
Most assistant projects are a thin wrapper around one model, so the day you swap models you lose the personality, the memory, and everything it knew about your house. The design decision here was to invert that. Identity lives in a service that sits between you and whichever model is answering.
It keeps a file of durable household facts injected into every conversation, plus a searchable store of past ones. Routing is by request type. Anything latency-sensitive stays on the model running locally on the GPU, open-ended questions go to the cloud, and if the cloud call fails it quietly falls back rather than dying.
Vision runs entirely on the local machine. Camera frames never leave the house. That was a requirement, not an optimization.
My part: Set the architecture constraints, including local-first, model-agnostic identity, and no camera data leaving the house, then drove the build against them.
- Local model
- Runs on-device, on GPU
- Vision
- Never leaves the machine
- Memory
- Durable facts + conversation recall
- Model swaps
- Identity survives them
- Python
- FastAPI
- Ollama
- Chroma
- Claude API
Game · Built, unlaunched
Vault Legacy
A 3×3, nine-line slot with a pick-em bonus. Math model and front end are both finished at a 0.965 return and a 10,000× cap. It has not been launched.
A smaller, tighter game than Sakura Storm on purpose. Three reels, three rows, nine fixed paylines, and a Key to Fortune pick-em bonus where the top box is a routed max win rather than a lucky roll.
The constraint I set was that the paytable, symbols and paylines had to be defined once and mirrored exactly between the Python math model and the TypeScript front end. If those two ever drift, the game pays out something different from what it displays, and you will not find out until someone else does.
Everything is built and the numbers hold. I have not put it through certification or launched it, and I am not going to claim otherwise.
My part: Set the game design and the mirroring constraint between math and front end, and verified the model held its targets.
- Return to player
- 0.965
- Max win
- 10,000×
- Layout
- 3×3, nine fixed lines
- Status
- Complete, not launched
- Stake Engine
- Python
- TypeScript
- Svelte
- PixiJS