Description
The file modification tools (edit, write, apply_patch) and shell tool lack fundamental data-loss prevention guards. AI agents can silently overwrite files, replace unintended content, or delete project files without adequate safeguards. Unlike V2 core tools (which have partial protection like writeIfUnchanged and TargetExistsError), the V1 tools lack these entirely.
Data-Loss Risks by Tool
1. edit.ts (V1) — packages/opencode/src/tool/edit.ts
| # |
Risk |
Lines |
Details |
| A |
replaceAll: true + short oldString → unintended replacements |
714–715 |
No minimum-length or uniqueness validation. String like "a" or "const" with replaceAll: true silently replaces every occurrence |
| B |
"oldString not found" error doesn't tell AI to re-read |
725 |
Message: "It must match exactly, including whitespace, indentation, and line endings" — encourages retry guessing instead of re-reading |
| C |
"multiple matches" error doesn't tell AI to re-read |
728 |
Message: "Provide more surrounding context to make the match unique" — doesn't suggest re-reading |
| D |
No stale-content guard between read (L126) and write (L155) |
126→155 |
File changed by another agent/user between read and write is silently overwritten. V2 core already has writeIfUnchanged (file-mutation.ts:143-156) |
2. write.ts (V1) — packages/opencode/src/tool/write.ts
| # |
Risk |
Lines |
Details |
| E |
Unconditionally overwrites existing files |
64 |
yield* fs.writeWithDirs(filepath, ...) — no stale-content check, no abort on existing file |
| F |
No content validation before writing |
entire tool |
Can write empty or truncated content |
3. shell.ts (V1) — packages/opencode/src/tool/shell.ts
| # |
Risk |
Lines |
Details |
| G |
rm/del/rmdir inside project not flagged specially |
410 |
containsPath check skips extra permissions for project-internal paths. Destructive commands on project files get same treatment as cat or ls |
| H |
No git awareness |
entire tool |
Cannot distinguish tracked vs untracked files; no recovery path for accidental deletion |
4. apply_patch.ts (V1) — packages/opencode/src/tool/apply_patch.ts
| # |
Risk |
Lines |
Details |
| I |
No stale-content check for update hunks |
115→231 |
File read at start, written after all hunks processed — stale content overwritten |
| J |
"add" hunks don't check if file already exists → silent overwrite |
226 |
No TargetExistsError check (unlike V2 core at file-mutation.ts:134-136) |
| K |
"delete" hunks remove files with generic permission only |
247 |
No additional confirmation for destructive deletion |
5. All V1 tools
| # |
Risk |
Details |
| L |
No git integration |
Cannot snapshot/restore files before modification. No post-hoc recovery |
Contrast with V2 Core
The V2 core tools already implement some protections that V1 lacks:
writeIfUnchanged (file-mutation.ts:143-156): Compares current file content with read snapshot; returns StaleContentError if modified
files.create() with "wx" flag (file-mutation.ts:123-141): Fails with TargetExistsError if file already exists
edit.ts (core V2, L114–116): Error message says "File changed after permission approval. Read it again before editing."
These patterns should be applied to V1 tools.
Expected Behavior
- edit tool should validate that oldString is specific enough before allowing
replaceAll
- Error messages for "not found" and "multiple matches" should tell the AI to re-read the file
- write tool should warn or abort when overwriting existing files
- shell tool should flag destructive commands (
rm, del, rmdir) with additional warning
- apply_patch tool should check file existence before "add" hunks and validate stale content before "update" hunks
- V1 tools should adopt the V2 core patterns (
writeIfUnchanged, TargetExistsError) where applicable
Suggested Fix
This is a cross-cutting concern. The canonical fix is to adopt the V2 core's FileMutation service in V1 tools, which already implements stale-content detection and existence checks. The V1 tools at packages/opencode/src/tool/edit.ts, write.ts, apply_patch.ts should be migrated to use @opencode-ai/core/filesystem/file-mutation where possible, and the error messages in edit.ts should be updated to recommend re-reading.
Description
The file modification tools (edit, write, apply_patch) and shell tool lack fundamental data-loss prevention guards. AI agents can silently overwrite files, replace unintended content, or delete project files without adequate safeguards. Unlike V2 core tools (which have partial protection like
writeIfUnchangedandTargetExistsError), the V1 tools lack these entirely.Data-Loss Risks by Tool
1. edit.ts (V1) —
packages/opencode/src/tool/edit.tsreplaceAll: true+ short oldString → unintended replacements"a"or"const"withreplaceAll: truesilently replaces every occurrencewriteIfUnchanged(file-mutation.ts:143-156)2. write.ts (V1) —
packages/opencode/src/tool/write.tsyield* fs.writeWithDirs(filepath, ...)— no stale-content check, no abort on existing file3. shell.ts (V1) —
packages/opencode/src/tool/shell.tsrm/del/rmdirinside project not flagged speciallycontainsPathcheck skips extra permissions for project-internal paths. Destructive commands on project files get same treatment ascatorls4. apply_patch.ts (V1) —
packages/opencode/src/tool/apply_patch.tsTargetExistsErrorcheck (unlike V2 core atfile-mutation.ts:134-136)5. All V1 tools
Contrast with V2 Core
The V2 core tools already implement some protections that V1 lacks:
writeIfUnchanged(file-mutation.ts:143-156): Compares current file content with read snapshot; returnsStaleContentErrorif modifiedfiles.create()with"wx"flag (file-mutation.ts:123-141): Fails withTargetExistsErrorif file already existsedit.ts(core V2, L114–116): Error message says "File changed after permission approval. Read it again before editing."These patterns should be applied to V1 tools.
Expected Behavior
replaceAllrm,del,rmdir) with additional warningwriteIfUnchanged,TargetExistsError) where applicableSuggested Fix
This is a cross-cutting concern. The canonical fix is to adopt the V2 core's
FileMutationservice in V1 tools, which already implements stale-content detection and existence checks. The V1 tools atpackages/opencode/src/tool/edit.ts,write.ts,apply_patch.tsshould be migrated to use@opencode-ai/core/filesystem/file-mutationwhere possible, and the error messages inedit.tsshould be updated to recommend re-reading.