diff --git a/.agents/AGENTS.md b/.agents/AGENTS.md index 44d8139..2a026ef 100644 --- a/.agents/AGENTS.md +++ b/.agents/AGENTS.md @@ -151,6 +151,12 @@ calling the script. See `agent-infrastructure.md` item 22 for the refactor plan. - Fires once per session. Good for: current branch, active investigations, dead ends. - Not good for: precise rule reminders (use PostToolUse or nested AGENTS.md). +- **OpenCode delivery:** injected as a synthetic `text` part via + `output.parts.unshift()` on the first `chat.message` turn. **Not** via + `experimental.chat.system.transform` — that hook fires for task-spawned + subagent sessions after a user message is already in context, which causes + Qwen-family GGUF models to abort with a Jinja "System message must be at the + beginning" error. See Forbidden Patterns below. ### `stop.sh` — End-of-session reflection @@ -237,6 +243,15 @@ Some things cannot be unified and live in tool-specific locations: model may be correct. Applies to: OpenCode tool names (`read`/`edit`/`task`), parameter names (`offset`/`limit` not `startLine`/`endLine`), and plugin guard logic. +- ❌ Using `experimental.chat.system.transform` to inject session-start content + in OpenCode. That hook fires for every model call — including task-spawned + subagent sessions — **after** the task prompt (a user message) is already in + the conversation. Pushing to `output.system` at that point places a system + message at a non-zero position, which Qwen-family GGUF models reject with + _"System message must be at the beginning"_ (Jinja chat template guard). + Fix: inject session-start as a synthetic `text` part via `output.parts.unshift()` + on the first `chat.message` turn (guarded by an `initializedSessions` set). + Text parts have no position constraint. Committed `f0d21e9` in dotfiles. - ❌ Asserting that a third-party tool does **not** support a feature (config mechanism, directory, option) without fetching the tool's current docs first. Training data is frequently stale. Negative claims ("X doesn't have Y") must