Skip to content

fix(claude-sdk-oauth): ignore volatile thinking timing - #751

Merged
code-yeongyu merged 3 commits into
code-yeongyu:mainfrom
goldtg:fix/claude-sdk-oauth-thinking-timing
Aug 10, 2026
Merged

fix(claude-sdk-oauth): ignore volatile thinking timing#751
code-yeongyu merged 3 commits into
code-yeongyu:mainfrom
goldtg:fix/claude-sdk-oauth-thinking-timing

Conversation

@goldtg

@goldtg goldtg commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Why

Claude SDK OAuth captures the provider-final assistant message during the last
message_update, before agent-core adds display-only startedAt and endedAt
fields to thinking blocks. Comparing that capture with the committed
message_end content therefore classified otherwise identical turns as
assistant_rewritten.

That false divergence abandoned resident-session continuity and repeatedly
re-sent the growing conversation history, increasing cache writes and eventually
exposing the replay buffer limit reported in #691.

What

  • exclude only thinking-block startedAt and endedAt fields from the
    commit-boundary digest
  • preserve thinking text, signatures, tool calls, text, provider identity, and
    all other semantic content in rewrite detection
  • add a deterministic 10-turn issue regression covering timing-only enrichment,
    non-mutation, thinking rewrites, and text rewrites
  • document the provider-specific behavior and merge-conflict surface

Verification

  • npm --prefix packages/coding-agent test -- test/suite/regressions/691-claude-sdk-oauth-thinking-timing.test.ts
  • Claude SDK OAuth owning suite: 39 files, 324 passed, 3 skipped
  • npm run check
  • npm run build
  • Senpi CLI smoke: 8/8
  • zero-token Anthropic mock loop: 20/20
  • built-module driver: 10/10 timing-enriched turns remained clean; semantic
    rewrites remained rewritten

Fixes #691


Summary by cubic

Prevents assistant_rewritten forks in claude-sdk-oauth when only thinking timing changes by excluding startedAt/endedAt from continuity hashing. Preserves resident-session and prompt-cache continuity (fixes #691).

  • Bug Fixes
    • Exclude only startedAt/endedAt in thinking blocks from the continuity hash; keep all semantic fields.
    • Preserve rewrite detection for real changes (thinking text, signatures, tool calls, text).
    • Add a deterministic regression test covering timing-only enrichment and true rewrites.
    • Document the fix in CHANGELOG.md and the provider’s changes.md.

Written for commit cb1f05e. Summary will update on new commits.

Review in cubic

@goldtg
goldtg marked this pull request as ready for review August 7, 2026 21:01
@goldtg

goldtg commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

Hi @code-yeongyu — the CI and Changelog gate workflow runs are currently action_required because this is a first-time fork contribution. Could you approve the workflow runs when convenient?

Per CONTRIBUTING.md, I left package CHANGELOG.md maintainer-owned and added the required provider-local changes.md entry. Local verification is listed in the PR body; no real provider calls were used.

@1vivy

1vivy commented Aug 10, 2026

Copy link
Copy Markdown

Validated #751 independently against #691 on current Senpi 2026.8.9-2.

Fresh Docker reproduction:
https://gist.github.com/1vivy/9445e7275b552a3a734fcd6bcab30e7c

  • pinned unpatched main (da63874bd0df56fef2051fea384ed8b9f648383c):
    regression fails with Expected: "clean" / Received: "rewritten";
  • pinned PR head (14cef475e7d833ca364a5b1e0393c8fa8c861aa2):
    the same regression passes;
  • the container exits 0 only if main fails for that exact semantic reason and
    the PR passes.

I also checked the fix boundary. It removes only startedAt/endedAt from
thinking blocks before hashing. Thinking text, signatures, changed assistant
text, and every non-thinking block remain hash-significant and fail closed.

On a live affected session, 38 of 40 continuity decisions were
assistant_rewritten (21 flatten, 17 fork), with one cold registry miss
and one healthy delta. Cache reads stayed pinned at 42,596 tokens while cache
writes grew on every turn, matching full-history replay after false divergence.

I tested Hindsight separately because it was enabled on the affected machine.
It is not the direct cause: assistant_rewritten predates its installation and
Hindsight injects a synthetic user context message rather than mutating
assistants. It does add replay weight (12,000-character mental-model budget plus
800 recall tokens), so I kept that memory-quality issue out of this narrowly
correct PR.

Recommendation: merge #751 rather than open a duplicate issue or competing PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

claude-sdk-oauth: thinking-block timing fields flip commit-boundary hash → assistant_rewritten nearly every turn → repeated history re-send

3 participants