feat: a turn-scoped note stops Claude repeating a long reply after a housekeeping call

Merged
AN
1d ago
+1189-4

When Claude writes a long final reply and then calls a housekeeping tool in the same response, the response ends tool_use, the host sends the small result back, and the model often writes the reply again. Replays of a real OpenCode request: unchanged, the model rewrote its reply 3 of 3 times; the same "don't repeat" wording inside the tool result stopped it 1 of 3; a turn-scoped system message after the result stopped it 3 of 3. On a mid-work step (short narration, then the tool, then real work) the model kept working 3 of 3 with the note.

  • After each assistant message with at least 350 characters of visible text whose tool calls are all in turnEndNote.tools (default board, ctx_reduce; [] turns it off), the request carries {"role":"system","clear_at":"next_user_message","content":"Your reply above has already reached the user. …"} after that message's tool results.
  • It is derived only from that message and its results, so every request re-sends earlier notes byte for byte and the prompt cache holds. The one exception: a note that would sit directly before another user message (Anthropic rejects that) is left out at that position only.
  • OAuth routes only, on Fable 5.1, Opus 5.5, Sonnet 5.5 and Haiku 5.5; no beta header changes. OpenCode 1, OpenCode 2 and Pi through one Core function, after effort-marker handling and before signing. Settings field only, no menu change.

Tests: per-host sequence tests (requests N, N+1, N+2 share an identical prefix through every earlier note), the 349/350 boundary, mixed tools, API-key routes and unsupported models unchanged, no cache_control on the note. Mutation rows: inject only at the latest point, drop the all-tools check, drop the length minimum; all CAUGHT.


Summary by cubic

Prevents Claude from repeating a long final reply after a housekeeping tool call in the same response; the model rewrote its reply 3 of 3 times on replayed OpenCode requests without the note.

  • Qualifying turns — at least 350 visible characters of reply text, and every tool call in turnEndNote.tools — get a turn-scoped system note (clear_at: "next_user_message") after the tool results, on OAuth routes for Fable 5.1, Opus 5.5, Sonnet 5.5, and Haiku 5.5.
  • Earlier notes are replayed byte-for-byte on every request so the prompt cache holds; the only exception omits a note that would sit directly before another user message, which Anthropic rejects.
  • API-key routes, unsupported models, and the beta/header shape are unchanged; the note carries no cache or effort fields.

Configuration

  • New native turnEndNote.tools setting, default ["board", "ctx_reduce"]; an empty array disables the note, a custom list uses the host's tool spellings.
  • The 350-character minimum is a safety margin for short mid-work steps; thinking content does not count as visible text.