hold graph rows members to their exact spelling - #131
Merged
Conversation
encoding/json case-folds member names, so a rows document carrying "Cases" or "ID" bound past DisallowUnknownFields and was silently read as the members it is not — the same hole the pack matrix closed under ADR-0025 (a matrix is a closed input) and the argument decoders closed under ADR-0028, live here since the rows format predates both. The hold runs on the document and on every row before the decoder, refusing a case-variant by naming the exact spelling and a stranger as the unknown member it is. Found during design recon for #128, whose graphMatrixVersion gating would rest on a closedness premise this defect made false. Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Brian Jin <35789537+kikashy@users.noreply.github.com>
The review found the same case-fold one level deeper than the row members: DecodeDisposition — the one gate every expected disposition passes, corpus, pack matrix, and graph rows alike — relied on the strict decoder, so "Kind", "OutcomeID", or a handoff carrying "State" bound and canonicalized as the members they are not, on the pack surface as much as this one, including beside the canonical spelling, which the fold silently overwrote. The gate now holds the disposition's members and its handoff member's to their exact §8.3 spellings, once, for every reader; expectedNodes keys are node ids and are deliberately not held. And a cases element that is not a JSON object is refused as the shape defect it is, rather than decoding to a zero row misdiagnosed as declaring no id. Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Brian Jin <35789537+kikashy@users.noreply.github.com>
Contributor
Author
Cross-vendor review — disposition tableReviewer: Codex (codex-cli 0.145.0). Reviewed SHA: 4eedd53 (full output captured to file). 2 findings, both confirmed, applied in 91b5c97 under the dispositioned-finding exception.
Gate green at 91b5c97 (full suite + bundled conformance). Ready to merge. 🤖 Generated with Claude Code |
|
🎉 Thank you for your contribution to Judgment Pack! If you’d like another task, choose a path that interests you: |
Merged
kikashy
added a commit
that referenced
this pull request
Aug 24, 2026
The release completing the wire-only client's upstream asks, all found building the desk against v0.18.0: the document-digest binding on every graph matrix run and validation (ADR-0030, #132), per-node evaluation traces on request (ADR-0031, #127), the handoff-target assertion on graph rows discharging ADR-0025's deferral (ADR-0032, #128), and the graph rows spelling holds (#131). CHANGELOG's Unreleased section becomes the 0.19.0 entry. Signed-off-by: Brian Jin <35789537+kikashy@users.noreply.github.com> 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.
Closes a live defect found during #128 design recon (empirically confirmed): the graph rows loader relied on
DisallowUnknownFieldsalone, andencoding/jsoncase-folds member names —{"Cases":[…]}and{"ID":…}were accepted and silently read as the members they are not. This is the third instance of the class (pack matrix closed it under ADR-0025; the MCP argument decoders under ADR-0028), live here because the rows format predates both.The hold runs on the document and every row before the decoder: a case-variant is refused naming the exact spelling; a stranger is refused as unknown. Table-driven tests pin both refusal shapes plus the fixture still loading; the hold is mutation-verified (removing it re-admits the folded document). The existing rot-pin (
expectedHandoffTargetrefused on graph rows) is unaffected and now produced by the hold with the same code.#128's
graphMatrixVersiongating will rest on "a matrix is a closed input" — this makes that premise true first.Material-decision impact: public-surface; review: round to be posted on this PR
🤖 Generated with Claude Code