CR-2026-036: implement the metadata enrichment block as specified - #38
Merged
Conversation
The spec side is la-payload-schema's cr/2026-036-metadata-enrichment, which adds PS-309 to PS-325 for a construct that had been in the meta-schema since the initial release with no clause defining it. This is the reference implementation catching up to what describing it required. Three defects, all silent, found by probing the implementation in order to specify it rather than by any test: - **An enriched key overwrote a decoded payload field.** An `include` entry named for a field already decoded replaced it - a `u16` decoding to 60 came back as an ISO timestamp string. PS-313 gives the decoded field precedence and warns. - **A missing runtime value emitted a null.** `mode: rx_time` with no `recvTime` wrote `measured_at: None`, which a consumer cannot tell from a device that reported nothing. PS-314 omits the key and warns. - **Four swallowed exceptions.** A malformed `recvTime` produced no timestamp and no warning. Each now names the key and why it was omitted. `_enrich_metadata` is rewritten around a single `place()` that applies both rules, so a fifth mode cannot reintroduce either by forgetting to check. `validate_schema.py` validates the block for the first time (PS-315 to PS-317). Nothing did before, so `mode: elapsed_to_absolut` was accepted and silently derived nothing; the eight malformed shapes in the test are all newly rejected. `vector-verdicts.py` passes a vector's `input_metadata` to `decode` (PS-324). Without it no vector could reach the block on any path, which is the CR-2026-014 lesson applied before rather than after. `metadata-enrichment.yaml` is deliberately conservative: it carries a `metadata` block but lists only its two decoded fields in `expected`. Enrichment is OPTIONAL, so asserting the enriched keys in the shared corpus would fail the four implementations that correctly do not produce them. What the fixture proves is PS-310 and PS-311 - a schema carrying the block decodes its payload identically everywhere - and all five now demonstrate that, C included. The enrichment semantics are asserted in the CR test against the one implementation that has them. Verified: Python 2819 passed / 4 skipped (was 2783); both conformance paths 1253/1253 with 0 disagreements; Go ok; Java 46; C# 92; C harness 491 of 491 attempted with 0 differ, up from 488 because it builds the new fixture too. Co-Authored-By: Claude Opus 5 (1M context) <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.
Paired with the spec-side MR on
la-payload-schema(cr/2026-036-metadata-enrichment), which adds PS-309 to PS-325 for a construct that had sat inschemas/payload-schema.jsonsince the initial release with no clause defining it.The count was wrong, and the reason matters
I reported "five undocumented meta-schema keys". The real answer is a whole block of twelve:
metadata.include(name,source) andmetadata.timestamps(name,mode,field,offset_field,elapsed_field,time_base,source,format), plusencode_formulaandinput_metadata.The five I found were the five whose names aren't ordinary words.
mode,source,field,nameandformatall appear in the spec for unrelated reasons, so a name-match reported "documented" for keys nothing described. That's now a rule in AGENTS.md: check whether the construct is described, not whether its key names occur.Specified as OPTIONAL
Only the Python reference implements any of it — Go, Java, C#, the TS013 generator and C have nothing, and no corpus schema used it. Requiring it would make five implementations non-conformant on a feature nothing exercises. It's also optional in kind: the block contributes no bytes, reads no payload, and runs after decoding, so an implementation ignoring it decodes every field identically.
Three defects, all silent, found by probing to describe it
includenamed for a decoded fieldu16decoding to60came back as an ISO timestamp stringmode: rx_time, norecvTimemeasured_at: null— indistinguishable from a silent devicerecvTime_enrich_metadatais rewritten around oneplace()applying both rules, so a fifth mode can't reintroduce either by forgetting to check.Making the requirements reachable
validate_schema.pyvalidates the block for the first time (PS-315–317).mode: elapsed_to_absolutwas previously accepted and silently derived nothing; 8 malformed shapes are newly rejected.vector-verdicts.pypasses a vector'sinput_metadatatodecode(PS-324). Without it no vector could reach the block on any path — the CR-2026-014 lesson applied up front instead of a CR later.Why the fixture asserts only the payload
metadata-enrichment.yamlcarries ametadatablock but lists only its two decoded fields inexpected. Asserting the OPTIONAL enriched keys in the shared corpus would fail the four implementations that correctly don't produce them. The fixture's job is PS-310/PS-311 — a schema carrying the block decodes its payload identically everywhere — and all five demonstrate that, C included. Enrichment semantics are asserted in the CR test against the one implementation that has them.Verified
🤖 Generated with Claude Code