every row, every leg: the gate that keeps the edge cases held - #970
Draft
gafferongames wants to merge 3 commits into
Draft
every row, every leg: the gate that keeps the edge cases held#970gafferongames wants to merge 3 commits into
gafferongames wants to merge 3 commits into
Conversation
The rows of docs/FIXED-FORM-VERSIONING-TESTS.md are the fixed form's versioning edge cases, and each leg's harness probes them BY ROW NAME. Nothing said a row is probed on EVERY leg: a row could be written into the page, probed on four legs, and nobody would see the other five. Glenn today: "The edge cases must be probed, tested and known to hold, and stay held." compiler/everyrow_test.go is that sentence as a test. It reads the page's row tables (the main table and the divergence table — a table whose first header cell is `row`), takes the nine legs' harnesses, and fails naming every (row, leg) pair nobody probes. A row whose NEW-READS-OLD column is `—` is LOCK-only and owed to internal/lockfile rather than to the nine, read off the page so a row that GAINS a read column starts being owed without editing Go. docs/FIXED-FORM-OWED-ROWS.md is the ledger of the pairs that are owed today, each with the PR or card that owes it. It can only shrink: the gate fails on a line whose pair IS probed, a row the page does not have, a leg outside the nine, or a row the page marks LOCK-only. A row added to the page is owed on nine legs the same minute it is written. The second half, TestEveryRowHasCorpusBytes, wants a `row=` in build/fixedform-corpus/manifest.txt for every row with a read column: a skip when the corpus is absent, a failure under SCHEMA_REQUIRE_CORPUS. Its exceptions are the same ledger under the target `corpus`. Seeded with today's true state: 39 rows, 10 LOCK-only, 29 × 9 = 261 pairs, 192 probed, 69 owed — the 24 rows #920 brings to the Java leg, `fixed_I_grow_element` on all nine, and the four divergence rows (§5.8's 4, 9, 11, 12) on all nine — plus 5 rows the dump writes no bytes for. 50 of those lines are unassigned. Red first, by hand, on all five refusals: a deleted line, a line for a probed pair, an unknown row, a leg outside the nine, a LOCK-only row; and the corpus half skipping without SCHEMA_REQUIRE_CORPUS and failing with it. TestEveryRowProbeNameIsAnchored is the gate's own red, so `string_grow` never takes credit from `wstring_grow`. Wired into ci.yml's go-test after `make tables-go-versioning`, which is the step that builds the corpus, so the corpus half runs for real. #966's fast lane has not merged yet. Co-Authored-By: Claude Fable 5.1 <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.
The silence
The rows of
docs/FIXED-FORM-VERSIONING-TESTS.mdare the fixed form's versioning edge cases — one definition change per row, each read two ways — and each leg's harness probes them by row name:{row: "field_append"}in the Go-driven harnesses,field_append_case()in the C++ reference. CI's full lane runs all of them.Nothing said a row is probed on every leg. A row could be written into the page, probed on four legs, and nobody would see the other five. Glenn, today:
The gate
compiler/everyrow_test.go, two tests and a ledger.TestEveryRowEveryLegparses the page's row tables — a table whose first header cell isrow, which is the main table of definition changes and the divergence table, and not the tables about the rows — greps each of the nine legs' harnesses for each row name, and fails naming every(row, leg)pair nobody probes. The match is anchored on both sides and allows only the reference's_case/_hostile_casesuffixes, sostring_growtakes no credit fromwstring_growandfixed_I_grownone fromfixed_I_grow_element. A leg whose harness file does not exist yet probes nothing, which is the true state of the Java leg.A row whose NEW-READS-OLD column is
—is LOCK-only: no file exists for a leg to read, its proof is the lock's refusal ininternal/lockfile, and the nine read harnesses do not owe it. That is read off the page rather than listed in Go, so a row that gains a read column starts being owed on nine legs without anyone editing this file.docs/FIXED-FORM-OWED-ROWS.mdis the exception list, and it is a ledger rather than an escape — row | leg | owed by | since. The gate also fails when a line is for a pair that is probed, for a row the page does not have, for a leg outside the nine, or for a row the page marks LOCK-only. The list can only shrink. A row added to the page is owed on nine legs the minute it is written; a row that lands on a leg is one line deleted.TestEveryRowHasCorpusBytesis the second gate: a row with a read column needs bytes, and the dump writes onerow=per row intobuild/fixedform-corpus/manifest.txt. The corpus is a build product, so the test skips when it is absent and fails underSCHEMA_REQUIRE_CORPUS. Its exceptions are the same ledger, under the targetcorpus.The counts, seeded with today's true state
—)field_undeprecatefield_modifyarray_shapetext_kindrange_addeddefault_changekeyword_changeclosure_plain_tableclosure_variable_kindclosure_selfThe 69 are three groups:
internal/codegen/javatable/fixedversioning_test.godoes not exist; java leg: §5, the fixed table reads backward (the lineage, LOAD's eleven steps, the two columns of every row) #920 writes it and names exactly these rows. Those lines go when it merges.fixed_I_grow_element.[4]fixed(12,4)→[4]fixed(28,4), the element's I per slot. Probed on no leg, no bytes in the corpus. Its scalar siblingfixed_I_growis on all nine, so this is a port of a case that exists. Unassigned.writer_bound_count,refuse_writes_nothing,unknown_census,forged_ordinal_both_plans(§5.8's 4, 9, 11, 12), probed on no leg and written by no dump. These are the rows whose counters are asserted EXACTLY rather than>= 1, so a leg that counts twice is caught nowhere else. The page says the reference and the dump are Johnny's and every other leg builds its fixture from the page's text and the row's manifest line. Unassigned.Red first
By hand, all five refusals, each observed red and then green again: a deleted ledger line (
field_append on javanamed), a ledger line for a pair that is probed, a row that does not exist, a leg outside the nine, a LOCK-only row listed as owed; and the corpus half skipping withoutSCHEMA_REQUIRE_CORPUSand failing with it.TestEveryRowProbeNameIsAnchoredpins the near-misses as a unit test.Where it runs
ci.yml'sgo-test, as a named step aftermake tables-go-versioning— that step is what builds the corpus, so the corpus half runs for real instead of skipping. It rides the plaingo test ./...too, where the corpus half skips by design. Seconds: two file reads and a regexp. #966's fast lane has not merged; when it does, this belongs inlint-fast.gofmt -l .clean;go test ./internal/ci/green;go test ./compiler/ -run 'EveryRow|Owed'green with the seeded ledger and the corpus built.🤖 Generated with Claude Code