- NDJSONDecoder emits .toolUseRequested whenever tool_calls is present on
any chunk; never gates on done:true (AGENT-04 transport gotcha).
- Each tool_use gets a fresh UUID id (Ollama emits no ids on /api/chat).
- done_reason mapping: stop→endTurn (or toolUse if calls seen), length→
maxTokens, tool_calls→toolUse, missing→toolUse-if-calls-else-endTurn.
- Mid-stream EOF emits .stopReason(.streamTruncated) — no
partialToolUseAtDisconnect (NDJSON is atomic per line).
- OllamaRequestBody.encodeNative drops the tools array entirely when
ToolChoice == .none (AGENT-07 cap-recovery invariant).
- ToolChoice.tool(name:) appends a best-effort system hint message
(Ollama has no first-class tool-choice.force).
- OpenAI-compat path: tool_choice serializes as "auto"/"none"/"required"
string or {type:function,function:{name}} object.
- Replaces Plan 04-01 placeholder files; tests: 19 passing.