Conversation
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A compacted turn does not always end with a fresh instruction: when the compaction summary is the final user item, the anchor is the envelope message itself, and the walk-back never inspected the anchor's own content parts. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Pushed a second commit: the same failure has a second shape, seen on another thread today. A compacted turn does not always end with a fresh instruction. Thread
So the anchor The new commit checks the anchor's own content parts before walking back, and allows index 0 as an anchor for the same reason. The envelope still has to bind to canonical turn and sandbox metadata, so this widens where the envelope may sit, not what it may claim. A test reproduces the five-item shape and fails without the change.
|
Problem
Every turn after an automatic compaction fails:
Codex 0.155 rebuilds a compacted turn in this order (observed on a real thread, 7 input items):
additional_toolsplugins.recommendations,agents_md.instructions,environments.environment_contextcanonicalMetadataEnvironmentBeforeUser()walks back from item 7 and skips onlydevelopermessages, so item 5 ends the search. Item 4's envelope — the one that carriescwd— is never read, and the turn is refused. Codex then retries five times and gives up.The envelope itself is well-formed; nothing is wrong with the request except the position of the summary.
Change
Skip a compaction summary while walking back, exactly as a developer message is skipped, under the same provenance rule: its turn id must match the canonical turn, or it must carry a server-owned item id. A summary is recognized by the same predicate the code already uses elsewhere (
isReadableCompactionSummaryText/OPAQUE_COMPACTION_NOTE).This does not widen what can become authority:
environmentMatchesCanonicalMetadata.Tests
tests/environment.test.ts:bun test tests/environment.test.ts tests/thread-environment.test.tson top ofmain: 63 pass, 1 skip, 0 fail.How it was found
The bridge logged nothing when it refused a turn, so this could only be placed by reproducing it against a real thread and instrumenting the refusal path. If you want, I can send that diagnostic (which branch refused, plus the input's shape — types, roles, sizes, whether a part holds an envelope; never prompt text) as a separate PR; it turned a five-retry mystery into a one-line answer.
🤖 Generated with Claude Code