Conceptio › Archive › arXiv CS
arXiv CS open access

A Jagged Frontier: Evaluating Robustness of Code Agents to Semantics-Preserving Transformations

2026 · arxiv_cs
arXiv CS · Papers · 2026
Open Source ↗Direct PDF ↓
software-architecturesoftware-engineeringtesting
Conceptio Open Archive

Analyze & explore related research in Conceptio

Connect this record directly into your research workflow or AI agent. Explore citations across open repositories, query full text, and export structured proof bundles.

A Jagged Frontier: Evaluating Robustness of Code Agents to Semantics-Preserving Transformations Hasan Najib Mahmud∗1 , Shreya Gupta∗2 , Isha Chaudhary3 , Nathaniel Enis1 , Ravi Mangal1 , Gagandeep Singh3 , Corina Pasareanu4 1

arXiv:2608.18389v1 [cs.AI] 18 Aug 2026

Colorado State University 2 Microsoft 3 University of Illinois Urbana-Champaign 4 Carnegie Mellon University Abstract AI code agents are increasingly deployed to resolve real software issues, yet their reliability under superficial code variations remains poorly understood. We evaluate whether coding agents that repair repository-level issues remain reliable when the surrounding codebase is rewritten into a semantically equivalent form. We introduce a random variant sampler that applies common semantics-preserving transformations (SPTs)—spanning control-flow rewrites, dead-code injection, and identifier renaming—to produce perturbed variants. We evaluate two agentic scaffolds (mini-SWE agent and OpenCode) each backed by one of four frontier models (Claude Opus 4.5, Kimi K2.5, MiniMax M2.5, and Qwen 3.6-27B) across instances drawn from SWE-bench Verified and SWEbench Pro. For each instance, the agent is run multiple times on the unperturbed and perturbed variants, yielding paired resolve-rate estimates that isolate the perturbation effect from intrinsic stochasticity. We find small degradation in most configurations: up to 6.7 percentage points mean resolve-rate drop in the most affected configurations with statistically significant degradations in 6 of 16 configurations of model, scaffold, and dataset. Crucially, no single model ranking by robustness holds across scaffolds—Qwen is among the most robust under mini-SWE agent on SWE-bench Verified yet the most brittle under OpenCode—revealing a jagged robustness frontier. The simpler scaffold (mini-SWE agent) is more robust to perturbation. Our results demonstrate that even top frontier models are susceptible to semantics-preserving perturbations although the effect is not uniform, raising concerns about the deployment reliability of AI code agents in diverse real-world codebases.

Code — https://github.com/CSU-TrustLab/jagged-frontier

Introduction In the span of a few years, AI-powered coding tools have moved from research prototypes into mainstream software development, with developer surveys reporting that a majority of professionals now use them regularly (Stack Overflow 2025; GitHub 2025; JetBrains 2025; Google DORA 2025). Their progress is charted on challenging coding benchmarks such as SWE-bench Verified (OpenAI 2024) and SWE-bench ∗

These authors contributed equally.

Pro (Deng et al. 2025), against which nearly every new model and agent release is measured. While performance numbers on these benchmarks can be instructive, they do not account for the phenomenon that neural models, in general, are known to learn shortcuts (Geirhos et al. 2020) and therefore be susceptible to small input perturbations. Two concerns follow. First, if agent behavior shifts with superficial changes to the surrounding code, then benchmark numbers may overstate deployment reliability. Second, such shifts would suggest that the underlying models rely on shallow syntactic patterns rather than an understanding of program semantics. Prior work has evaluated the robustness of code LLMs to semantics-preserving perturbations in single-turn, nonagentic settings (Yefet, Alon, and Yahav 2020; Ramakrishnan et al. 2022; Wang et al. 2023). However, the robustness of repository-level code agents, which interact with the LLM over many turns, has received little systematic study. We present, to our knowledge, the first such evaluation, and find that robustness is not a fixed property of a model but a jagged frontier: a model that holds up under one scaffold or codebase can be the most brittle under another, so benchmark rankings do not transfer to deployment. For robustness evaluation, we compare agent performance on unperturbed code repositories with semantically equivalent perturbed variants. The perturbations are injected via local, semantics-preserving transformations (SPTs) of the code. We develop a library of SPTs that either mimic refactorings a developer may routinely perform or are intended to stress-test the agent. We use the library to build a randomized algorithm, i.e., a sampler, that draws perturbed variants of a base repository. Our sampler randomly chooses which SPTs to apply and where to apply them. Each variant is constructed independently, and unlike algorithms that aim to find adversarial examples (Srikant et al. 2021), the sampling process is not guided by feedback computed from model outcomes. This non-adversarial design is intentional. Our aim, in this work, is to compute lower bounds for the impact of SPTs on code agents. A feedback-guided adversary can only do more damage. These bounds can inform developer choices about whether and which code agents to use in deployment. They can also help guide engineers training models and building agentic scaffolds towards robustness-enhancing designs.

The stochastic nature of LLM-based agents makes the robustness evaluation challenging. If an agent has a failing run on a perturbed variant but a passing run on the unperturbed repository, this observation is not sufficient to conclude that the perturbation was the cause; the observation might simply be an artifact of agent stochasticity. Experiment design is further constrained by the cost of each agentic run. Accordingly, we design the experimental methodology to isolate the perturbation effect from intrinsic run-to-run variability while balancing the statistical validity of our claims against the cost of the experiments. We do this by running the agent repeatedly on both the unperturbed seed and its variants and pairing the outcomes. We evaluate two agentic scaffolds (mini-SWE agent and OpenCode) each backed by one of four frontier models (Claude Opus 4.5, Kimi K2.5, MiniMax M2.5, and Qwen 3.6-27B) across a total of 54 instances drawn from SWEbench Verified and SWE-bench Pro. Throughout, we study repository-level issue resolution: each task instance pairs a repository at a base commit with an issue description, the tests an accepted patch must satisfy, and a gold patch, the reference edit that resolves the issue. We measure the degradation in issue resolve rates across unperturbed and perturbed versions of a repository, as well as the change in step count and the cost of an agent run. Our experiments reveal the following insights: (1) localized perturbations applied in a simple, non-feedbackguided manner can cause small degradations in most configurations—up to 6.7 percentage points in the most affected configurations and statistically significant degradations in 6 of 16 configurations; (2) perturbations raise the effort an agent expends (increasing step counts and token cost by up to 9.9% and 22.9% respectively even in configurations where resolve rate is left largely unchanged), so an outcome-only view understates their impact; (3) comparing models within a scaffold, those such as Claude Opus 4.5 with higher capability on unperturbed versions can be impacted more drastically by perturbations than lower-capability models, whereas comparing across scaffolds, the simpler scaffold tends to be the more robust one; (4) the agentic scaffold and the benchmark shift the robustness ranking of models, so that Qwen, for instance, is among the most robust under mini-SWE agent on SWE-bench Verified yet the most brittle under OpenCode; and (5) the impact of the perturbations varies dramatically across different repositories, concentrating in a small set of instances while leaving others untouched. Together these observations indicate that robustness is a joint property of the model, the scaffold, and the workload, not of the model alone, revealing a jagged robustness frontier.

Semantics-Preserving Transformations Definition A transformation T is semantics-preserving if the transformed program T (P ) produces the same observable behavior as the original program P on every possible program input. Concretely, under any input, P and T (P ) must (i) return the same value or raise the same exception, and (ii) produce the same externally observable effects. If either halts,

so must the other. In the context of evaluating coding agents, we operationalize this definition through functional test-suite equivalence. Specifically, a transformation is considered semanticspreserving if T (P ) yields the same per-test outcome as P across a project’s test-suite.

Transformation Catalog Table 1 lists the 14 semantics-preserving transformations (SPTs) we implement. We represent this catalog using the notation T . The catalog includes a mixture of SPTs that either mimic refactorings a developer might routinely perform (e.g., reordering commutative operands, swap if and else branches) or are intended to stress-test the agent by introducing unnatural or behaviorally inert code fragments (e.g., splitting string literals, dead code/method injection). Each SPT is specified by a structural pattern that needs to match for the SPT to be applicable and by a rewrite rule. We call the locations in a file where an SPT’s pattern matches its candidate sites. Two SPTs, namely Dead String Assignment and Dead Method Injection, must be bound to a target keyword, either a string literal or a method name, before rewriting. Given such a keyword, the former injects an unread assignment of that string and the latter appends a dead method of that name. Both plant a decoy: dead code that contains the keyword, so it surfaces whenever the agent searches the repository for that term. An agent that localizes by keyword must tell the decoy apart from genuine sites of interest. We write Tkw ⊂ T for this keyword-bound subset of the catalog T . Full implementation details of SPTs are provided in Appendix A.

Validation We validate that our SPTs are semantics-preserving empirically through differential testing (McKeeman 1998) against the test suites of three projects drawn from our experimental benchmark, SWE-bench (Jimenez et al. 2024), spanning distinct domains: SymPy (symbolic mathematics; 12,994 tests), sqlfluff (SQL linting; 10,060 tests), and xarray (labeled N dimensional arrays; 19,917 tests). Each transformation is validated in isolation: for a given transformation, we apply the transformation at every applicable site, run the full test-suite, and compare the per-test outcome against the unmodified baseline. Validating one transformation at a time renders any divergence in behavior attributable to a single transformation type. Across all three projects, every test retained its outcome under all 14 transformations. This evidence is bounded by the coverage of the underlying test-suites and is therefore not a proof of equivalence. As each transformation is independently validated to be preserving, we rely on this property rather than re-verifying the test outcome of every perturbed task instance.

Composition and Scope Individual transformations act on candidate sites within a single file, whereas evaluating an agent on a code repair task requires perturbing a whole repository. We therefore apply a finite sequence ⟨t1 , . . . , tm ⟩ of SPTs to the source

Table 1: Catalog of semantics-preserving transformations (SPTs). Transformation

Summary

If Else Switcher

Swaps if/else branches and negates the condition For Loop Rewriting Rewrites a for loop using an explicit iterator And Condition Splitter Decomposes if A and B into nested ifs Comparison Swapper Swaps operands and inverts the operator While Loop Unrolling Unrolls one iteration of a while loop Double Negation Injector Wraps a condition in not not (·) Commutative Operand Permuter Reorders commutative operands Local Variable Renamer Renames safe local variables to synonyms If True Wrapper Wraps a block in a permanently true guard Try Except Injector Wraps a block in a redundant try/except Dead Code Injector Inserts an unreachable block Dead String Assignment Inserts an unread variable assignment Dead Method Injection Appends an unreachable method to a class String Literal Splitter Splits a string literal into a concatenation

files, excluding test suite files, of a repository. Each tj is individually semantics-preserving, and because observational equivalence is transitive, their composition is semanticspreserving as well. The perturbed repository is therefore observationally equivalent to the original. The exclusion of test suite files is what keeps such a perturbed repository usable as an evaluation target. The oracle that defines task success is identical before and after perturbation, and no change in an agent’s score can be attributed to a moved target.

Sampling Semantics-Preserving Variants Given a seed repository associated with a task instance, the variant sampler (Algorithm 1; its subroutine AssignTargetNames is given as Algorithm 2 in Appendix B) applies a sequence of SPTs at randomly chosen sites in randomly chosen files and returns a population of variants: repositories that, by the composition argument of the previous section, are semantically equivalent to the seed. Each variant becomes an independent task instance used to evaluate the agent. For each variant, the sampler makes four random decisions: 1. Which transformations? A subset of Nt transformations is drawn uniformly from the list of transformations T . 2. Which files? For each selected transformation, an inclusion probability pfile ∼ U (0, 1) is drawn and each file, excluding test suite files, is included with probability pfile . The files, Fgold , modified by the gold patch (i.e., the reference edit that resolves the issue) are exempt from this filter and from the Nf cap introduced below. So they are

Algorithm 1 Random Variant Sampler Input: Seed repository Cseed , Sample count N , List of transformations T , Files modified by the gold patch Fgold , Issue description I, Number of transformations to apply Nt , Maximum number of keywords selected Nk , Fraction of candidates transformed ϕ, Maximum files per keyword-bound transformation Nf Output: Variant population V 1: procedure GenerateVariants(Cseed , N , T , Fgold , I, Nt , Nk , ϕ, Nf ) 2: V←∅ 3: K ← None 4: for j ← 1 to N do 5: Cmut ← Clone(Cseed ) 6: Tselected ← RandomSelect(T , Nt ) 7: pfile (t) ∼ U (0, 1) for each t ∈ Tselected 8: if Tselected ∩ Tkw ̸= ∅ and K = None then 9: K ← ExtractKeywords(I) ▷ LLM call; cached 10: end if 11: B ← AssignTargetNames(Tselected , K, Nk ) 12: for each (t, τ ) ∈ B do 13: c←0 14: for each f ∈ SourceFiles(Cmut ) do 15: if f ∈ / Fgold and Random > pfile (t) or  16: (t ∈ Tkw and c ≥ Nf ) then continue 17: c←c+1 18: S ← GetCandidates(f, t, τ ) 19: if S = ∅ then continue 20: S ′ ← RandomSelect(S, ⌈ϕ|S|⌉) 21: Cmut [f ] ← ApplyTransform(f, S ′ , t, τ ) 22: end for 23: end for 24: V.append(Cmut ) 25: end for 26: return V 27: end procedure

always included. These are the files an agent must locate and edit to resolve the issue. So every variant targets the solution-relevant region rather than targeting it by chance. 3. Which sites? Within each included file, a fraction ϕ of the candidate sites is chosen uniformly for rewriting. 4. Which keywords? For each selected keyword-bound transformation t, up to Nk targets are drawn uniformly from its extracted candidates. We extract the targets for Tkw from the issue description with a single LLM call: method names it mentions for Dead Method Injection, literal strings for Dead String Assignment. Because pfile is resampled for every transformation, different transformations reach different portions of the repository, and the population spans from a single localized edit to pervasive, repository-wide perturbation. Notation. Random ∼ U (0, 1) is a uniform random number generator. RandomSelect(X, m) returns m elements drawn uniformly without replacement from X. SourceFiles(C) returns the source files of C, excluding test suite files. Clone(C) copies repository C. ExtractKeywords(I) invokes an LLM to obtain the keyword map, K, where K holds keyword candidates for

t ∈ Tkw . AssignTargetNames(·) binds each selected t ∈ Tkw to up to Nk of its candidates, emitting one pair (t, τ ) per keyword; every other t, and any t with no candidates, is emitted as (t, None) (Algorithm 2). GetCandidates(f, t, τ ) returns sites in f where t can be applied. ApplyTransform(f, S ′ , t, τ ) rewrites f at every site in S ′ . Hyperparameters. Five hyperparameters govern the sampler. N is the number of variants drawn from each seed instance. Nt is the number of transformations sampled for each variant. Nk caps how many keywords each keyword-bound transformation is bound to. ϕ ∈ (0, 1] is the fraction of candidate sites rewritten within each included file. Finally, Nf caps the number of files that a single keyword-bound transformation may select. This last bound is a practical necessity. We observed that agents frequently detected the perturbation and reverted the repository outright (for instance via git reset) when a variant contained too many decoys. Capping the reach of the keyword-bound transformations keeps variants within the range an agent treats as ordinary code. The one quantity that is not fixed, the file-inclusion probability pfile , is drawn from U (0, 1) for every transformation. The population V returned by Algorithm 1 is consumed by the agent evaluation loop (Algorithm 3 in Appendix C), which provisions an isolated environment for each variant, runs the agent, and evaluates its patch against the instance’s test oracle.

Experiments Research Questions Our evaluation is organized around the following questions. RQ1 To what extent do SPTs degrade agent performance, and how does this effect vary across models and scaffolds? RQ2 How much additional effort do SPTs induce on agents, controlling for task outcome? RQ3 What failure patterns emerge when agents fail on semantics-preserving variants?

Setup Benchmarks and instance selection. We draw task instances from two popular repository-level program-repair benchmarks: SWE-bench Verified (OpenAI 2024), a humanvalidated 500-instance subset of SWE-bench (Jimenez et al. 2024), and SWE-bench Pro (Deng et al. 2025), which contains 731 instances. Constrained by a compute budget, we selected 28 task instances from SWE-bench Verified and 26 from SWE-bench Pro. Our selection procedure is detailed in Appendix C. Each task instance pairs a repository at a base commit with FAIL_TO_PASS and PASS_TO_PASS test sets that an accepted patch must satisfy. The FAIL_TO_PASS tests are those that fail at the base commit but must pass once the issue is fixed. PASS_TO_PASS tests, by contrast, are those that already pass at the base commit but must remain passing to demonstrate that the patch fixes the issue without causing any regression.

Agents and models. We evaluate two agentic scaffolds, mini-SWE agent (Yang et al. 2024) and OpenCode (OpenCode Contributors 2024), each driven by one of four backing models: Claude Opus 4.5 (Anthropic 2025), Kimi K2.5 (Team et al. 2026), MiniMax M2.5 (MiniMax AI 2026), and Qwen 3.6-27B (Qwen Team 2026). Crossing two scaffolds, four models, and two benchmarks yields 16 configurations, each of which we evaluate independently. Within a configuration the agent is run under a fixed setting, identical on the seed and on its variants, so that any change in outcome is attributable to the perturbation rather than to the agent. Variant generation. We configure the Random Variant Sampler (Algorithm 1) with N = 20, Nt = 3, Nk = 5, Nf = 10, and ϕ = 0.7. Under this configuration the sampler produces 20 variants per instance. For keyword-bound transformations, the target keywords are extracted from the issue description alone, using the same model that backs the agent under evaluation. Perturbation magnitude. Averaged over a task instance’s variants, the transformations target a median of 6.9% of lines of source code on SWE-bench Verified and 7.7% on SWEbench Pro. These percentages are lower bounds, since each transformation also inserts new code at the sites it touches.

Metrics All metrics are computed per configuration, a (scaffold, model, benchmark) triple. Metrics are reported both per instance and in aggregate. Resolve rate. A run resolves an instance if its patch passes both the FAIL_TO_PASS and PASS_TO_PASS test sets. For instance i, the baseline resolve rate r0 (i) is the fraction of the N =20 unperturbed runs that resolve it, and the perturbed resolve rate rp (i) is the fraction of the N =20 variant runs that resolve it. Both are proportions in [0, 1]. We report them in percentage points. Degradation. degradation

Our primary metric is the per-instance

∆(i) = r0 (i) − rp (i), where a positive value means the agent resolves the issue less often after perturbation. We summarize each configuration ¯ = 1 P ∆(i) (I is the set of by the mean degradation ∆ i |I| ¯ across configurations. instances) and compare ∆ Effort and cost. To capture overhead that resolve rate alone misses, we report the mean difference between perturbed and baseline runs in two quantities: agent steps and cost. We use s(·) for the number of agent steps in a run (model turns or tool invocations) and c(·) for its token cost. Let s̄0 (i) and s̄p (i) be the mean step count over the baseline and perturbed runs of instance i. We report the relative change δstep (i) =

s̄p (i) − s̄0 (i) × 100%, s̄0 (i)

and define δcost (i) the same way from c(·). We summarize a P 1 configuration by the mean over instances, δ̄ = |I| δ(i). i When conditioning these metrics on whether the issue was

resolved or not, we exclude instances where the baseline has no resolved runs.

Experimental Protocol For each instance we perform N = 20 runs on the unperturbed seed and one run on each of N = 20 sampled variants. Every run, unperturbed or perturbed, executes in a freshly provisioned, isolated environment, so no state carries between runs. Concretely, for each instance we extract the seed repository, gold-patch file list, and issue description; execute the N unperturbed runs; generate N variants with Algorithm 1; and then, for each variant, provision a fresh environment, inject the variant, run the agent, and evaluate the resulting patch against the instance’s test oracle. Algorithm 3 in Appendix C gives the full procedure. Two sources of randomness. A perturbed run varies for two independent reasons. Variant randomness: the sampler draws transformations, files, and sites at random, so variants of the same instance differ in difficulty. Writing pV for the agent’s resolve probability on variant V , this is the spread σ 2 = Var(pV ). Agent randomness: with the variant held fixed, a single run is a Bernoulli(pV ) draw, contributing average within-variant noise ν = E[pV (1 − pV )]. The unperturbed condition carries only the second. The quantity rp (i) targets is µ = E[pV ], the resolve probability averaged over the variant population, and degradation contrasts it with the unperturbed resolve probability. One run per variant is the efficient split. With a budget of R perturbed runs per instance, the design choice is how to split them into N variants of K runs each (R = N K). Averaging the per-variant rates is unbiased for µ at every K, since a single run already has conditional mean pV ; repetition tightens each per-variant estimate around a center that is already correct rather than moving it. The variance does depend on the split: Var(µ̂) = (Kσ 2 + ν)/R, strictly increasing in K whenever σ 2 > 0. Intuitively, a run spent on a fresh variant samples both sources of randomness, whereas re-running a variant resamples only the agent. We therefore set N = R = 20, K = 1. Appendix E gives the derivation. Statistical protocol. Our inference is fixed-population: the instance set of each benchmark is held fixed and all intervals quantify run-to-run variability on those instances, not sampling of instances from the benchmark. We refer to the unperturbed and perturbed runs of an instance as its two conditions. For the configuration-level means (degradation, step count, and cost) we report 95% bootstrap percentile intervals from B = 20,000 resamples, resampling runs within each instance while leaving the instance set intact. For degradation, we redraw each instance’s per-run outcomes in each condition from a binomial model, Binomial(n, p̂)/n, with p̂ the observed resolve rate over that condition’s n runs. For step count and cost, we draw the per-run values within each condition with replacement and recompute the instance’s relative change. For per-instance degradation, a difference of two proportions, each estimated from 20 runs, we instead report 95% Newcombe intervals (Newcombe 1998; Fagerland, Lydersen, and Laake 2015).

¯ (percentage points) for each Figure 1: Mean degradation ∆ model under each scaffold on both benchmarks. Error bars are fixed-population 95% bootstrap confidence intervals.

RQ1: Degradation of Agent Performance Robustness rankings do not transfer across scaffolds or ¯ for benchmarks. Figure 1 gives the mean degradation ∆ each scaffold-model pair on each benchmark with its fixedpopulation 95% bootstrap confidence interval. Perturbation ¯ is positive in reduces resolve rates in most configurations: ∆ 13 of the 16, and the interval excludes zero in 6 of the 16. No scaffold-model pair is significant on both benchmarks, so the effect is configuration-dependent rather than uniform. No single ordering of models by robustness holds across the two scaffolds, and none holds across the two benchmarks either. On SWE-bench Verified, Qwen is the most robust model under mini-SWE agent, degrading only 0.2 points, yet the most brittle under OpenCode at 5.5 points. MiniMax moves the other way, from 2.7 points under mini-SWE agent down to 0.5 under OpenCode. The benchmark axis is just as jagged. Opus under mini-SWE agent degrades 1.8 points on SWEbench Verified but 6.7 points on Pro, the largest drop in the study, while under OpenCode on Pro it is the least degraded of the four models. Kimi stays at or below one point in three of its four cells but is the most degraded OpenCode model on Pro at 4.2 points. Every model is among the most robust in at least one cell and among the most brittle in another. A mean degradation measured on one scaffold and benchmark therefore does not predict behavior on another. A practitioner who picks a model for how it holds up under mini-SWE agent on SWE-bench Verified may get the opposite outcome after switching scaffold or codebase. We call this a jagged robustness frontier: robustness is a joint property of the model, the scaffold, and the workload, not of the model alone. The simpler scaffold is consistently more robust. Averaged over the four models, mini-SWE agent degrades less than OpenCode on both benchmarks: 1.34 points against 1.88 on SWE-bench Verified, and 1.88 against 3.65 on SWEbench Pro. Its absolute strength, by contrast, is benchmarkdependent. It resolves 89.05% of unperturbed runs on Verified against OpenCode’s 81.20%, but 76.35% on Pro against OpenCode’s 79.33%. The robustness gap survives this capability flip, which is what makes it informative. The simpler scaffold loses less under perturbation. Degradation is concentrated, not diffuse. Appendix D reports the per-instance degradation ∆(i) with its New-

Figure 2: Mean relative change in agent steps (δ̄step ) and cost (δ̄cost ) after perturbation, for each scaffold–model configuration on the 28 SWE-bench Verified instances (left) and the 26 SWE-bench Pro instances (right), restricted to runs the agent resolved in both cases. Positive values mean perturbed runs take more steps, or cost more, than unperturbed runs on the same instance. Error bars are fixed-population 95% bootstrap confidence intervals.

combe 95% interval for every instance-configuration. At the level of an individual instance the comparison is underpowered. With 20 runs per condition, only swings of roughly 25 points or more can exclude zero. Only 14 out of 432 instance-configuration items exclude zero in their interval. The mass of point estimates is shifted toward positive values. The aggregate effect is carried by a small heavy tail of instance-configuration items. Three instances alone account for roughly two-thirds of the 6.7-point mean degradation of mini-SWE agent with Opus on SWE-bench Pro. The concentration mirrors the jaggedness we saw at the aggregate level. No instance degrades under all eight configurations on either benchmark, and a few cells swing sharply the other way. Brittleness attaches to particular instance-configuration pairs rather than to instances, models, or repositories alone.

RQ2: Effort Induced by Perturbation Perturbation inflates effort more broadly than it degrades outcomes. Figure 2 reports δ̄step and δ̄cost for each configuration on both benchmarks, restricted to the runs the agent resolved, so that the comparison cannot be driven by long failing runs. On SWE-bench Verified, cost rises in all 8 configurations, from 4.0% (mini-SWE agent with Opus) to 22.9% (OpenCode with MiniMax), and the interval excludes zero in every one. On SWE-bench Pro the increments are smaller and concentrated in the richer scaffold. All four OpenCode configurations pay 8.8–12.6% more with intervals excluding zero, while the four mini-SWE agent configurations sit near zero. The same holds over all runs (Appendix D): cost rises in all eight Verified configurations and seven of eight on Pro. Because the trend is already present when only successful runs are counted, it is not an artifact of failure. Measured by resolve rates, most configurations are impacted modestly by the perturbations, but, measured by what the agent spends, the impact is more drastic.

The agent spends more per step, not only more steps. Steps and cost do not move together. Cost per step rises in twelve of the sixteen configurations. On SWE-bench Verified, step overhead never exceeds 9.9% while cost overhead reaches 22.9%. The agent is not merely taking more turns after a rewrite. It is consuming more context on each turn, consistent with longer files and heavier reading under perturbation. Among runs the agent resolved, input tokens per step rise in 13 of the 16 configurations. The scaffold contrast from the degradation analysis reappears here on Pro. Restricted to resolved instances, the four OpenCode configurations pay 4.6–7.2% more in cost per step, while the mini-SWE agent configurations are flat or slightly cheaper. Opus compresses its trajectory rather than extending it. Opus under mini-SWE agent on SWE-bench Verified responds to perturbation by taking fewer steps. This behavior is uniform. For every instance, it takes fewer steps on perturbed runs (mean −19.8%, range −6% to −39%). But output tokens per step more than double, causing cost to rise on every instance (median +101%), while input tokens per step fall by 17%. Rather than taking more turns, Opus emits fewer, denser actions, for a net +30.4% cost per step and +4.0% total cost. This behavior is also benchmark-specific. On SWE-bench Pro the step reduction shrinks to (−1.29%).

RQ3: Observed Failure Patterns We manually analyze 20 agent trajectories across both scaffolds, both benchmarks (14 distinct instances), and all 4 models to check for behavioral patterns and how SPTs influence agent handling of tasks. These tasks are selected for displaying high variance (3), high degradation (3), large increase in step count (1), file coverage (2) or cost (1). Additionally, cases with one mutant failure out of 20 (2) and those with high likelihood of SPT interference (8) are also picked, with a focus on covering a diverse set of model-scaffoldbenchmark combinations. Details on selection can be found

in Appendix F. Here, we present 4 interesting behavior patterns that we observed. For additional observations, refer to Appendix F. Detecting and reverting SPTs. In the cases where there is significant overlap between the SPT edited files and the files that the agent touches, there are instances where the agent recognizes that the code is "obfuscated". For example, in one case, with MiniMax on Qutebrowser and mini-SWE agent, the agent checks the commit history and spots that the transformations were added in the latest commit. It then reverts the repository state before it makes the final changes so that all SPTs are cleared. Degradation of code localization capabilities. SPTs may make it harder for agents to localize relevant sections of the code, either by diluting grep results or making core files lose credibility. For example, Opus with mini-SWE agent on Openlibrary tries to grep for a keyword in the issue description, but ends up getting thrown off by multiple noisy dead string assignments which use the same keyword and turn up in the search. Editing/"fixing" of perturbed code. The agent occasionally simplifies the perturbed code during patching, for example, Opus with mini-SWE agent on Qutebrowser mentions that it has recognized and fixed the perturbed code in multiple places. This additional editing may also increase the risk of the patch failing due to the increased volume of changes. Corrupted patch validation. With Kimi on Pytest-dev, one of the unit tests in the test suite fails. The part of the code the unit test refers to contains a string literal splitter in one of the logs. The agent gets confused and incorrectly attributes the failure to the split string, reasons that this was not due to an edit it made, and then submits the incorrect patch without attempting to resolve the error.

Related Work Robustness of code language models. A substantial body of work shows that neural models of code are brittle to surface-level perturbations that preserve semantics. Identifier renaming attacks have been demonstrated against neural code models (Yefet, Alon, and Yahav 2020), formalized under robustness constraints (Bielik and Vechev 2020), and scaled to black-box settings against pretrained models like CodeBERT (Yang et al. 2022). Structural perturbations such as dead code insertion and operator substitution have been used to attack program classifiers (Srikant et al. 2021). Ramakrishnan et al. (2022) combined renaming, dead code, and operand swapping to expose fragility across method-name prediction and code summarization. On the defense side, contrastive learning on equivalent programs (Jain et al. 2021) and naturalizing transformations as a pretraining objective (Chakraborty et al. 2022) have been shown to improve robustness. At the benchmark level, perturbations to docstrings, signatures, and syntax have been used to evaluate code generation models (Wang et al. 2023), attack frameworks have been proposed across defect detection and clone detection (Jha and

Reddy 2023), and minor refactorings in prompt context have been shown to significantly alter Copilot’s completions (Mastropaolo et al. 2023). All of the above evaluate single-turn model inferences on classification or short-generation tasks where the perturbation is applied to a fixed-length input. Our work extends this to multi-turn agents that localize faults, navigate entire repositories, and synthesize patches across dozens of reasoning steps. The perturbations occur randomly over the codebase. Adversarial robustness of LLMs. LLMs are fragile to semantics-preserving transformations of general naturallanguage inputs. Prompt formatting changes alone (spacing, delimiters, option ordering) cause up to 76-point accuracy swings (Sclar et al. 2024), and systematic perturbation benchmarks confirm this across character-, word-, and sentencelevel attacks (Zhu et al. 2023; Vega et al. 2023). The phenomenon extends to structured problem solving. GSM-Symbolic (Mirzadeh et al. 2024) and GSM-Plus (Li et al. 2024) create variants of math benchmarks by changing surface features (names, numbers, phrasing) while preserving problem structure, observing up to 10% performance drops. Similarly, reordering multiple-choice options (Zheng et al. 2024; Chaudhary, Jain, and Singh 2024) or generating structurally equivalent reasoning problems (Zhu et al. 2024) significantly shifts model rankings. Formal certification of LLM robustness has also been proposed (Chaudhary et al. 2025a; Wang et al. 2026; Chaudhary et al. 2025b). Geirhos et al. (Geirhos et al. 2020) frame these failures as shortcut learning, where networks exploit spurious surface statistics rather than learning the intended decision rule. Dziri et al. (Dziri et al. 2023) provide evidence that transformers linearize compositional reasoning, offering a mechanistic explanation for why surface changes can derail multi-step tasks. Our findings echo this pattern in the code domain. We show coding agents are sensitive to how the surrounding code is structured. A further dimension absent from prior work is the scaffold interaction. We find that robustness rankings can change when the same model is embedded in a different agent architecture. Robustness certification for agentic systems has also been studied for simple, non-code tool-selection (Yeon, Chaudhary, and Singh 2025).

Conclusion In this work, we contribute a library of local, semanticspreserving transformations (SPTs) for code repositories and a randomized sampler that draws semantically equivalent variants of a repository without feedback from the agent; an experimental methodology that isolates the perturbation effect from the intrinsic stochasticity of LLM-based agents through paired seed-and-variant runs while balancing statistical validity against the cost of agentic runs; and, to our knowledge, the first systematic robustness evaluation of repositorylevel code agents. Our experiments reveal a jagged robustness frontier across models, scaffolds, and repositories.

Generative AI Usage Statement Generative AI tools were used in the preparation of this manuscript to improve the clarity of the writing, to assist in

writing Python scripts for the experiments, and to develop the arguments in Section E. Everything was carefully reviewed by the authors and they remain fully accountable for this work.

References Anthropic. 2025. Introducing Claude Opus 4.5. https: //www.anthropic.com/news/claude-opus-4-5. System card: https://assets.anthropic.com/m/64823ba7485345a7/ClaudeOpus-4-5-System-Card.pdf. Bielik, P.; and Vechev, M. 2020. Adversarial Robustness for Code. In Proceedings of the 37th International Conference on Machine Learning (ICML). Chakraborty, S.; Ahmed, T.; Ding, Y.; Devanbu, P.; and Ray, B. 2022. NatGen: Generative Pre-training by “Naturalizing” Source Code. In Proceedings of the 30th ACM Joint European Software Engineering Conference and Symposium on the Foundations of Software Engineering (ESEC/FSE). Chaudhary, I.; Hu, Q.; Kumar, M.; Ziyadi, M.; Gupta, R.; and Singh, G. 2025a. Certifying Counterfactual Bias in LLMs. In International Conference on Learning Representations (ICLR). Chaudhary, I.; Jain, V.; Parhar, P.; Sachdeva, K.; Singh, A.; Ranu, S.; and Singh, G. 2025b. Lumos: Let there be Language Model System Certification. arXiv preprint arXiv:2512.02966. Chaudhary, I.; Jain, V. V.; and Singh, G. 2024. Certifying Knowledge Comprehension in LLMs. arXiv preprint arXiv:2402.15929. Deng, X.; Da, J.; Pan, E.; He, Y. Y.; Ide, C.; Garg, K.; Lauffer, N.; Park, A.; Pasari, N.; Rane, C.; et al. 2025. Swe-bench pro: Can ai agents solve long-horizon software engineering tasks? arXiv preprint arXiv:2509.16941. Dziri, N.; Lu, X.; Sclar, M.; Li, X. L.; Jiang, L.; Lin, B. Y.; West, P.; Bhagavatula, C.; Le Bras, R.; Hwang, J. D.; et al. 2023. Faith and Fate: Limits of Transformers on Compositionality. In Advances in Neural Information Processing Systems (NeurIPS). Fagerland, M. W.; Lydersen, S.; and Laake, P. 2015. Recommended confidence intervals for two independent binomial proportions. Statistical methods in medical research, 24(2): 224–254. Geirhos, R.; Jacobsen, J.-H.; Michaelis, C.; Zemel, R.; Brendel, W.; Bethge, M.; and Wichmann, F. A. 2020. Shortcut Learning in Deep Neural Networks. Nature Machine Intelligence, 2(11): 665–673. GitHub. 2025. Octoverse 2025: The State of Open Source and Rise of AI. https://github.blog/news-insights/octoverse/. Accessed: 2026-07-22. Google DORA. 2025. 2025 DORA Report: State of AIassisted Software Development. https://dora.dev/research/ 2025/. Accessed: 2026-07-22. Jain, P.; Jain, A.; Zhang, T.; Abbeel, P.; Gonzalez, J.; and Stoica, I. 2021. Contrastive Code Representation Learning. In Proceedings of the 2021 Conference on Empirical Methods in Natural Language Processing (EMNLP).

JetBrains. 2025. The State of Developer Ecosystem 2025. https://devecosystem-2025.jetbrains.com/. Accessed: 202607-22. Jha, A.; and Reddy, C. K. 2023. CodeAttack: Code-Based Adversarial Attacks for Pre-trained Programming Language Models. In Proceedings of the AAAI Conference on Artificial Intelligence. Jimenez, C. E.; Yang, J.; Wettig, A.; Yao, S.; Pei, K.; Press, O.; and Narasimhan, K. 2024. Swe-bench: Can language models resolve real-world github issues? In International Conference on Learning Representations, volume 2024, 54107–54157. Li, Q.; Cui, L.; Zhao, X.; Kong, L.; and Bi, W. 2024. GSMPlus: A Comprehensive Benchmark for Evaluating the Robustness of LLMs as Mathematical Problem Solvers. In Proceedings of the 62nd Annual Meeting of the Association for Computational Linguistics (ACL). Mastropaolo, A.; Pascarella, L.; Guglielmi, E.; Ciniselli, M.; Scalabrino, S.; Oliveto, R.; and Bavota, G. 2023. On the Robustness of Code Generation Techniques: An Empirical Study on GitHub Copilot. In Proceedings of the 45th International Conference on Software Engineering (ICSE), 2149– 2160. McKeeman, W. M. 1998. Differential testing for software. Digital Technical Journal, 10(1): 100–107. Miller, G. A. 1995. WordNet: a lexical database for English. Communications of the ACM, 38(11): 39–41. MiniMax AI. 2026. MiniMax-M2.5. https://huggingface.co/ MiniMaxAI/MiniMax-M2.5. Mirzadeh, I.; Alizadeh, K.; Shahrokhi, H.; Tuzel, O.; Bengio, S.; and Farajtabar, M. 2024. GSM-Symbolic: Understanding the Limitations of Mathematical Reasoning in Large Language Models. arXiv preprint arXiv:2410.05229. Newcombe, R. G. 1998. Interval estimation for the difference between independent proportions: comparison of eleven methods. Statistics in medicine, 17(8): 873–890. OpenAI. 2024. Introducing SWE-bench Verified. https: //openai.com/index/introducing-swe-bench-verified/. Accessed: 2026-07-10. OpenCode Contributors. 2024. OpenCode: An Open-Source AI Coding Agent for the Terminal. https://github.com/ anomalyco/opencode. Accessed: 2026-07-10. Pylint contributors. 2026. astroid: An Abstract Syntax Tree Library for Python. https://github.com/pylint-dev/astroid. Qwen Team. 2026. Qwen3.6-27B: Flagship-Level Coding in a 27B Dense Model. Ramakrishnan, G.; Henkel, J.; Wang, Z.; Albarghouthi, A.; Jha, S.; and Reps, T. 2022. Semantic Robustness of Models of Source Code. In IEEE International Conference on Software Analysis, Evolution and Reengineering (SANER), 526–537. Sclar, M.; Choi, Y.; Tsvetkov, Y.; and Suhr, A. 2024. Quantifying Language Models’ Sensitivity to Spurious Features in Prompt Design. In International Conference on Learning Representations (ICLR).

Srikant, S.; Liu, S.; Mitrovska, T.; Chang, S.; Fan, Q.; Zhang, G.; and O’Reilly, U.-M. 2021. Generating Adversarial Computer Programs using Optimized Obfuscations. In International Conference on Learning Representations (ICLR). Stack Overflow. 2025. 2025 Stack Overflow Developer Survey. https://survey.stackoverflow.co/2025/. Accessed: 202607-22. Team, K.; Bai, T.; Bai, Y.; Bao, Y.; Cai, S.; Cao, Y.; Charles, Y.; Che, H.; Chen, C.; Chen, G.; et al. 2026. Kimi K2. 5: Visual Agentic Intelligence. arXiv preprint arXiv:2602.02276. Vega, J.; Chaudhary, I.; Xu, C.; and Singh, G. 2023. Bypassing the Safety Training of Open-Source LLMs with Priming Attacks. arXiv preprint arXiv:2312.12321. Wang, C.; Chaudhary, I.; Hu, Q.; Ruan, W.; Gupta, R.; and Singh, G. 2026. How Catastrophic is Your LLM? Certifying Risks in Conversation. In International Conference on Learning Representations (ICLR). Wang, S.; Li, Z.; Qian, H.; Yang, C.; Wang, Z.; Shang, M.; Kumar, V.; Tan, S.; Ray, B.; Bhatia, P.; et al. 2023. ReCode: Robustness Evaluation of Code Generation Models. In Proceedings of the 61st Annual Meeting of the Association for Computational Linguistics (ACL). Yang, J.; Jimenez, C. E.; Wettig, A.; Lieret, K.; Yao, S.; Narasimhan, K. R.; and Press, O. 2024. SWE-agent: AgentComputer Interfaces Enable Automated Software Engineering. In The Thirty-eighth Annual Conference on Neural Information Processing Systems. Yang, Z.; Shi, J.; He, J.; and Lo, D. 2022. Natural Attack for Pre-trained Models of Code. In Proceedings of the 44th International Conference on Software Engineering (ICSE), 1482–1493. Yefet, N.; Alon, U.; and Yahav, E. 2020. Adversarial Examples for Models of Code. Proceedings of the ACM on Programming Languages (OOPSLA), 4. Yeon, J.; Chaudhary, I.; and Singh, G. 2025. Quantitative Certification of Agentic Tool Selection. arXiv preprint arXiv:2510.03992. Zheng, C.; Zhou, H.; Meng, F.; Zhou, J.; and Huang, M. 2024. Large Language Models Are Not Robust Multiple Choice Selectors. In International Conference on Learning Representations (ICLR). Zhu, K.; Chen, J.; Wang, J.; Gong, N. Z.; Yang, D.; and Xie, X. 2024. DyVal: Dynamic Evaluation of Large Language Models for Reasoning Tasks. In International Conference on Learning Representations (ICLR). Zhu, K.; Wang, J.; Zhou, J.; Wang, Z.; Chen, H.; Wang, Y.; Yang, L.; Ye, W.; Zhang, Y.; Gong, N. Z.; and Xie, X. 2023. PromptRobust: Towards Evaluating the Robustness of Large Language Models on Adversarial Prompts. arXiv preprint arXiv:2306.04528.

A

Semantics-preserving Transformation Implementation Details

The appendix details the implementation of each SPT. It describes the applicability condition of each SPT that restricts the application of the SPT to the candidate sites. Writing these conditions is where the difficulty lies. They must hold across diverse repositories, where the same construct appears in many different implementations, so a condition has to rule out every unsafe variant rather than the common ones. Writing an SPT for a function-level code snippet is comparatively easy. The snippet is short and self-contained, its bindings and callers are visible in the code being rewritten, and the only observable behavior is the value it returns. None of this holds in a repository. Names resolve through nested scopes and imports, so a builtin such as iter, next, or Exception may be shadowed at the rewrite site. Types are not written down either. Addition commutes on numbers, but not on strings, lists, or a class with a custom __add__. A program can also observe its own structure. It can do so through locals(), frame introspection, metaclasses, attribute-dispatch hooks, and framework base classes that fix what a class namespace may contain. Code that never runs can therefore still change behavior. Scale makes this more difficult. A single variant transforms thousands of sites in a repository. So a rule that is not semantics-preserving in a rare case will meet that case. We therefore keep every SPT conservative. When an applicability condition cannot be established from the code, we skip the site. We group the transformations of Table 1 by the operation they perform: rewrites of existing structure and insertions of inert code.

Rewrites If Else Switcher negates the condition and exchanges the two branches. It is applied only to if statements that have a direct else clause. An if whose else branch is another if (i.e. an elif) is not switched. Although an elif clause carrying its own else is itself a valid target. This SPT is also applied to inline ternary expressions, where an else is syntactically required. The condition, and in the ternary case both result expressions, are wrapped in parentheses before negation to maintain correct operator precedence. And Condition Splitter decomposes a compound if statement whose condition is a Boolean conjunction (A and B) into semantically equivalent nested if statements. When the statement has an else clause, that clause is duplicated onto both levels so that failure of either conjunct reaches it. Comparison Swapper exchanges the operands of an asymmetric relational comparison (<, >, <=, >=) and inverts the operator to preserve semantic equivalence. It is restricted to simple two-operand comparisons: chained comparisons and symmetric operators are excluded. Double Negation Injector wraps an if or while condition in not not (Condition). It skips literal True/False conditions and conditions that are themselves a top-level negation, so that a condition such as not x is left alone while a compound condition that merely contains a not (e.g. not a and b) remains eligible.

While Loop Unrolling unrolls one iteration of a while loop: the loop body is duplicated at the head of the new body, followed by an inner while carrying the original test and body, followed by an unconditional break. The outer test is therefore evaluated the same number of times as in the original loop, which matters when the test has side effects. Only loops with an indented block body are transformed, and loops carrying an else clause are excluded, since the injected break would suppress it. For Loop Rewriting rewrites a for loop into a semantically equivalent while True loop using the explicit iterator protocol. It materializes an iterator with iter(...) and advances it with next(...) inside a try/except StopIteration: break block. The introduced iterator and flag names carry a random suffix so they cannot collide with existing bindings. It also emulates the for ... else contract via a sentinel flag. Specifically, each break statement belonging to the rewritten loop—breaks inside nested loops are left untouched—is rewritten to flag = False; break, so that the flag correctly records whether the loop exited early. If the iterable is an implicit tuple, it is explicitly parenthesized before being passed to iter() to avoid the two-argument iter(callable, sentinel) misinterpretation. The transformation is skipped when any of iter, next, or StopIteration is shadowed by a binding in an enclosing scope. async for loops are excluded, as their asynchronous protocol cannot be emulated with synchronous iter()/next(). Commutative Operand Permuter swaps the operands of commutative binary operations: addition, multiplication, bitwise AND, OR, and XOR. Because commutativity holds for these operators only over specific types in Python (e.g., string and list + are order-dependent, and a user-defined __add__/__radd__ need not commute), the transformation performs type inference using Astroid (Pylint contributors 2026) before swapping. The swap is applied only when both operands are independently inferred to lie within the allowed type set for that operator. If inference is inconclusive or the inferred type lies outside the allowed set, the transformation is skipped. Logical and/or are never permuted. Local Variable Renamer renames local variables to semantically related synonyms. Candidates are the targets of plain assignment statements inside function bodies. Module, class-, lambda- and comprehension-level bindings are never renamed. Candidate names are looked up in WordNet (Miller 1995) for a synonym. If none is suitable, or the synonym would collide with an identifier already present in the module, a random five-letter lowercase name is generated. All occurrences within the scope of the binding are updated consistently, including nested scopes that do not rebind the name. We apply a conservative exclusion list to avoid renaming anything whose identity may be externally meaningful or whose rename could not be confined to one scope: built-ins, keywords, very short names, function names, parameters, imported and decorator names, names declared global or nonlocal, loop targets, and variables used in a call position, as an argument, or as part of an attribute access or the base of a subscript. We additionally exclude variables that alias another name (a = b), variables assigned the result of

a call, and any variable bound more than once in its scope, since control flow then determines which binding a reference observes. String Literal Splitter fragments a string literal into a +-joined concatenation at a randomly chosen split point, exploiting that Python evaluates the concatenation of literals to the original value. Because the literal no longer appears as one contiguous token, this frustrates localization strategies that search for the whole string. Splitting is skipped for literals inside type annotations, prefixed byte/raw/unicode strings (escape semantics), strings shorter than a safe split length of four characters, literals used as the base of an attribute access, and literals already part of an implicit concatenation, a non-+ binary operation, or a match pattern. Formatted (f-)strings are never targeted.

Inert Insertions These transformations add code that would never alter program behavior. Two of them—Dead String Assignment and Dead Method Injection—insert code that is inert but lexically salient, forcing an agent that relies on surface cues such as identifier or method names to distinguish genuine edit sites from decoys. If True Wrapper encloses an indented block in a guard built from a grammar of randomly generated tautologies, whose complexity is set by a depth parameter. Because the guard always evaluates to True, every wrapped statement still executes. Candidate blocks are those spanning between 5 and 100 lines, and blocks whose first statement is a docstring are skipped. Try Except Injector wraps an indented block in try ... except Exception: raise. The except clause unconditionally re-raises any exception it catches, so all exceptions are propagated to the same handler as in the unmodified code. We use the except Exception: raise pattern instead of except: raise to avoid catching BaseException subclasses such as KeyboardInterrupt and SystemExit. As with the previous transformation, candidates are blocks of 5 to 100 lines and blocks whose first statement is a docstring are skipped; injection is additionally skipped when Exception is shadowed by a binding at the injection site, which would otherwise make the handler itself raise TypeError. Dead-Code Injector inserts an if False block containing a dummy assignment at the head of an indented block. The guard renders the block statically unreachable. When the block begins with a docstring, the injection is placed after it so that __doc__ is preserved. Dead String Assignment injects an unread assignment of the form <name> = "<keyword>" before selected statements inside a function body. The keyword-like string serves as a distractor resembling content an agent might search for, while remaining a no-op. The <name> is drawn from a fixed pool, chosen so as not to shadow any identifier used in the enclosing function, and is never read. Injection never displaces a leading docstring and is not placed after an unconditional terminator (return/raise/break/continue) in the same block. Any function that reflects on its lo-

Algorithm 2 Target Assignment Input: Selected transformations Tselected , Keyword map K, Maximum number of keywords to select Nk Output: Bound (transformation, target) pairs B 1: procedure AssignTargetNames(Tselected , K, Nk ) 2: B←∅ 3: for each transformation t ∈ Tselected do 4: if t ∈ / Tkw or K = None then 5: B ← B ∪ {(t, None)} ▷ no target required 6: else 7: names ← K[t] ▷ candidates extracted for t 8: if names = ∅ then 9: B ← B ∪ {(t, None)} 10: else 11: targetedKeywords ← RandomSelect(names, min(Nk , |names|)) 12: for each τ ∈ targetedKeywords do 13: B ← B ∪ {(t, τ )} 14: end for 15: end if 16: end if 17: end for 18: return B 19: end procedure

cal namespace is excluded, as introducing a new binding would be observable: this covers locals(), argument-less vars(), eval/exec calls that do not pass explicit globals and locals, and frame introspection via sys._getframe, inspect.currentframe, inspect.stack, and related APIs. Dead Method Injection appends a structurally complete method, def <name>(self, *args, **kwargs) whose entire body is guarded by if False, to a class body, serving as a highly plausible edit decoy. The method is callable but its body is unreachable, so it always returns None without side effects. Crucially, appending a method is not unconditionally behavior-preserving, because a class may observe its own attribute namespace. The transformation is therefore skipped whenever a class controls that namespace: classes declaring a custom metaclass, classes that override attribute dispatch (__getattr__, __getattribute__, __setattr__, __delattr__), property-only namespaces, sentinel classes whose body is a bare pass or ..., and classes whose base list mentions an attributeconstraining framework type (e.g., Pydantic BaseModel, Enum, NamedTuple, TypedDict, Protocol, ABC), matched by the simple name of the base expression. A class is also skipped when it already declares the target name as a method or class attribute, and dunder target names are excluded outright.

B

Sampler Procedure Details

Algorithm 2 describes the sub-procedure invoked by the sampler described in Algorithm 1.

C

Experimental Procedure Details

Sampling Procedure To construct our task sample, we first identified instances resolved by Claude Opus 4.5 using official SWE-bench Verified leaderboard results, ensuring that our sampled tasks were solvable under standard (unperturbed) conditions. We then performed stratified sampling over repository–difficulty combinations, drawing one instance per stratum to ensure balanced coverage of the instance space. Since official instance wise results were unavailable for SWE-bench pro, we started by sampling an equal number of instances from each of the repos, and running Claude Opus 4.5 on the set. Then, 26 passing instances were sampled across all repos that contained at least one valid python file to which the SPTs could be applied.

Full Experimental Procedure Algorithm 3 gives the full experimental procedure summarized in the Protocol paragraph of the experiments section. For each instance it proceeds in four phases: seed retrieval, baseline evaluation (N runs on the unperturbed seed), variant generation via the sampler of Algorithm 1 of the variant sampler section, and perturbed evaluation (one run per variant, each in a freshly provisioned environment).

Computational Infrastructure All experiments were run on one lab server. It has two AMD EPYC 9554 64-core processors (128 cores, 256 threads), 768 GB RAM, 6 Nvidia RTX PRO 6000 Blackwell GPUs (96 GB VRAM per GPU), and a 7 TB NVMe drive. The operating system is Ubuntu 24.04.4 LTS. Each agent run executes in its own Docker container (Docker version 29.5.2). We serve Qwen 3.6-27B on this machine with vLLM (v0.20.1) using 2 GPUs. We access Claude Opus 4.5( AWS bedrock ID: anthropic.claude-opus-4-5-20251101v1:0), Kimi K2.5 (AWS bedrock ID: moonshotai.kimi-k2.5) and Minimax M2.5 (AWS bedrock ID: minimax.minimaxm2.5) using Amazon Bedrock API. All 4 models used temperature 1.0. Our code is Python 3.10, using LibCST v1.8.5 for SPTs, Astroid v3.3.0 for type inference, and NLTK v3.6.0 for WordNet lookups. The scaffolds are mini-SWE agent v1.17.5 and OpenCode v1.18.4. Cost accounting of Qwen 3.6. Reported costs are token costs. For the three models accessed through Bedrock we use the provider’s published per-token prices. Qwen 3.6-27B is served locally and to keep costs comparable across models we price its input and output tokens at the OpenRouter rates for the same model. The same price schedule is applied to the unperturbed and perturbed runs of an instance, so δcost is an internally consistent within-instance comparison.

Randomness and Reproducibility We do not fix a random seed. Our pipeline is random in two places. The sampler (Algorithm 1) draws the transformation subset, the file-inclusion probability pfile , the sites within each file, and the target keywords. And all four models are sampled at temperature 1.0, so a run is stochastic even on a fixed repository. A seed fixes which 20 variants we draw, not

Algorithm 3 Agent Robustness Experiment Input: Set of Instance IDs I, Number of samples N , Configuration C, Agent A, Evaluator E, Transformations T , Sampler hyperparameters Nt , Nk , ϕ, Nf Output: Baseline Reports R0 , Perturbed Reports Rp 1: procedure RunExperiment(I, N , C, A, E, T , Nt , Nk , ϕ, Nf ) 2: R0 ← ∅, Rp ← ∅ ▷ Initialize report collections 3: for each instance i ∈ I do 4: ▷ Phase 1: Seed Retrieval 5: (Cseed , Fgold , desc) ← ExtractInstance(i) 6: ▷ Phase 2: Baseline Evaluation 7: for k ← 1 to N do 8: Eeval ← ProvisionEnvironment(i) ▷ unperturbed seed, no injection 9: R ← RunAndEvaluate(A, E, Eeval , i, C) 10: R0 ← R0 ∪ R 11: end for 12: ▷ Phase 3: Variant Generation (Algorithm 1) 13: S ← GenerateVariants(Cseed , N , T , Fgold , desc, Nt , Nk , ϕ, Nf ) 14: ▷ Phase 4: Perturbed Evaluation 15: for each sample s ∈ S do 16: Eeval ← ProvisionEnvironment(i) 17: InjectCode(Eeval , s) 18: R ← RunAndEvaluate(A, E, Eeval , i, C) 19: Rp ← Rp ∪ R 20: end for 21: end for 22: return (R0 , Rp ) 23: end procedure 24: procedure RunAndEvaluate(A, E, E, i, C) 25: P atch ← ExecuteAgent(A, E, i, C) 26: Report ← EvaluatePatch(E, i, P atch) 27: return Report 28: end procedure

what the agent does on them: rerunning the agent on the same variant can give a different outcome. Reproducing our results therefore means drawing 20 fresh variants per instance at the same hyperparameters and recovering our reported effects. The bootstrap of the statistical protocol is the exception: it is seeded.

Code and Instance Lists Our code and data are publicly available at https://github. com/CSU-TrustLab/jagged-frontier. The repository contains the full implementation of the experiment and analysis. This includes the SPT implementations, the variant sampler of Algorithm 1, the evaluation harness of Algorithm 3, the analysis scripts that produce the reported statistics and figures, and an interactive dashboard for exploring the results. The prompts used are included there as well, as is the list of the 28 SWEbench Verified and 26 SWE-bench Pro instance IDs used in the study.

Agent Scaffold Comparison This table 2 compares between mini-SWE agent and OpenCode scaffold.

Selection of hyperparameter values We did not conduct a search over the sampler’s hyperparameter space. A single configuration at a single hyperparameter setting costs 54 × 40 = 2,160 agent runs. So even a coarse grid over (Nt , Nk , ϕ, Nf ) would multiply the cost of the study by an order of magnitude. We instead fixed values for each parameter. Nt = 3 of the 14 transformations makes a variant a composition of several SPTs. ϕ = 0.7 leaves a minority of candidate sites in a file untouched. So a variant contains both transformed and untransformed instances of the same pattern. Nk = 5 and Nf = 10 are the only values set from observation. Without them, agents frequently detected the perturbation and reverted the repository outright (e.g. via git reset), which destroys the measurement rather than making it harder.

D

Additional Experiment Results

Resolve rates fall, but capability rankings survive. Figure 3 shows the mean resolve rate on unperturbed and perturbed runs for each model under each scaffold, separately on SWE-bench Verified and SWE-bench Pro. In 13 of the 16 scaffold-model-benchmark combinations the agent resolves fewer issues after perturbation. The three remaining combinations move slightly in the other direction, each by less than one point, within run-to-run noise. Perturbation, however, barely disturbs the models’ capability ordering. In three of the four scaffold-benchmark panels, the ranking of models by resolve rate is identical before and after perturbation. In the fourth (OpenCode on SWE-Pro), the only change is a swap between MiniMax and Qwen, which are separated by just 0.2 points at baseline. This shows that a leaderboard-style comparison would not register the impact of SPTs. The ranking that perturbation does scramble is the ranking by robustness, as we show next.

Effort Overhead over All Runs Figure 4 repeats the RQ2 effort analysis of the main text over all runs, rather than only the runs the agent resolved. The trends match the resolved-only figure. On SWE-bench Verified cost rises in all eight configurations, from 4.5% (miniSWE agent with Opus) to 25.4% (OpenCode with MiniMax), with the interval excluding zero in seven of the eight. On SWE-bench Pro cost rises in seven of the eight, by up to 14.7% (OpenCode with Kimi), with six intervals excluding zero. The one exception, mini-SWE agent with Opus, is flat at −0.1%. Step counts move less than cost in both benchmarks, and Opus under mini-SWE agent on Verified again takes 19.7% fewer steps while still costing more. Because the two views agree, the overhead cannot be attributed to long failing runs, and we report the resolved-only view in the main text as the more conservative one.

Per-Instance Degradation Plots Figures 5 and 6 give the per-instance degradation ∆(i) with its Newcombe 95% interval for every instance-configuration cell. This section reports the underlying numbers for the concentration claim of the RQ1 results. With 20 runs per condition, a Newcombe interval is wide by construction: even an instance resolved in every run of both conditions carries a ±16-point interval. The interval excludes zero in only 7 of the 224 cells on SWE-bench Verified and 7 of the 208 on SWE-bench Pro. Most intervals are therefore too wide to establish degradation for a specific instance, although their mass is shifted toward positive values. Point estimates are positive in 65 cells against 35 negative on SWE-bench Verified, and 79 against 44 on SWE-bench Pro. The individually significant cells concentrate in the tail. On SWE-bench Verified, scikit-learn__scikit-learn-14983 loses 40 points under OpenCode with Qwen, matplotlib__matplotlib-20859 loses 35 under mini-SWE agent with Qwen, and sympy__sympy-12489 loses 30 under mini-SWE agent with MiniMax. On SWEbench Pro, element-web_dae13 loses 50 points, openlibrary_f3b26 40, and openlibrary_a7b7d 35, all under mini-SWE agent with Opus. These three Pro cells alone account for roughly two thirds of that configuration’s 6.7-point mean degradation. Across configurations, qutebrowser_ef5ba and ansible_9142b degrade in seven of eight, and sympy__sympy-11618 in five while never improving. Single cells also swing the other way: mwaskom__seaborn-3069 improves by 55 points under OpenCode with MiniMax and by 35 under mini-SWE agent with Qwen, both with intervals excluding zero. With a single mwaskom__seaborn instance in the sample, such swings should not be read as a repository-level effect.

E

Unbiasedness of the Degradation Estimator

We estimate perturbed performance by running the agent once on each of N = 20 sampled variants. Because a single run of a stochastic agent is a noisy measurement of that variant’s difficulty, it is reasonable to ask whether one run per variant is enough. An alternative would be to draw fewer variants and run each several times, averaging away the agent’s randomness. This appendix shows that no such averaging is needed. Per-instance degradation is unbiased for any number of runs per variant including one, and under a fixed run budget one run per variant is in fact the variance-minimizing allocation.

Setup and notation Consider, a task instance i and a configuration (scaffold, model, benchmark). Variant sampling. A variant V is drawn by the variant sampler from the population of semantics-preserving variants of instance i. Each variant carries a true resolve probability pV = Pr(agent resolves V | V ), (1)

Table 2: Comparison of mini-SWE and OpenCode Agent Scaffolds Category

mini-SWE

OpenCode

Architecture

Single, centralized agent

Primary agents invoke tools and subagents for specific tasks (e.g., Build, Plan, General, Explore)

Available Tools

bash

bash, edit, write, read, grep, glob, lsp, apply_patch, skill, todo_write, web_fetch, web_search, question

Access Restrictions

None

Available tools determined by an agent’s role and user configuration

Context Management Continuous, append-only

Multiple, dynamically changing contexts for different subagents

Figure 3: Mean resolve rate (%) on unperturbed and perturbed runs for each model under each scaffold, on SWE-bench Verified (top) and SWE-bench Pro (bottom).

Figure 4: Mean relative change in agent steps (δ̄step ) and cost (δ̄cost ) after perturbation over all runs, for each scaffold–model configuration on the 28 SWE-bench Verified instances (left) and the 26 SWE-bench Pro instances (right). Positive values mean perturbed runs take more steps, or cost more, than unperturbed runs on the same instance. Error bars are fixed-population 95% bootstrap confidence intervals.

the probability that the agent resolves that specific variant, averaged over the agent’s own randomness. Because V is itself random, pV is a random variable. It is the difficulty of a randomly chosen semantically equivalent rewrite of instance

i.

Figure 5: Per-instance degradation ∆(i) for the 28 SWE-bench Verified instances under each configuration. Error bars are Newcombe 95% confidence intervals for the difference between the unperturbed and perturbed resolve proportions (n=20 runs per condition). Agent sampling. Given a fixed variant v, a single agent run yields a resolve/no-resolve indicator Y | (V = v) ∼ Bernoulli(pv ),

E[Y | V = v] = pv . (2) The agent’s stochasticity is conditionally independent of how the variant was chosen, given the variant. This is enforced by the experimental protocol. Every run executes in a freshly provisioned, isolated environment, so no state carries between runs.

Estimands. The population quantity that rp (i) targets is the mean per-variant resolve probability, µ = E[pV ],

(3)

and its companion, the spread of difficulty across variants, is σ 2 = Var(pV ).

(4)

Here µ summarizes average performance on variants, while σ 2 measures consistency — how much the agent’s success probability swings across semantically identical inputs.

Figure 6: Per-instance degradation ∆(i) for the 26 SWE-bench Pro instances under each configuration. Error bars are Newcombe 95% confidence intervals for the difference between the unperturbed and perturbed resolve proportions (n=20 runs per condition). Degradation is ∆(i) = p0 − µ, where p0 is the resolve probability on the unperturbed seed. ∆(i) = p0 − µ is estimated ˆ by ∆(i) = r0 (i) − rp (i), with rp (i) = µ̂. Data. We draw N variants V1 , . . . , VN independently and run the agent K times on each, recording the pass count and empirical pass rate Xj | (Vj = vj ) ∼ Binomial(K, pvj ),

p̂j = Xj /K. (5)

Our protocol is N = 20, K = 1. A useful identity. One identity relates the within-variant noise to the two estimands and is used repeatedly below.

Write   ν = E pV (1 − pV )

(6)

for the average within-variant Bernoulli variance. Expanding and applying E[p2V ] = Var(pV ) + (E[pV ])2 = σ 2 + µ2 , ν = E[pV ] − E[p2V ] = µ − (σ 2 + µ2 ) = µ(1 − µ) − σ 2 , (7) so that σ 2 + ν = µ(1 − µ).

(8)

The total variability in a single perturbed run therefore splits into a between-variant part σ 2 and a within-variant part ν.

The estimator

Step 1: variance of one per-variant rate. Decompose Var(p̂j ) with the law of total variance,    Var(p̂j ) = Var E[p̂j | Vj ] + E Var(p̂j | Vj ) . (14)

The estimator of µ is the average of the per-variant rates, N

µ̂ =

1 X p̂j . N j=1

(9)

At K = 1 we have p̂j = Yj ∈ {0, 1} and this collapses to µ̂ =

#{variants resolved} , N

(10)

an ordinary binomial proportion. We use this formula to calculate resolve rate for perturbed runs.

The first term is Var(pVj ) = σ 2 by Eqs. (11) and (4). For the second, p̂j = Xj /K with Xj | Vj ∼ Binomial(K, pVj ), so Var(p̂j | Vj ) = pVj (1 − pVj )/K, whose expectation over variants is ν/K by Eq. (6). Hence ν Var(p̂j ) = σ 2 + . (15) K Step 2: variance of the estimator. The variants are drawn independently and each is run in an isolated environment, so the p̂j are i.i.d. and

Why it is unbiased for any K, including K = 1 Var(µ̂) = The argument conditions on the variant first and averages  over variants second, using the tower property E[ · ] = E E[ · |  V] . Step 1: collapse the agent randomness. Condition on the j-th variant Vj and write Yj1 , . . . , YjK for the K runs on it. By Eq. (2) each has conditional mean pVj , so h P i PK K 1 1 E[p̂j | Vj ] = E K = K k=1 Yjk Vj k=1 E[Yjk | Vj ] 1 = · K p Vj = p Vj . K (11) The factors of K and 1/K cancel, so this holds regardless of K. Even a single draw, K = 1, is already unbiased for its own pVj . Step 2: collapse the variant randomness. Because Vj is itself random, the conditional mean in Eq. (11) is a random variable, and averaging it over the variant population gives, by the tower property and Eq. (3),     E[p̂j ] = E E[p̂j | Vj ] = E pVj = µ. (12) Step 3: average over variants. applied to Eq. (9),

By linearity of expectation,

N

1 X 1 E[µ̂] = E[p̂j ] = · N µ = µ. N j=1 N

(13)

Consequence. The parameter K never appears in Eqs. (11)–(13). Repetition is a variance-reduction operation. It tightens each p̂j around the center pVj , but that center was already correct, so tightening cannot remove a bias that was never there. One run per variant is exactly as unbiased as a thousand.

Variance, and why K = 1 is the efficient allocation Unbiasedness alone does not justify K = 1. An unbiased estimator can still be noisy. We now show that K = 1 is not only admissible but optimal.

N 1 X σ2 ν σ2 ν Var(p̂ ) = + = + , j 2 N j=1 N NK N R

(16) writing R = N K for the total number of agent runs. The within-variant noise term ν/R depends only on the total budget R; how those runs are distributed across variants is irrelevant to it. The between-variant term σ 2 /N depends only on the number of distinct variants N , and K does not appear in it at all. Step 3: optimize under a fixed budget. Assume a fixed run budget R and substitute N = R/K into Eq. (16): Var(µ̂) =

Kσ 2 ν Kσ 2 + ν + = . R R R

(17)

This is strictly increasing in K whenever σ 2 > 0, and is therefore minimized at K = 1. Under a fixed number of agent runs, the variance-optimal design for estimating the mean is to spend every run on a new variant and run the agent once. Step 4: the K = 1 specialization. At K = 1 the estimator’s variance simplifies. Substituting the identity (8) into Eq. (17) with K = 1 and R = N , µ(1 − µ) σ2 + ν = . (18) N N This has a direct interpretation. Each Yj is marginally Bernoulli(µ) and the N trials are independent, since each uses a distinct variant and no two share a draw. So µ̂ is p a textbook binomial proportion with standard error µ̂(1 − µ̂)/N , and rp (i) may be compared to r0 (i) with a standard two-proportion procedure. No clustering correction is needed at the variant level precisely because every trial is a different variant. Var(µ̂) =

F

Qualitative Analysis Details

Instance Selection Procedure 12/20 of these instances are manually picked by evaluating characteristics like high variance (3), high degradation (3), large increase in step count (1) or file coverage (2) or cost (1), or cases with 1/20 mutant failures (2). The remaining 8/20 are picked by passing mutants that the agent had failed

to resolve through an LLM prompt designed to take the SPT log as well as a condensed version of the agent trajectory as input, and predict possible SPT impact based on the SPTs that were applied, intersection of files touched by both the agent and the SPTs, and specific snippets from agent thoughts or tool outputs that have SPT markers. This is done for 115 failing trajectories across all 16 experiments. The resulting output is then manually evaluated to shortlist 8 trajectories for final human review.

AI-Assisted Trajectory Analysis The same prompt also extracts a sequence of events from the trajectory, citing snippets from the raw trajectory for each, while also classifying each event as one of the following: Localization (exploring the repo to find relevant code), Debugging (reasoning, specifically based on observed outputs), Planning (forming a plan for patching), Patching (Implementation of changes), Validation (Testing of changes), Recovery (Backtracking on implemented changes or proposed plan) or General (additional events that don’t come under any of the 6 aforementioned types, for example, patch submission). A final HTML is generated, containing the raw trajectory, a graph with the extracted events, including snippets from the actual trajectory, a record of files touched by both the agent and the SPTs, and script based results like git statements, Human evaluators then use this html to get a comprehensive view of the trajectory while analyzing. This is strictly an assistive method, and all qualitative analysis examples mentioned in the paper have involved actual human review of all relevant portions of the raw trajectories.

Additional Qualitative Insights Variability in SPT detection. There is high variance in whether SPTs are detected at all even in cases where the agent repeatedly accesses mutated code. While some SPTs like double negation are easier to miss, SPTs which have been detected in other cases, like if true wrapper, are ignored in cases like Opus on Psf-Requests with mini-SWE agent. In this particular case, even though the agent accesses mutated code multiple times, it never acknowledges any SPT presence. Moreover, consistent with the qualitative results, SPT impact appears to be variable across instances, with more impact seen in repos like qutebrowser, openlibrary, ansible, pytest and sympy as compared to repos like nodeBB or astropy, based on qualitative reviews. Additional examples of agent response to SPTs. There are multiple other examples of how agents choose to respond to SPTs. In Qwen on Matplotlib with OpenCode, after detecting SPTs, the agent decides to reset the repository. However, it claims to have reset it multiple times without actually doing so, and only later ends up proceeding with it. In another case, Opus on Qutebrowser with mini-SWE agent, the agent notices complicated booleans introduced by the if true wrapper in the relevant code, and spends additional time in resolving the booleans into final true/false values. It later also "fixes" them in the final patch, thereby investing significant effort in interacting with the SPTs. In contrast, MiniMax with miniSWE agent on Qutebrowser chooses to avoid core files that

have been transformed by SPTs, and instead tries to get information from other sources in the repository, subsequently increasing the time taken to localize the issue as well as file coverage. Input prompt impacts agent jaggedness. We observe that issue description quality and nature of issue may impact agent jaggedness. We analyse Qwen, Kimi and Opus on the same NodeBB issue which exhibits high variance across various model and scaffold pairs. The issue description contains two conflicting statements — editing the code to satisfy issue requirements causes one of the unit tests to break, and the description explicitly states not to alter any unit tests. This leads to all three agents falling into a loop of patching, validating, and debugging, while going back to the issue description multiple times, which substantially adds to both the step count and cost. In a passing trajectory for the same issue, the agent comes across the same conflict and fails the same test, but doesn’t backtrack on the code and therefore ends up passing. So the conflicting nature of the issue instructions greatly contributes to jaggedness in agent performance, as it is left to its own judgement to resolve the conflict. Robustness of test suite formation varies. For Astropy, Kimi uses a three-level test suite, complete with custom tests for basic functionality, project test suite, and a dedicated edge cases script. However, in Pytest and Qutebrowser, the validation framework is brittle, with insufficient debugging and incorrect failure attribution to SPTs in the former and shifting test cases during debugging in the latter. Similarly, for MiniMax, validation setup is comprehensive in Sympy, but has incorrect assertions in custom test scripts in Qutebrowser.

Related documents

Record · ID 471321 · SHA-256 7389f613a8d3b29f
Retrieved via Conceptio: every document is proof-bundled with source, license, and retrieval metadata.
Bring this data into your agent: Connect via MCP or API · 20 free credits to start · no card required
Read the Docs → · View CLI source on GitHub · Conceptio Open Knowledge Archive