Repository navigation
agent: edit takes a path per entry; each file applies on its own - #249
Merged
Merged
Conversation
Luna still failed 27.3% of its edit calls on main. The two largest causes were the call's shape: an `edits[]` batch whose entries belonged to two files sent under one `path` (28.7% of errors), and an ambiguous `old_string` (25.9%). - An `edits[]` entry may name its own `path`; the top-level `path` stays the default, so a single-file call is unchanged. Every file is planned before any is written: one bad entry anywhere writes nothing, and the error lists each failing file. The dispatch lock covers every file (`Tool::write_targets`, `WriteLockRegistry::lock_all` in sorted order); `--deny-path`, approval scoping and compaction's modified files read every path through one `tool::written_paths`. - A failed match never applies anything new; it explains itself. Not found names another file of the call, or one `read`/`write`/`edit` recently touched, that holds the exact text; else "already applied at line N"; else the closest lines with numbers. Not unique lists each match's line and enclosing definition. Bounded and error-path only. Replayed through the real tool against the 174 remaining Luna@main errors: the original call still fails in all 174; giving each wrong-file entry its file rescues 32 (18.4%) with no apply the model did not name, and the new error names the right file for 47 of the 58 wrong-file calls. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JimHGjsfk2Ktm5GxyZJKKk
Luna pads an `edits[]` batch with `old == new` entries. When every entry for one file was such padding, the per-file "made no changes" check failed the whole atomic call and the real edits to the other files were lost — 4 of the candidate's errors in the first A/B attempt. A call that changes no file still errors; a file of a multi-file call that changes nothing is now left alone and named in the result. The replay through the real tool now rescues 35 of the 174 remaining Luna@main errors (20.1%), still with no apply the model did not name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JimHGjsfk2Ktm5GxyZJKKk
The all-or-nothing rule across files sank whole batches: Luna packs 3.9 entries across 1.4 files per call, and in the A/B's candidate arm 131 of 303 failed calls were all-or-nothing rejections, 112 of them (85.5%) with at least one file the tool itself reported valid. - A file applies all of its entries or none, independent of the call's other files. The call errors only when no file was written; otherwise the result lists each edited file and each FAILED one, with the usual diagnosis, so the model resends only the failed files. A disk-changed refusal fails that file alone and the rest are still written. - A multi-file result names files as the model spelled them. Single-file calls are unchanged. - The "text is in X" hint searches a file being written in its new text. - Deny-path, approval and the write lock still decide the whole call before anything applies. TouchedFiles and compaction's modified files count only the files that landed (`tool::edit_failed_paths`). A blank top-level `path` on an edit no longer counts as a written path. Replaying the candidate arm's calls per file cuts the entries lost to failed calls from 32.5% to 26.4% and the pooled edit error rate from 25.2% to 15.9%. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JimHGjsfk2Ktm5GxyZJKKk
jaredLunde
marked this pull request as ready for review
October 12, 2026 23:29
jaredLunde
enabled auto-merge
October 12, 2026 23:29
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follows closed #248. This keeps #248's per-entry
pathand diagnostic errors, but each file of a multi-file call now applies on its own. Draft: no confirmation A/B has run yet, so whether to run one is the owner's call.Why
#248 was all-or-nothing across files, and its Luna A/B showed no gain: edit errors went from 27.6% to 25.7% per call. Wrong-file errors went away, but the all-or-nothing rule became the top error. Luna packs a call: 3.9 entries across 1.4 files on average. So one bad entry sank whole batches.
Change
path.What the gates and tracking count
--deny-path: a denied file blocks every file of the call.TouchedFiles.maskingalso reads).agent_core::tool::edit_failed_pathsparses theFAILED <path> (not edited):lines and subtracts them from the call'swritten_paths. The tool writes those lines withedit_failed_line, so writer and reader share one definition. A single-file failure has no such line, so it counts its path as before.extract_bash_writesis unaffected.FsBackend. A remote backend writes the file that plans and leaves the failing one untouched. There is a test for this.pathon anedit(Luna sends""beside entries that each name a file) no longer counts as a written path.Tests
edit_failed_paths, thatTouchedFilesholds only the files that landed, and the disk contents.FsBackendpartial.cargo test -p beyond-ai-agent -p beyond-ai-agent-core: 3,759 passed, 0 failed (155 targets); clippy-D warningsand fmt clean.Offline replay (free; no paid runs)
These come from the per-call data of #248's candidate arm (
cand-47db6dea): 25 Luna runs, 1,204 edit calls, 4,728 entries, 347 multi-file calls. Whole-run outcomes were ignored because rate limits confounded them.Ground truth is each rejection's own list of files that were "valid but not written". The shadow file states agree with it on all 320 files they could check.
Caveat: this is first-order. It does not model how the model would have acted after a partial success.
The replay script and its output are in
/home/jared/longctx-eval/edit-ab2/(replay_perfile.py,replay_perfile.out).🤖 Generated with Claude Code
https://claude.ai/code/session_01JimHGjsfk2Ktm5GxyZJKKk