The agent gets its strongest tool: run_command runs any command the model writes, inside the project's folder. Any command includes rm, which deletes files. Run the starting code and you will see it: the model makes the failing test go away by deleting the test file.
So the model proposes and your code decides. Every command gets one of three answers: "run" (it is on a short list of safe commands), "refuse" (it contains a piece of text that is never allowed) or "ask" (everything else: the user says yes or no). Asking is the safe default, because no list of dangerous commands is ever complete.
Two uses of in: with a list, in looks for a whole item. With a string, it looks for a piece of text anywhere inside.
"pwd" in ["pwd", "date"] # True: the whole item is in the list
"pwd -L" in ["pwd", "date"] # False: not the same text
"--force" in "git push --force" # True: the piece is inside the string
A command that is refused, or that the user says no to, must never start. The model gets a result that begins with Error: instead, so it can change its plan.
The finished program prints each decision. The check then tries a few commands of its own:
Decision: run - ls Decision: run - python3 -m unittest Decision: ask - rm test_cart.py User is asked: Run rm test_cart.py? User answers: no Decision: refuse - rm -rf __pycache__ Tests pass after the run: True ls -la → ask, the user says no → Error: the user said no. The command did not run. cat /etc/passwd → refuse → Error: this command is never allowed here. Find another way. ls .. → refuse sudo ls → refuse wc -l cart.py → ask, the user says yes → 24 cart.py
Your task: create the lists ALLOWED and BLOCKED, and write decide(cmd), which returns "refuse", "run" or "ask". Then use it in run_command: print the decision, return an error for a refused command, and call user_confirms for a command that needs a yes.
Assignment
Follow the Coding Tutorial to make run_command run safe commands at once, ask the user about unknown ones and refuse the dangerous ones.
Hint
The order inside decide matters: the blocked pieces first, then the safe list, and return "ask" last. In run_command, both error returns come before subprocess.run, so the command never starts.
Free plan: 30 tutor messages. PRO is unlimited.
