Execution-Conditioned Repair LoRA Experiment
The one idea you need
Show the model broken code, its own failed fix, and the exact test error that fix triggered, then train it to write a correction. Like a mechanic who memorizes repairs for the specific cars in the shop manual but stalls on any model the manual never listed.
The question
If you train a small model to fix its own broken code by showing it the failed attempt and the error it caused, does that skill work on brand-new bugs?
What we found
No. On bugs built from the same templates it practiced on, the fixer repaired all 60 of 60 cases, versus 11 of 60 with ordinary patch training and 6 of 60 with no training at all. But on bug types it never saw, every method fixed zero of 27, and scrambling or deleting the error message changed nothing. It memorized templates, not repair.
Why it matters
Impressive repair scores on familiar bugs can be pure template memorization. Test any small-model code fixer on bug types absent from training, and read the hidden tests: high patch-apply and visible-pass rates can mask zero real repair.
On this page
Results at a glance 7
How to read
Each group along the bottom is a way of training the model to fix its broken code; bar height is the share of bugs fixed after the first failed try. Darker bars are familiar practiced bug types, lighter bars are brand-new types. Taller is better.
Takeaway → The three repair-trained methods hit full height on familiar bugs, but every brand-new-type bar sits flat at zero — memorization, not transferable repair.
Data table
| condition | IID families (n=60) | held-out families (n=27) |
|---|---|---|
| frozen second attempt | 10% | 0% |
| final-patch SFT | 18.3% | 0% |
| no-trace repair SFT | 100% | 0% |
| trace repair SFT | 100% | 0% |
| shuffled-trace repair SFT | 100% | 0% |
Numbers from reports/v2_*_iid_results.json and reports/v2_*_family_holdout_results.json (summary.repair_after_first_failure@1)
Technical framing
Repair success collapses on held-out bug families (Qwen3-4B) — Repair-conditioned adapters solve 100% of same-family bugs but 0% of unseen families — template memorization, not transferable repair.
How to read
Bars group by four training methods for a model already specialized in code; height is the share of bugs fixed. Darker bars are familiar practiced types, lighter bars are unseen types. Taller is better.
Takeaway → Familiar bars again reach full height while unseen-type bars barely lift off the floor even with the error message shown — too tiny to credit.
Data table
| condition | IID families (n=60) | held-out families (n=27) |
|---|---|---|
| final-patch SFT | 28.3% | 0% |
| no-trace repair SFT | 100% | 7.4% |
| trace repair SFT | 100% | 11.1% |
| shuffled-trace repair SFT | 100% | 0% |
Technical framing
Coding-specialist ablation: tiny held-out transfer, same IID saturation (Qwen2.5-Coder-3B) — The coder model recovers only 3/27 held-out repairs with traces vs 2/27 without — one success above the no-trace control, too weak to credit traces.
How to read
Bars group by how much the prompt tells the model (real error, blank error, wrong-fix only, error-only, files hidden). One color is how often the patch applies without error, the other how often it truly fixes the bug. Fix higher is better.
Takeaway → Apply-cleanly bars stand tall, up to 93%, while every real-fix bar is zero — getting a patch to apply is not the same as fixing the bug.
Data table
| prompt mode | patch apply rate | repair rate @1 |
|---|---|---|
| trace | 44.4% | 0% |
| no trace | 55.6% | 0% |
| wrong patch only | 18.5% | 0% |
| trace only | 92.6% | 0% |
| gold file removed | 18.5% | 0% |
Numbers from reports/execution_conditioned_repair_paper.md (table: v2 Trace Adapter on v2 Held-Out Families)
Technical framing
Trace-prompt ablation on held-out families: patches apply but nothing repairs — Every prompt ablation repairs 0/27 held-out bugs even when most patches apply cleanly — execution traces show no causal benefit.
How to read
Two bars for how long the model was trained, short versus long. One color is fixes on the 20 practiced bugs, the other is fixes on set-aside bugs it never saw. Taller is better, especially the set-aside bar.
Takeaway → Longer training lifts practiced-bug fixes from 15% to 95%, yet set-aside fixes stay flat at zero — extra training only deepens memorization.
Data table
| Training length | Repair rate on 20 training episodes | Repair rate on 14 held-out episodes |
|---|---|---|
| 3-epoch adapter | 15% | 0% |
| 12-epoch adapter | 95% | 0% |
Technical framing
More training buys memorization, not transfer (Qwen3-4B trace adapter) — Extending training from 3 to 12 epochs lifts train-set repair from 15% to 95%, yet held-out repair stays at exactly zero.
How to read
Bars group by five training methods on unseen bug types. One color is how often the patch applies, the other how often it passes the shown test but fails the hidden ones. A tall second bar is bad — it means gaming.
Takeaway → For the repair-trained methods most applied patches pass the visible test yet fail the hidden ones — satisfying the shown check, not fixing the bug.
Data table
| Condition | Patch applies | Passes visible test, fails hidden tests |
|---|---|---|
| Frozen second attempt | 18.5% | 14.8% |
| Final-patch SFT | 37% | 0% |
| No-trace repair SFT | 44.4% | 37% |
| Trace repair SFT | 44.4% | 44.4% |
| Shuffled-trace repair SFT | 44.4% | 25.9% |
Numbers from report table (reports/execution_conditioned_repair_paper.md, v2 held-out-family results)
Technical framing
On new bug families, repair SFT learns to game the visible test (Qwen3-4B, v2 held-out) — Every applied trace-adapter patch on held-out families passes the visible test but fails hidden tests — overfitting, not repair.
How to read
Bars group by five training methods on unseen bug types. One color is the share fixed when keeping the best of three tries, the other is how often the patch applies. A taller fix bar is better.
Takeaway → The best-of-three fix bars are all zero while patches still apply — extra attempts buy nothing on bug types the model never practiced.
Data table
| Condition | Repair success, best of 3 samples | Patch applies |
|---|---|---|
| Frozen second attempt | 0% | 18.5% |
| Final-patch SFT | 0% | 40.7% |
| No-trace repair SFT | 0% | 44.4% |
| Trace repair SFT | 0% | 44.4% |
| Shuffled-trace repair SFT | 0% | 44.4% |
Numbers from report table (reports/execution_conditioned_repair_paper.md, v2 held-out-family best-of-3 results)
Technical framing
Sampling 3 candidates does not rescue held-out repair (Qwen3-4B, v2) — At temperature 0.2 with 3 samples per episode, patches still apply but repair@3 is 0 for every condition — more samples buy nothing.
How to read
Bars group by five training methods on the first pilot's unseen bugs. Colors show how often the patch applies, how often the output is valid code, and how often it actually fixes the bug. A taller real-fix bar is better.
Takeaway → Apply and valid-code bars climb toward 71% while the real-fix bar stays at zero for every method — surface polish, no repair.
Data table
| Condition | Repair success | Patch applies | Output is valid Python |
|---|---|---|---|
| Frozen second attempt | 0% | 7.1% | 7.1% |
| Final-patch SFT | 0% | 42.9% | 28.6% |
| No-trace repair SFT | 0% | 57.1% | 57.1% |
| Trace repair SFT | 0% | 71.4% | 64.3% |
| Shuffled-trace repair SFT | 0% | 64.3% | 64.3% |
Numbers from report table (reports/execution_conditioned_repair_paper.md, v1 held-out synthetic results)
Technical framing
v1 pilot: SFT fixed diff formatting, never semantics (Qwen3-4B, 14 held-out episodes) — In the first pilot, SFT raised patch applicability from 7% to 71% while repair success stayed at zero across all conditions.
In the author’s words from the Report · “Abstract”
We tested whether a single QLoRA adapter trained to repair after a failed patch outperforms a single final-patch SFT adapter. On an expanded synthetic IID split, failure-conditioned adapters solved all examples while the final-patch SFT repaired 11/60 and the frozen second-attempt baseline repaired 6/60. However, this success did not transfer to held-out synthetic bug families: every condition repaired 0/27 examples. A secondary coding-specialist ablation with Qwen2.5-Coder-3B reproduced the IID result and found a small held-out-family trace result, 3/27, compared with 2/27 for no-trace, 0/27 for shuffled-trace, and 0/27 for final-patch. … Read the full result →
Overview
This workspace implements the experiment brief in /root/.codex/attachments/67be2ef6-a2f4-424d-a411-f0479b10c076/pasted-text-1.txt.
Core question:
Does single-adapter QLoRA SFT on
buggy repo + wrong patch + execution trace -> corrective diffimprove executable repair over ordinary final-patch SFT?
The code is deliberately organized around the brief's required deliverables:
scripts/build_repair_dataset.pyscripts/sample_wrong_patches.pyscripts/compute_corrective_diffs.pyscripts/train_repair_lora.pyscripts/eval_repair_synthetic.pyscripts/eval_repair_swebench.pyscripts/run_trace_ablation.py
Current environment note: Docker can be installed but nested container execution is blocked by kernel namespace/mount restrictions in this runner. SWE-smith and SWE-bench scripts are present, but official Docker-backed evaluation is not considered verified until scripts/eval_repair_swebench.py --preflight-only passes.
Recommended first pass:
python scripts/build_repair_dataset.py --output-dir data
python scripts/compute_corrective_diffs.py --input data/repair_train.jsonl --output data/repair_train.checked.jsonl
python scripts/train_repair_lora.py --train data/repair_train.jsonl --eval data/repair_val_synth.jsonl --mode final_patch --output-dir models/final_patch_sft_lora
python scripts/train_repair_lora.py --train data/repair_train.jsonl --eval data/repair_val_synth.jsonl --mode no_trace --output-dir models/failure_conditioned_no_trace_lora
python scripts/train_repair_lora.py --train data/repair_train.jsonl --eval data/repair_val_synth.jsonl --mode trace --output-dir models/failure_conditioned_trace_lora
python scripts/eval_repair_synthetic.py --data data/repair_val_synth.jsonl --output reports/frozen_second_attempt_results.json --prompt-mode trace
python scripts/run_trace_ablation.py --data data/repair_val_synth.jsonl --adapter models/failure_conditioned_trace_lora --output reports/trace_ablation_results.json
python scripts/make_report.py --output reports/transfer_gap_report.mdReport
Rendered from reports/transfer_gap_report.md
Abstract
We tested whether a single QLoRA adapter trained to repair after a failed patch outperforms a single final-patch SFT adapter. On an expanded synthetic IID split, failure-conditioned adapters solved all examples while the final-patch SFT repaired 11/60 and the frozen second-attempt baseline repaired 6/60. However, this success did not transfer to held-out synthetic bug families: every condition repaired 0/27 examples. A secondary coding-specialist ablation with Qwen2.5-Coder-3B reproduced the IID result and found a small held-out-family trace result, 3/27, compared with 2/27 for no-trace, 0/27 for shuffled-trace, and 0/27 for final-patch. Three non-official direct pytest probes on SWE-bench Verified Flask/Requests tasks had base-fails/gold-passes behavior; the trace repair condition scored 0/3, and no Qwen3 repair condition solved any probe. Trace controls did not establish a causal benefit from execution traces. Official SWE-bench-style Docker execution is unavailable in this runner because Docker cannot register container layers (unshare: operation not permitted), so no valid real-task transfer ratio is claimed.
Main Claim
The experiment does not support the hypothesis that failure-conditioned trace SFT learns transferable execution-conditioned repair. The stronger observed effect is template-family memorization: the repair adapters master same-family synthetic validation but the primary Qwen3 adapters fail completely on unseen synthetic families. The coding-specialist ablation weakens the broadest version of that negative claim, but its 3/27 held-out-family result is small and only one success above the no-trace control.
Model and Training
- Base model:
Qwen/Qwen3-4B-Instruct-2507. - Revision:
cdbee75f17c01a7cc42f958dc650907174af0554. - Quantization/training: 4-bit NF4 QLoRA, frozen base, BF16, rank 32, alpha 64.
- Loss: assistant diff tokens only.
- Compared adapters: final-patch SFT, no-trace repair SFT, trace repair SFT, shuffled-trace repair SFT.
- Secondary model ablation:
Qwen/Qwen2.5-Coder-3B-Instructat revision488639f1ff808d1d3d0ba301aef8c11461451ec5for C/D/E/F. - Evaluation applies generated diffs to the wrong-patched tree and then runs visible and hidden tests.
v2 adapter metadata:
| adapter | model | mode | shuffle_traces | rank | alpha | dropout | epochs | lr | max_length | train_records |
|---|---|---|---|---|---|---|---|---|---|---|
| coder_v2_failure_conditioned_no_trace_lora | Qwen/Qwen2.5-Coder-3B-Instruct | no_trace | False | 32 | 64 | 0.05 | 3 | 0.00015 | 4096 | 240 |
| coder_v2_failure_conditioned_shuffled_trace_lora | Qwen/Qwen2.5-Coder-3B-Instruct | trace | True | 32 | 64 | 0.05 | 3 | 0.00015 | 4096 | 240 |
| coder_v2_failure_conditioned_trace_lora | Qwen/Qwen2.5-Coder-3B-Instruct | trace | False | 32 | 64 | 0.05 | 3 | 0.00015 | 4096 | 240 |
| coder_v2_final_patch_sft_lora | Qwen/Qwen2.5-Coder-3B-Instruct | final_patch | False | 32 | 64 | 0.05 | 3 | 0.00015 | 4096 | 240 |
| v2_failure_conditioned_no_trace_lora | Qwen/Qwen3-4B-Instruct-2507 | no_trace | False | 32 | 64 | 0.05 | 3 | 0.00015 | 4096 | 240 |
| v2_failure_conditioned_shuffled_trace_lora | Qwen/Qwen3-4B-Instruct-2507 | trace | True | 32 | 64 | 0.05 | 3 | 0.00015 | 4096 | 240 |
| v2_failure_conditioned_trace_lora | Qwen/Qwen3-4B-Instruct-2507 | trace | False | 32 | 64 | 0.05 | 3 | 0.00015 | 4096 | 240 |
| v2_final_patch_sft_lora | Qwen/Qwen3-4B-Instruct-2507 | final_patch | False | 32 | 64 | 0.05 | 3 | 0.00015 | 4096 | 240 |
Prompt
System prompt:
You are a coding agent repairing a repository. Output only a unified diff.
Do not explain. Do not include markdown fences.User prompt template:
<ISSUE>
{issue_text}
</ISSUE>
<REPO_CONTEXT>
{opened_files_or_current_files}
</REPO_CONTEXT>
<CURRENT_DIFF>
{wrong_patch}
</CURRENT_DIFF>
<TEST_OUTPUT_AFTER_CURRENT_DIFF>
{traceback_stdout_stderr_or_apply_error}
</TEST_OUTPUT_AFTER_CURRENT_DIFF>
Task:
Produce the minimal corrective unified diff to make the repository pass the tests.Prompt modes: final-patch SFT uses the original buggy files and targets base_buggy_diff; repair SFT uses the wrong-patched files and targets target_next_diff; no-trace blanks test output; shuffled-trace replaces test output with another training trace; wrong-patch-only removes repository file context and blanks test output; trace-only removes the current diff; gold-file-removed replaces file contents with a withholding marker.
Dataset
v1 Pilot
- Dataset:
local_synthetic_python_v1. - Tasks:
13. - Episodes:
64. - Splits:
{'train': 50, 'val_synth': 14}. - Failure classes:
{'assertion': 13, 'import': 13, 'syntax': 13, 'visible_pass_hidden_fail': 25}. - Bug families:
{'algorithmic_edge': 5, 'boundary_condition': 5, 'case_normalization': 5, 'comparison_flip': 5, 'edge_case': 5, 'exception_case': 5, 'normalization': 5, 'off_by_one': 10, 'ordering': 9, 'parser_partial': 5, 'path_norm': 5}.
v2 Expanded Synthetic
- Dataset:
local_synthetic_python_v2. - Tasks:
66. - Episodes:
327. - Splits:
{'train': 240, 'val_synth_family_holdout': 27, 'val_synth_iid': 60}. - Failure classes:
{'assertion': 66, 'import': 66, 'syntax': 66, 'visible_pass_hidden_fail': 129}. - Bug families:
{'case_normalization': 50, 'comparison_flip': 50, 'exception_case': 50, 'normalization': 50, 'off_by_one': 50, 'ordering': 50, 'path_norm': 15, 'tie_breaking': 12}.
v2 includes an IID validation split from trained bug families and a held-out-family split using path_norm and tie_breaking, which are absent from training.

Exact v2 train task IDs:
train_clamp_0, train_clamp_1, train_clamp_2, train_clamp_3, train_clamp_4, train_clamp_5, train_clamp_6, train_clamp_7, train_dedupe_0, train_dedupe_1, train_dedupe_2, train_dedupe_3, train_dedupe_4, train_dedupe_5, train_dedupe_6, train_dedupe_7, train_moving_average_0, train_moving_average_1, train_moving_average_2, train_moving_average_3, train_moving_average_4, train_moving_average_5, train_moving_average_6, train_moving_average_7, train_parse_bool_0, train_parse_bool_1, train_parse_bool_2, train_parse_bool_3, train_parse_bool_4, train_parse_bool_5, train_parse_bool_6, train_parse_bool_7, train_safe_get_0, train_safe_get_1, train_safe_get_2, train_safe_get_3, train_safe_get_4, train_safe_get_5, train_safe_get_6, train_safe_get_7, train_slugify_0, train_slugify_1, train_slugify_2, train_slugify_3, train_slugify_4, train_slugify_5, train_slugify_6, train_slugify_7Exact v2 IID validation task IDs:
val_synth_iid_clamp_8, val_synth_iid_clamp_9, val_synth_iid_dedupe_8, val_synth_iid_dedupe_9, val_synth_iid_moving_average_8, val_synth_iid_moving_average_9, val_synth_iid_parse_bool_8, val_synth_iid_parse_bool_9, val_synth_iid_safe_get_8, val_synth_iid_safe_get_9, val_synth_iid_slugify_8, val_synth_iid_slugify_9Exact v2 held-out-family validation task IDs:
val_synth_family_holdout_normalize_path_0, val_synth_family_holdout_normalize_path_1, val_synth_family_holdout_normalize_path_2, val_synth_family_holdout_top_k_0, val_synth_family_holdout_top_k_1, val_synth_family_holdout_top_k_2Results
v1 Pilot Held-Out Synthetic
| condition | status | repair_after_first_failure@1 | patch_apply_rate | syntax_valid_rate | visible_pass_hidden_fail_rate | records | successes |
|---|---|---|---|---|---|---|---|
| B. frozen second attempt | ok | 0 | 0.0714286 | 0.0714286 | 0.0714286 | 14 | 0 |
| C. final-patch SFT | ok | 0 | 0.428571 | 0.285714 | 0.0714286 | 14 | 0 |
| D. no-trace repair SFT | ok | 0 | 0.571429 | 0.571429 | 0.142857 | 14 | 0 |
| E. trace repair SFT | ok | 0 | 0.714286 | 0.642857 | 0.142857 | 14 | 0 |
| F. shuffled-trace repair SFT | ok | 0 | 0.642857 | 0.642857 | 0.214286 | 14 | 0 |
v2 IID Synthetic
| condition | status | repair_after_first_failure@1 | patch_apply_rate | syntax_valid_rate | visible_pass_hidden_fail_rate | records | successes |
|---|---|---|---|---|---|---|---|
| B. frozen second attempt | ok | 0.1 | 0.183333 | 0.166667 | 0 | 60 | 6 |
| C. final-patch SFT | ok | 0.183333 | 0.383333 | 0.383333 | 0.0333333 | 60 | 11 |
| D. no-trace repair SFT | ok | 1 | 1 | 1 | 0 | 60 | 60 |
| E. trace repair SFT | ok | 1 | 1 | 1 | 0 | 60 | 60 |
| F. shuffled-trace repair SFT | ok | 1 | 1 | 1 | 0 | 60 | 60 |

v2 Held-Out-Family Synthetic
| condition | status | repair_after_first_failure@1 | patch_apply_rate | syntax_valid_rate | visible_pass_hidden_fail_rate | records | successes |
|---|---|---|---|---|---|---|---|
| B. frozen second attempt | ok | 0 | 0.185185 | 0.148148 | 0.148148 | 27 | 0 |
| C. final-patch SFT | ok | 0 | 0.37037 | 0.185185 | 0 | 27 | 0 |
| D. no-trace repair SFT | ok | 0 | 0.444444 | 0.444444 | 0.37037 | 27 | 0 |
| E. trace repair SFT | ok | 0 | 0.444444 | 0.444444 | 0.444444 | 27 | 0 |
| F. shuffled-trace repair SFT | ok | 0 | 0.444444 | 0.444444 | 0.259259 | 27 | 0 |

v2 Held-Out-Family Synthetic, Best-of-3 Sampling
Sampling used temperature=0.2, top_p=0.95, and three candidate diffs per episode. The @1 column is the first sampled candidate; @3 is best-of-three by hidden-test pass.
| condition | status | repair_after_first_failure@1 | repair_after_first_failure@3 | patch_apply_rate | syntax_valid_rate | visible_pass_hidden_fail_rate | records | successes |
|---|---|---|---|---|---|---|---|---|
| B. frozen second attempt | ok | 0 | 0 | 0.185185 | 0.185185 | 0.185185 | 27 | 0 |
| C. final-patch SFT | ok | 0 | 0 | 0.407407 | 0.185185 | 0 | 27 | 0 |
| D. no-trace repair SFT | ok | 0 | 0 | 0.444444 | 0.444444 | 0.37037 | 27 | 0 |
| E. trace repair SFT | ok | 0 | 0 | 0.444444 | 0.444444 | 0.444444 | 27 | 0 |
| F. shuffled-trace repair SFT | ok | 0 | 0 | 0.444444 | 0.444444 | 0.259259 | 27 | 0 |
Coding-Specialist Repair-Control Ablation
To test whether the primary held-out-family collapse was specific to Qwen3-4B, I trained the same v2 final-patch, no-trace repair, trace repair, and shuffled-trace repair adapters on Qwen/Qwen2.5-Coder-3B-Instruct. This is still a secondary ablation because the frozen B baseline was not rerun for the coder model, but it includes the trace-specific D/E/F controls needed to interpret the small held-out-family trace result.
| split | condition | status | repair_after_first_failure@1 | patch_apply_rate | syntax_valid_rate | visible_pass_hidden_fail_rate | records | successes |
|---|---|---|---|---|---|---|---|---|
| IID | C'. coder final-patch SFT | ok | 0.283333 | 0.6 | 0.533333 | 0 | 60 | 17 |
| IID | D'. coder no-trace repair SFT | ok | 1 | 1 | 1 | 0 | 60 | 60 |
| IID | E'. coder trace repair SFT | ok | 1 | 1 | 1 | 0 | 60 | 60 |
| IID | F'. coder shuffled-trace repair SFT | ok | 1 | 1 | 1 | 0 | 60 | 60 |
| Held-out family | C'. coder final-patch SFT | ok | 0 | 0 | 0 | 0 | 27 | 0 |
| Held-out family | D'. coder no-trace repair SFT | ok | 0.0740741 | 0.666667 | 0.666667 | 0.296296 | 27 | 2 |
| Held-out family | E'. coder trace repair SFT | ok | 0.111111 | 0.666667 | 0.666667 | 0.222222 | 27 | 3 |
| Held-out family | F'. coder shuffled-trace repair SFT | ok | 0 | 0.37037 | 0.37037 | 0.111111 | 27 | 0 |

v2 Transfer Gap View

Trace Controls
v1 Trace Adapter on v1 Held-Out Synthetic
| prompt_mode | repair_after_first_failure@1 | patch_apply_rate | syntax_valid_rate | visible_pass_hidden_fail_rate | successes | records |
|---|---|---|---|---|---|---|
| trace | 0 | 0.714286 | 0.642857 | 0.142857 | 0 | 14 |
| no_trace | 0 | 0.857143 | 0.642857 | 0.0714286 | 0 | 14 |
| wrong_patch_only | 0 | 0.285714 | 0.285714 | 0 | 0 | 14 |
| trace_only | 0.0714286 | 0.571429 | 0.571429 | 0.142857 | 1 | 14 |
| gold_file_removed | 0 | 0.142857 | 0.142857 | 0 | 0 | 14 |
v2 Trace Adapter on v2 Held-Out Families
| prompt_mode | repair_after_first_failure@1 | patch_apply_rate | syntax_valid_rate | visible_pass_hidden_fail_rate | successes | records |
|---|---|---|---|---|---|---|
| trace | 0 | 0.444444 | 0.444444 | 0.444444 | 0 | 27 |
| no_trace | 0 | 0.555556 | 0.555556 | 0.37037 | 0 | 27 |
| wrong_patch_only | 0 | 0.185185 | 0.185185 | 0.148148 | 0 | 27 |
| trace_only | 0 | 0.925926 | 0.925926 | 0.777778 | 0 | 27 |
| gold_file_removed | 0 | 0.185185 | 0.185185 | 0 | 0 | 27 |
The requested evidence pattern normal trace > no trace, normal trace > shuffled trace, and normal trace > wrong-patch-only is not present. On v2 IID, no-trace, trace, and shuffled-trace adapters all repair 60/60. On v2 held-out families, all five ablation prompt modes repair 0/27.
Representative Cases
Same-Family Success
- Episode:
val_synth_iid_clamp_8::near_miss. - Task:
val_synth_iid_clamp_8. - Bug family:
comparison_flip. - Failure class:
visible_pass_hidden_fail. - Outcome: patch_applied=
True, visible_passed=True, hidden_passed=True.
Issue:
`clamp_value_8` should clamp a value into an inclusive range and reject inverted bounds.Target corrective diff:
--- a/src/repair_target.py
+++ b/src/repair_target.py
@@ -4,5 +4,5 @@
if value < lower:
return lower
if value > upper:
- return value
+ return upper
return valueGenerated diff:
--- a/src/repair_target.py
+++ b/src/repair_target.py
@@ -4,5 +4,5 @@
if value < lower:
return lower
if value > upper:
- return value
+ return upper
return valueHeld-Out-Family Failure
- Episode:
val_synth_family_holdout_normalize_path_0::near_miss. - Task:
val_synth_family_holdout_normalize_path_0. - Bug family:
path_norm. - Failure class:
visible_pass_hidden_fail. - Outcome: patch_applied=
False, visible_passed=False, hidden_passed=False.
Issue:
`normalize_path_0` should collapse duplicate slashes, ignore '.', and resolve '..' without escaping above root.Target corrective diff:
--- a/src/repair_target.py
+++ b/src/repair_target.py
@@ -3,8 +3,9 @@
for part in path.split("/"):
if part in {"", "."}:
continue
- if part == ".." and parts:
- parts.pop()
+ if part == "..":
+ if parts:
+ parts.pop()
continue
parts.append(part)
return "/" + "/".join(parts)Generated diff:
--- a/src/repair_target.py
+++ b/src/repair_target.py
@@ -1,7 +1,7 @@
def normalize_path_0(path):
- parts = [part for part in path.split("/") if part]
+ parts = []
+ for part in path.split("/"):
+ if part in {"", "."}:
+ continue
+ if part == ".." and parts:
+ parts.pop()
+ continue
+ parts.append(part)
return "/" + "/".join(parts)Direct Real-Task Probe Failures
pallets__flask-5014
- Instance:
pallets__flask-5014frompallets/flask. - Harness:
direct_pytest_not_official_docker. - Base failed official FAIL_TO_PASS test:
True. - Gold patch passed the same direct test:
True. - Frozen first patch resolved:
False. - Trace repair resolved after first failure:
0.0.
Frozen first patch:
diff --git a/src/flask/blueprints.py b/src/flask/blueprints.py
index 9d0a3d0..3d8d8f5 100644
--- a/src/flask/blueprints.py
+++ b/src/flask/blueprints.py
@@ -1,6 +1,6 @@
import os
import typing as t
-from collections import defaultdict
from functools import update_wrapper
from . import typing as ft
@@ -100,6 +100,10 @@ class Blueprint(Scaffold):
if url_defaults is None:
url_defaults = {}
+ if not name:
+ raise ValueError("Blueprint name must be non-empty.")
+
self.name = name
self.url_prefix = url_prefix
self.subdomain = subdomain
@@ -108,6 +112,7 @@ class Blueprint(Scaffold):
self.url_values_defaults = url_defaults
self.cli_group = cli_group
...Trace repair generated diff:
--- a/src/flask/blueprints.py
+++ b/src/flask/blueprints.py
@@ -99,7 +99,7 @@ class Blueprint(Scaffold):
if url_defaults is None:
url_defaults = {}
- if not name:
+ if not name or not name.strip():
raise ValueError("Blueprint name must be non-empty.")
self.name = nameObserved failure:
error: patch failed: src/flask/blueprints.py:99
error: src/flask/blueprints.py: patch does not applypsf__requests-5414
- Instance:
psf__requests-5414frompsf/requests. - Harness:
direct_pytest_not_official_docker. - Base failed official FAIL_TO_PASS test:
True. - Gold patch passed the same direct test:
True. - Frozen first patch resolved:
False. - Trace repair resolved after first failure:
0.0.
Frozen first patch:
--- a/requests/models.py
+++ b/requests/models.py
@@ -308,7 +308,7 @@ class PreparedRequest(RequestEncodingMixin, RequestHooksMixin):
if not host:
raise InvalidURL("Invalid URL %r: No host supplied" % url)
- # In general, we want to try IDNA encoding the hostname if the string contains
- # non-ASCII characters. This allows users to automatically get the correct IDNA
- # behaviour. For strings containing only ASCII characters, we need to also verify
- # it doesn't start with a wildcard (*), before allowing the unencoded hostname.
- if not unicode_is_ascii(host):
- try:
- host = self._get_idna_encoded_host(host)
- except UnicodeError:
- raise InvalidURL('URL has an invalid label.')
+ # In general, we want to try IDNA encoding the hostname if the string contains
+ # non-ASCII characters. This allows users to automatically get the correct IDNA
+ # behaviour. For strings containing only ASCII characters, we need to also verify
+ # it doesn't start with a wildcard (*), before allowing the unencoded hostname.
+ if not unicode_is_ascii(host):
+ try:
+ host = self._get_idna_encoded_host(host)
+ except idna.IDNAError:
+ raise InvalidURL('URL has an invalid label.')
...Trace repair generated diff:
--- a/requests/models.py
+++ b/requests/models.py
@@ -308,7 +308,7 @@ class PreparedRequest(RequestEncodingMixin, RequestHooksMixin):
if not host:
raise InvalidURL("Invalid URL %r: No host supplied" % url)
- # In general, we want to try IDNA encoding the hostname if the string contains
- # non-ASCII characters. This allows users to automatically get the correct IDNA
- # behaviour. For strings containing only ASCII characters, we need to also verify
- # it doesn't start with a wildcard (*), before allowing the unencoded hostname.
- if not unicode_is_ascii(host):
- try:
- host = self._get_idna_encoded_host(host)
- except UnicodeError:
- raise InvalidURL('URL has an invalid label.')
+ # In general, we want to try IDNA encoding the hostname if the string contains
+ # non-ASCII characters. This allows users to automatically get the correct IDNA
+ # behaviour. For strings containing only ASCII characters, we need to also verify
+ # it doesn't start with a wildcard (*), before allowing the unencoded hostname.
+ if not unicode_is_ascii(host):
+ try:
+ host = self._get_idna_encoded_host(host)
+ except idna.IDNAError:
+ raise InvalidURL('URL has an invalid label.')
...Observed failure:
error: patch failed: requests/models.py:308
error: requests/models.py: patch does not applypsf__requests-6028
- Instance:
psf__requests-6028frompsf/requests. - Harness:
direct_pytest_not_official_docker. - Base failed official FAIL_TO_PASS test:
True. - Gold patch passed the same direct test:
True. - Frozen first patch resolved:
False. - Trace repair resolved after first failure:
0.0.
Frozen first patch:
@@ -100,7 +100,7 @@ def resolve_proxies(request, proxies, trust_env=True):
proxies = proxies if proxies is not None else {}
url = request.url
scheme = urlparse(url).scheme
- no_proxy = proxies.get('no_proxy')
+ no_proxy = proxies.get('no_proxy') or getproxies_environment()
new_proxies = proxies.copy()
if trust_env and not should_bypass_proxies(url, no_proxy=no_proxy):
@@ -108,7 +108,7 @@ def resolve_proxies(request, proxies, trust_env=True):
environ_proxies = get_environ_proxies(url, no_proxy=no_proxy)
proxy = environ_proxies.get(scheme, environ_proxies.get('all'))
- if proxy:
+ if proxy and proxy != 'http://': # Skip empty or invalid proxy
new_proxies.setdefault(scheme, proxy)
return new_proxiesTrace repair generated diff:
--- a/requests/utils.py
+++ b/requests/utils.py
@@ -100,7 +100,7 @@ def resolve_proxies(request, proxies, trust_env=True):
proxies = proxies if proxies is not None else {}
url = request.url
scheme = urlparse(url).scheme
- no_proxy = proxies.get('no_proxy')
+ no_proxy = proxies.get('no_proxy') or getproxies_environment()
new_proxies = proxies.copy()
if trust_env and not should_bypass_proxies(url, no_proxy=no_proxy):
@@ -108,7 +108,7 @@ def resolve_proxies(request, proxies, trust_env=True):
environ_proxies = get_environ_proxies(url, no_proxy=no_proxy)
proxy = environ_proxies.get(scheme, environ_proxies.get('all'))
- if proxy:
+ if proxy and proxy != 'http://': # Skip empty or invalid proxy
new_proxies.setdefault(scheme, proxy)
return new_proxiesObserved failure:
error: patch failed: requests/utils.py:108
error: requests/utils.py: patch does not applySynthetic-to-Real Transfer Status
- v2 IID trace gain over frozen second attempt:
0.9. - v2 held-out-family trace gain over frozen second attempt:
0.0. - Direct non-Docker SWE-bench Verified probe count:
3. - Direct non-Docker frozen second-attempt repair rate:
0.0. - Direct non-Docker trace repair rate:
0.0. - Direct non-Docker real-task gain:
0.0. - Direct non-Docker transfer ratio:
0.0. - Official Docker SWE-bench real-task gain:
not measured. - Official Docker SWE-bench transfer ratio:
not defined.
Direct non-Docker SWE-bench Verified probes:
| instance | repo | condition | initial_resolved@1 | repair_after_first_failure@1 | end_to_end_resolved@2 |
|---|---|---|---|---|---|
| pallets__flask-5014 | pallets/flask | A. frozen first patch | 0 | n/a | 0 |
| pallets__flask-5014 | pallets/flask | B_frozen_second_attempt | 0 | 0.0 | 0 |
| pallets__flask-5014 | pallets/flask | C_final_patch_sft | 0 | 0.0 | 0 |
| pallets__flask-5014 | pallets/flask | D_no_trace_repair_sft | 0 | 0.0 | 0 |
| pallets__flask-5014 | pallets/flask | E_trace_repair_sft | 0 | 0.0 | 0 |
| pallets__flask-5014 | pallets/flask | F_shuffled_trace_repair_sft | 0 | 0.0 | 0 |
| psf__requests-5414 | psf/requests | A. frozen first patch | 0 | n/a | 0 |
| psf__requests-5414 | psf/requests | B_frozen_second_attempt | 0 | 0.0 | 0 |
| psf__requests-5414 | psf/requests | C_final_patch_sft | 0 | 0.0 | 0 |
| psf__requests-5414 | psf/requests | D_no_trace_repair_sft | 0 | 0.0 | 0 |
| psf__requests-5414 | psf/requests | E_trace_repair_sft | 0 | 0.0 | 0 |
| psf__requests-5414 | psf/requests | F_shuffled_trace_repair_sft | 0 | 0.0 | 0 |
| psf__requests-6028 | psf/requests | A. frozen first patch | 0 | n/a | 0 |
| psf__requests-6028 | psf/requests | B_frozen_second_attempt | 0 | 0.0 | 0 |
| psf__requests-6028 | psf/requests | C_final_patch_sft | 0 | 0.0 | 0 |
| psf__requests-6028 | psf/requests | D_no_trace_repair_sft | 0 | 0.0 | 0 |
| psf__requests-6028 | psf/requests | E_trace_repair_sft | 0 | 0.0 | 0 |
| psf__requests-6028 | psf/requests | F_shuffled_trace_repair_sft | 0 | 0.0 | 0 |
Direct-probe selection note: I preflighted every SWE-bench Verified task in the currently supported pallets/flask and psf/requests profiles. The validated direct slice includes tasks with base-fails/gold-passes behavior. Excluded same-profile candidates either failed gold validation under the local profile (psf__requests-2931) or could not install on Python 3.12 because older vendored urllib3 code imports removed stdlib symbols (psf__requests-1142, psf__requests-1724, psf__requests-1766, psf__requests-1921, psf__requests-2317).
Docker/SWE-bench preflight:
{
"docker_preflight": {
"ok": false,
"probe_output": "Unable to find image 'hello-world:latest' locally\nlatest: Pulling from library/hello-world\n4f55086f7dd0: Pulling fs layer\n4f55086f7dd0: Verifying Checksum\n4f55086f7dd0: Download complete\ndocker: failed to register layer: unshare: operation not permitted\n\nRun 'docker run --help' for more information\n",
"probe_returncode": 125,
"server_version": "29.1.3"
},
"reason": "Docker preflight failed; official SWE-bench evaluation is not valid in this runner.",
"status": "blocked"
}The official real-task portion is blocked by the runner, not by a modeling decision. The direct probes are useful negative evidence, but they are not a replacement for the official Docker SWE-bench harness or a statistically meaningful real slice.
Interpretation
- Final-patch SFT is weaker than repair-conditioned SFT on same-family synthetic validation.
- The apparent same-family synthetic gain does not survive held-out-family validation.
- Execution traces are not shown to be causally useful in the current setup.
- A coding-specialist model can recover a small amount of held-out-family repair under the trace-conditioned objective, but the effect is weak: 3/27 for trace versus 2/27 for no-trace and 0/27 for shuffled-trace.
- Patch application and visible-test pass rates can be high while hidden repair remains zero, so executable hidden tests are essential.
- The current result is negative and should not be framed as successful synthetic-to-real transfer.
Reproducibility Artifacts
- Dataset builders:
scripts/build_repair_dataset.py,scripts/build_repair_dataset_v2.py. - Training:
scripts/train_repair_lora.py. - Evaluation:
scripts/eval_repair_synthetic.py,scripts/run_trace_ablation.py. - Direct real-task probe:
scripts/eval_repair_swebench_direct.py. - v2 adapters:
models/v2_final_patch_sft_lora,models/v2_failure_conditioned_no_trace_lora,models/v2_failure_conditioned_trace_lora,models/v2_failure_conditioned_shuffled_trace_lora. - Coder ablation adapters:
models/coder_v2_final_patch_sft_lora,models/coder_v2_failure_conditioned_no_trace_lora,models/coder_v2_failure_conditioned_trace_lora,models/coder_v2_failure_conditioned_shuffled_trace_lora. - v2 result JSONs:
reports/v2_*_results.json,reports/v2_trace_ablation_family_holdout_results.json. - Coder ablation result JSONs:
reports/coder_v2_*_results.json. - Direct real-task result JSONs:
reports/swebench_direct_flask5014_qwen3_results.json,reports/swebench_direct_requests5414_qwen3_results.json,reports/swebench_direct_requests6028_qwen3_results.json.
Experiment log 15
Show the running log (15 entries, 2026-06-19 → 20)
2026-06-19 Environment Setup
- Read the experiment brief from
/root/.codex/attachments/67be2ef6-a2f4-424d-a411-f0479b10c076/pasted-text-1.txt. - Hardware: NVIDIA RTX 6000 Ada, 48GB VRAM; BF16 supported.
- Installed missing Python prerequisites:
transformers,accelerate,datasets,peft,trl,bitsandbytes, plotting and test utilities. - Verified
bitsandbytesCUDA support. Verified primary model config:
Qwen/Qwen3-4B-Instruct-2507- revision
cdbee75f17c01a7cc42f958dc650907174af0554 - model type
qwen3, 36 layers, hidden size 2560.
- Installed Docker and started
dockerdwith bridge networking disabled, then withvfsstorage. - Docker preflight failed at container layer registration with
unshare: operation not permitted. - Conclusion: official SWE-smith/SWE-bench Docker-backed execution is not valid in this runner until kernel/container privileges change.
Synthetic Pilot Dataset v1
- Built a local executable Python repair suite with 13 tasks and 64 wrong-patch episodes.
Splits:
- Train: 50 episodes.
- Synthetic held-out: 14 episodes.
Wrong-patch variants:
- near miss
- wrong localization
- syntax error
- import error
- visible-test overfit
Failure classes:
- assertion: 13
- import: 13
- syntax: 13
- visible-pass-hidden-fail: 25
Correctness audit:
- Recomputed every
target_next_difffrom current wrong-patched files to clean files. - 50/50 train target diffs applied and passed hidden tests.
- 14/14 validation target diffs applied and passed hidden tests.
- Recomputed every
Frozen-Model Sampling Smoke
- Loaded
Qwen/Qwen3-4B-Instruct-2507in 4-bit successfully. - Sampled first-patch outputs on two synthetic tasks.
- Initial patch extraction failed on standard
index ...diff headers; fixed extractor. - Model often emits plausible final-fix diffs against the original buggy file, but with bad hunk counts or against the wrong tree.
- Added
git apply --recountso count-mismatched hunks can apply when context is otherwise valid.
Frozen-Model Wrong-Patch Stream
- Ran
scripts/sample_wrong_patches.pyover all 13 local tasks with one sample per task. - Output:
data/frozen_wrong_patches_qwen3_local.jsonl. Breakdown:
- 13 total records.
- 6 applied model patches.
- 7 rejected/apply-error model patches.
- 10 hidden-failing records usable as repair episodes.
- 3 records already passed hidden tests and are not useful first-failure repair examples.
- Filtered usable failures to
data/frozen_wrong_patches_qwen3_local_failures.jsonl. Correctness audit:
- 10/10 filtered target diffs apply.
- 10/10 filtered target diffs pass hidden tests.
This stream is small but more faithful to the brief than the scripted wrong-patch variants because W_i comes from the frozen Qwen3 model.
Baseline and Adapter Runs
All adapters used:
- base model:
Qwen/Qwen3-4B-Instruct-2507 - revision:
cdbee75f17c01a7cc42f958dc650907174af0554 - 4-bit NF4 QLoRA
- rank 32, alpha 64
- target modules: Qwen attention projections and MLP projections
- assistant diff tokens only in loss
Initial 3-epoch results on held-out synthetic v1:
| Condition | repair_after_first_failure@1 | patch_apply_rate | syntax_valid_rate |
|---|---|---|---|
| Frozen second attempt | 0.00 | 0.071 | 0.071 |
| Final-patch SFT | 0.00 | 0.429 | 0.286 |
| Failure-conditioned no-trace SFT | 0.00 | 0.571 | 0.571 |
| Failure-conditioned trace SFT | 0.00 | 0.714 | 0.643 |
| Failure-conditioned shuffled-trace SFT | 0.00 | 0.643 | 0.643 |
Interpretation:
- SFT improved diff format/application substantially.
- It did not improve semantic repair on held-out tasks.
- Normal trace beat shuffled/no-trace on patch application but not on hidden-test repair.
- No scientific success claim is supported.
Undertraining Diagnostic
- Trace adapter after 3 epochs repaired only 3/20 train episodes.
- Shorter generation (
max_new_tokens=256) did not improve this. Trained a stronger trace adapter v2:
- 12 epochs
- gradient accumulation 4
- learning rate 2e-4
- LoRA dropout 0.0
- v2 repaired 19/20 train examples, proving the pipeline can learn executable corrective diffs.
- v2 repaired 0/14 held-out synthetic examples.
Interpretation:
- The initial failure was partly undertraining, but the held-out failure remains after memorization.
- Current synthetic v1 data does not support transfer beyond memorized task patterns.
- The next experimental step should expand data diversity and task count, not further tune on the same 50 episodes.
Trace Ablations
Ran full held-out synthetic trace ablations for the 3-epoch core trace adapter:
| Prompt mode | repair_after_first_failure@1 | patch_apply_rate |
|---|---|---|
| normal trace | 0.000 | 0.714 |
| no trace | 0.000 | 0.857 |
| wrong patch only | 0.000 | 0.286 |
| trace only | 0.071 | 0.571 |
| gold-file context removed | 0.000 | 0.143 |
Interpretation:
- The required evidence pattern
normal trace > no trace,normal trace > shuffled trace, andnormal trace > wrong-patch-onlyis absent. - Trace-only producing one success while normal trace produced zero is likely noise on a 14-record slice, not evidence of useful trace grounding.
- The current positive effect is mostly patch applicability/formatting, not execution-conditioned semantic repair.
- The wrong-patch-only row above was rerun after fixing the stricter control definition to remove repository file context.
Current Hypotheses
- The core prompt/training/evaluation machinery is functional.
- The local synthetic v1 train set is too small and too template-specific for held-out task transfer.
- The model is learning patch formatting and current-tree anchoring before learning robust repair semantics.
- Execution traces may help formatting/anchoring but there is no evidence yet that trace content causes repair success.
- Official real-task transfer cannot be measured in this runner until Docker/SWE-bench execution works.
Next Actions
- Build a larger synthetic v2 dataset with many more train tasks per bug family and separate held-out families.
- Generate at least some wrong patches from the frozen model and filter for valid first-failure episodes.
- Re-run the C/D/E/F comparison on v2 with enough data to test transfer.
- Only after positive synthetic repair exists, spend compute on SWE-bench-style real slices.
2026-06-20 Synthetic v2 Expansion
- Added
scripts/build_repair_dataset_v2.py. - Built a larger executable synthetic dataset under
data/v2. v2 manifest:
- 66 tasks.
- 327 repair episodes.
- 240 train episodes.
- 60 IID validation episodes from trained bug families.
- 27 held-out-family validation episodes from
path_normandtie_breaking. - 3 skipped episodes where a wrong patch already passed hidden tests.
Verified target corrective diffs:
- 240/240 train target diffs applied and passed hidden tests.
- 60/60 IID validation target diffs applied and passed hidden tests.
- 27/27 held-out-family validation target diffs applied and passed hidden tests.
Trained four v2 adapters using the same base revision and QLoRA recipe:
models/v2_final_patch_sft_loramodels/v2_failure_conditioned_no_trace_loramodels/v2_failure_conditioned_trace_loramodels/v2_failure_conditioned_shuffled_trace_lora
v2 IID synthetic executable results:
| Condition | repair_after_first_failure@1 | patch_apply_rate | syntax_valid_rate | successes |
|---|---|---|---|---|
| Frozen second attempt | 0.100 | 0.183 | 0.167 | 6/60 |
| Final-patch SFT | 0.183 | 0.383 | 0.383 | 11/60 |
| Failure-conditioned no-trace SFT | 1.000 | 1.000 | 1.000 | 60/60 |
| Failure-conditioned trace SFT | 1.000 | 1.000 | 1.000 | 60/60 |
| Failure-conditioned shuffled-trace SFT | 1.000 | 1.000 | 1.000 | 60/60 |
v2 held-out-family executable results:
| Condition | repair_after_first_failure@1 | patch_apply_rate | syntax_valid_rate | successes |
|---|---|---|---|---|
| Frozen second attempt | 0.000 | 0.185 | 0.148 | 0/27 |
| Final-patch SFT | 0.000 | 0.370 | 0.185 | 0/27 |
| Failure-conditioned no-trace SFT | 0.000 | 0.444 | 0.444 | 0/27 |
| Failure-conditioned trace SFT | 0.000 | 0.444 | 0.444 | 0/27 |
| Failure-conditioned shuffled-trace SFT | 0.000 | 0.444 | 0.444 | 0/27 |
v2 held-out-family best-of-3 sampled results (temperature=0.2, top_p=0.95):
| Condition | repair_after_first_failure@1 | repair_after_first_failure@3 | patch_apply_rate | syntax_valid_rate | successes |
|---|---|---|---|---|---|
| Frozen second attempt | 0.000 | 0.000 | 0.185 | 0.185 | 0/27 |
| Final-patch SFT | 0.000 | 0.000 | 0.407 | 0.185 | 0/27 |
| Failure-conditioned no-trace SFT | 0.000 | 0.000 | 0.444 | 0.444 | 0/27 |
| Failure-conditioned trace SFT | 0.000 | 0.000 | 0.444 | 0.444 | 0/27 |
| Failure-conditioned shuffled-trace SFT | 0.000 | 0.000 | 0.444 | 0.444 | 0/27 |
Held-out-family trace ablation for models/v2_failure_conditioned_trace_lora:
| Prompt mode | repair_after_first_failure@1 | patch_apply_rate | syntax_valid_rate |
|---|---|---|---|
| normal trace | 0.000 | 0.444 | 0.444 |
| no trace | 0.000 | 0.556 | 0.556 |
| wrong patch only | 0.000 | 0.185 | 0.185 |
| trace only | 0.000 | 0.926 | 0.926 |
| gold-file context removed | 0.000 | 0.185 | 0.185 |
Interpretation:
- v2 proves the training/eval pipeline can produce strong same-family synthetic repair behavior.
- The same success does not transfer to held-out bug families.
- The trace controls still do not show the required evidence pattern.
- The normal trace adapter is not better than no-trace, shuffled-trace, or wrong-patch-only controls on hidden repair.
- The result is a negative transfer result, not a positive execution-conditioned repair result.
Control audit:
- Found and fixed a prompt-control bug:
wrong_patch_onlyhad incorrectly preserved repository file context, making it equivalent to no-trace. - Updated
src/repair_experiment/prompts.pysowrong_patch_onlyremoves repository file context and blanks trace output while preserving the current wrong diff. - Reran
reports/v2_trace_ablation_family_holdout_results.jsonafter the fix. - The corrected wrong-patch-only control still repaired 0/27 hidden cases, and its patch-apply rate dropped from 0.556 to 0.185.
2026-06-20 Report Generation
- Regenerated the paper-style report at
reports/execution_conditioned_repair_paper.md. - Also refreshed
reports/transfer_gap_report.mdto the same content for compatibility with the earlier report path. Generated v2 figures:
- Official SWE-bench-style Docker execution remains blocked by
unshare: operation not permittedduring Docker layer registration, recorded inreports/swebench_preflight.json.
2026-06-20 Coding-Specialist Ablation
Question:
- Is the Qwen3-4B held-out-family collapse specific to the primary base model, or does a coding-specialist base show the same behavior?
Setup:
- Model:
Qwen/Qwen2.5-Coder-3B-Instruct. - Revision:
488639f1ff808d1d3d0ba301aef8c11461451ec5. - Same v2 train/eval splits and QLoRA recipe as the primary runs.
Trained the C/D/E/F coder adapter set:
models/coder_v2_final_patch_sft_loramodels/coder_v2_failure_conditioned_no_trace_loramodels/coder_v2_failure_conditioned_trace_loramodels/coder_v2_failure_conditioned_shuffled_trace_lora
Training checks:
- Coder final-patch adapter final IID eval loss:
7.366e-05. - Coder no-trace adapter final IID eval loss:
3.829e-04. - Coder trace adapter final IID eval loss:
1.235e-04. - Coder shuffled-trace adapter final IID eval loss:
1.363e-04.
Deterministic executable results:
| Split | Condition | repair_after_first_failure@1 | patch_apply_rate | syntax_valid_rate | successes |
|---|---|---|---|---|---|
| IID | Coder final-patch SFT | 0.283 | 0.600 | 0.533 | 17/60 |
| IID | Coder no-trace repair SFT | 1.000 | 1.000 | 1.000 | 60/60 |
| IID | Coder trace repair SFT | 1.000 | 1.000 | 1.000 | 60/60 |
| IID | Coder shuffled-trace repair SFT | 1.000 | 1.000 | 1.000 | 60/60 |
| Held-out family | Coder final-patch SFT | 0.000 | 0.000 | 0.000 | 0/27 |
| Held-out family | Coder no-trace repair SFT | 0.074 | 0.667 | 0.667 | 2/27 |
| Held-out family | Coder trace repair SFT | 0.111 | 0.667 | 0.667 | 3/27 |
| Held-out family | Coder shuffled-trace repair SFT | 0.000 | 0.370 | 0.370 | 0/27 |
Interpretation:
- The coding-specialist base reproduces the same-family synthetic sanity result.
- Unlike the primary Qwen3-4B trace adapter, it finds 3 held-out-family repairs, so the broadest "zero transfer" claim is model-dependent.
- The trace result has only a weak edge over controls: 3/27 for trace, 2/27 for no-trace, 0/27 for shuffled-trace.
- This is suggestive enough to report as a secondary ablation, but too small for a strong causal trace claim.
- The result remains a weak held-out-family transfer signal, not a SWE-bench transfer result.
2026-06-20 Direct Non-Docker SWE-bench Probe
Motivation:
- Official SWE-bench Docker execution is still blocked by
unshare: operation not permitted. - I built a direct local pytest probe for one SWE-bench Verified task to get at least some real-task evidence outside Docker.
- This is not the official harness and should not be treated as a replacement for full Verified evaluation.
Task:
- Instance:
pallets__flask-5014. - Repo:
pallets/flask. - Base commit:
7ee9ceb71e868944a46e1ff00b506772a53a4f1d. - Test:
tests/test_blueprints.py::test_empty_name_not_allowed. - Context file shown to the model:
src/flask/blueprints.py.
Harness validation:
- Base + official test patch failed as expected.
- Base + official test patch + official gold patch passed.
Local runner caveats:
- Uses direct pytest, not Docker.
- Uses a manually validated Flask dependency profile under Python 3.12.
- Forces
PYTHONPATHto the current worktreesrcdirectory so each worktree imports its own source.
Qwen3 primary direct-probe results:
| Condition | repair_after_first_failure@1 | end_to_end_resolved@2 |
|---|---|---|
| Frozen first patch | n/a | 0/1 |
| Frozen second attempt | 0/1 | 0/1 |
| Final-patch SFT | 0/1 | 0/1 |
| No-trace repair SFT | 0/1 | 0/1 |
| Trace repair SFT | 0/1 | 0/1 |
| Shuffled-trace repair SFT | 0/1 | 0/1 |
Observed failure mode:
- The frozen first patch recognized the semantic fix, adding a
ValueErrorfor empty blueprint names, but inserted the check at the wrong location and duplicated it. - The first patch did not apply cleanly.
- The trace repair adapter generated another plausible local edit, but it was still anchored to the wrong hunk and did not apply.
Interpretation:
- This one-task real probe gives real-task negative evidence consistent with the synthetic held-out-family result.
- Direct non-Docker real gain for trace over frozen second attempt is
0.0. - Using the v2 IID synthetic gain of
0.9, the direct-probe transfer ratio is0.0. - Because this is one task and not the official Docker harness, it is reported as a probe, not as the definitive SWE-bench result.
2026-06-20 Second Direct Non-Docker SWE-bench Probe
Motivation:
- Add a second validated real task using the same non-Docker direct pytest runner.
- Test whether the Flask negative result was an idiosyncratic failure of one repository layout.
- Generalize
scripts/eval_repair_swebench_direct.pyto per-repository profiles instead of hardcoding Flask.
Task:
- Instance:
psf__requests-5414. - Repo:
psf/requests. - Base commit:
39d0fdd9096f7dceccbc8f82e1eda7dd64717a8e. - Test:
tests/test_requests.py::TestRequests::test_invalid_url[InvalidURL-http://.example.com]. - Context file shown to the model:
requests/models.py.
Harness validation:
- Base + official test patch failed as expected with
urllib3.exceptions.LocationParseError: Failed to parse: '.example.com', label empty or too long. - Base + official test patch + official gold patch passed.
Local runner caveats:
- Uses direct pytest, not Docker.
- Uses a manually validated Requests dependency profile under Python 3.12.
- Forces
PYTHONPATHto the current worktree root so each worktree imports its own source.
Qwen3 primary direct-probe results:
| Condition | repair_after_first_failure@1 | end_to_end_resolved@2 |
|---|---|---|
| Frozen first patch | n/a | 0/1 |
| Frozen second attempt | 0/1 | 0/1 |
| Final-patch SFT | 0/1 | 0/1 |
| No-trace repair SFT | 0/1 | 0/1 |
| Trace repair SFT | 0/1 | 0/1 |
| Shuffled-trace repair SFT | 0/1 | 0/1 |
Observed failure mode:
- The frozen first patch applied, but it added an
idna.IDNAErrorhandler in the non-ASCII-host branch instead of changing the ASCII leading-dot guard. - The visible test still failed with
LocationParseError. - Every second attempt emitted the same stale first-attempt diff, which then failed to apply on top of the wrong-patched tree.
Updated direct-probe aggregate:
- Validated direct probes: 2 (
pallets__flask-5014,psf__requests-5414). - Frozen second-attempt repair rate: 0/2.
- Trace repair SFT repair rate: 0/2.
- Direct non-Docker real gain for trace over frozen second attempt:
0.0. - Using the v2 IID synthetic gain of
0.9, the direct-probe transfer ratio is0.0. - The aggregate remains negative evidence only; official Docker SWE-bench execution is still blocked by the environment.
2026-06-20 Direct Runner Correction and Third Probe
Evaluation correction:
- While inspecting
psf__requests-6028, I found that the direct runner evaluated second attempts after a patch-apply failure asbad_first_patch + second_patch. - That is too strict for an apply-error failure: if the first patch does not apply, the repository remains at the original tree, so the second attempt should be evaluated as a replacement patch conditioned on the failed diff and apply-error trace.
I changed
scripts/eval_repair_swebench_direct.pyso:- if the first patch applied, repair is evaluated on top of the wrong-patched tree;
- if the first patch did not apply, repair is evaluated as a standalone replacement patch on the original tree.
- I reran affected direct probes
pallets__flask-5014andpsf__requests-6028; both remained 0/1 for every Qwen3 condition.
Additional preflights:
psf__requests-6028: base failed and gold passed, usable.psf__requests-2931: base failed but gold did not pass under the direct local profile, so excluded.psf__requests-1142: local install failed on Python 3.12 because old vendored urllib3 importsMutableMappingfromcollections, so excluded.psf__requests-1724: local install failed on Python 3.12 because old vendored urllib3 importsMutableMappingfromcollections, so excluded.psf__requests-1766: local install failed on Python 3.12 because old vendored urllib3 cannot importssl.match_hostnameand lacks the backport, so excluded.psf__requests-1921: local install failed on Python 3.12 for the same vendoredssl_match_hostnameissue, so excluded.psf__requests-2317: local install failed on Python 3.12 because old vendored urllib3 importsMappingandMutableMappingfromcollections, so excluded.
Third task:
- Instance:
psf__requests-6028. - Repo:
psf/requests. - Base commit:
0192aac24123735b3eaf9b08df46429bb770c283. Tests:
tests/test_utils.py::test_prepend_scheme_if_needed[http://user:pass@example.com/path?query-http://user:pass@example.com/path?query]tests/test_utils.py::test_prepend_scheme_if_needed[http://user@example.com/path?query-http://user@example.com/path?query]
- Context file shown to the model:
requests/utils.py.
Qwen3 primary direct-probe results:
| Condition | repair_after_first_failure@1 | end_to_end_resolved@2 |
|---|---|---|
| Frozen first patch | n/a | 0/1 |
| Frozen second attempt | 0/1 | 0/1 |
| Final-patch SFT | 0/1 | 0/1 |
| No-trace repair SFT | 0/1 | 0/1 |
| Trace repair SFT | 0/1 | 0/1 |
| Shuffled-trace repair SFT | 0/1 | 0/1 |
Observed failure mode:
- The frozen first patch omitted file headers, so it failed before tests.
- Trace repair generated a file-scoped diff, but it edited
resolve_proxiesinstead of the correctprepend_scheme_if_neededbehavior and failed to apply.
Updated direct-probe aggregate:
- Validated direct probes: 3 (
pallets__flask-5014,psf__requests-5414,psf__requests-6028). - Frozen second-attempt repair rate: 0/3.
- Trace repair SFT repair rate: 0/3.
- Direct non-Docker real gain for trace over frozen second attempt:
0.0. - Using the v2 IID synthetic gain of
0.9, the direct-probe transfer ratio is0.0. - Official Docker SWE-bench execution remains blocked by
unshare: operation not permitted; the direct probes are negative supporting evidence, not an official SWE-bench score.
Figures 8
Data files 24
Result tables and metrics copied from the experiment folder — preview inline or open the raw file.
reports/coder_v2_failure_conditioned_no_trace_family_holdout_results.json182 kBreports/coder_v2_failure_conditioned_shuffled_trace_family_holdout_results.json156 kBreports/coder_v2_failure_conditioned_trace_family_holdout_results.json193 kBreports/coder_v2_final_patch_sft_family_holdout_results.json91 kBreports/failure_conditioned_no_trace_results.json52 kBreports/failure_conditioned_shuffled_trace_results.json56 kBreports/failure_conditioned_trace_results.json61 kBreports/failure_conditioned_trace_train20_max256_results.json76 kBreports/failure_conditioned_trace_train20_results.json76 kBreports/failure_conditioned_trace_v2_results.json60 kBreports/failure_conditioned_trace_v2_train20_results.json48 kBreports/final_patch_sft_results.json47 kBreports/frozen_second_attempt_results.json31 kBreports/swebench_direct_flask5014_qwen3_results.json21 kBreports/swebench_direct_requests5414_qwen3_results.json40 kBreports/swebench_direct_requests6028_qwen3_results.json24 kBreports/swebench_slice_results.json563 Breports/trace_ablation_results.json3.2 kBreports/v2_failure_conditioned_no_trace_family_holdout_results.json78 kBreports/v2_failure_conditioned_no_trace_iid_results.json126 kBreports/v2_failure_conditioned_shuffled_trace_family_holdout_results.json82 kBreports/v2_failure_conditioned_shuffled_trace_iid_results.json126 kBreports/v2_failure_conditioned_trace_family_holdout_results.json76 kBreports/v2_failure_conditioned_trace_iid_results.json126 kB
5 more result files not shown here — browse the full folder on GitHub.
Reproduce
Run steps are documented inside the experiment folder (README and scripts).


