DEV Community

Quinn Wang
Quinn Wang

Posted on

Minute One Should Fail On Purpose

The first fifteen minutes of an AI coding session are a compile test, not a personality quiz. If the working tree cannot fail a tiny assertion, you have been chatting instead of onboarding. I treat that red test as the only welcome screen that still tells me the truth. Would you trust a kitchen that never burns a piece of toast on purpose during setup?

Here is the usual first quarter hour, and it still makes me restless every time I watch it. You open a shiny assistant, you pick a model you cannot explain, and you paste a repo path. The assistant writes a README that already sounds finished, while your compiler has not spoken a word. Does that sequence feel like engineering to you, or more like a hotel lobby with expensive lighting?

I call that stretch the courtesy corridor, because everyone is polite and almost nothing can break. The agent apologizes, restates your goal, and then offers three architecture options that all sound plausible. You nod along, because nodding is cheaper than wiring a test runner in a scratch folder. Meanwhile the clock eats the only window when you still remember what "done" was supposed to mean.

The one fix that actually stuck for me is embarrassingly small, which is why I ignored it for months. Before any chat message, I plant a failing Node test in a disposable directory and refuse to continue until it prints red. That single constraint turns the assistant from a roommate with opinions into a worker with a ticket. Can a model still hallucinate after that planted failure, or does the lie at least have to compile now?

The workflow below is a recipe I keep as a script, not a benchmark study with timings I cannot defend. You should treat the commands as copy-pasteable, and you should treat my tone as opinion rather than lab data. I have not named models, quotas, or hardware because I do not have numbers I can stand behind today. Does that make the ritual weaker in a blog sense, or does it keep the planted failure honest?

I keep the whole ritual in one script so I cannot bargain with myself at eight a.m. The script creates a scratch directory, writes a broken add module, and runs Node's built-in test runner. It then stamps a receipt file so later-me can see whether the agent quietly deleted the evidence. If the test ever passes before the agent has worked, the script treats that as contamination and exits.

#!/usr/bin/env bash
# fifteen.sh — proposed onboarding gate, not a captured benchmark.
set -euo pipefail

ROOT="$(mktemp -d /tmp/fifteen-XXXXXX)"
cd "$ROOT"
echo "scratch=$ROOT"

cat > package.json <<'JSON'
{
  "name": "fifteen-scratch",
  "private": true,
  "type": "module",
  "scripts": {
    "test": "node --test"
  }
}
JSON

cat > add.js <<'JS'
export function add(a, b) {
  throw new Error("not implemented on purpose");
}
JS

cat > add.test.js <<'JS'
import { test } from "node:test";
import assert from "node:assert/strict";
import { add } from "./add.js";

test("add returns the sum of two integers", () => {
  assert.equal(add(2, 3), 5);
});
JS

set +e
npm test > test-before.log 2>&1
STATUS=$?
set -e

if [[ $STATUS -eq 0 ]]; then
  echo "refusing to start: the planted test already passed" >&2
  exit 2
fi

{
  echo "scratch=$ROOT"
  echo "when=$(date -u +%Y-%m-%dT%H:%M:%SZ)"
  echo "node=$(node -v)"
  echo "test_status_before=$STATUS"
  echo "uname=$(uname -s)"
} > RECEIPT.txt

echo "red test recorded; receipt at $ROOT/RECEIPT.txt"
echo "only now may an agent edit add.js"
exit 0
Enter fullscreen mode Exit fullscreen mode

You can start it with two commands, and you should stop if either one argues with you. The shebang expects bash, and the test runner expects a reasonably current Node that still ships node:test. I label this as a proposed local run, not a captured session from a specific date. If chmod is blocked on that box, the developer experience problem is already bigger than the model.

chmod +x fifteen.sh
./fifteen.sh
Enter fullscreen mode Exit fullscreen mode

Notice what this onboarding script refuses to do, because those refusals are the actual developer experience. It does not open a browser, it does not ask which model you like, and it does not generate a tutorial. It only asks whether this machine can run node --test and whether failure is still possible. If that question takes more than a minute, your tooling is the story, not the model.

I want the receipt to be boring on purpose, like a parking stub you keep in a jacket. Timestamp, Node version, and the failing status are enough to catch a rewrite that pretends the test was always green. An agent that deletes RECEIPT.txt has already told you something blunt and important about its manners. Would you keep a contractor who throws away the work order after the first site walkthrough?

When I need a box I can abandon without a billing argument, I reach for MonkeyCode's free model access and free server option. Disclosure: This article was prepared as part of MonkeyCode's product outreach, which is the only affiliation I am stating here. The point is not a leaderboard; the point is that a scratch machine should be cheap enough to throw away after the red test. If the server cannot run the script above, I stop talking to the model and I fix the box.

That is the whole first-fifteen teardown, compressed into one sentence you can tape above a monitor. Friction is rarely the chat quality; friction is the missing failure that would have proven the path. I paste a single instruction after the script succeeds, and I do not add architecture questions until the assertion flips. The instruction looks like the block below, and I keep it as boring as the receipt.

You are in a throwaway Node module. Do not edit RECEIPT.txt.
Read add.js, add.test.js, and test-before.log.
Change add.js until `npm test` exits 0.
Do not add dependencies. Do not rewrite the test name.
When you finish, print the new npm test output and cat RECEIPT.txt.
Enter fullscreen mode Exit fullscreen mode

If the agent starts scaffolding a monorepo, I treat that as a failed onboarding, not a creative flourish. The ticket was addition, the compiler is Node, and the clock is still inside fifteen minutes. I am not scoring eloquence; I am scoring whether the working tree can move from planted red to honest green. Does your current setup even let you see that delta without opening five extra browser tabs?

An honest green for this ticket is allowed to be ugly, and I show one only so nobody invents a framework. The proposed module below is not production code; it is the smallest function that should satisfy the planted assertion. If your agent writes fifty lines around this tiny function, the onboarding has already drifted off the ticket.

export function add(a, b) {
  return a + b;
}
Enter fullscreen mode Exit fullscreen mode

After a pass I read three files in order, because order keeps me honest when the prose gets charming. test-before.log should still show the original throw, add.js should return a number, and RECEIPT.txt should be byte-identical to the stamp. Then I run npm test myself in the same directory, which is the part people skip when the screenshot looks fine. A model that cannot survive a second human run of the same command is simply not done.

# proposed checks after the agent claims victory
test -f RECEIPT.txt
grep -q "test_status_before=" RECEIPT.txt
npm test
node --input-type=module -e "import { add } from './add.js'; if (add(2, 3) !== 5) process.exit(1)"
Enter fullscreen mode Exit fullscreen mode

There is a limitation hiding inside this niceness, and I should say it before anyone copies the script into a real app. The harness proves that a runtime exists and that an agent can satisfy one assertion, not that the model understands your production domain. Free model access and a free server can be slower than a paid desk, and I am not claiming quotas or uptime. If you need confidential customer data, regulated logs, or a guaranteed SLA, this scratch path is the wrong door.

Anyone who cannot isolate secrets from tmp should skip this ritual, along with anyone hoping the first session will design their company. It also wastes time if you already have a red CI job on a branch you trust. I would not run it against a repo with deploy keys sitting in the same tree. I also would not let the agent helpfully paste that receipt into some random public gist.

The analogy I keep coming back to is a fire alarm, not a demo kitchen with perfect lighting. You do not praise the alarm for its voice; you praise it for screaming when smoke is still small. A first session that cannot fail is a building with the alarm disabled so guests feel calm. Why would we onboard coding agents that way, then act surprised when the fifteenth minute is only vibes?

I am not arguing that chat is useless, and I am not arguing that models cannot write real software. I am arguing that developer experience in the first quarter hour is a gate, and gates need a state that can go red. Plant the failure, stamp the receipt, and then let the free box do that disposable work. If you try the script on a throwaway box, tell me whether the receipt survived the first reply.

Disclosure: This article was prepared as part of MonkeyCode's product outreach.

Top comments (0)