tools: add structured STATUS prefix signals for smaller model clarity

Addresses the loop/no-op problem where small models (e.g. devstral-small)
fail to interpret ambiguous prose output as terminal control signals.

Changes:
- file_write: prefix STATUS=done/no_change/error with STATE_CHANGED and RETRYABLE
- file_edit: same prefix scheme; also RETRYABLE=true for ambiguous match errors
- file_read: prefix STATUS=ok/empty/not_found/error to distinguish data absence from failure
- file_glob: prefix STATUS=ok/no_matches/error with MATCH_COUNT
- file_grep: prefix STATUS=ok/no_matches/error with MATCH_COUNT
- task_add: emit STATUS=ok ADDED=N TOTAL_TASKS=M
- task_check: emit STATUS=done TASK_COMPLETE=true/false REMAINING=N
- task_clear: emit STATUS=ok CLEARED=N REMAINING=N TASK_COMPLETE=true/false
- cascade: rewrite worker termination block as numbered mandatory rules;
  add explicit STATUS: error branch; clarify stop-after-write requirement
This commit is contained in:
Levi Neely 2026-05-19 10:15:08 +00:00
parent dd522e48f9
commit 137d2c0e84
9 changed files with 85 additions and 23 deletions

23
tools/cascade Executable file → Normal file
View File

@ -38,11 +38,24 @@ prompt="[parent_session_id=${OLLIE_SESSION_ID}]
[session_id=${id}]
You are a worker agent. Execute the following task exactly. Output only the result.
When finished, write your result to: ${OLLIE}/s/${OLLIE_SESSION_ID}/prompt
Use this exact format:
[from=${id}]
STATUS: done
SUMMARY: <your result>
TERMINATION RULES (mandatory — follow exactly):
1. Complete the task using whatever tools are needed.
2. When finished (success or failure), write your result to: ${OLLIE}/s/${OLLIE_SESSION_ID}/prompt
Use file_write with this exact format and nothing after it:
[from=${id}]
STATUS: done
SUMMARY: <one-line result or confirmation>
On failure, use:
[from=${id}]
STATUS: error
REASON: <why the task could not be completed>
3. After writing the result, STOP. Do not call any more tools. Do not write again.
4. Do not re-read the file to verify. Do not retry the write. One write, then stop.
5. Do not expand the task scope. If the task is ambiguous or impossible, report STATUS: error immediately.
TASK:
${instruction}"

25
tools/file_edit Executable file → Normal file
View File

@ -11,7 +11,7 @@ def format_diff(path, old, new):
new_lines = new.splitlines(keepends=True)
diff = ''.join(difflib.unified_diff(old_lines, new_lines, fromfile=path, tofile=path))
if not diff:
return "(no changes)"
return None
return f"```diff\n{diff}```"
def find_exact(content, find):
@ -70,13 +70,13 @@ def robust_replace(content, old_string, new_string, replace_all):
find_indent_flexible(content, old_string) or
find_trimmed_boundary(content, old_string))
if match is None:
return None, "old_string not found in file"
return None, "old_string not found in file", False
if replace_all:
return content.replace(match, new_string), None
return content.replace(match, new_string), None, False
n = content.count(match)
if n > 1:
return None, f"old_string is not unique ({n} occurrences); use replace_all=true or provide more context"
return content.replace(match, new_string, 1), None
return None, f"old_string is not unique ({n} occurrences); use replace_all=true or provide more context", True
return content.replace(match, new_string, 1), None, False
if len(sys.argv) < 4:
print("usage: file_edit <file_path> <old_string> <new_string> [replace_all=true|1|yes]")
@ -89,20 +89,24 @@ _ra = sys.argv[4].lower() if len(sys.argv) > 4 else ''
replace_all = _ra.split('=')[-1] in ('true', '1', 'yes')
if not os.path.isabs(file_path):
print(f"STATUS=error STATE_CHANGED=false RETRYABLE=false")
print(f"error: path must be absolute, got: {file_path}")
sys.exit(1)
if old_string == new_string:
print("STATUS=no_change STATE_CHANGED=false RETRYABLE=false")
print("error: old_string and new_string must be different")
sys.exit(1)
if not os.path.exists(file_path):
print(f"STATUS=error STATE_CHANGED=false RETRYABLE=false")
print(f"error: file not found: {file_path}")
sys.exit(1)
with open(file_path, 'r', errors='replace') as f:
original = f.read()
new_content, err = robust_replace(original, old_string, new_string, replace_all)
new_content, err, retryable = robust_replace(original, old_string, new_string, replace_all)
if err:
print(f"STATUS=error STATE_CHANGED=false RETRYABLE={'true' if retryable else 'false'}")
print(f"error: {err}")
sys.exit(1)
@ -110,7 +114,14 @@ try:
with open(file_path, 'w') as f:
f.write(new_content)
except OSError as e:
print(f"STATUS=error STATE_CHANGED=false RETRYABLE=false")
print(f"error: {e}")
sys.exit(1)
print(format_diff(file_path, original, new_content))
diff = format_diff(file_path, original, new_content)
if diff is None:
print("STATUS=no_change STATE_CHANGED=false RETRYABLE=false")
print("(no changes)")
else:
print("STATUS=done STATE_CHANGED=true")
print(diff)

12
tools/file_glob Executable file → Normal file
View File

@ -9,6 +9,7 @@ search_path="${2:-$PWD}"
[ -z "$pattern" ] && echo "usage: file_glob <pattern> [path]" && exit 1
if [ ! -d "$search_path" ]; then
echo "STATUS=error"
echo "error: path is not a directory: $search_path"
exit 1
fi
@ -17,14 +18,21 @@ fi
rg_out=$(rg --no-config --files -g "$pattern" "$search_path" 2>&1)
rg_exit=$?
if [ $rg_exit -gt 1 ]; then
echo "STATUS=error"
echo "error: $rg_out"
exit 1
fi
if [ -z "$rg_out" ]; then
echo "STATUS=no_matches MATCH_COUNT=0"
echo "no matches"
exit 0
fi
echo "$rg_out" \
sorted=$(echo "$rg_out" \
| xargs -d '\n' stat --printf '%Y\t%n\n' 2>&1 \
| sort -rn \
| cut -f2-
| cut -f2-)
count=$(echo "$sorted" | wc -l | tr -d ' ')
echo "STATUS=ok MATCH_COUNT=$count"
echo "$sorted"

5
tools/file_grep Executable file → Normal file
View File

@ -26,7 +26,6 @@ parser.add_argument('--offset', type=int, default=0)
args = parser.parse_args()
rg = 'rg'
search_path = args.path or os.getcwd()
cmd = ['rg', '--no-config', '--color=never']
@ -58,9 +57,11 @@ cmd += ['-e', args.pattern, search_path]
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode == 1:
print("STATUS=no_matches MATCH_COUNT=0")
print("no matches")
sys.exit(0)
if result.returncode > 1:
print(f"STATUS=error")
print(f"error: {result.stderr.strip() or f'rg exited with {result.returncode}'}")
sys.exit(1)
@ -81,7 +82,6 @@ if args.mode == 'content':
if line == '--':
formatted.append(line)
continue
# file:lineno:content or file-lineno-content (context lines)
for sep in (':', '-'):
parts = line.split(sep, 2)
if len(parts) == 3 and parts[1].isdigit():
@ -91,6 +91,7 @@ if args.mode == 'content':
formatted.append(line)
lines = formatted
print(f"STATUS=ok MATCH_COUNT={total}")
print('\n'.join(lines))
if capped:
print(f"\n(showing {max_matches} of {total} matches; use --head=N or --offset=N for more)")

14
tools/file_read Executable file → Normal file
View File

@ -30,19 +30,23 @@ start = int(args[1]) if len(args) > 1 else 1
end = int(args[2]) if len(args) > 2 else None
if not os.path.isabs(file_path):
print(f"STATUS=error")
print(f"error: path must be absolute, got: {file_path}")
sys.exit(1)
if not os.path.exists(file_path):
print("STATUS=not_found")
print("(new file)")
sys.exit(0)
if not os.path.isfile(file_path):
print(f"STATUS=error")
print(f"error: not a regular file: {file_path}")
sys.exit(1)
with open(file_path, 'rb') as f:
if b'\x00' in f.read(8192):
print("STATUS=ok BINARY=true")
print("(binary file)")
sys.exit(0)
@ -55,14 +59,17 @@ else:
end = min(end, start + MAX_SEGMENT - 1)
with open(file_path, 'r', errors='replace') as f:
# Skip lines before start
for _ in islice(f, start - 1):
pass
# Read only the lines we need
segment_lines = list(islice(f, end - start + 1))
if not segment_lines:
print("(empty file)" if start == 1 else "(no lines in range)")
if start == 1:
print("STATUS=ok EMPTY=true")
print("(empty file)")
else:
print("STATUS=ok EMPTY=true")
print("(no lines in range)")
sys.exit(0)
out = []
@ -73,4 +80,5 @@ for i, line in enumerate(segment_lines):
text = text[:MAX_LINE_LEN] + '...'
out.append(f"{lineno:>6}\t{text}")
print(f"STATUS=ok LINES={len(out)}")
print('\n'.join(out))

13
tools/file_write Executable file → Normal file
View File

@ -11,7 +11,7 @@ def format_diff(path, old, new):
new_lines = new.splitlines(keepends=True)
diff = ''.join(difflib.unified_diff(old_lines, new_lines, fromfile=path, tofile=path))
if not diff:
return "(no changes)"
return None
return f"```diff\n{diff}```"
if len(sys.argv) < 3:
@ -22,11 +22,13 @@ file_path = sys.argv[1]
content = sys.argv[2]
if not os.path.isabs(file_path):
print(f"STATUS=error STATE_CHANGED=false RETRYABLE=false")
print(f"error: path must be absolute, got: {file_path}")
sys.exit(1)
parent = os.path.dirname(file_path)
if parent and not os.path.isdir(parent):
print(f"STATUS=error STATE_CHANGED=false RETRYABLE=false")
print(f"error: parent directory does not exist: {parent}")
sys.exit(1)
@ -39,7 +41,14 @@ try:
with open(file_path, 'w') as f:
f.write(content)
except OSError as e:
print(f"STATUS=error STATE_CHANGED=false RETRYABLE=false")
print(f"error: {e}")
sys.exit(1)
print(format_diff(file_path, old_content, content))
diff = format_diff(file_path, old_content, content)
if diff is None:
print("STATUS=no_change STATE_CHANGED=false RETRYABLE=false")
print("(no changes)")
else:
print("STATUS=done STATE_CHANGED=true")
print(diff)

3
tools/task_add Executable file → Normal file
View File

@ -20,4 +20,5 @@ added=0
done
} > "$plan"
echo "added $added task(s)"
total=$(grep -c '^- \[' "$plan" 2>/dev/null || echo 0)
echo "STATUS=ok ADDED=$added TOTAL_TASKS=$total"

7
tools/task_check Executable file → Normal file
View File

@ -23,6 +23,7 @@ lines = content.splitlines(keepends=True)
tasks = [(i, l) for i, l in enumerate(lines) if l.startswith("- [ ]") or l.startswith("- [x]")]
if not tasks:
print("STATUS=done TASK_COMPLETE=true REMAINING=0")
print("no tasks in plan")
sys.exit(0)
@ -32,6 +33,8 @@ if n is None:
# First unchecked
target = next(((i, l) for i, l in tasks if l.startswith("- [ ]")), None)
if target is None:
remaining = 0
print(f"STATUS=done TASK_COMPLETE=true REMAINING=0")
print("all tasks already checked")
sys.exit(0)
else:
@ -43,4 +46,8 @@ else:
idx, line = target
lines[idx] = line.replace("- [ ]", "- [x]", 1)
open(plan_path, "w").write("".join(lines))
remaining = sum(1 for _, l in tasks if l.startswith("- [ ]") and _ != idx)
task_complete = remaining == 0
print(f"STATUS=done TASK_COMPLETE={'true' if task_complete else 'false'} REMAINING={remaining}")
print(f"checked: {lines[idx].rstrip()}")

6
tools/task_clear Executable file → Normal file
View File

@ -7,11 +7,15 @@
OLLIE="${OLLIE:-$HOME/mnt/ollie}"
plan="$OLLIE/s/$OLLIE_SESSION_ID/plan"
[ ! -f "$plan" ] && echo "no plan found" && exit 0
[ ! -f "$plan" ] && echo "STATUS=ok CLEARED=0 REMAINING=0 TASK_COMPLETE=true" && echo "no plan found" && exit 0
before=$(grep -c '^\- \[.\]' "$plan" 2>/dev/null || echo 0)
grep -v '^\- \[x\]' "$plan" > "$plan.tmp" && mv "$plan.tmp" "$plan"
after=$(grep -c '^\- \[.\]' "$plan" 2>/dev/null || echo 0)
removed=$(( before - after ))
task_complete="false"
[ "$after" -eq 0 ] && task_complete="true"
echo "STATUS=ok CLEARED=$removed REMAINING=$after TASK_COMPLETE=$task_complete"
echo "cleared $removed completed task(s), $after remaining"