Apply to my task
arXiv:2610.23782 ★ 92 Oct 16, 2026

DeskCheck: Forcing a Coding Agent to “Hand-Trace” Its Code at Every Step of a Bug Fix

Key result

Finding: coding agents already reason about how code executes, but they do it haphazardly. That kind of reasoning shows up in roughly two thirds of runs. Where it does, tasks get solved noticeably more often. The DeskCheck method forces the agent to hunt for the root cause of a bug instead of the symptom in the ticket, and to stop losing requirements in a long task. The trick: the line “reason about the code” in a system prompt barely works; you need a mandatory written output at each of the four stages. The agent does a manual dry run (desk checking): it spells out calls, variable values and conditional branches. Bottom line: a gain in solved tasks of a few to ten percent for a small extra token cost.

01

TL;DR

DeskCheck is a workflow for coding agents in which, at each of four stages (finding the cause, writing the fix, checking it against the task, validating with tests), the agent is forced to spell out how the code executes on concrete inputs. It is the old-school programmer habit of desk checking: walking through the code step by step “in your head” without running it. Instead of just “looking at the code and deciding,” the agent explicitly traces calls, variable values and the result.

The headline finding: agents already reason about code, they just do it haphazardly. Reasoning about code execution shows up in roughly two thirds of runs, and where it does, tasks get solved noticeably more often. On harder tasks agents reason more. But without guidance, four typical failures creep in. The agent fixes only the symptom from the bug report and never finds the root cause. It can't verify an “almost right” fix because the test won't run. It forgets part of the requirements in a long task. It writes tests for the same kind of case over and over and never checks the edge cases.

The method plugs each hole with a separate mandatory reasoning step. It traces the call chain down to the root of the problem. It runs its own fix “on paper” and refines it. It lists the requirements and checks the fix against each one. Before testing, it comes up with diverse inputs and expected outputs. The result: more tasks solved than with a plain agent, at a small extra token cost.

Want this for your own case? Apply this study to your task: AI adapts its method to what you are working on and writes the prompt.

02

Method Blueprint

STAGE 1. Localization: trace the call chain from the entry point → list of suspicious methods (not just the ones named in the bug report)
STAGE 2. Fix and refine: write a patch → “run” it on paper on the inputs from the task → if the behavior is wrong, fix it
STAGE 3. Audit: list every requirement from the task → for each one, check that the patch satisfies it
STAGE 4. Validation: come up with diverse inputs + expected outputs (case, empty, compound, edge cases) → only then write tests

This is a multi-stage process. In the paper it's implemented as a multi-agent scaffold. In a regular agent (Claude Code, Cursor) you can hand it over as a single instruction with stages.

03

Example in Practice

Task: You run the Python backend for a small online store. Customers complain that Apple Pay checkout crashes with an error when the cart has a promo code and an item from the “Digital” category. The bug ticket is long and lists five requirements. The agent already “fixed” it once, but only patched the first function, and the neighboring one still crashes.

Prompt (in Claude Code or Cursor):

Task: fix the Apple Pay checkout crash when the cart contains a promo code
and a digital item. The bug is described in ticket PAY-482.

Work strictly in four stages. Do not move on to the next one
until you have written out the result of the previous one.

STAGE 1. LOCALIZATION.
Find the entry point (checkout → Apple Pay payment). Write out the call chain
down from it. For each function in the chain, describe how it behaves
on the input “promo code + digital item.” Don't stop at the function
named in the ticket: check every neighboring function in the same chain,
including the ones that look unrelated to the symptom.

STAGE 2. FIX AND REFINE.
Write the patch. Then step through it on three concrete inputs
from the ticket: what each variable holds, which if branch runs,
what gets returned or which exception is raised. If the result doesn't match
what the ticket expects, fix the patch and run through it again.

STAGE 3. REQUIREMENTS AUDIT.
List every requirement from the ticket as a numbered list.
For each item, state: whether your patch satisfies it,
on which line, and on which input you checked it.

STAGE 4. VALIDATION.
Before writing tests, build a table: input → expected output.
The inputs must vary: empty cart, promo code in different letter case,
several digital items, zero total, mixed cart.
Only after the table, write the tests and run them.

At the end: what you changed, which requirements you covered, what remains unverified.

Result: The agent will produce four blocks. The first is a trace of the call chain, flagging where it breaks. The second is the patch plus a “dry run” on three inputs, possibly with a correction. The third is a table of “requirement → satisfied? → where.” The fourth is an input/output table, followed by the tests. The odds that it finds not just the obvious function but the neighboring one too, and remembers all five points in the ticket, are higher than with a plain “fix the bug.”

04

Why It Works

The weakness. By default an agent chases the loudest hint in the description. If the ticket says “crashes when iterating over values,” it will check every function that has that kind of loop. The function that crashes for a different reason gets skipped. It skims a long spec and drops some of the requirements. The tests it writes keep repeating the same type of case. And when a test won't run, the agent either burns dozens of steps wrestling with the environment or gives up and ships something unverified.

The strength. A model traces code well if you explicitly ask it to. It can track variable values and unwind conditional branches and function calls. It doesn't need to run the program to see “no exception gets raised here.”

How the method exploits this. It replaces “solve it however” with mandatory artifacts at every stage: a call chain, a step-by-step dry run, a requirements list, an input/output table. Until the artifact is written, you can't move on. Reasoning becomes visible and checkable instead of accidental.

Control knobs: - Number of inputs in stages 2 and 4 → more inputs mean stricter checking but more tokens. For small fixes, two is enough. - Stage 3 (audit) → you can keep it on its own even if you don't need the rest. It's cheap and pays off when the task is long. - The “edge case” input list in stage 4 → swap in your own: dates, currencies, empty values, non-ASCII characters, letter case. - The gating condition (“don't move on until you've written it out”) → remove it and the agent starts skipping stages, and the method weakens.

Prompt Template

The accessible part of the paper contains no verbatim prompts, only descriptions of the stages. The template below is built from those descriptions: four stages and a mandatory artifact at each one.

Task: {bug or feature description, ticket link}.
Codebase: {language, framework, where the relevant module lives}.

Work strictly in four stages. Do not move on to the next one
until you have written out the result of the previous one.

STAGE 1. LOCALIZATION.
Find the entry point for the scenario {scenario}. Write out the call chain downward.
For each function, describe how it behaves on the input {input data from the bug}.
Check not only the functions named in the description but every neighboring one
in this chain. Identify the root cause, not the symptom.

STAGE 2. FIX AND REFINE.
Write the patch. Then “run” it without executing on {number} concrete inputs:
variable values, branches taken, return value or exception.
If the result doesn't match what the task expects, fix it and run through it again.

STAGE 3. REQUIREMENTS AUDIT.
List every requirement from the task as a numbered list.
For each one: is it satisfied in the patch, on which line, on which input was it checked.
Rework any that are not satisfied.

STAGE 4. VALIDATION.
Before testing, build an “input → expected output” table.
The inputs must differ in type: {list of edge cases}.
Then write tests from the table and run them if the environment allows.

At the end, briefly: what changed, which requirements are covered, what is unverified.

What to fill in: {bug or feature description} — the full ticket text, not a summary. {scenario} and {input data} — how the error is reproduced. {number} — usually 2–4. {list of edge cases} — whatever actually breaks in your code: empty values, letter case, long strings, zeros, mixed types.

🚀 Quick start — paste this into the chat or into your agent's instructions file:

Here is a template for a four-stage bug-fixing workflow (tracing → fix with a paper dry run → requirements audit → input/output table before tests). Adapt it to my task: {your task}.
Ask me questions to fill in the fields.

[paste the template above]

The LLM will ask about your language and project structure, how the error is reproduced, and which edge cases actually come up for you. That's what ties stages 1 and 4 to your code rather than to abstract examples. It will pick up the “stage → mandatory artifact” pattern from the template and carry it over to your task.

05

Limitations

⚠️ Correlation ≠ causation: the finding that “agents that reason about code solve more tasks” is an association, not proof. The causal role is backed by a separate experiment: the gain grew as stages were added. But the first finding on its own proves nothing.

⚠️ It has to be multi-stage: drop “reason about the code” into the system prompt as a single line and the effect is weak. Agents that were asked to reason only once did it inconsistently. The method relies on repetition across stages.

⚠️ Not a substitute for running code: the “paper dry run” is for when a test is hard to run. If you can run it, a real test is more reliable. In the paper, simulation stands in for execution; it doesn't replace it.

⚠️ Code only: all evaluations are on bug-fixing tasks in repositories (Python, Go, TypeScript, JavaScript). The method wasn't tested on writing, analytics or other tasks.

⚠️ The gain has a ceiling: the increase in solved tasks ranged from a few to ten percent. The agent still makes mistakes, just less often. It also spends slightly more tokens.

06

How They Studied It

The research had two phases. First, the team analyzed almost 8,000 “trajectories”. That's the term for a full record of an agent's work: every thought and every action, step by step. The records came from six different agent scaffolds, including Claude Code, on three SWE-bench task sets. These are real bugs from open-source repositories. A classifier model found code-reasoning fragments in the agent's thoughts (variable values, calls, loops, conditions, returns) and sorted them into 12 types. The labeling was checked by hand on a sample of 120 runs, with three annotators agreeing with each other.

The result was surprising. Reasoning about code appears in roughly two thirds of runs. Where it's present, about 70% of tasks get solved; where it isn't, about 51%. The harder the task, the more reasoning. But it happens haphazardly: some scaffolds reason during bug localization, others during testing. In scaffolds where it's requested only once in the system prompt, agents tend to ignore it. Where it's required at every stage, it shows up in every run.

That led to the idea: require reasoning at every stage and hint at exactly what kind. This scaffold was tested on 731 SWE-bench-Pro tasks with three different models, against the stripped-down mini-SWE-Agent and Claude Code. The gain was 6 to 10 percent, at an extra cost of about 14 cents per task. Token usage is on average 7.6% higher. Bug localization became noticeably more accurate: the share of correct methods found rose to 0.66 versus 0.38–0.46 for the competitors. An ablation (adding components one at a time) showed growth from 53% to 68% as stages were switched on, so every stage contributes. Statistical tests and repeated runs confirmed the result isn't a fluke.

07

Adaptations and Extrapolations

💡 Adaptation for a long spec (not code): stage 3 (the requirements audit) carries over to any task with a long input: a contract, a brief, a policy document. In the paper this stage is applied only to code. The transfer is my extrapolation.

Here is the client brief: {brief text}.
Here is my draft response: {draft}.

1. List every requirement from the brief as a numbered list (explicit and implied).
2. For each item, say whether the draft satisfies it, where,
   and quote the passage.
3. Rework any item that has no quote.

🔧 Technique: drop “run the tests” → simulate where execution isn't possible. If the agent has no access to the environment, replace “run the tests” in stage 4 with “for each row of the table, step through the code and write down what gets returned.” Effect: even without execution, the agent will catch bugs in conditions and branches.

08

Resources

  • Paper: Enforcing Code Reasoning in Agentic Scaffold for More Effective Issue Resolution
  • Authors: Changshu Liu, Ji Young Kim, Alireza Ghazanfari, Saanvi Nallu, Reyhaneh Jabbarvand. The university is not stated in the paper.
  • Benchmarks: SWE-bench-Verified, SWE-bench-Pro, SWE-bench-Lite
  • Baseline scaffolds for comparison: mini-SWE-Agent, Claude Code, OpenHands, SWE-Doctor

Research digest

Key result

Finding: coding agents already reason about how code executes, but they do it haphazardly. That kind of reasoning shows up in roughly two thirds of runs. Where it does, tasks get solved noticeably more often. The DeskCheck method forces the agent to hunt for the root cause of a bug instead of the symptom in the ticket, and to stop losing requirements in a long task. The trick: the line “reason about the code” in a system prompt barely works; you need a mandatory written output at each of the four stages. The agent does a manual dry run (desk checking): it spells out calls, variable values and conditional branches. Bottom line: a gain in solved tasks of a few to ten percent for a small extra token cost.

Principle

A four-stage process, and at each stage the agent must produce a written output. 1. Localization: the call chain from the entry point down. The output is a list of suspicious functions, not just the one named in the ticket. 2. Fix and refine: write a patch, dry-run it on paper on the inputs from the task. If it doesn't match the expectation, keep fixing. 3. Audit: list every requirement, and for each one name the line of the patch that covers it. 4. Validation: an “input → expected output” table with varied cases. Only then tests. Until a stage's output is written, you can't move to the next one. It's like a pilot's pre-flight checklist: the only way to skip an item is to pretend it isn't there. Without this condition the agent starts jumping over stages and the method weakens.

Why it works

By default an agent grabs the loudest hint in the description. The ticket says “crashes when looping over values.” It checks every such loop and misses the function that crashes for a different reason. It skims a long task and loses some of the requirements. It writes cookie-cutter tests. If a test won't run, it burns dozens of steps wrestling with the environment or gives up. Yet the model can trace code if you ask it directly. It tracks variable values and unwinds branches. It doesn't need to run the program for that. The method turns a skill that kicks in by chance into a mandatory step with a visible output. By the numbers: reasoning about code execution appears in two thirds of runs, and those runs solve more tasks. But that's an association, not proof. The cause is confirmed by a different experiment: the gain grew as stages were added. The gain is honest, not a miracle: a few to ten percent. The agent still makes mistakes, just less often.

When to apply

Fixing bugs in repositories (in the paper: Python, Go, TypeScript, JavaScript) → especially when the ticket is long, with five or more requirements. Also when the agent's previous attempt fixed one function and the neighboring one still crashes. Also when tests are hard to run: no environment, no database, everything depends on external services. Stage 3 (the audit) can be used on its own; it's cheap and pays off on long tasks. NOT a fit for writing, analytics or anything that isn't code: the method wasn't tested there. If a test runs easily, actually running it beats a paper dry run. Reasoning stands in for execution where execution isn't available; it doesn't replace it.

Mini recipe

1. Give it the full ticket: not a summary, the complete text. Requirements get lost precisely in the summary. 2. Set four stages: localization, fix with a dry run, audit, input/output table. Write the stage names right in the prompt. 3. Add the lock: `Do not move on to the next stage until you have written out the result of the previous one.` Without this line the method falls apart. 4. Name the inputs for the dry run: 2–4 concrete cases from the ticket. For a small fix, two is enough. 5. Plug in your own edge cases at stage 4: dates, currencies, empty values, non-ASCII characters, letter case, zeros. 6. Demand a wrap-up: what changed, which requirements are covered, what remains unverified. The last item is the most honest one. 7. Not sure you need the whole set? Start with stage 3 only. It's the cheapest.

Examples

[BAD]: `Fix the bug: Apple Pay checkout crashes when the cart has a promo code and a digital item. Ticket PAY-482.` [GOOD]: `Task: fix the Apple Pay checkout crash with a promo code and a digital item, ticket PAY-482. Work in four stages, and don't move to the next one until you've written out the result of the previous one. STAGE 1: write out the call chain from checkout to payment, for each function describe its behavior on the input “promo code + digital item,” and check the neighboring functions too, not only the one named in the ticket. STAGE 2: write the patch and step through it on three inputs from the ticket: variable values, which if branch is taken, the result or exception. If it doesn't match the expectation, fix it and run through it again. STAGE 3: list every requirement in the ticket, and for each one give the patch line and the input you checked it on. STAGE 4: build an “input → expected output” table: empty cart, promo code in different letter case, several digital items, zero total, mixed cart. Then write the tests and run them. At the end: what you changed, which requirements you covered, what's unverified.` In the good version the agent won't stop at the first function from the ticket. It walks the whole chain and checks against all five points.

In plain words

Coding agents don't screw up because they don't know the syntax. They screw up because they skim the code. They grab the first trigger word in the ticket, crank out a shallow patch and hope for the best. The DeskCheck framework breaks this bad LLM habit and makes the model do what seasoned senior devs call “running the code on a napkin”: spelling out variable values step by step at every stage instead of just taking its own hallucinations at face value.

Picture a mechanic who hears a knock in the engine and immediately swaps the spark plugs without even popping the hood. Looks busy, sure, but the car still won't start, because the problem ran deeper. A typical AI assistant latches onto the flashiest word in the bug report and fixes only the tip of the iceberg, completely forgetting the other 5 hidden conditions buried in the client's long spec.

DeskCheck builds a rigid scaffold around the model across all 4 stages of development: finding the cause, writing the fix, checking it against the task and validating with tests. Instead of abstract musings, the agent has to do a step-by-step trace: take concrete inputs and write down, right in the text, the function calls and the state of every variable. If a promo code crashes checkout, it manually walks the algorithm from start to finish, so missing the neighboring function is no longer an option.

The mechanics were tested on Python web services, but the desk-checking principle is universal. It saves the day in any complex system, from microservices to smart contracts, where an agent usually gets tangled in dependencies or drowns in environment wrangling when the test suite fails. Forced step-by-step reasoning knocks the attention deficit out of the model and makes it see the whole picture.

Bottom line: stop expecting telepathy from AI and hoping the agent will figure out on its own that it should test the non-obvious scenario. Don't let the model write code until it has proven the logic step by step. Build explicit execution simulation into your system prompts and you'll stop mopping up half-baked garbage after your agent. Either you make the AI show its work, or you keep fixing its bugs by hand forever.

AI lab assistant

Apply this study to your task

Describe what you're working on. AI takes the method and the measured results from this paper and adapts them to your case, or writes a ready prompt built on them.

Based on DeskCheck: Forcing a Coding Agent to “Hand-Trace” Its Code at Every Step of a Bug Fix arXiv:2610.23782

Sign in to apply this study New accounts get 50 free credits.