# Agent File Corruption Pitfall: Line-Number Prefixes in write_file

**Date:** 2026-06-01

## The Problem

When agents use `from hermes_tools import read_file, write_file` inside `execute_code`, a subtle data-format mismatch corrupts source files:

1. `read_file(path)` returns a dict with key `"content"` whose value is the file text **with line-number prefixes**:
   ```
   1|package com.example.app
   2|
   3|import android.os.Bundle
   ```

2. An agent passes `result['content']` directly to `write_file(path, text)` — treating it as clean source text.

3. The `write_file` tool writes the line-number-prefixed text verbatim:
   ```
   1|1|package com.example.app
   2|2|
   3|3|import android.os.Bundle
   ```

4. The Kotlin compiler sees `1|package...` and reports `Expecting a top level declaration` on line 1, column 1 — cascading to errors on every subsequent line because nothing can parse.

## Detection

```bash
# Check if file starts with a number prefix
head -c 50 path/to/file.kt | cat -A
# Corrupted: 1|1|package...  (double prefix from compounding)
# Corrupted: 1|package...    (single prefix)
# Clean:     package...      (no prefix)
```

Also detectable via:
```bash
# First line has a digit followed by pipe
head -1 file.kt | grep -P '^\d+\|'
```

## Fix

Use `terminal` with `sed` or a Python script that strips prefixes:

```bash
# Strip number| prefix from all lines
sed -i 's/^[0-9]*|//' path/to/file.kt
```

Or in Python via execute_code:
```python
text = content['content']  # has line number prefixes
stripped = '\n'.join(
    line.split('|', 1)[1] if '|' in line and line.split('|', 1)[0].isdigit() else line
    for line in text.split('\n')
)
```

**Or better: use the `terminal` tool directly for file writes** — it bypasses the read_file pipe:

```bash
# Write via heredoc (works on bash, NOT fish)
cat > path/to/file.kt << 'KOTLIN'
package com.example

// ... clean content
KOTLIN
```

## When This Happens

- **Delegate_task subagents**: When a subagent reads files, processes content, and writes back via `write_file`, the line numbers from their `read_file()` calls propagate.
- **Execute_code scripts**: Any script that chains `read_file()` → string processing → `write_file()` without stripping the `1|` prefix.
- **Multi-turn edits**: First a subagent corrupts a file, then the parent agent reads the corrupted file and writes it again — compounding the prefixes (`1|1|content`).

## The Correct Pattern

```python
from hermes_tools import read_file, write_file

result = read_file('/path/to/file.kt')
raw = result['content']

# STRIP line number prefix if present
lines = raw.split('\n')
clean_lines = []
for line in lines:
    # Line format: "N|content" or just "content" (no prefix for short files)
    parts = line.split('|', 1)
    if len(parts) == 2 and parts[0].strip().isdigit():
        clean_lines.append(parts[1])
    else:
        clean_lines.append(line)
clean = '\n'.join(clean_lines)

write_file('/path/to/file.kt', clean)
```

## Prevention

1. **Prefer `terminal` over `execute_code` for file writes** — `write_file` via terminal (cat heredoc) is immune to this issue
2. **Use `patch` tool for targeted edits** — it operates on content, not file reads
3. **When using `execute_code`**, always strip line-number prefixes from `read_file` output before calling `write_file`
4. **After any subagent finishes**, verify critical files haven't been corrupted with:
   ```bash
   head -1 path/to/file.kt | grep -qP '^\d+\|' && echo "CORRUPTED" || echo "OK"
   ```

## Real Example (2026-06-01)

Working on Unspooled (NexStream) catalog manager. After subagents built the backend and data layer, writing the UI screen `CatalogManagerScreen.kt` resulted in the file having `1|1|package...` prefixes. The Kotlin compiler produced 400+ errors all saying `Expecting a top level declaration` on every line. Fix was stripping prefixes with sed and rewriting.

## Related: Unicode Box-Drawing Characters Break KSP

Unicode box-drawing characters (`═ ║ ╔ ╗ ╚ ╝`) in Kotlin comments cause KSP (and sometimes the Kotlin parser itself) to fail. KSP error: `Function declaration must have a name` at the function body opening brace, or cascading `Expecting a top level declaration` on every line from 1 onward.

**Detection:**
```bash
grep -Pn '[\\x{2500}-\\x{257F}]' path/to/file.kt
```

**Fix:** Replace with ASCII equivalents (`=`, `|`, `#`, `+`):
```bash
sed -i 's/═/=/g; s/║/|/g; s/╔/#/g; s/╗/#/g' path/to/file.kt
```

**Root cause:** KSP uses a different lexer than kotlinc and does not handle full Unicode in comment bodies. ASCII-only comments are safe.
