All `.java` source files **must be UTF-8 without BOM** (no `EF BB BF` byte prefix).
- Maven's `javac` fails on BOM with `illegal character: '\uFEFF'`; IntelliJ IDEA tolerates BOM, so IDE-only compilation masks the problem until `mvn compile`.
- If `mvn compile` reports `illegal character: '\uFEFF'`, a tool has written the file with BOM. Strip it before retrying:
### Stream dropouts (`Error: Stream ended without finish_reason`)
The LLM's streamed (SSE) response was cut off before the terminal `finish_reason` event. It is **not** a bug in your code or in a tool — it is the upstream/relay dropping the connection mid-generation.
This repo runs through a relayed provider (`PI_PROVIDER=new-provider`, `PI_MODEL=claude-opus-4-8`, forwarded via `127.0.0.1`), which makes dropouts more likely on large single turns.
**Most common triggers, worst first:**
- **Oversized single turn** — reading several long files at once (e.g. both `crm-lead/CONTEXT.md` + `crm-opportunity/CONTEXT.md`) then immediately doing a large write. The turn right after a big context dump drops most often.
- **One huge output** — emitting a large file (a full HTML report, hundreds of lines) in a single `write`.
- **Network / relay idle timeout** — the local forwarder or an nginx/VPN layer closing an idle SSE long-connection.
**How to avoid it:**
- Read large files with `offset`/`limit` in chunks; do not inhale whole long docs in one call.
- Write large files in small steps: `write` a skeleton, then append with successive `edit` calls, instead of one giant `write`.
-`/compact` or start a fresh session when the conversation history has grown large.
- Deterministic recovery is usually just **retry** — if the same action succeeds on a retry, it was relay jitter, not a real failure.