encoding: a derived decode that collects every field's failure (WEB F6) #95
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Goal
A derived record
decodereports every field that failed, not only the first. A form with three bad fields yields three problems, and so does a config file (decision D12 (a): every format gains it).Source
decodecollects (notstd/webdecoding field by field).docs/design/ENCODING.md(section 2DecodeError, section 3 "Fields with a default…", the deriveddecode).Acceptance criteria
DecodeErrorgainsproblems: List<DecodeError> = [](default empty, so every existing construction andDecodeError messagestill compiles andShowof a single error is unchanged).decodekeeps reading after a failing field and fails once at the end. The returned error carries one entry inproblemsper failed field, each with its ownpath(price.currency,items[2].name), in declaration order. A record with exactly one failing field still reports that one problem.decode(for example theEmail/Slugwrappers) and theTryFromfailure path still produce a singleDecodeError.tests/conformance/encoding-*.trbpin: three bad fields give three problems with paths; one bad field gives one; a bad nested field gives its full path; JSON and one non-JSON format both collect.problemsand the collecting derivation and notes the resume contract below; WEB.md F6 is marked done.Seed
Not expected to touch the seed: no syntax change, no new native, no driver flag, no std name the compiler looks up by string (
DecodeErroris not inwellknown.trb). The change is in the derivation (compiler/src/ir/lower/derive.trb,semantics/checker/derive.trb) andstd/encoding. To verify during implementation: if the compiler's own sources use a derivedDecode, the first commit must still bootstrap with the old seed; if that fails it becomes the two-commit seed path from CLAUDE.md.Size
One PR, one or two Conventional Commits:
feat(encoding): derived decode collects every field's failure, plus optionallydocs(encoding): ...if kept separate. Do not mix in the forms work (WEB section 3.5,Submitted/Form), which is a separate item.Open question
How a
Decoderresumes after a failed field (position after the failed value, nested records and sequences, streaming formats) is not specified in ENCODING.md. See the owner decision comment; the issue is notreadyuntil it is answered.Dependencies
None known.
Moved from the planning lists of the docs; the design record stays the specification.
[loop:torbscript] intake: in scope (author orion, label loop). Matches WEB.md F6 and decision D12 (a), which settles the design: change ENCODING's derived
decodeto collect. No collision with a design record or CONCEPT "Open Questions". Possibly touches the seed (derived decode); to settle in refine. next: refine (waiting for the ready buffer slot, 0 of 2 ready).[loop:torbscript] claim refine by session:loop-torbscript until 2026-10-06T06:58:30Z
[loop:torbscript] owner decision: how does a
Decoderresume after a failed field?What: the derived
decodemust keep going after a field fails (D12 (a) settles that it collects), but ENCODING.md does not say what state aDecoderis in after anErrfrombool/int/string/...,record,sequenceor a nestedfield. Collecting needs a defined position to read the next field from.Options:
(1) Contract: after an
Errfrom a scalar the value is consumed and the decoder stays positioned for the nextfield; anErrfrom a structural call (record,sequence,variant) is fatal for that subtree and its enclosing record stops collecting there. No newDecodermember; each format (JSON, CSV, XML, ...) must honour it.(2) Add a required
Decoder.skip()that the derivation calls after a failed field to discard the rest of that value. Most robust for streaming formats, but it grows the trait every format implements.(3) Collect only for fields read by the derivation itself over an in-memory value (
ValueDecoder), and stay first-error for streaming decoders. Smallest change, but a config file would not say "three mistakes".Recommendation: (1) with conformance tests for JSON and one non-JSON format; no trait growth, and D12's "every format gains it" holds. Not breaking (
problemshas a default); no seed change expected.Not labelled
readyuntil you answer.[loop:torbscript] refine: body rewritten to definition of ready (goal, criteria, design record, seed: not expected, size: one PR); open owner question on decoder resume after a failed field, not labelled ready, next: wait for owner decision
[loop:torbscript] owner decision recorded (torben, 2026-10-06): option 1. A failed scalar field is consumed and the
Decoderis positioned at the next field, so the deriveddecodecollects every field error in one pass. ENCODING.md documents this state. Labelledready.Flags#47[loop:torbscript] claim implement by session:loop-torbscript-20261007 until 2026-10-07T05:32:48Z
[loop:torbscript] implement: PR #150 open (one commit
feat(encoding): derived decode collects every field's failure), all acceptance criteria covered, forge CI green (tier A, tier B, bootstrap, cross-compile, same-C, playground, archives); tier A also green in a local gcc container, check-commits clean, no seed change. Worker usage: ~160k tokens. next: review (waiting on merge gate argus)[loop:torbscript] claim review-fix by session:loop-torbscript-20261007 until 2026-10-07T04:07:23Z
std/htmlmarkup (WEB slice 1) #93