Skip to content

Adds a payload-schema drift test for the doc - #81

Merged
johnnyt merged 1 commit into
mainfrom
sui-o4e-payload-schema-drift
Sep 2, 2026
Merged

Adds a payload-schema drift test for the doc#81
johnnyt merged 1 commit into
mainfrom
sui-o4e-payload-schema-drift

Conversation

@johnnyt

@johnnyt johnnyt commented Sep 2, 2026

Copy link
Copy Markdown
Member

Why

docs/wire-format.md is the format's normative home: when it and an
implementation disagree, the document is what conformance means. But only its
type index was mechanically guarded (wire_format_spec_test.exs). Nothing
tied its per-table field, type, and presence schemas to what
StatifierUI.Trace.Manifest actually builds, so drift in those tables could
only be found by reading them. The sui-o5c verify walk found two such prose
defects by hand, which is what filed this bead.

What

A sibling test, test/statifier_ui/trace/wire_format_payload_schema_test.exs,
parses the six markdown tables of the session.start section - the top-level
payload table, states, transitions, contents, data, and the location
object - and checks each against three built messages: a chart written to
reach every conditional field, a bare one written to reach none, and the
first of those projected (so the projection header has somewhere to be
observed present).

It parses the document rather than restating it, the way the type-index test
already does, so the document stays the single place a field is written down.
Three properties are checked per table:

  • a field the producer emits with no doc row fails;
  • a doc row nothing emits fails;
  • the presence column is enforced both ways - a row marked always must
    be present on every sample row, and a row marked present only when ... or
    omitted ... must be observed both present and absent, so a conditional
    row that has quietly become unconditional fails rather than passing
    vacuously.

A fourth guard test pins the set of table names the parser resolved. Without
it, a restructured section that parsed to nothing would make every other test
here iterate an empty schema and pass.

The one disagreement it found

data.value_location was documented as present only when the compiler
recorded a span for the element's value
. That is stale: every arm of
Statifier.Compiler's build_data_value/2 returns a Location.t() - the
written value's span for an expr- or src-written element, the <data>
element's own span otherwise - and the document's own prose immediately below
the table already described exactly that fallback. The table cell contradicted
its own section.

Resolved on the document side, which owns this contract: the presence cell now
reads always, with the fallback named. No producer was changed - the code
was right and the table was stale.

Notes

  • Full mix quality green and attested on the rebased HEAD (909 tests, 92.9%
    coverage). The two lines are the repo's permanent Gettext and Sobelow
    skips.
  • The test was verified to bite rather than merely pass, by six mutations run
    and reverted: an extra producer field with no doc row, a phantom doc row, an
    always cell flipped to conditional (on data.d_index and on
    states.children), a conditional cell flipped to always
    (transitions.cond_location), and a renamed table label that makes the
    parser find nothing. All six failed the suite.
  • Scope note: this covers the session.start payload tables only. The nine
    trace.* and ten effect.* schemas are the same shape of gap and would be
    a follow-up bead, not a silent extension of this one.
  • A changelog fragment is included: the presence correction changes what the
    published wire-format contract promises a consumer, even though no emitted
    bytes moved.

Closes sui-o4e

wire_format_spec_test.exs guards only the type index. Nothing tied
docs/wire-format.md's per-table field and presence schemas to what
StatifierUI.Trace.Manifest actually builds, so the sui-o5c verify walk
had to find the document's data-table defects by hand.

The new test parses the six tables of the `session.start` section out
of the markdown - the payload table, states, transitions, contents,
data, and the location object - and checks each against three built
messages: a chart written to reach every conditional field, a bare one
written to reach none, and the first projected. A field the producer
emits with no doc row fails, a doc row nothing emits fails, and the
presence column is enforced both ways: an `always` row must be on
every sample row, a conditional row must be observed present and
absent. A guard test pins the parsed table names so a restructured
section fails loudly rather than skipping every check.

It found one disagreement immediately. `data.value_location` was
documented as present only when the compiler recorded a value span,
but Statifier.Compiler returns a location from every arm of
build_data_value/2, and the document's own prose below the table
already described the fallback. The table cell was stale; it now says
always.

Refs: sui-o4e
@johnnyt
johnnyt merged commit 8119f19 into main Sep 2, 2026
1 check passed
@johnnyt
johnnyt deleted the sui-o4e-payload-schema-drift branch September 2, 2026 18:02
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