Repository navigation
Conversation
A reloaded turn recorded by Sonnet 5.5 on the Claude API keeps its signed thinking on the same model, on Haiku 5.5 and on Vertex (verbatim, under the drop_block binding), and on Bedrock as signed reasoning; the new attachment reaches every transport. The API drops thinking the new model or account cannot read; stripping it client-side would lose it. Signed-off-by: Arnaud Héritier <aheritier@apache.org>
The API answers a refused compaction with a 200, empty content and stop_reason refusal. It takes the same unexpected-stop-reason error as an end_turn answer, so the runtime keeps the context. Signed-off-by: Arnaud Héritier <aheritier@apache.org>
5 tasks
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
Static review found no blocking issues in these focused test-only changes; tests were not executed during review.
No open issues 🎉
What changed in this PR
Adds test-only coverage for Claude 5.x history replay after reload and model or transport switches, completing the switch-testing portion of #4654.
Changes:
- Checks signed thinking and attachment requests across Claude API, Vertex, and Bedrock.
- Extends request capture to accept full conversations.
- Adds a native-compaction refusal safeguard case.
| File | Description |
|---|---|
pkg/model/provider/providers/claude5_switch_requests_test.go |
Tests reloaded history across model and transport switches. |
pkg/model/provider/providers/claude5_requests_test.go |
Supports full-history request capture. |
pkg/model/provider/anthropic/compaction_test.go |
Checks compaction refusal error handling. |
Review effort: Balanced
aheritier
enabled auto-merge
October 21, 2026 16:06
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #4654 (PR 3 of 3, after #4686 and #4688). Part of #4583 and epic #4580.
What
Test-only. This PR pins what a reloaded Claude 5.x conversation sends after a model or transport switch, and adds the one compaction safeguard case that was missing.
TestClaude5SwitchAfterReload(pkg/model/provider/providers)drop_blockand withthinking-binding-controls, on the same model, on Haiku 5.5 and on Vertex; as signedreasoningContenton Bedrock. The raw blocks are replayed, not rebuilt: aredacted_thinkingblock that exists only in the raw state reaches the Claude API and Vertex. The new PDF attachment rides on the new user turn on every transportReplayableProviderStateand own-raw recovery); stripping thinking when the recorded model differs from the request model; dropping the signature in Bedrock's fallback pathTestCompactConversation_Safeguards/refusal(pkg/model/provider/anthropic)stop_reason: refusal): it takes the same unexpected-stop-reason error as anend_turnanswer, so the runtime keeps the context (TestNativeCompactionErrorLeavesTranscriptIntact)The switch test reuses the request-capture harness from
claude5_requests_test.go, now able to send a whole conversation. There is no runtime and no fake server, and each case takes milliseconds.Why "keep sending" is the correct behavior
The docs say to "keep sending the full history on every request, thinking blocks included, and let the API drop what the current model can't read". The reasoning is lost for good only if the client strips it. Sonnet 5.5 and Haiku 5.5 blocks are also bound to the account that produced them; another account's request succeeds and the blocks are dropped. Replay in docker-agent never checks which model recorded a turn, and this test keeps it that way.
Results table
The full model × transport × feature table is posted on #4654. In short:
drop_blockbinding on Bedrock (not documented there);Not added, and why
TestForeignProviderStateKeepsThinking.TestUnreplayableRawStateandTestUnreplayableNativeBlocks.Notes
native_compactionon Vertex.References
thinking-binding-controls-2026-08-01reports drops on the Claude API and Google Cloudsystem,toolsand earliermessages;drop_blockdrops rather than rejectscontent; checkstop_reasonValidation
task buildpasses.task testpasses.golangci-lintv2.14.0 reports 0 issues, andgo run ./lint .reports no offenses.go test -race -shuffle=on ./pkg/model/provider/...passes.An independent review found no critical issues and three important ones, all fixed here:
redacted_thinkingblock now pins it;compact-*beta assertion could never fail, and is removed;modelsdev.NewDatabaseStore, as elsewhere.Minor findings fixed: a realistic
Version/MessageIDon the fixture, checked type assertions, the attachment checked on the new turn, and the refusal commit's wording.