Skip to content
How it worksVerificationAgentsBenchmarkBlogBlogReleasesReleasesStar

Deterministic replay and fix verification for journal-driven services.

Product

How it worksFix verificationFor coding agentsAgent benchmarkPerformanceRelease notes

Developers

SourceAgent skillsJournal formatAgent guidellms.txtContributing

Blog

All postsGuidesConceptsProductEngineeringRSS

Project

LicenseDCOReport a bugContact

Install Kavach CLI & Agent Skills

curl -fsSL https://www.thekavachlabs.com/install.sh | shnpx skills add kavachlabs/kavach
© 2026 Kavach LabsPre-alpha. Apache 2.0.
kavach
Blog/Engineering/Deterministic Verification

Why Coding Agents Write Narrow Fixes (And Why Logs Won't Save Them)

This post is about why coding agents write narrow patches that only fix one crash trace, and how replaying 56 variants catches those patches in milliseconds.

KC

Koustav Chowdhury

FounderOctober 16, 20264 min read

Before I introduce variant verification, let me tell you who I am and why we built this. I have worked in financial industry for about half-a-decade, and when I recently build HFT infrastructure from scratch, we never merged a bug fix without replaying recorded traffic variations against it first. While building that, I found certain patterns that are helpful for me, and also helpful for agents, to debug faster, to reproduce the issue exactly, and to verify the fixes.

Variant verification12 is about replaying the event variations which govern transitions in your state machine. What is a narrow fix, you may ask? A narrow fix is a software's incomplete patch which determines whether only the recorded crash passes while sibling events still fail.

Why does a variant check help to catch narrow fixes faster? Whenever we are stuck reviewing a bug fix pull request by looking at unit tests that the agent wrote itself, a simple variant check lays out in bare bones the events that took place, which caused the software to fail on sibling inputs. Let's say you have a bank account. Your bank account is a summation of all the credits and debits of your money. Now imagine one day you go up to your bank, and it says that you have 10 dollars. When you checked last night, you had 100k. So you will demand the transaction ledger for this, right? You are not ready to accept a green unit test when a deposit patch still leaves transfers broken.

{"id": "evt-008", "type": "deposit", "account": "bob", "amount": null}
if event.Type == "deposit" && event.Amount == nil {
    env.Emit("ledger.rejections", Rejection{Event: event.ID, Reason: "missing amount"})
    return nil
}
Why single-trace reproduction lets coding agents ship narrow fixes. The top lane shows that without variant verification, an Incident at seq 31 (deposit: amount=null) leads the agent to write a narrow guard (if type=="deposit" && nil), which merges and crashes in production tomorrow on transfer: amount=null. The bottom lane shows kavach mcp running 56 incident perturbations and 48 neighbour regressions in 5.9 ms, rejecting the narrow patch with variant_failed(6)@22 (deposit to transfer), forcing the agent to guard all events until verdict: fixed (47/47 variants pass).
Single-trace reproduction rewards narrow patches; variant perturbation rejects them

A variant verifier is kind of like that. It has a transactional ledger which keeps account of all the state changes, all the event variations that lead up to the same crash. In a way, it makes the generality of a bug fix auditable.

Now, since I have worked in the finance industry, I see its applications everywhere. It helps to catch narrow patches, to actually see what variations break the fix, and so on.

Key invariantWhat counts as a verified fix in Kavach (SPEC.md §6.1)

A candidate build only receives the verdict fixed when:

  1. The recorded failure is gone and all declared invariants hold after every step.
  2. Every step before the failing input produces the exact outputs production saw (no collateral behaviour changes).
  3. The build passes at least 10 reproducing incident variants—perturbed copies of the journal on which the old build still fails the same way.
  4. The build matches the old build's outputs across up to 48 neighbour regression variants—mutations of earlier valid inputs that resemble the failing one.
Interactive fix verification across the ledger crash variants: toggle between the narrow deposit-only patch and the general patch.

Why deterministic variants matter#

Starting from a snapshot, if you keep replaying the variations that are in the journal, your fix should hold on every step. That's the ultimate goal for Kavach34. What makes it challenging are certain shortcuts sprinkled through agent patches. Shortcuts come from hardcoding an event ID. They can come from guarding only one branch. They can come from the fact that the agent is rejecting valid inputs too.

Having the ability to replay 56 variations deterministically in milliseconds is one of the key guarantees of our verifier, and that is what makes the agent loop so reliable.

Spike pitWhy incident variants alone aren't enough: the "drop everything" cheat

What if an agent fixes a crash by rejecting every deposit—valid or invalid? Every incident variant will stop crashing! That is why kavach diff also generates up to 48 regression variants (--regressions 48): it takes earlier inputs in the journal that succeeded on the old build and resemble the failing input, perturbs them, and verifies that --new produces the exact same outputs as --old. If an over-broad fix breaks valid traffic, kavach diff rejects it with regressed(K)@N.

Challenges of verifying agent bug fixes#

These challenges all come down to how agents optimize for a passing test. Verifying an agent's patch has several such traps.

Guarding only one branch. Can a single replay catch a narrow patch? Catch every missing guard? How does it know what happens on a transfer? Which other branches share the same bug? If these variations aren't tested, the same bug will crash production the next day on a different event type. As a company, Kavach Labs is going to tackle these challenges so that narrow fixes get rejected automatically.

Ten Planted Bugs Benchmark (bench/bugs.go) — go test ./bench -run TestBenchmark -v
# Planted Bug Tempting Narrow Fix Verdict
1 Nil pointer on missing email Guard signup only, leave profile_update unguarded variant_failed
2 Slice index on empty items Guard checkout only, leave quote unguarded variant_failed
3 Division by zero on metric window Guard only the recorded metric name variant_failed
4 Write to uninitialized nil map Init map only when step 0 is init variant_failed
5 Type assertion panic on string qty Validate qty type but forget price variant_failed
6 Group booking exceeds capacity Check capacity on reserve but not extend variant_failed
7 Update delivered before create Buffer only for the recorded customer ID variant_failed
8 Redelivered charge applied twice Deduplicate only back-to-back duplicates variant_failed
9 Leap-day array index on day 366 Special-case the exact recorded timestamp variant_failed
10 Modulo zero on empty lottery pool Refill pool only at the recorded draw count variant_failed

Variations that don't reproduce the bug. Software often behaves differently when you change a field value. Say you design a check that replaces a missing amount with 5,000 dollars. How do you score that test without running it on the old build first? With 5,000 dollars the old build works fine, so on replay you are testing a happy path and not the crash.

Patches that break valid traffic. One system requirement for a good fix is that earlier valid events should produce the exact same outputs as before. Most careful human patches follow this principle, but quite a few chunks of agent code still don't. How do you catch those? These are the uncomfortable parts of the system that we want to tackle.

claude mcp add kavach -- kavach mcp
npx skills add kavachlabs/kavach

We're building Kavach Labs to tackle this problem head-on. We love deterministic verification as an architectural concept, and we want agentic software to be written and deployed so that it's easy to capture a bug, replay it, fix the code, and deploy the fix with more confidence.

References

  1. ArticleYour agent can now ship reliable distributed systemsantithesis.com↩
  2. ArticleDid you get lucky or unlucky?antithesis.com↩
  3. DocsKavach Agent Loop & Verdict Specification (AGENTS.md)github.com↩
  4. CodeKavach Ten Planted Bugs Benchmarkgithub.com↩
Series · Part 3 of 6

Deterministic Verification

  1. 1Event Sourcing
  2. 281.2 Nanoseconds: Designing an Always-On Production Flight Recorder
  3. 3Why Coding Agents Write Narrow Fixes (And Why Logs Won't Save Them)
  4. 4The Hidden Tests Pass. The Contract Doesn't.
  5. 5What Invariants Should My Service Have?
  6. 6How to Read a Kavach Strip Chart
← Part 2Part 4 →
  • coding agents
  • mcp
  • verification
  • replay

On this page

  1. Why deterministic variants matter
  2. Challenges of verifying agent bug fixes

Quick links

  • 1Your agent can now ship reliable distributed systems
  • 2Did you get lucky or unlucky?
  • 3Kavach Agent Loop & Verdict Specification (AGENTS.md)
  • 4Kavach Ten Planted Bugs Benchmark
Ask ChatGPTAsk ClaudeStar on GitHub

Keep reading

  • 81.2 Nanoseconds: Designing an Always-On Production Flight RecorderEngineering4 minOct 14, 2026
  • What Invariants Should My Service Have?Guides4 minOct 19, 2026
  • How to Read a Kavach Strip ChartGuides4 minOct 19, 2026