Repository navigation
Narrow decoded records from the shape check, and restore Pi field paths - #2783
Merged
Merged
Conversation
_RecordDecoder.fits_wire returns TypeGuard[dict[str, object]], so checked() returns the narrowed value and its cast(dict, data) is gone. The family form gets its own check, tagged(), also a TypeGuard; fits_wire and member() both use it, which deletes member()'s cast and its unbound _FamilyRecordDecoder.fits_wire(self, data) call that existed only to skip the leaf document's override. _declared_member takes the wire value as object, like DeclaredFamily.member_named, the owner it forwards to. mypy on field_codec.py: 112 before, 112 after, identical error set. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#2543 (94526e1) moved Pi payloads from normalize-then-FieldCodec.decode to PiPayload.decode_fields, which constructs the member directly. The per-field try/except that located a refusal under its key and fix lived only inside _RecordDecoder.decode_selected, so the new path dropped it: a transcript entry with content 42 refused as bare "Expected a JSON array." instead of "message.content: ...; fix: supply ...". FieldPlan.locating(problems) now owns that wrapping (MalformedRecord._Located records the refusal under the field key and suppresses it so sibling refusals are reported together). decode_selected's hand-written try/except is deleted in favour of it, and PiPayload.decode_fields uses the same owner and raises RecordProblems, so both decode paths derive the location from one place. test_native_transcript: the parametrized match was declared but never passed to pytest.raises, so it asserted nothing. It is now applied. The JSON case expects MalformedRecord("Invalid JSON: ...") since 79cd5dc moved NativeEntry.read onto FieldCodec.parse; the content case matches the field path and type without pinning the annotation's repr. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
trissim
marked this pull request as ready for review
October 23, 2026 13:56
There was a problem hiding this comment.
Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.
An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.
|
debt-src at 37beb25, every finding: |
debt-src counted three new NoneAbsence spellings at field_codec.py:103-104: the exit parameters were copied from _Refusal as `X | None`. The locator only asks whether the exception is a MalformedRecord, so `object` states exactly what it needs. Co-Authored-By: Claude Opus 5.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.
Two fixes in
field_codec.py.1. The casts after
fits_wireare deleted. #2778 left twocast(dict, data)calls right afterfits_wire. Slop: IDEN-3. The fact "data is a dict" is established byfits_wireand was restated by the cast; the check now narrows it with aTypeGuard._RecordDecoder.fits_wirereturnsTypeGuard[dict[str, object]], sochecked()returnsdatadirectly._FamilyRecordDecoder.tagged()(TypeGuard) names the family form.fits_wireandmember()both use it. That also removesmember()'s unbound_FamilyRecordDecoder.fits_wire(self, data)call, which only existed to skip the leaf document's override._declared_member(name: object)now matchesDeclaredFamily.member_named(name: object), the owner it forwards to.2. Refused Pi payload fields have their field path again.
tests/test_native_transcript.pywas red on main for two reasons.PiPayload.decode_fields, which builds the member directly. The step that put a refused field under its key and fix lived only as a hand-written try/except inside_RecordDecoder.decode_selected, so the new path lost it:content: 42refused as a bareExpected a JSON array..FieldPlan.locating(problems)now owns that step, throughMalformedRecord._Located.decode_selected's try/except is deleted in favour of it.PiPayload.decode_fieldsuses the same owner and raisesRecordProblems.message.content: Expected a JSON array.; fix: supply typing.Annotated[tuple[...PiContent, ...], ...], the same text the good revisions printed.NativeEntry.readgoes throughFieldCodec.parse. Bad JSON is nowMalformedRecord("Invalid JSON: ..."), whichMalformedRecord's docstring declares (field_codec.py:57-60), so the test now expects that.matchchecked nothing. It was declared in the parametrize table but never passed topytest.raises. It is now applied. The content regex matches the field path and type without pinning the annotation's repr.Checks
tests/test_native_transcript.py,tests/test_field_codec.pyand the pi tests: 156 passed.tools/debt_ratchet.pydoes, base vs head:field_codec.py: 112 → 112, identical error set.pi_payloads.py: 111 → 111, identical error set.🤖 Generated with Claude Code