DEV Community

Cover image for My AI Said "Fixed" Three Times. It Was Wrong Three Times.
Seiji Nakaya
Seiji Nakaya

Posted on • Originally published at vibsync.com

My AI Said "Fixed" Three Times. It Was Wrong Three Times.

I nearly shipped three broken fixes in a row because an AI told me they were done and I wanted to believe it. What stopped me was not a better model — it was a second agent that was not allowed to have an opinion until it had run the code. Here is what that loop caught.

“Fixed,” the AI said.

I believed it until another AI wrote a five-line check, ran it, and showed me the same failure.

Then it happened again. And again.

This was not a toy prompt or an interview puzzle. I was trying to finish a feature on the read path of a product we were preparing to release. The code looked plausible. The explanation sounded complete. The tests the author could run were green. I wanted the answer to be true.

It was still wrong.

What finally changed my mind was not a smarter model or a more elaborate prompt. It was a second agent with a separate checkout, permission to distrust the first one, and one rule: do not accept “fixed” without reproducing the failure.

I was the person who wanted to believe it

I run LOOSEDAYS, the company building Vibsync. In this project, Claude Code usually writes a change and Codex reviews it. I decide what matters, settle disagreements, and own the merge.

That sounds disciplined when written after the fact. In the moment, I was a founder trying to get a release out. Every review round added delay. Every “fixed” message offered a reason to move on.

The pull request was meant to solve a real trust problem: a shared note may have been true when it was written and wrong by the time another agent reads it. We wanted each retrieved note to show when it was recorded and the current status of any task or question it mentioned.

The idea was small. The review was not. Across seven rounds, the reviewer raised ten blocking findings.

Three of them were the same humanly familiar mistake in different places: we fixed the decision in one layer and forgot another layer that consumed it.

  • Two retrieval paths used the new annotation; the fresh-session handoff path did not.
  • A shared failure path was corrected; another route bypassed it and kept the old behavior.
  • The analyzer correctly decided which reference mattered; the renderer threw that answer away and re-created the old, wrong one.

After each change, the author could point to code that was now correct. After each change, the product still had a path where the old behavior survived.

That is why “I changed the right function” is not evidence that a bug is fixed.

The reviewer did not read the code better

All ten blocking findings came from running something.

The reviewer pulled the exact commit into a separate checkout, ran the full suite, and then tried realistic inputs around the claimed fix. It also had access to tests the author's environment could not run. That difference between environments turned out to be useful, not inconvenient.

The author knew what the code was intended to do. The reviewer only saw what it did.

That distance mattered more than model intelligence. An author reads an implementation through the story in its own head: this helper is now the source of truth; this condition handles the edge case; this renderer only displays the result. A reviewer can ask the less flattering question: Which route did you not run?

The reviewer also caught the pull request moving after an earlier approval. It did not treat “approved once” as a permanent property of the branch. It pinned the decision to a commit and reviewed the new head again.

The hardest round ended with less code, not a better patch. We had tried to warn when an old note called a finished task “pending.” After four versions, the detector still misread “Task 42 processes pending jobs”: the jobs were pending, not the task. That was a grammar problem, not a word-list problem. The author proposed another fix; the reviewer proposed removing the semantic guess and keeping only reliable evidence—the note's date and the task's current status. We deleted the clever part. Sometimes a second agent's best contribution is making less code survive.

The rule that changed the loop

The early rounds were noisy because the author answered findings too quickly. “I see it” quietly became “fixed.” Reading the report felt close enough to reproducing it.

It is not close enough.

The rule that stopped this was simple:

Before changing the code, reproduce the reviewer's exact failure. After changing it, run the same case again.

That turns a review comment from an opinion into a before-and-after observation. It also prevents a polite but expensive failure mode: two agents debating what the code should do while neither has checked what it does.

The protocol we use now

You do not need Vibsync to try this. You need two agents that can work independently, a branch, and a durable place for the evidence.

THE “FIXED” GATE

Author
1. Show the exact failing input and its output before the change.
2. Make the change. Show the same input passing afterward.
3. State what your environment could not verify.
4. If the branch changes after approval, say so explicitly.

Reviewer
5. Review a commit, not “the latest branch.” Record its SHA.
6. Re-run the reported failure in a separate checkout.
7. Add at least one adjacent, realistic case the author did not choose.
8. Run the broadest suite your environment allows; report the numbers.
9. Separate blocking behavior from non-blocking preference.

Human owner
10. Decide whether the risk justifies another round, and own the merge.
Enter fullscreen mode Exit fullscreen mode

The protocol is intentionally biased toward evidence. “Looks good,” “makes sense,” and “I updated the helper” are not evidence. A failing case that becomes a passing case is.

What this does not prove

This is one team, one codebase, and roughly one month of working this way. It is not a benchmark, and I am not claiming that two agents are always better than one.

The loop is slower than accepting the first plausible answer. For a copy edit or a reversible experiment, the extra round may be waste. For a change that sits on an authentication boundary, a data migration, or a read path people will trust, the cost looks different.

It also does not remove human responsibility. The agents can generate, challenge, and test. I still decide which risks deserve the loop, when to stop, and whether to merge.

The lesson is narrower: do not use a second AI as another voter. Use it as an independent source of friction. Give it a different checkout, different constraints where possible, the authority to block, and a requirement to bring executable evidence.

Why the record has to outlive the session

By round seven, no single context window held the whole argument. The useful artifact was not the agents' conversation; it was the written trail of findings, reproductions, decisions, and exact commits.

That is where Vibsync enters the story. Vibsync is the shared brain we build at LOOSEDAYS for AI coding teams. Claude Code and Codex used it to leave review findings and decisions for each other across sessions and machines. The agents did not need to be awake together or share one context window. Each round started from the same durable record instead of a summary reconstructed from memory.

The product did not make either model smarter. It made the disagreement survive long enough to be useful.

You can run the protocol above with a shared document today. If you want different agents to inherit the same decisions, open questions, and review trail automatically, connect them to the same Vibsync team.

Vibsync is built by LOOSEDAYS Co., Ltd. This is a first-hand account of one pre-release pull request, not a controlled comparison.

Originally published at https://vibsync.com/blog/ai-said-fixed-three-times.

Top comments (0)