- Tool results are always plain strings; any failure must start with the exact prefix `error:` because guardrails, compaction, and reporting depend on it.
- Read-before-write guard is enforced across `write_file`, `edit_file`, and `delete_file`: existing files must be read or previously written in-session unless the guard is disabled.
- All file paths are resolved through sandbox checks (symlink-resolving, allowed-root containment), and even in YOLO/unrestricted mode the filesystem root is still blocked.
- `.swival/` is the shared runtime state root for history, todo, REPL history, trash, and large command outputs; multiple subsystems assume these paths.
- Output size caps are strict and consistent: file/list/grep/fetch are capped at 50 KB with 2,000-char line truncation, command output is 10 KB inline with spill to `.swival/`, and MCP has higher caps (20 KB inline, 10 MB file).
- CLI/REPL I/O contract is fixed: final answers go to stdout only, diagnostics go to stderr, and exit codes are 0 success, 1 error, 2 exhausted turns.
- Config precedence is always CLI > project `swival.toml` > global config > defaults, using `_UNSET` sentinels only at argparse boundaries for fallthrough.
- MCP tools are always namespaced `mcp__<server>__<tool>`; degraded servers return `error:` immediately and tool schemas are dropped when they exceed 50% of context budget (warn at 30%).
- Message access must go through `_msg_*` helpers to support dict-or-object shapes; direct indexing is avoided and content mutation uses `_set_msg_content`.
