test(dispatch): prove which decoder runs on shared shapes + sync twins#48
Merged
Conversation
…wins Closes the Medium + two test nits from planning/audit/2026-06-12-delta-audit.md. The shared-shape routing tests (dict, dataclass) asserted only output equality — but PydanticDecoder and MsgspecDecoder decode dict[str,int] / a stdlib dataclass to identical values, so a regression that routed to the wrong decoder would still pass. They now spy on each real decoder's decode() via a _decode_spies helper and assert WHICH one ran (first-in-list wins; the other is never called), pinning the epic's ordering invariant. Also adds the missing sync Client twins for dataclass routing and list-of-BaseModel routing (previously async-only). Verified the strengthened asserts catch the regression: temporarily reversing _dispatch_decoder makes them fail on the spy assertion while the old output-equality check still passed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
Summary
Closes the Medium finding plus two related test nits from the 0.9.0 delta audit (
planning/audit/2026-06-12-delta-audit.md). Test-only; no behavior change.The shared-shape routing tests asserted only output equality — but
PydanticDecoderandMsgspecDecoderdecodedict[str, int]and a stdlib dataclass to identical values, so a regression that routed to the wrong decoder would still pass. The central ordering invariant of the multi-decoder epic ("shared shapes go to the first decoder in the list") was never actually verified.What changed
_decode_spies(*decoders)helper wraps each real decoder'sdecode()so a test can assert which decoder the dispatcher selected.first.decoderan once and the other was never called — pinning the ordering invariant with real decoders, not synthetic stubs.Clienttwins for dataclass routing andlist[BaseModel]routing (previously async-only).Proof the strengthening is real
Temporarily reversing
_dispatch_decoder(last-match-wins) makes the strengthened tests fail on the spy assertion — while the oldassert result == {...}still passed, because the wrong decoder produces the same value. Mutation reverted; that gap is exactly what this PR removes.Test Plan
just lintcleanjust test— 509 passed, 100% coverage (+2 sync twins)🤖 Generated with Claude Code