The task

Rover is going to add a feature to itself.

This is not a stunt. It exercises everything in the module at once — read, edit, shell,
permissions, path safety — and it produces the clearest possible evidence that the loop you
built in Module 1 is doing real work.

Set up

Work in a copy, and put it under git so you can undo anything:

cp -r rover rover-selfedit && cd rover-selfedit
git init && git add -A && git commit -m "before"

Rover should now have: the text editor tool (3.2), bash with cwd and a timeout (3.3), the
permission layer (3.4), and safe_path on every file tool (3.5).

The prompt

Add a tool called word_count to this agent.

It should take a path and return the number of words in that file.

Steps:
1. Read agent.py to see how the existing tools are written.
2. Add the tool definition and the function, following the same style.
3. Run: python3 -c "import agent" to check it still imports.

Tell me what you changed.

What to watch for

Four moments, in order:

It reads before it writes. Nobody told it the file layout. It asks for agent.py first
because your read_file description says to.

It edits rather than rewrites. With str_replace available, it changes the TOOLS list
in place. Watch the old_str it sends — it includes surrounding lines to make the match
unique. That is Lesson 3.1’s error message having taught it a technique.

It asks permission to run Python. Your prompt appears. This is the moment where the two
halves of the module meet: the model wants to run a command, and a human decides.

It checks its own work. The import either succeeds or it does not, and the exit code comes
back. If it fails, watch it read the traceback and fix the file. That recovery loop is all of
Module 4, arriving early.

When it goes wrong

It will, on some runs. Three common ones:

What happens Why What it teaches
str_replace finds no match Its memory of the file is stale after its own edit Re-read after editing
Adds the function but not the definition It did half the job and stopped at end_turn Lesson 4.2, exactly
Import fails, it fixes the wrong line It guessed instead of reading the traceback Lesson 4.4

The second one is worth stopping on. It will say something like “I’ve added the word_count
tool” and it will be half true. The tool definition is there and the function is missing, or
the other way around.

Nothing errored. stop_reason was end_turn. The claim was confident. And it is wrong.

That is the failure the whole of Module 4 is built on, and you have now met it in the wild.

Check the diff yourself

git diff

Read every line. Not because you expect sabotage — because reading a change you did not write
is a skill, and this is the module where you start.

Try this before the next lesson

Run the same task again from the clean commit, twice.

The two runs will differ — different edit points, different order, maybe one succeeds and one
does not. Same prompt, same code, different behaviour.

Sit with that for a moment. It is why Module 7 exists, and why “I tried it and it worked” is
not evidence about an agent.