Skip to content

fix(edit): create new files when oldText is empty#63

Open
willwashburn wants to merge 6 commits into
mainfrom
advisor/001-edit-create-file
Open

fix(edit): create new files when oldText is empty#63
willwashburn wants to merge 6 commits into
mainfrom
advisor/001-edit-create-file

Conversation

@willwashburn

Copy link
Copy Markdown
Member

Problem

relaywash blocks the built-in Write tool and redirects agents to relaywash__Edit (builtin_block.rs:21) — but Edit hard-fails on nonexistent paths. An agent following the plugin's own guidance has no sanctioned way to create a file and must fall back to Bash heredocs, which the nudge hooks discourage and which bypass savings attribution.

Fix

  • An edit with empty oldText against a nonexistent path creates the file with newText as its contents (parent directories created as needed).
  • Remaining edits in the same batch apply against the new in-memory content; the existing post-edit tree-sitter syntax check runs on the result, and a failure leaves no file on disk.
  • Clearer error messages in both directions: nonexistent path + non-empty oldText"file does not exist (to create it, pass an edit with empty oldText)"; existing file + empty oldText"oldText must be non-empty for existing files".
  • The Write/NotebookEdit block message now teaches the recipe at the moment of redirect.
  • The tool's input_schema is unchanged (no new properties — cache-stable); only the description string was extended.

Tests

Six new unit tests in edit.rs (create, nested dirs, create+edit batch, syntax-check rollback leaves no file, both error messages). Full suite: 167 unit + 5 integration tests pass, including tools_list_is_byte_stable_across_profiles.

Notes for review

  • The creation path duplicates the locate/splice loop from the existing-file path rather than refactoring to share it — deliberate to keep the change additive; flagging in case reviewers prefer a unification follow-up.
  • Repo-wide cargo fmt --check fails at main (~1900 diff lines, pre-existing); the files touched here are fmt-clean apart from one pre-existing import brace at edit.rs:6.

Implements plans/001-edit-create-file.md from the 2026-06-10 codebase audit.

🤖 Generated with Claude Code

relaywash__Edit now accepts an empty oldText against a nonexistent path
as a file creation request. Parent directories are created automatically.
The Write block reason is updated to explain the recipe, and 6 new unit
tests cover creation, nested dirs, batched create+edit, syntax rollback,
and both error paths.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@gemini-code-assist

Copy link
Copy Markdown

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

relaywash__Edit gains the ability to create new files when the first edit for a path supplies an empty oldText and the full content in newText. The apply_to_file function is restructured into a two-branch flow for missing files, and a guard is added to reject empty oldText on existing files. The Write/NotebookEdit block-hook message is updated with creation instructions, and a changelog entry is added.

Changes

Edit tool file creation

Layer / File(s) Summary
Block hook redirect message and tool description
crates/wash/src/hooks/builtin_block.rs, crates/wash/src/tools/edit.rs
Write and NotebookEdit block reasons now include creation-via-edit instructions; DESCRIPTION constant updated to reflect atomic-creation semantics.
apply_to_file creation path and existing-file guard
crates/wash/src/tools/edit.rs
Missing-file branch splits into: (1) empty oldText seeds a buffer, applies remaining edits, runs a syntax check, creates parent dirs, and writes atomically with rollback on failure; (2) non-empty oldText returns an updated error. Existing-file loop gains a guard that immediately fails and rolls back when oldText is empty.
Tests and changelog
crates/wash/src/tools/edit.rs, CHANGELOG.md
New tests cover creation, nested directories, create-then-edit batch, syntax-invalid rollback, and both new failure cases. Changelog documents the feature and the Write redirect message.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 Hop, hop, a blank oldText in hand,
A brand-new file springs up as planned!
No more "file not found" despair,
Just seed the buffer, write it there.
With rollback safe and syntax blessed,
This little rabbit's quite impressed! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 70.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title directly and concisely describes the main change: enabling the Edit tool to create new files when oldText is empty.
Description check ✅ Passed The description thoroughly documents the problem being solved, the implementation approach, testing performed, and design decisions, directly addressing the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch advisor/001-edit-create-file

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@willwashburn

Copy link
Copy Markdown
Member Author

@copilot resolve the merge conflicts in this pull request

Copilot AI commented Jun 21, 2026

Copy link
Copy Markdown

@copilot resolve the merge conflicts in this pull request

Resolved in 1d9414c.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
crates/wash/src/tools/edit.rs (1)

15-15: ⚡ Quick win

Align the description text with actual batch behavior.

The description says “single edit”, but this implementation (and tests) supports “first edit creates, later edits continue in the same batch.” Wording this as “first edit” will avoid misleading clients.

Suggested wording tweak
-const DESCRIPTION: &str = "Batched multi-file edit with fuzzy matching and post-edit syntax check. Pass an array of edits and they apply atomically per-file. Whitespace and visually-equivalent Unicode differences in `oldText` are tolerated for matching only. To create a new file, pass a single edit with empty oldText and the full contents as newText.";
+const DESCRIPTION: &str = "Batched multi-file edit with fuzzy matching and post-edit syntax check. Pass an array of edits and they apply atomically per-file. Whitespace and visually-equivalent Unicode differences in `oldText` are tolerated for matching only. To create a new file, make the first edit for that path use empty oldText and put full contents in newText.";
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/wash/src/tools/edit.rs` at line 15, The DESCRIPTION constant in the
edit.rs file describes the behavior for creating a new file using only "single
edit" wording, but the actual implementation supports multiple edits in a batch
where the first edit can create the file and subsequent edits continue within
the same batch. Update the wording in the DESCRIPTION constant to replace
"single edit" with "first edit" to accurately reflect that it is the first edit
in a batch that creates a new file, not necessarily the only edit in the
request.
crates/wash/src/hooks/builtin_block.rs (1)

25-32: ⚡ Quick win

Add regression tests for the new Write/NotebookEdit reason branch.

This new branch is behaviorally important and currently unpinned in the shown tests; please assert that both tools include the create-file guidance to prevent silent message drift.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/wash/src/hooks/builtin_block.rs` around lines 25 - 32, Add regression
tests that verify the conditional branch for "Write" and "NotebookEdit" tools in
the reason formatting logic. The tests should explicitly assert that both the
"Write" and "NotebookEdit" tools produce the longer reason message that includes
the create-file guidance text "(create files by passing an edit with empty
oldText)", while also verifying that other tools use the shorter message format
without this guidance. This will prevent unintended silent drift in the message
content for these behaviorally important tool cases.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@crates/wash/src/hooks/builtin_block.rs`:
- Around line 25-32: Add regression tests that verify the conditional branch for
"Write" and "NotebookEdit" tools in the reason formatting logic. The tests
should explicitly assert that both the "Write" and "NotebookEdit" tools produce
the longer reason message that includes the create-file guidance text "(create
files by passing an edit with empty oldText)", while also verifying that other
tools use the shorter message format without this guidance. This will prevent
unintended silent drift in the message content for these behaviorally important
tool cases.

In `@crates/wash/src/tools/edit.rs`:
- Line 15: The DESCRIPTION constant in the edit.rs file describes the behavior
for creating a new file using only "single edit" wording, but the actual
implementation supports multiple edits in a batch where the first edit can
create the file and subsequent edits continue within the same batch. Update the
wording in the DESCRIPTION constant to replace "single edit" with "first edit"
to accurately reflect that it is the first edit in a batch that creates a new
file, not necessarily the only edit in the request.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e5dae408-5301-49f5-93f6-9fbffd9dccde

📥 Commits

Reviewing files that changed from the base of the PR and between d659c66 and 1d9414c.

📒 Files selected for processing (4)
  • CHANGELOG.md
  • crates/wash/src/hooks/builtin_block.rs
  • crates/wash/src/tools/edit.rs
  • memory/workspace/.relay/state.json

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants