docs: survey how five code agents design their edit tool - #17
Merged
Conversation
Verified the research note against the checked-out sources and fixed what did not hold up. - Record the OpenCode V2 matching contract accurately: its "exact" runs after stripping the UTF-8 BOM and re-encoding both oldString and newString to the file's detected line ending, so it is not raw-byte exact. Update the comparison table rows and cite the helpers. - Replace the proposed dual-candidate line-ending rule with V2's approach: one raw exact pass, then at most one LF->CRLF retry, never a union of both. The union left candidate dedup and cross-encoding span overlap undefined; the sequential form makes uniqueness and the replace_all count unambiguous. - Pin down the BOM contract (strip before matching, restore on write), which the read tool's lack of U+FEFF stripping makes load-bearing. - Stop telling the model old_text is matched verbatim while the tool re-encodes line endings, the same prompt/runtime drift the note criticizes elsewhere. Extend the test matrix to cover both passes. - State the scope up front: the claude-code mirror is about four months older than the other four checkouts, and pi ships two edit tools -- the note covers the pi-coding-agent CLI one, not the pi-agent-core harness variant.
The research index listed only agent_tools and read_tool. Add the entry for this series' edit_tool note, and the missing write_tool entry that predates it.
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.
What this adds
docs/research/edit_tool.md— a survey of the model-callable editing tools inthe five reference agents (Grok Build, Pi, Claude Code, OpenCode, Codex), written
before building the equivalent here. Same shape as the existing
read_tool.mdand
write_tool.mdnotes: read the checked-out sources, record what each projectactually does, then derive a contract for this project.
What it found
All five ship structured localized editing, but they have not converged on one
Edit:
search_replaceby default; presets swap inhashline_edit, OpenCodeeditorapply_patchedits[]ofoldText/newTextold_string/new_stringwithreplace_all, plusNotebookEditedit; GPT models getapply_patchinsteadapply_patchonlyThe shared trait is therefore not the name or the schema but the shape: the model
states a change and its precondition, and the runtime reads the current file,
verifies the precondition, and leaves everything else alone. The note draws the
line the other way too — an Edit tool is not automatically a security boundary or
a transaction, since bash can still write anywhere and the checks are not one
storage transaction with the write.
Each project section records the limits, not just the design: Grok's empty
old_stringstill overwrites a non-empty file under the default config, ClaudeCode's delete path can leave an occurrence behind while reporting that all were
replaced, OpenCode V1's prompt still promises a read-before-edit check that was
removed from the implementation, and Codex re-parses and re-applies the patch
after approval, so the committed result can differ from the previewed one.
What it recommends here
A fourth built-in tool: a thin, exact, single-replacement
Edit(path, old_text, new_text, replace_all=false)with a deliberately honestcontract — existing UTF-8 regular files only, non-empty
old_text, unique matchor explicit
replace_all, no regex/trim/similarity fuzz, strict UTF-8 with theBOM stripped before matching and restored on write, and one documented LF→CRLF
retry so text copied out of
read(which drops\r) can still match a CRLFfile. It explicitly leaves out prior-Read enforcement,
edits[],apply_patch,formatter/LSP/history and a per-file queue in the first version, and says why for
each.
Also
docs/research/README.mdnow indexesedit_tool.md, plus thewrite_tool.mdentry that had been missing since that note landed.
Notes
docs/research/convention.