The experiment

The course makes a claim: the right words and real gates get you better work from an agent. We tested it, 480 times, on a real model. This page reports what happened, including where the results went against what we expected.

In short: the right words helped, and most of that help came from one task. The harness made code pass more of its own checks, and barely changed whether the code did what was wanted. The gates were weak at spotting broken code, and our own hidden test missed a real security hole.

This is one small measurement. The limits come straight after the result, on purpose.

The result

Runs that passed every hidden scenario
Vague brief, one shot88% 80 to 92
Vague brief, harness on91% 84 to 95
Right words, one shot98% 93 to 99
Right words, harness on100% 97 to 100

Amber is the vague brief and blue is the right words. A stripe means the harness was on. The line under each bar is its 95% interval, and those are the numbers beside the figure. 105 runs per bar without that task, 120 with it.

Tasks counted

88%, 91%, 98%, 100%. The vague brief’s intervals don’t overlap the right words’ at the same harness setting, and each brief’s harness-off and harness-on intervals do overlap. So in this data the brief made a visible difference, and the harness did not make one we can tell from noise.

Then change which tasks are counted. Without one task, payment-events, the figures are 96%, 99%, 97% and 100%, and every interval overlaps every other.

A 95% interval here treats each run as independent. It says how sure we can be about these 8 tasks, on this model. For a task we didn’t try, the number that matters is much closer to 8 than to 480, and no interval on this page covers that.

What it can’t tell you

Read these before the findings, because they decide what the findings are worth.

One small model
Everything ran on Claude Haiku 5.5. A stronger model might need no help on these tasks, and a weaker one might need more.
One-function tasks
Each task is one function in one file. Nothing here tests changing code that already exists, or work that spreads across files, which is where we’d most expect gates to earn their keep.
No repo, no tools, no context
The agent got a brief and replied with files. It couldn’t read a codebase, run anything or look anything up. A real coding agent does all of those.
Small numbers per task
15 runs per cell. One run going the other way moves a task’s figure by about 7 points.
Tasks chosen by someone with a stake
The tasks and the hidden scenarios were written by the same person who hoped the course would work, after replacing a first set that showed too little. There’s more on that below.

It doesn’t show that gates are useless at scale. We measured whether a gate predicts a hidden-scenario failure on a single function. We didn’t measure whether gates keep a large codebase in order over months.

It doesn’t show that words always win. On 3 of the 8 tasks, every cell scored 100% whatever the brief said, and the biggest effect belongs to a single task.

How it was run

A 2×2 design. The brief is either vague or uses the right words. The harness is either off or on. That makes four cells, with 8 tasks and 15 runs per cell, so 480 runs, all on Claude Haiku 5.5 through claude -p with tools, settings and MCP servers switched off.

Off means one shot: the agent replies once and that reply gets judged. On means what the gates said goes back to the agent, for up to 3 retries.

Every reply went through the same real gates:

  • Types: tsc with strict plus noUncheckedIndexedAccess.
  • Lint: Biome’s recommended rules on the implementation.
  • Tests: the agent’s own, under bun test. At least one has to pass.
  • Mutation: a mutation tester breaks the code in small ways, up to 30 mutants, and asks whether the agent’s tests notice. The bar was a score of 0.7.

Then the part the agent never saw. A hidden holdout of 91 scenarios across the tasks: 41 core, which is what the vague brief literally asks for, and 50 trap, which is what an experienced engineer would insist on. A run counts as passing only if it passes all of its task’s scenarios. A second agent in a fresh session also reviewed the final code, without being able to run it.

Code the model wrote ran in sandbox-exec with no network, and could only write to its own folder and the temporary folders.

The main run cost $2.51 over 1,097 model calls and about 184 minutes of model time run in parallel, with results stamped 5 November 2026, 09:21 to 09:54 UTC. The cost is what claude -p reported. The reviewer test and the neutral re-review recorded no cost, so they aren’t in that figure.

Task

Handle payment webhooks

The vague brief
Write createPaymentProcessor. apply(event) updates an order's status from a payment provider's webhook event. It calls onPaid when an order gets paid, so we can ship it.
The right words
Write createPaymentProcessor. Webhooks are delivered at least once and out of order, so apply must be idempotent. Dedupe by event id: a redelivered event changes nothing. An event older than the newest one applied to that order, by at, is stale and changes nothing. onPaid fires exactly once per order, however many distinct paid events arrive, and never for a stale event. status(orderId) returns the type of the newest applied event.
The signature, sent with both
export type PaymentEvent = { id: string; orderId: string; type: 'paid' | 'refunded' | 'failed'; at: number } export function createPaymentProcessor(onPaid: (orderId: string) => void): { apply: (event: PaymentEvent) => void; status: (orderId: string) => string | undefined }

What we found

A mechanical gate can’t catch what nobody asked for

payment-events asks for a handler for a payment provider’s webhooks. The vague brief says:

Write createPaymentProcessor. apply(event) updates an order's status from a payment provider's webhook event. It calls onPaid when an order gets paid, so we can ship it.

It doesn’t say that webhooks arrive more than once and out of order. With that brief, 27% of one-shot runs passed, and 33% with the harness. With the right words, 100% and 100%.

Only 2 of its 9 scenarios ever failed, and they are the same situation: a refund arrives, then an older paid event turns up late. The order should stay refunded and not ship. “a late, older paid does not undo a refund” failed 11 of 15 one-shot runs and 10 with the harness. “a late, older paid does not ship” failed 8 and 10.

The mechanical gates had almost nothing to say. Of the 11 broken one-shot runs, types stopped 0 and lint stopped 0, and 9 passed all four gates. The other 2 failed because the agent’s own test about late events disagreed with its own code. Retrying can’t fix what no check mentions: 5 of 15 passed with the harness, against 4 of 15 without.

Reading did better than running, with a catch. The neutral reviewer rejected all 15 vague-brief runs of this task, including the 4 that passed every scenario, and 0 of the 15 worded ones. By a keyword count on the stored text, 10 of the 11 reviews of broken code mention ordering or stale events, but 4 lead with something else: if onPaid throws, the event is already marked as seen, so a retry never ships the order. So do all 4 rejections of the passing runs. That’s a real hazard the holdout never tests, so calling those rejections false alarms is generous to our holdout.

So the line is narrower than it first sounds, which is why the heading says mechanical. A check that only runs what was specified can’t catch what wasn’t. Someone reading the code and thinking about webhooks sometimes can.

Most of the gap comes from this one task. Without it, the one-shot gap between the briefs falls from 10 points to 1, and with the harness on, from 9 points to 1. Dropping a task after seeing the results is a choice too, so read that as a check on how fragile the headline is, and not as the real answer. 3 tasks scored 100% in every cell, so they couldn’t have shown any effect at all.

Passed every hidden scenario, by task
TaskVague, offVague, onWords, offWords, on
split-bill939393100
safe-redirect87100100100
resolve-upload100100100100
render-comment9310093100
memo-async100100100100
payment-events2733100100
next-billing100100100100
search-query10010093100

Percentages of 15 runs. Off and on mean the harness. Redder means more failures.

The hidden scenario: a late, older paid does not undo a refund
(m) => { const { p } = processor(m); p.apply(ev("2", "o", "refunded", 2)); p.apply(ev("1", "o", "paid", 1)); eq(p.status("o"), "refunded"); }
The hidden scenario: a late, older paid does not ship
(m) => { const { p, paid } = processor(m); p.apply(ev("2", "o", "refunded", 2)); p.apply(ev("1", "o", "paid", 1)); eq(paid, []); }

What the harness really changed

Final code passing strict types plus unchecked index access went from 80% to 99%. Lint went from 85% to 100%, and the average mutation score from 80% to 90%, at an average of 1.6 tries.

Those are real changes to the code, and they’re partly circular: the harness tells the agent to raise exactly those numbers, which is Goodhart’s law waiting to happen. The number nobody told the agent about, the hidden scenarios, moved 3 points, from 93% to 95%.

140 of 240 harness runs passed the gates first time, and the most any took was 4 tries. 2 ran out of tries with a type error still there, which is why types stops short of 100%. Per run, not counting the reviewer, the harness cost $0.0041 against $0.0022.

None of that makes the harness pointless. Code with stricter types and tests that notice breakage may be much easier to change next month. This experiment ends when the function is written, so it can’t see that.

What the final code did, across all 480 runs
One shot Harness on
Passes types80% to 99%
Passes lint85% to 100%
Own tests pass91% to 100%
Average mutation score80% to 90%

The gates are weak detectors here

To judge a gate as a detector, take the 240 one-shot runs, where no gate had any say in the result. 18 failed a hidden scenario, so call them broken. 222 passed them all, so call them good. Then ask what each gate would have stopped.

Base rates matter. With only 18 broken in 240, most stops are false alarms, even from a gate that works. A gate saying no at random would be right 7.5% of the time. Types managed 2% and lint 6%, which is worse than random in this sample. Tests and the neutral reviewer did best, at about 24% and 25%.

Types stopped 1 broken and 47 good, but that gate was stricter than its name, because it included noUncheckedIndexedAccess. Plain strict alone stops 0 broken and 3 good of those 48.

Lint stopped 34 good runs, and 32 of them tripped one rule, noControlCharactersInRegex, which objects to regular expressions that look for control characters, and looking for them is what a careful URL check does. Our own reference solution needs an exemption from that rule too.

Mutation isn’t independent of tests. A run whose tests fail scores zero, so the 5 broken runs it stopped are the same 5 that tests stopped. Among runs whose tests passed, it stopped 0 broken and 18 good. It’s also a coarse instrument here: the median program had 10 mutants, 120 of 459 tested programs had 5 or fewer, and 2 had none and scored zero.

All four mechanical gates together stopped 8 broken and 99 good.

A stop isn’t a diagnosis either. The broken run types stopped had a complaint about a possibly undefined value, and what it really failed was refusing empty weights. The 2 that lint stopped were flagged by noControlCharactersInRegex, and really failed on upper-case hostnames. They were right to stop for the wrong reason.

And “false alarm” only means it passed the hidden scenarios. A warning that a value may be undefined can be perfectly true. So this table says these gates were weak predictors of these scenarios on one-function tasks, and nothing wider.

What each gate stopped, of 240 one-shot runs
Broken code stopped Good code stopped
Types1 broken, 47 good
Lint2 broken, 34 good
Tests5 broken, 16 good
Mutation5 broken, 34 good
Reviewer, neutral prompt13 broken, 39 good
Reviewer, told to find a defect16 broken, 126 good
18 broken and 222 good. Saying no at random would be right 7.5% of the time.
GateBroken stoppedGood stoppedStops that were right
Types1 of 1847 of 2222%
Lint2 of 1834 of 2226%
Tests5 of 1816 of 22224%
Mutation5 of 1834 of 22213%
Reviewer, neutral prompt13 of 1839 of 22225%
Reviewer, told to find a defect16 of 18126 of 22211%

The reviewer’s prompt decides what you hear

We took one correct function and one with a real bug, and had fresh agents review each 40 times under each of two prompts. On the correct code, the neutral prompt approved 33 of 40. The prompt told to find a defect approved 1 of 40. On the bug, both rejected 40 of 40.

Some warnings about that. The prompts differ by more than one sentence, as the comparison shows, so we can’t say which words did it. And the bug was an easy one: the request shown to the reviewer says not to cache failures, and the code caches them. Note too that the neutral prompt said no 7 times to the same correct code, so a single verdict is flaky whichever prompt you use.

On real code the same pattern shows up. Over the 240 one-shot runs, the neutral prompt stopped 13 broken and 39 good. Told to find a defect, it stopped 16 and 126: 3 more catches for 87 more false alarms. In the harness-on, right-words cell, where every run passed every hidden scenario, that prompt still rejected 66 of 120.

The reviewer looks like the best detector in the table, and much of that record is one task. Without payment-events there are 7 broken runs and 203 good. The neutral prompt stops 2 and 35, and the other prompt 5 and 108.

One more oddity worth reading. The neutral reviewer approved 2 of the 3 empty files. Both times it wrote the missing code itself and then approved what it had written.

How often each prompt approved
Approved Rejected
Correct code
Neutral prompt33 of 40
Told to find a defect1 of 40
Code with a real bug
Neutral prompt0 of 40
Told to find a defect0 of 40
The neutral prompt, exactly
You are a senior engineer reviewing a change. You cannot run the code. Finish with one final line that is exactly VERDICT: APPROVE or VERDICT: REJECT.
The prompt told to find a defect, exactly
You are a senior engineer reviewing code another agent wrote. You did not write it. You cannot run it. Find a real defect if there is one, and do not approve out of politeness. Finish with one final line that is exactly VERDICT: APPROVE or VERDICT: REJECT.

Underlined words are in that prompt and not the other. The underlining is ours, and everything else is the text as sent.

Our own holdout missed a real hole

In the security chapter we went back to the recorded comment renderers with an attack added afterwards. With a vague brief, 7 of 29 produced a javascript: link. With the right words, 0 of 29. The count is 29 and not 30 because one empty file in each brief is left out.

All 7 had passed every hidden scenario. 5 of them had passed every gate as well, and the harness didn’t help: 3 came from one-shot runs and 4 from harness runs.

The attack puts a control character in front of the scheme. A hand-written check doesn’t see javascript:, and the browser’s URL parser throws the control character away. Our scenarios tried plain and mixed-case javascript:, and didn’t try this. So our own holdout missed it, and “good” on this page only means it passed the hidden scenarios. Treat every pass rate here as an upper limit.

A correction to our own wording: the exact string above doesn’t run. These renderers stop reading a link at the first closing bracket, so the script gets cut to alert(1, which is a syntax error, in all 7. Swap in a payload with no brackets, [click](\u0001javascript:alert`1`), and we get the link from the same 7 programs and 0 from the right words, and clicking it in Chromium really ran the script. So the hole is real, and the attack as recorded only shows that the link gets through. The worded brief states an allowlist of schemes and all 29 held, though this design can’t say that’s why. The wider lesson is encoding for the place the value lands.

Comment renderers that produced a javascript: link
Vague brief7 of 29
Right words0 of 29

A solid lamp is one program that produced the link. Harness on and off are counted together.

The attack, with its control character shown
[click](\u0001javascript:alert(1))
What one recorded renderer made of it
<a href="\u0001javascript:alert(1">click</a>)

What we got wrong

And how we found out. A harness on the experiment caught some of this, and looking at strange results caught the rest.

  1. Our first task set was too easy

    Claude Haiku 5.5 passed nearly everything from vague briefs on famous problems. So we replaced the tasks with trap-laden ones and kept two as controls. That’s a researcher degree of freedom, and it biases towards finding an effect: we changed the test after seeing it didn’t show what we hoped. The first set’s results aren’t in the published data, so you can’t check this one.

  2. The first reviewer prompt was biased, by us

    We wrote “find a real defect” and treated the answers as neutral. We only noticed when the results looked strange: it was rejecting 57% of good code. That’s why the reviewer test exists, and why every one-shot run was reviewed again under a neutral prompt. The neutral reviews are a later pass over the one-shot runs only, so harness-on runs have only the biased review.

  3. Our holdout had a false positive

    Our reference solution failed “a quote cannot break out of the link”, because the regular expression matched encoded quotes, which are safe. The instrument test caught it: every reference solution has to pass every scenario before a run means anything.

  4. Our workspaces slowed down our own runs

    The experiment’s temporary workspaces lived in the repo, so the dev server restarted each time one appeared, and runs slowed down. They moved outside the repo.

  5. The broken pile isn’t what it sounds like

    3 of the 18 broken runs are empty files, and 11 of 18 are payment-events. That leaves very little else. We also can’t say why the files are empty, because we didn’t save the raw replies. They cost $0.0014 to $0.0026 against a median of $0.0021, so the model probably wrote something, and our parser may have lost it. Leave them out and the one-shot figures are 88% and 99%.

  6. The worded briefs state the rules as well

    The worded payment brief doesn’t just say idempotent. It also says: “An event older than the newest one applied to that order, by at, is stale and changes nothing.” So this doesn’t isolate what the word itself does. It tests a word plus the rule that goes with it, and the rule alone might do all of the work.

  7. Some agent-written tests really hang

    3 attempts, all on memo-async, had tests that never finish. We ran them again to be sure, and each printed the test runner’s banner and then nothing until killed. They count as test failures, and 1 of them is among the good runs the tests gate stopped.

What would change our mind

About the claim

  • Tasks picked by someone with no stake, where vague briefs do as well as worded ones. Then the words claim shrinks to “sometimes”.
  • A test where the word alone adds nothing beyond stating the rule. Then the honest advice is to say the rule, and the vocabulary is only a shortcut.
  • Real repos over months, where gated work breaks as often as ungated work. Then the gates claim fails where it matters most. If gates catch much more on multi-file changes, our gate finding is just a small-task result.

A better experiment

  • Fix the tasks and the analysis in writing before any run, and publish that.
  • Have someone else sample tasks from real issues, and write the holdout too.
  • Split the brief into three arms: vague, the rule in plain words, and the word alone.
  • Use several models, a real repo, tools and multi-file changes.
  • Treat the task as the unit of analysis, with enough tasks for that to mean something.
  • Save every raw reply, and attack the results afterwards as routine.
  • Follow the code past the first version, to see whether gated code is cheaper to change.

Check it yourself

Nothing here needs taking on trust. The figures on this page are worked out from these files when it renders, and a check in the repo fails if any of them drifts.

  • main.jsonlEvery run, byte for byte what the experiment wrote: each attempt’s code, tests and gate output, the hidden results, and the first review. 5.1 MB.
  • review-neutral.jsonlThe neutral re-review of every one-shot run. 310 KB.
  • review-flake.jsonThe reviewer test: both prompts and the tallies.
  • tasks.jsonEvery task, both briefs and each hidden scenario with its source.
  • tasks.ts.txtThe same tasks as the file the experiment imported.
Reproduce the first number in the headline. This prints 105, and 105 of 120 is 88%.
curl -s https://dev.dqnotes.com/data/main.jsonl | jq -s '[.[] | select(.brief=="vague" and .harness==false) | select(.holdout.results | all(.pass))] | length'

Every task, every scenario

Figures are the share passing every hidden scenario. Open a task to see each scenario and how many runs in each cell failed it.

Split a billsplit-billVague, off: 93%Vague, on: 93%Words, off: 93%Words, on: 100%
Runs that failed each scenario, of 15 per cell.
ScenarioKindVague, offVague, onWords, offWords, on
two equal people share evenlycore0010
three people: no cent is lostcore0010
awkward weights: no cent is lostcore0010
shares are whole centscore0010
one share per personcore0010
shares are within a cent of proportionalcore0010
a zero bill is all zeroscore0010
a large bill still adds upcore0010
ties go to the earliest indextrap0010
largest remainder wins the spare centtrap0010
weight zero gets nothingtrap0010
empty weights: refusedtrap1100
negative weight: refusedtrap0000
all weights zero: refusedtrap0000
fractional total: refusedtrap0000
negative total: refusedtrap0000
Redirect after loginsafe-redirectVague, off: 87%Vague, on: 100%Words, off: 100%Words, on: 100%
Runs that failed each scenario, of 15 per cell.
ScenarioKindVague, offVague, onWords, offWords, on
a plain path is keptcore0000
a path with a query is keptcore0000
an allowed host is keptcore0000
another host is refusedcore0000
javascript: is refusedcore0000
protocol-relative is refusedcore0000
suffix lookalike is refusedcore0000
userinfo trick is refusedcore0000
allowed name in the path is refusedcore0000
backslash after the slash is refusedcore0000
data: is refusedcore0000
empty string is refusedcore0000
two backslashes are refusedtrap0000
leading whitespace is refusedtrap0000
a tab inside the slashes is refusedtrap0000
hostname case is ignoredtrap2000
scheme without slashes is refusedtrap0000
ftp is refusedtrap0000
Save an uploaded fileresolve-uploadVague, off: 100%Vague, on: 100%Words, off: 100%Words, on: 100%
Runs that failed each scenario, of 15 per cell.
ScenarioKindVague, offVague, onWords, offWords, on
a plain name lands in the foldercore0000
dots in a name are finecore0000
a trailing slash on the folder is finecore0000
dot-dot cannot climb outtrap0000
dot-dot in the middle cannot climb outtrap0000
an absolute path cannot escapetrap0000
a sibling folder with the same prefix cannot passtrap0000
a null byte cannot passtrap0000
an empty name does not return the folder itselftrap0000
a single dot does not return the folder itselftrap0000
Render a commentrender-commentVague, off: 93%Vague, on: 100%Words, off: 93%Words, on: 100%
Runs that failed each scenario, of 15 per cell.
ScenarioKindVague, offVague, onWords, offWords, on
bold workscore1010
a link workscore1010
plain words staycore1010
a script tag cannot runtrap1010
an image handler cannot runtrap1010
a javascript: link is refusedtrap1010
capitals do not hide javascript:trap1010
a data: link is refusedtrap1010
a quote cannot break out of the linktrap1010
an ampersand is encodedtrap1010
Cache an async callmemo-asyncVague, off: 100%Vague, on: 100%Words, off: 100%Words, on: 100%
Runs that failed each scenario, of 15 per cell.
ScenarioKindVague, offVague, onWords, offWords, on
a later call uses the cachecore0000
keys are kept apartcore0000
concurrent callers share one call (stampede)trap0000
a failure is not cachedtrap0000
every waiter sees the failuretrap0000
the key "constructor" workstrap0000
the key "__proto__" workstrap0000
Handle payment webhookspayment-eventsVague, off: 27%Vague, on: 33%Words, off: 100%Words, on: 100%
Runs that failed each scenario, of 15 per cell.
ScenarioKindVague, offVague, onWords, offWords, on
a paid event sets the statuscore0000
a paid event calls onPaidcore0000
a failed event sets the statuscore0000
an unknown order has no statuscore0000
a redelivered event ships only oncetrap0000
two paid events ship only oncetrap0000
a late, older paid does not undo a refundtrap111000
a late, older paid does not shiptrap81000
a late, older failure does not undo a paymenttrap0000
Work out a billing datenext-billingVague, off: 100%Vague, on: 100%Words, off: 100%Words, on: 100%
Runs that failed each scenario, of 15 per cell.
ScenarioKindVague, offVague, onWords, offWords, on
one month on, mid-monthcore0000
twelve months oncore0000
period zero is the anchorcore0000
across a year endcore0000
Jan 31 plus one is the end of Februarytrap0000
a leap year has a Feb 29trap0000
no drift: Jan 31 plus two is Mar 31trap0000
Aug 31 plus one is Sep 30trap0000
the time of day survivestrap0000
the input date is not changedtrap0000
Build a search querysearch-queryVague, off: 100%Vague, on: 100%Words, off: 93%Words, on: 100%
Runs that failed each scenario, of 15 per cell.
ScenarioKindVague, offVague, onWords, offWords, on
finds by termcore0000
no filters finds everythingcore0000
sorts by a columncore0010
respects a limitcore0000
a quote in the term is harmlesscore0000
injection through the term failstrap0000
sortBy cannot read another tabletrap0000
sortBy cannot end the statementtrap0000
a bad limit cannot reach the SQLtrap0000
a search for 50% means a literal 50%trap0000
an underscore means an underscoretrap0000
The 18 broken one-shot runs, one by one
  • Failed: empty weights: refused.

    Stopped by: Types, Reviewer, neutral prompt, Reviewer, told to find a defect.

  • An empty file: it failed every scenario.

    Stopped by: Tests, Mutation, Reviewer, told to find a defect.

  • Failed: hostname case is ignored.

    Stopped by: Lint.

  • Failed: hostname case is ignored.

    Stopped by: Lint, Reviewer, told to find a defect.

  • An empty file: it failed every scenario.

    Stopped by: Tests, Mutation, Reviewer, neutral prompt, Reviewer, told to find a defect.

  • An empty file: it failed every scenario.

    Stopped by: Tests, Mutation, Reviewer, told to find a defect.

  • Failed: a late, older paid does not undo a refund; a late, older paid does not ship.

    Stopped by: Reviewer, neutral prompt, Reviewer, told to find a defect.

  • Failed: a late, older paid does not undo a refund; a late, older paid does not ship.

    Stopped by: Tests, Mutation, Reviewer, neutral prompt, Reviewer, told to find a defect.

  • Failed: a late, older paid does not undo a refund; a late, older paid does not ship.

    Stopped by: Reviewer, neutral prompt, Reviewer, told to find a defect.

  • Failed: a late, older paid does not undo a refund; a late, older paid does not ship.

    Stopped by: Reviewer, neutral prompt, Reviewer, told to find a defect.

  • Failed: a late, older paid does not undo a refund; a late, older paid does not ship.

    Stopped by: Tests, Mutation, Reviewer, neutral prompt, Reviewer, told to find a defect.

  • Failed: a late, older paid does not undo a refund; a late, older paid does not ship.

    Stopped by: Reviewer, neutral prompt, Reviewer, told to find a defect.

  • Failed: a late, older paid does not undo a refund.

    Stopped by: Reviewer, neutral prompt, Reviewer, told to find a defect.

  • Failed: a late, older paid does not undo a refund.

    Stopped by: Reviewer, neutral prompt, Reviewer, told to find a defect.

  • Failed: a late, older paid does not undo a refund; a late, older paid does not ship.

    Stopped by: Reviewer, neutral prompt, Reviewer, told to find a defect.

  • Failed: a late, older paid does not undo a refund; a late, older paid does not ship.

    Stopped by: Reviewer, neutral prompt, Reviewer, told to find a defect.

  • Failed: a late, older paid does not undo a refund.

    Stopped by: Reviewer, neutral prompt, Reviewer, told to find a defect.

  • Failed: sorts by a column.

    Nothing stopped it.

Read the real attempts

Pick a task, a cell and a run, and read the code the model wrote and what each gate said about it, unedited. It starts on the task that decided the result.

Brief and harness
Run

A hollow red dot on a run means it failed a hidden scenario, and a solid green dot means it passed them all.

Loading the recorded runs…

The words

Everything this page leans on has its own entry in the course, with an instrument where one helps.

Brief
What the agent was told. Changing it is one side of the design.
The right word
The claim under test, and the part this design can’t isolate.
Edge case
What most trap scenarios are.
Acceptance criteria
What the worded briefs add, and the reason they aren’t a clean test of a word.
Harness
Everything around the model. Here, the loop that hands failures back.
Quality gate
A check that can say no.
Type checker
The Types gate, run with tsc.
Strict mode
Where the extra index-access flag gets confused for part of strict.
Linter
The Lint gate, run with Biome.
False positives
What most stops in the gate table turned out to be.
Mutation testing
Breaking the code on purpose to see if the tests notice.
Mutation score
The share of those breaks the tests caught. The bar here was on this.
Holdout scenario
The test the agent never saw, and what this page calls the truth, with limits.
Test oracle
What decides right from wrong. Ours had a bug, and it has a blind spot.
Flaky test
The same input with different verdicts, as with the reviewer.
Goodhart’s law
Why gate scores rising under a harness that targets them says little.
Reviewer prompt
The wording that moved approvals so far.
AI reviewer
The second agent, reading code it can’t run.
Fresh eyes
Why that second agent started a new session.
Base rate
Why a gate that stops mostly good code can still look busy.
Confidence interval
The line under each bar in the headline chart.
Honest limits
What this page tries to do at the top and not in a footnote.
Webhook
What the task that decided the result was about.
At-least-once delivery
Why the same webhook can arrive twice.
Idempotency
The word the worded payment brief used.
Cross-site scripting
What a javascript: link in a comment is.
Output encoding
The rule the worded comment brief states.
Sandbox
Where the model’s code ran, with no network.
Model tier
Why one small model is a real limit.

The workshop

Name a word, or describe what you mean in everyday language.