- tools.py: four flat tools (read_file, write_file, list_dir,
run_command) per A15's reduced manifest. Deliberately unsandboxed:
the VM is the trust boundary (B3) and tool use is auto-approved
inside an approved unit of work (A4), so path confinement would add
failure modes without adding safety. What is enforced is
operational — timeout with process-group kill so a backgrounded
server cannot outlive its command, output truncation so a build log
cannot eat the context window, closed stdin so prompts fail fast,
and a scrubbed environment so project code never sees the agent's
credentials
- executor.py: renders the log, calls the executor role with the
reduced manifest, dispatches tool calls, and checkpoints every
result (A13). Escalation is observable, never self-assessed (A12):
consecutive command failures and a hard turn cap. Failed reads do
not count — looking around is not failing
- Until delegation exists (step 7), escalation gates to the human
with the failures attached
- control.py: start milestone now runs the executor; a stopped
milestone gates to AWAIT_INPUT
Two bugs found by running it live against real models:
- A turn-ending gate tool (submit_plan) left a tool_call with no
tool_result, which providers reject outright, so every planning
turn after the first failed with a 400. The planner now records the
gate as the call's outcome, which is also the truthful transcript
- The renderer now emits a placeholder for any tool_call lacking a
result, so a crash between call and result (A3) cannot poison the
transcript permanently
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>