Skip to content

CR-2026-036: implement the metadata enrichment block as specified - #38

Merged
reissjason merged 1 commit into
masterfrom
cr/2026-036-metadata-enrichment
Aug 26, 2026
Merged

CR-2026-036: implement the metadata enrichment block as specified#38
reissjason merged 1 commit into
masterfrom
cr/2026-036-metadata-enrichment

Conversation

@reissjason

Copy link
Copy Markdown
Contributor

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 in schemas/payload-schema.json since 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) and metadata.timestamps (name, mode, field, offset_field, elapsed_field, time_base, source, format), plus encode_formula and input_metadata.

The five I found were the five whose names aren't ordinary words. mode, source, field, name and format all 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

Was Now
include named for a decoded field overwrote it — a u16 decoding to 60 came back as an ISO timestamp string PS-313: decoded field wins, warns
mode: rx_time, no recvTime measured_at: null — indistinguishable from a silent device PS-314: key omitted, warns
malformed recvTime 4 swallowed exceptions, no value and no warning names the key and why

_enrich_metadata is rewritten around one place() applying both rules, so a fifth mode can't reintroduce either by forgetting to check.

Making the requirements reachable

  • validate_schema.py validates the block for the first time (PS-315–317). mode: elapsed_to_absolut was previously accepted and silently derived nothing; 8 malformed shapes are 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 — the CR-2026-014 lesson applied up front instead of a CR later.

Why the fixture asserts only the payload

metadata-enrichment.yaml carries a metadata block but lists only its two decoded fields in expected. 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

  • Python 2819 passed / 4 skipped (was 2783; +36)
  • Both conformance paths 1253/1253, 0 disagreements
  • Go ok · Java 46 · C# 92
  • C harness 491 of 491 attempted, 0 differ — up from 488 because it builds the new fixture too

🤖 Generated with Claude Code

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>
@reissjason
reissjason merged commit 5fb32c4 into master Aug 26, 2026
5 checks passed
@reissjason
reissjason deleted the cr/2026-036-metadata-enrichment branch August 26, 2026 14:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant