D529 - The record format already carried what D512 said it lacked
decided - 2026-09-04
D512 closed with a forward-looking claim that has been quoted as a blocker in every plan since:
Two hundred and ninety-five cases, and every libc function that can be driven from the record format as it stands now has some. What remains needs the format to change first, and both items are the same shape: the wide-character family needs a wide text encoding, and a test that could tell a
strtok_rdelegating tostrtokneeds two interleaved sequences where the record carries one subject per case.
Both halves are wrong. The format carries both today, and has since before D512 was written.
The wide family needs
b:, which exists
Argument::Bytes - the b: field - is a raw
byte blob in hex, and its own documentation says why it exists:
Element data cannot ride in a text field: a four-byte
5is05 00 00 00, and a NUL-terminated field would stop at the first of those. Its own type, no escaping to get wrong.
A wchar_t string is element data of exactly
that shape. Thirteen cases already use b:, and the replay
already marshals it - qsort and bsearch clone
the blob into a mutable array and pass its address, which is the same
thing a wide string needs.
Encoding the array directly is also the more honest choice than a
"wide text encoding" would have been: the functions under test operate
on arrays of wchar_t, so recording the array avoids
inventing a conversion and then testing the conversion instead of the
function.
The interleaved sequence needs ordering, which exists
strtok is already sequenced in the
corpus:
REF|case|strtok/simple#0|strtok|s:a,b,c|s:,
REF|case|strtok/simple#1|strtok|n:|s:,
REF|case|strtok/simple#2|strtok|n:|s:,
Reference.cases is "the cases, in the order the run made
them", the replay runs them in that order, and
Argument::Null exists precisely so
strtok(NULL, ..) is a value rather than a missing argument
- its documentation says "both occur in the same sequence".
So interleaving two sequences is emitting A#0,
B#0, A#1 as three ordered cases. Nothing about
"one subject per case" prevents it; a case is one call, and a
sequence is what the order of cases already means. For
strtok_r, which save pointer a call uses is an ordinary
argument and needs no new type.
What this costs, and why it is worth a decision rather than a fix
Four functions - wcslen, wcscmp,
wcsncpy, wcsrchr - are declared and
implemented in orbistoun and have zero differential cases. They
have been verifiable the whole time.
The cost was not the format. It was that a decision's forward-looking sentence, written without checking the format it was describing, became the reason nobody looked. This is D510's pattern in its most expensive form yet: not a message describing a gap that outlived the gap, but a description of a blocker that was never accurate, repeated into a plan and a standing prompt for fifteen ticks.
D510 said the habit is to grep for a gap's own words when a change closes one. This is the other half: grep for them when the gap is first written down, because the cheapest moment to find out a blocker is imaginary is before it is quoted.
What is not decided here
How the wide cases should be shaped - which inputs are worth
recording. That is the same question every other family faced and D511
answered generally: vary the parameter nobody varied.
For the wide family the obvious candidates are element width
assumptions, embedded values above the ASCII range, and a
wcsncpy that does or does not terminate - none of which
needs a format change either.