fix: updated execute_command to not mangle heredocs and also added explicit instructions to the coder and sisyphus agents to use fs_write and fs_patch over execute_command when writing files

This commit is contained in:
2026-06-03 10:20:39 -06:00
parent 28a283283f
commit aa2d4f3265
3 changed files with 37 additions and 4 deletions
+8 -2
View File
@@ -177,8 +177,14 @@ nodes:
1. Use `fs_patch` for surgical edits to existing files. 1. Use `fs_patch` for surgical edits to existing files.
2. Use `fs_write` for new files or full rewrites. 2. Use `fs_write` for new files or full rewrites.
3. NEVER output code to chat. Always use tools. 3. NEVER write files via `execute_command`. Do not use `cat >`,
4. ALWAYS pass ABSOLUTE paths to fs_write and fs_patch. Relative `cat >>`, `echo >`, `printf >`, `tee`, heredocs (`<<EOF`), or
`python3 -c "open(...).write(...)"`. Shell-based file writes
break on multi-line content, special characters, quoted strings,
and nested language blocks. `fs_write` and `fs_patch` handle
these correctly because they don't go through shell parsing.
4. NEVER output code to chat. Always use tools.
5. ALWAYS pass ABSOLUTE paths to fs_write and fs_patch. Relative
paths resolve against the coyote invocation directory (not the paths resolve against the coyote invocation directory (not the
project dir), which is rarely what you want. The project root project dir), which is rarely what you want. The project root
is {{project_dir}}. is {{project_dir}}.
+22
View File
@@ -39,6 +39,8 @@ global_tools:
- fs_grep.sh - fs_grep.sh
- fs_glob.sh - fs_glob.sh
- fs_ls.sh - fs_ls.sh
- fs_write.sh
- fs_patch.sh
- execute_command.sh - execute_command.sh
instructions: | instructions: |
@@ -237,6 +239,24 @@ instructions: |
**No evidence = not complete.** Mark a todo `completed` only after evidence is collected. **No evidence = not complete.** Mark a todo `completed` only after evidence is collected.
## File Operations (Direct Edits)
When you write or modify files yourself (rather than delegating to coder):
- **For writing files**, ALWAYS use `fs_write` (new file / full overwrite) or `fs_patch` (surgical edit). NEVER write files via `execute_command`. Do not use:
- `cat > file`, `cat >> file`, `tee`
- `echo >`, `printf >`
- Heredocs (`<<EOF`, `<<-EOF`, `<<'EOF'`)
- `python3 -c "open(...).write(...)"` or similar one-liners in any language
- Any other shell-based file write mechanism
Shell-based file writes break on multi-line content, special characters, quoted strings, and nested language blocks (Python triple-strings, JSON, etc.). `fs_write` and `fs_patch` handle these correctly because they don't go through shell parsing.
- **For reading files**, prefer `fs_read` over `cat` via `execute_command`. `fs_read` supports offset/limit for partial reads.
- **For listing/searching**, prefer `fs_ls`, `fs_glob`, `fs_grep` over shell equivalents (`ls`, `find`, `grep`).
`execute_command` is for: git operations, build/test commands, package management, runtime inspection (`ps`, `df`, etc.) — anything where the shell IS the right interface.
## Phase 7 - Failure Recovery ## Phase 7 - Failure Recovery
### 3-strike rule ### 3-strike rule
@@ -307,6 +327,7 @@ instructions: |
- Marking todos complete without evidence → dishonest reporting - Marking todos complete without evidence → dishonest reporting
- Suppressing errors (`as any`, `@ts-ignore`, `#[allow(...)]`, empty catches) → hidden bugs - Suppressing errors (`as any`, `@ts-ignore`, `#[allow(...)]`, empty catches) → hidden bugs
- 3 fix attempts without consulting Oracle → wasted budget - 3 fix attempts without consulting Oracle → wasted budget
- Writing files via `execute_command` (heredocs, `cat >`, `echo >`, `printf >`) → file corruption from shell parsing
## Hard Blocks (NEVER violate) ## Hard Blocks (NEVER violate)
@@ -315,6 +336,7 @@ instructions: |
- Speculate about unread code → never - Speculate about unread code → never
- Leave code in broken state after failures → never - Leave code in broken state after failures → never
- Deliver final user answer with Oracle still running → never - Deliver final user answer with Oracle still running → never
- Write files via `execute_command` instead of `fs_write`/`fs_patch` → never
## Available Tools ## Available Tools
{{__tools__}} {{__tools__}}
+7 -2
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -e set -e
# @describe Execute the shell command. # @describe Execute the shell command. DO NOT use this to write files — use fs_write (new files) or fs_patch (edits) instead. Shell-based file writes (cat >, echo >, printf >, tee, heredocs, python -c "open(...)") break on multi-line content, special characters, quoted strings, and nested language blocks.
# @option --command! The command to execute. # @option --command! The command to execute.
# @env LLM_OUTPUT=/dev/stdout The output path # @env LLM_OUTPUT=/dev/stdout The output path
@@ -11,6 +11,11 @@ source "$LLM_PROMPT_UTILS_FILE"
main() { main() {
guard_operation guard_operation
local script
script="$(mktemp)"
# shellcheck disable=SC2064
trap "rm -f '$script'" EXIT
# shellcheck disable=SC2154 # shellcheck disable=SC2154
eval "$argc_command" >> "$LLM_OUTPUT" printf '%s\n' "$argc_command" > "$script"
bash "$script" >> "$LLM_OUTPUT"
} }