I build test infrastructure. On weekends I build tools for tabletop games, which is the same job with the sign flipped: there, randomness is the feature.
Portfolio: sjzavala.github.io/portfolio — the site runs its own Playwright suite in CI and shows you the results, because a portfolio that claims to care about testing should be able to prove it.
Most teams have plenty of tests and not much trust in them. Someone re-runs a red build, someone mutes a spec "temporarily", and eighteen months later nobody can say whether the behaviour it covered still works. You end up paying for a test suite and getting a slot machine.
So most of what I build answers one question in different places: what should we trust, and how do we know?
| flake-radar | Scores flakiness from same-commit evidence and quarantines the worst offenders — with an expiry date, because a quarantine that never comes due is a deleted test with extra steps. |
| self-healing-e2e | Tracks known bugs as guards — green while a bug is live, red the moment it's fixed — and repairs its own drifted selectors, healing only what's safe and escalating the rest, because a broken selector is sometimes a regression wearing a disguise. |
| playwright-test-selector | Runs only the specs a pull request can actually affect. Never narrows on a guess: anything it can't explain escalates to the full suite. |
| claude-agent-swarm | Runs a task with one AI agent, then with nine, and measures whether the extra agents earned their keep. Mostly it refuses to declare a winner, which is usually the honest answer. |
| claude-qa-tms | The loop that produces the specs the rest of it consumes — explore a running app, file the cases, verify them in a real browser, generate traceable tests. |
| borrower-search | A deliberately broken app with ten planted bugs. It's the practice dungeon, and it doubles as the fixture everything above is tested against. |
They compose in that order: produce the specs, pick which to run, decide which to trust, keep them running as the app drifts underneath them, then check whether any of it was worth the money.
A flaky test is a trust problem, not a testing problem. Retries that hide a real defect are worse than a red build, so quarantine is a loan with interest — granted on evidence, repaid after N clean runs, escalated when it expires.
If a tool can't explain a decision, it shouldn't get to make it. Every narrowing, every quarantine, every score lands somewhere a human can argue with it. An automated decision you can't interrogate is just an outage nobody filed.
Measure it or don't claim it. I've published a benchmark whose headline section is "the first run found three flaws in this benchmark", because a result you can't reproduce is worth less than an honest "we don't know yet".
LoreBrain — extracts NPCs, factions, locations and events out of session notes into a queryable world state, so a campaign stops living in six months of increasingly panicked scrawl.
The Peculiar Persona Pot — a D&D 5e character generator: pick a race and class from a wall of pixel-art portraits, roll the dice, pick a fight with the alignment grid, export the sheet. Session zero in ten minutes instead of a lost evening. Live at the-peculiar-persona-pot.vercel.app.
Artificer — AI-assisted, human-approved deal intake for net-lease commercial real estate. It reads an offering memo, extracts the deal with a source citation on every field, and nothing reaches Salesforce until a person signs off. Same opinion as above, wearing a suit: if the model can't show where a number came from, it doesn't get to enter it.
Same underlying problem as the day job, honestly: keep state consistent, make it reproducible, and don't lose the thread. The dice are supposed to be random. The world isn't.
Currently building out a QA platform in the open — Postgres-backed test isolation, per-worker schema namespacing, and an API integration tier are the next pieces.


