the product, in three taps
No lawyers required. Results in under a minute.
The user sees three steps. Each one hides a piece of the system this page takes apart. Read the small print under each tap.
Choose your judge
Pick from 21 personas, from ancient dragons to chronically online teens to passive-aggressive butlers. Each has its own voice and verdict style.
Record the debate
Both people state their case, interruptions included. The app records one audio file and uploads it with the identity token it already holds.
Get the verdict
The judge names who is wrong, flags the rhetorical moves each side used, and on paid tiers reads it aloud and fact-checks the claims.
follow one request
Trace a verdict, stage by stage
The client uploads once, gets a job id back in 202, then polls roughly once a second. Everything slow happens on a queue worker off to the side. Press play, or step through it yourself.
what stage 06 actually returns
Structured output, not a paragraph
The judge does not just write a sentence. It returns a verdict line, a per-speaker scorecard, and the rhetorical techniques each side used, repaired into valid JSON before anything trusts it. The app renders that JSON; on paid tiers the verdict is also read aloud.
the whole system on one screen
Five layers, and most of them are managed
Read it top to bottom. The client holds the product. The edge gives it a domain and a cache. Two Lambdas do the work. State lives in three managed stores. Everything past the first row is somebody else's pager.
resilience / provider fallbacks
Every dependency has an answer to one question
If this provider dies right now, does the verdict stop, or ship degraded? Each external call has a decided answer, a fallback where one actually helps, and a place to land when it does not.
the load-bearing opinion
The backend is mostly defined by what is not in it
An earlier version had a VPC, Aurora, API Gateway, Cognito, and a web frontend. Every one of them got cut, and each cut was written down with the number that justified it. That habit is the point: a deletion you can defend with a figure ages better than a service you kept out of caution.
portable patterns / steal these
Six decisions that travel to other projects
None of these are specific to judging arguments. Each started as an annoying edge case and turned into a small rule. Tap a card for the mechanism and the payoff.
defense in depth / live
The argument is the prompt, so the argument is the attack surface
Whatever two people say gets transcribed and handed to a model. Someone will eventually try to talk the judge into ignoring its instructions. A working copy of the input-safety gates runs right here in your browser. Type a fake transcript and watch which gate stops it.
Every request also hides a one-time marker, for example [INTERNAL-a1b2c3d4], in the system prompt. If that string ever shows up in the model's answer, the injection worked, and the verdict is thrown away before anyone sees it.
safety gates, in order
21 unique personalities
Meet your judges
Every judge is a JSON file: a system prompt, a voice id, tone settings, catchphrases, and the tier that unlocks it. The pipeline treats them all the same. Filter by the tier a judge unlocks at.
how the project is actually run
Verification you can trust because it is honest about its gaps
A two-person app lives or dies on whether the two clients behave the same and whether the pipeline can be tested without spending real money on real models. The process is built around those two facts.
One app is the source of truth, the other is graded against it
A test rig drives iOS and Android through the same scripted flows and captures three views of every step: a screenshot, the accessibility tree, and the network transcript. A later phase scores how far the target drifts from the reference.
- Record once, replay paired. Backend responses are recorded to committed cassettes so both platforms replay byte-identical answers.
- Anti-gaming by ownership. The agent that edits an app may not edit the scorer, the labels, or the cassettes in the same change.
The expensive part is mocked, on purpose
Transcription, judging, fact check, and voice are all paid per call. Tests run against recorded responses, and the few live runs are capped so a single end-to-end verdict stays well under a fixed cent budget.
- Golden masters are committed. A response that changes is a reviewable diff, not a flaky test.
- Live smoke stays small. One paired live run confirms the contract still holds against the real services.
Path-filtered, and loud about the gaps
Android CI runs only when a pull request touches Android paths. An iOS-only or test-only change triggers zero Android jobs, by design. The team treats a check that did not run as expected, not as missing.
- iOS has no CI. A local Xcode build is the only gate, so it runs before every iOS change ships.
- Android needs JDK 21. A local build on the wrong JDK is a tooling mismatch, never reported as a code failure.
Run the check before claiming the tool is missing
The standing instruction for anyone working in the repo, human or agent: do not state that a tool or environment is unavailable until you have run the command. Verified build and test commands live in the repo guide so nobody guesses.
- Secrets stay in Parameter Store. API keys are never in code; the worker reads them at runtime and caches them.
- Failures retry, then quarantine. A bad job retries three times on the queue, then lands in a dead letter queue that pages on depth over zero.