The Second Time Is a Bug

A field workbook for engineering with AI coding agents

Almost right is the most expensive kind of wrong

You ask your coding agent for a change. A few minutes later it reports success, the diff looks right and the summary is confident. Then you read more closely and find the one line that is wrong: a price rounded through a float, a test quietly loosened, a button that renders but cannot be seen.

In Stack Overflow's 2025 developer survey, the most common frustration with AI tools, chosen by 66% of the developers who answered that question, was solutions that come close but are not quite right (source (opens in a new tab)). You fix it by hand. A week later, in a new session, the agent makes the same mistake, and you fix it again.

This book is about the second time.

The first time a coding agent makes a mistake, it is the model's. The second time, it is a bug in your harness.

The agent starts every session with no memory of yesterday's correction, so what it should have learned has to live in the repository: as an instruction it reads, or a check it cannot get past. Often the fix is a check. Sometimes it is a clearer requirement, a smaller task, or a written decision that the guard costs more than it saves.

What fixing the harness looks like

Invoicer, the small invoicing app written for this book, stores money as integer cents. Asked to accept prices like 12.345, an agent swaps the money parser for a float. The tests still pass.

Every guard in the book comes with a drill that replays a mistake like this one. Run npm run drill D06 in the companion code and you get the real output below, offline, with no API key and no model.

The change. A small diff, easy to approve at a glance.
-      unitPriceCents: parseCents(price),
+      // Accept any price the form sends, like 12.345,
+      // instead of rejecting it.
+      unitPriceCents: Math.round(parseFloat(price) * 100),
- unitPriceCents: parseCents(price),
+ // Accept any price the form sends,
+ // like 12.345, instead of
+ // rejecting it.
+ unitPriceCents: Math.round(
+   parseFloat(price) * 100),
The guard. It names the line, the reason and the fix (rewrapped to fit a phone screen).
$ node guards/no-float-money.ts
no-float-money: FAILED, 1 problem
  - app/src/http/invoice-routes.ts:160: parseFloat() turns a
    money amount into a float.
      unitPriceCents: Math.round(parseFloat(price) * 100),
    Fix: money in Invoicer is integer cents. Parse text with
      parseCents(), format with formatCents() and compute tax
      with taxCents(), all in app/src/domain/money.ts. Do not
      round floats.
$ node guards/no-float-money.ts
no-float-money: FAILED, 1 problem
  - app/src/http/invoice-routes.ts:160:
    parseFloat() turns a money amount
    into a float.
      unitPriceCents: Math.round(
        parseFloat(price) * 100),
    Fix: money in Invoicer is integer
      cents. Parse text with
      parseCents(), format with
      formatCents() and compute tax
      with taxCents(), all in
      app/src/domain/money.ts. Do not
      round floats.

One method, applied thirteen times

The first time a mistake happens, fix it and write it down. The second time, treat it as a bug in your harness.

  1. Find the cause in your harness

    Not in the model. Ask where your knowledge lived that the agent could not reach: your head, a review comment, a chat that ended.

  2. Choose a control

    A guide steers the agent before it acts. A sensor checks its work afterwards.

  3. Place it early

    As early as it can run cheaply: at edit, commit, build, deploy or against the live system.

  4. Prove it works

    Plant the mistake on purpose and watch the guard refuse it. A guard you have never seen fail is a guess.

  5. Write down when to delete it

    Guards encode assumptions about models, and those assumptions expire.

Some mistakes you cannot afford even once: a destructive command, a leaked secret, a migration with no way back. Those are guarded before they happen.

Every technique fits on one card

34 pattern cards, each with the same seven fields, so you can compare a test ratchet with a permissions rule at a glance and see what each one costs to keep. They also come as a printable deck, in A4 and US Letter.

Write error messages for the agent

P11
Symptom
A check fires, and the agent makes the smallest edit that silences it (Number() for parseFloat()), or retries variations until something passes.
Drill
D06
Guard
Every file-scanning guard reports file and line, the offending code, the reason in one clause, and a Fix: line naming the replacement and the wrong exit to avoid.
Proof
Apply the D06 patch in a scratch copy; the guard exits 1 and its message names the right money helpers.
Placement
edit and commit
Kind
sensor; computational (its message works as a guide)
Retire when
Amounts are a branded Cents type the compiler enforces and the guard has not fired for 90 days.

Twenty-six mistakes you can replay

Each drill replays one agent mistake against the companion code, next to the guard that stops it. A few of them:

  • A rounding test fails, so the agent deletes it.D09
  • It marks a failing test with test.skip.D10
  • It reports done without running the tests again.D12
  • A new style hides the Send invoice button. The unit tests still pass.D13
  • It proposes rm -rf app/src/db to start the schema from scratch.D17
  • It pastes a live API key into the source.D18
  • It adds a package that does not exist.D20
  • It tidies legacy code and changes totals customers reconcile against.D22

What you get

Cover of The Second Time Is a Bug: a looping arrow stopped by a short red bar, above the title and the author's name.
  • The book, 236 pages with 35 diagrams, as PDF and EPUB. Thirteen chapters in six parts, each ending with a checklist for your own repository.
  • 34 pattern cards, in the book and as a printable deck.
  • 26 drills that run offline against the companion code.
  • The companion code, public and MIT licensed: a small invoicing app, a deliberately tangled legacy exporter, every guard, a toy agent loop, an experiment kit and starter templates. TypeScript on Node.js, with zero runtime dependencies.

The book is built from guards, not tool features. A guard is a small script with an exit code, so it works with whichever coding agent you use, with git hooks and with any CI system.

Contents

Part 1. The Loop

  1. Two Harnesses
  2. The Second Time Is a Bug

Part 2. Guides

  1. Instruction Files That Stay Small
  2. Keeping Context Clean

Part 3. Sensors

  1. Gates That Say No
  2. Tests the Agent Cannot Game
  3. Behaviour You Can See

Part 4. Blast Radius

  1. Permissions and Credentials
  2. The Supply Chain You Did Not Choose

Part 5. Scaling the Loop

  1. Legacy Code
  2. Loops Beyond One Session

Part 6. Economics

  1. Does the Harness Pay?
  2. Retiring Guards

Appendices: Pattern Card Index, Templates, Wiring Guards into Today's Tools, Further Reading.

Who it is for

Written for

  • Engineers and tech leads who use a coding agent every day and lose time to output that is almost right.
  • Solo builders shipping real products with an agent as their main pair.
  • Anyone responsible for letting agents work in a shared codebase.

Not written for

  • Readers new to AI or to prompting.
  • Readers who want a manual for one tool. The book is deliberately tool-agnostic.
  • Anyone hoping for a productivity figure. The book shows you how to measure your own loop instead.

You need a terminal, Node.js 22.18 or later, git, and some patience with small scripts.

Questions

What is harness engineering?

Engineering everything around a coding agent so that its work can be trusted: the instructions it reads, the checks it cannot get past, and where in your workflow those checks run. The vendor's runtime loop is the agent harness. This book is about the harness you build around it.

What does "the second time is a bug" mean?

The first time a coding agent makes a mistake, it is the model's. The second time, it is a bug in your harness: what you learned the first time never reached the agent. A repeat says where to look. The fix is often a check, and sometimes a clearer requirement, a smaller task, or a written decision that a guard would cost more than it saves.

Which coding agents does it work with?

Any agent that can run a command. Every guard in the book is a small script that reads files, prints a message and sets an exit code, so it also works with git hooks and any CI system. A dated appendix shows the wiring for Claude Code, OpenAI Codex CLI, Cursor, GitHub Copilot and Gemini CLI.

Do the drills need an API key or a paid AI subscription?

No. The 26 drills replay agent mistakes from recorded patches and scripted turns, so they run offline, with no model and no API key, and give the same result every time.

What do I need to follow along?

A terminal, git and Node.js 22.18 or later. The companion code is TypeScript with zero runtime dependencies. Two browser drills also need Playwright's Chromium, downloaded once.

My team does not write TypeScript. Is it still useful?

Yes. The method and the 34 pattern cards are language-neutral: deleted tests, hollow assertions, destructive commands, phantom packages and oversized diffs look the same in any language. You translate the guards rather than copy them; each one is short.

Is the companion code free?

Yes. It is public on GitHub under the MIT licence: a small invoicing app, a legacy exporter, every guard, all 26 drills, a toy agent loop, an experiment kit and starter templates.

What formats does the book come in?

PDF (236 pages, 6 x 9 inches, with 35 diagrams) and EPUB, plus the printable pattern card deck in A4 and US Letter. There is no print edition.

Will it make me faster?

The book does not promise a speed-up. The published evidence on productivity is mixed, so it shows you how to measure your own loop instead, with an experiment kit to do it.

About the author

Rakesh Menon is the co-founder and product lead at Seerly and a software architect with fifteen years of experience building and scaling web platforms. Previously, he held senior engineering roles at Atlassian, A.P. Moller Maersk, and Publicis Sapient, working across frontend architecture, shared platforms, and engineering practices.

Today, he builds with AI coding agents as part of his everyday work. The Second Time Is a Bug draws on his experience to explore a simple engineering principle: the goal is not to prevent every mistake, but to build systems that stop the same mistake from happening twice.

Fix it once. Then make it stay fixed.