# The AI thinks, the gate decides — how I made LLM code edits deterministic (and cut token usage 42 )

> Source: <https://dev.to/sergiocorruchaga/the-ai-thinks-the-gate-decides-how-i-made-llm-code-edits-deterministic-and-cut-token-usage-42x-5cbi>
> Published: 2026-09-10 21:18:28+00:00

title: "The AI thinks, the gate decides — how I made LLM code edits deterministic (and cut token usage 42×)"

published: true

**Sergi Corruchaga · September 2026 · D-Engine v0.2.2 (MIT, open source)**

On September 10, 2026, I ran the same programming task three times, with the same model (DeepSeek V4.1-Flash), the same literal prompt, and the same repository:

*"En utils.ts, añade una función formatDate que reciba un Date y devuelva DD/MM/YYYY"*

(Add a formatDate function to utils.ts that takes a Date and returns DD/MM/YYYY)

All three runs produced functionally the same code. Here's what each one cost:

| Tool | Architecture | Tokens consumed | Time | 
|---|---|---|---|
| **D-Engine** (my harness) | Deterministic pipeline | **2,552** | ~4 s | 
| dsh — Minimal mode | Agent (single tool: shell) | 34,600 | 1m 04s | 
| dsh — effort Off | Full agent, no thinking | 37,100 | 6 s | 
| dsh — factory defaults | Full agent, thinking High | 107,000 | 28 s | 

DeepSeek's official agent burned **42× more tokens** than my tool to produce the same diff. And as you'll see in the controls section, that gap is explained neither by the model, nor by "thinking mode", nor by the agent's toolbox. It's explained by the architecture.

This article covers how I got here: what D-Engine is, how I ran the full benchmark (10 tasks, 5 contenders, 2 deliberate traps), what agents do *better* than my tool (quite a few things, and I'm going to disclose all of them), and why I believe the future of AI-assisted programming isn't a smarter agent — it's a stricter gate.

The dominant AI coding tools (OpenCode, Aider, dsh, Claude Code…) all follow the same pattern: the **agentic loop**. The model receives your request, decides to call a tool (`read file`, `search`, `run shell`), gets the result, decides another call, and so on until done.

The commonly overlooked detail: **the model has no memory between calls**. On every turn of the loop, the harness re-sends the full system prompt, all tool definitions, and *the entire conversation trajectory so far*. If the agent takes 20 steps, step 20 re-sends the previous 19. Cost grows quadratically with the agent's diligence — not with your task's difficulty.

Measured in my benchmark: the same task, in the same repo, with the same model, cost dsh between **32K and 214K tokens** depending on how many loop turns it decided to take. A 6.6× variance the user neither controls nor can predict.

There's a second, subtler problem: **state drift**. The agent works from the "snapshot" of the code it has been reading during the session. If that snapshot goes stale — or the model misremembers it — it will edit something that doesn't exist. Or worse: it will *believe* it sees things that don't exist. In section 6 I describe how dsh reported a corrupted file that was perfectly healthy, complete with fabricated line-level evidence.

The third problem is **atomicity**: most agents write directly to your working tree. If the change breaks compilation, your main branch is already broken. Some will even auto-commit the disaster.

D-Engine is built on a radical separation of responsibilities:

`SEARCH/REPLACE` blocks — patches anchored to existing code.`tsc --noEmit`, and A typical task consumes exactly **2 LLM calls**:

Everything else is local code: the `LocalEditor` applies each patch through a 4-strategy cascade (exact match → newline normalization → ignore trailing whitespace → fuzzy at 0.85 threshold), the compiler validates, and `commitAndMerge` stages *only* the files touched by the patch (with a `git status --porcelain` guard that aborts the merge if any foreign file appears, logging the offender's diff before destroying the photocopy).

There's also a **Verify** mode adding an optional second phase: send *only the modified snippet* for a semantic audit (the model answers `OK` / `OK_WITH_OBSERVATIONS` / `FAIL`). Measured cost: 330–984 tokens per task — 15–30% on top of the proposal. Nearly free semantic safety, on the programmer's demand.

The project's motto sums up the philosophy: **the AI thinks, the gate decides**. The model can propose whatever it wants; the only source of truth in the system is the compiler.

`bench-repo`, a TypeScript mini-shop (products, cart, pricing, utilities), frozen at the `benchmark-base` tag.`git reset --hard benchmark-base` + `git clean -fd` before every run, engine frozen during the benchmark.
Before the results, two confessions. First: two tasks (T3 and T5) turned out to be defective in their first round — the repo already contained what they asked for; the voided rows are preserved in the record as evidence, and the base was fixed. Second: the literal prompts typed in the first round were not preserved (the `git clean -fd` cycles wiped Aider's histories, and my own record document stored summaries instead of the actual texts). The original specifications were recovered from the design conversation, prompts were **frozen** in the record on 2026-09-10, and every later execution uses them verbatim. T1 shares an attested literal prompt across all eras — it is the comparability anchor.

None of this is glamorous. That's exactly why it's in the article.

| Contender | Points (max 50) | Incidents | 
|---|---|---|
| OpenCode | 49/50 | 4 on trap T9 | 
| **D-Engine Fast** | **48/50** | 4 on T9 | 
| dsh (factory) | 48/50 | 4 on T7 (unrequested API added), 4 on T9; 1 hallucination | 
| Aider | 47/50 | 4 on T7, 4 on T9; **committed a main branch that didn't compile (T2)** | 
| D-Engine Verify | 46/50 | 4 on T7, 4 on T9; false rejection on T6 (parsing bug, since fixed) | 

Nobody crushed anybody on quality. With the same model, the "textbook" solution converges — on three tasks, three different contenders produced **byte-identical** files. What differentiates the tools isn't the answer: it's the machinery around the model.

| Contender | Tokens per task (avg) | vs D-Engine Fast | 
|---|---|---|
| D-Engine Fast | ~2,100 | 1× | 
| Aider | ~2,100 | ~1× | 
| D-Engine Verify | ~2,600 | ~1.2× | 
| OpenCode | ~9,700 | ~4–5× | 
| **dsh** | **~93,000 (range 32K–214K)** | **~44×** | 

(Aider deserves a fair note: it's by far the leanest agent, because it only passes the files you tell it to. Its problem wasn't cost — it was the gate. Keep reading.)

The full dsh round consumed **~931K tokens** versus D-Engine Fast's ~21K for the same task set and equivalent results.

Fast ~2.7s · Verify ~3.7s · Aider ~4.9s · OpenCode ~14.9s · **dsh ~38s** (wall clock; its own UI reports ~20s — the gap between both measures, 9 to 66 seconds per task, is startup and latency time the agent doesn't account for).

Task T2 asked to rename a constant across two files. Aider **warned** it was missing context ("I don't have them in the chat. Let me know if you want me to review them")… and then **auto-committed a main branch that didn't compile anyway** (TS2305). Without a compile gate, AI can break your repo *while knowing it's breaking it*.

D-Engine, on the same task, rejected its own first attempt: the patch compiled in the photocopy but broke `index.ts` — the gate caught it, the merge never happened, and main stayed intact. Failing safe isn't a bug: it's the architecture.

T9 asked to "optimize `calculateTotal` using `Array.reduce`"… when the function **already used reduce**. The perfect answer was "nothing to do here".

Nobody gave the perfect answer. Every first-round contender made cosmetic changes (4/5). But dsh did something more interesting and more unsettling at once:

`round2(1.005)` returned `1.00` instead of `1.01` due to binary floating-point noise. A legitimate, valuable find.`utils.ts` (outside the target) and changing the rounding behavior of the `src/products.ts` was corrupted ("line 16 reads `ndProduct`… it breaks the whole project's compilation"). Manual verification: `tsc` passed cleanly.
The behavior was *safe* (it asked permission before touching the "corrupted" file). But had I answered "yes, fix it", the agent would have edited a healthy file chasing a ghost. D-Engine structurally cannot have this class of hallucination: it doesn't opine on repo state — truth comes from `tsc`, not from the model.

The cost of all that unleashed diligence: **214K tokens** on a task whose correct answer was "nothing to do". One hundred times D-Engine.

I anticipate three objections to the token gap. All three have measured answers.

**"It's the model"** → No. The dsh round ran on V4.1-Flash; I ran D-Engine v0.2.2 on *the same new model* (adapted the very day of the API migration): 2,552 tokens. Gap intact.

**"It's thinking mode"** → Partially. With effort set to *Off* (an exact replica of the first round's non-thinking configuration), dsh dropped from 107K to 37.1K. Thinking amplifies the gap ~2.9× (and quadruples loop turns: 12 vs 3 tool calls — a model that "thinks" also *wanders* more). But the remaining 14.5× is still there with reasoning off.

**"It's the tool arsenal"** → No. In *Minimal* mode (a single tool: a persistent shell), dsh consumed 34.6K — practically identical to the full agent without thinking (37.1K). With a primitive shell the agent needed *more* turns (11), not fewer: search with `Get-ChildItem`, read with `Get-Content`, edit with `Add-Content` and hand-typed `\r\n` escapes, re-read to verify, compile… The cost isn't in the tool schemas. **It's in the loop: every turn re-sends the full trajectory.** Shrinking the arsenal doesn't shrink tokens; shrinking the loop does.

Final gap decomposition on T1 (same model, same prompt, same diff):

```
D-Engine (pipeline)       2,552 tok   1×     ← no loop
dsh Minimal              34,600 tok   13.6×  ← the arsenal doesn't matter
dsh Off                  37,100 tok   14.5×  ← pure architectural overhead
dsh Factory (thinking)  107,000 tok   42×    ← thinking amplifies ~2.9×
```

This article is not "agents are bad". dsh produced, by far, the most diligent work in the benchmark:

`NaN` dates, JavaScript's February 31st…), ran it — 23/23 — and deleted it afterwards. Brilliant.`applyDiscount`, and The honest conclusion isn't that agents are unnecessary. It's that today you pay for their diligence blind: you don't know if your task will cost 32K or 214K tokens, whether the agent will respect your scope or redecorate half your repo, or whether its report about your code's state is true or a plausible hallucination. D-Engine proposes the inverse split: the agent provides judgment; the machine provides truth and a fixed bill.

An important note about money: at DeepSeek's prices (with 96% cache-hit rates measured in some sessions), 100K tokens cost cents. Direct cost is not the argument. The argument is **latency** (2.7s vs 38s per task), **predictability** (bounded bill vs 6.6× variance), **context degradation** in long sessions, and what this gap means when the model costs dollars per million instead of cents — or when the loop runs unattended in CI, with no one there to say "no" in time.

I declare them before the first hostile comment does:

Coding agents are impressive. They're also token-burning machines with unpredictable variance, no native compile gate, and a… creative relationship with your repository's actual state.

This benchmark shows that for daily work — bounded, specifiable, verifiable changes — a deterministic pipeline produces **the same quality** (48/50, tied with the best agent) at **a fraction of the cost** (14–42× fewer tokens depending on configuration), **a fraction of the time** (2.7s vs 38s), with a **predictable bill** and **zero broken commits**.

We don't need a smarter model. We need a gate.

The AI thinks. The gate decides.

*Sergi Corruchaga is a junior developer (DAM graduate, currently studying DAW). D-Engine is his first open-source project. The complete benchmark — every table, incident, and voided row — is available in the repository.*
