packet wire: payload-free arms enter the nine-leg corpus - #960
Draft
gafferongames wants to merge 6 commits into
Draft
packet wire: payload-free arms enter the nine-leg corpus#960gafferongames wants to merge 6 commits into
gafferongames wants to merge 6 commits into
Conversation
docs/SPEC.md §4.8 says all nine backends carry payload-free arms on the packet wire and that such an arm is the tag alone, but the only suite was test/packet-void/ (C and C++). No schema under examples/, examples128/ or examples-wide/ declared a bare-name arm, so the construct never reached the golden-source, wire-oracle or golden-wire gates on the other seven legs. (examples/Clauses.schema's EmptyUnion is arms-of-empty-TYPES, which §4.8 distinguishes.) examples/VoidArms.schema puts it in the shared nine-leg corpus: two payload-free arms bracketing two typed ones, so an emitter that special-cases the first or last arm is caught, carried by a message behind a 3-bit lead (the tag is not byte aligned), in a union field, a second union field, and a counted array of unions. Its own file rather than an arm on Wire.schema's ProbeShape: that union's 2-bit tag has one out-of-set value, 3, and all nine legs use it as the read-refusal negative control. An arm there would make it legal. VoidSignal has four arms, so its tag is 3 bits for [0, 4] and 5..7 stay out of set. All nine emitters carry it with no compiler change: each writes the tag in 3 bits and returns, the arm costing exactly what tag 0 costs. Goldens re-pinned (the new unit joins package example, so every file's protocol id moves to 0xcaa884d7062cccc8; the C ExampleView registry gains the types and the union). testdata/wire is untouched — no existing fixture's bytes move. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…dArms Two gates this branch left red, both found by a DeepSeek read. TestExportedSurfaceMovesNeitherWire pins the examples unit's protocol id and build version as LITERALS, on purpose: a re-pin of testdata/golden is the mistake it refuses, so a gate that re-pinned them would say nothing. Its own allowance is that a change to a PROJECTION — here an addition to the corpus, which is a change to the wire shape itself — moves them in the same commit as the goldens. This branch moved testdata/golden/id.txt and testdata/golden/build-version/examples.txt and left the literals behind, so the gate failed on its own re-pin. The literals now carry 0xcaa884d7062cccc8 and 0x68b43963ecc918e3, the values the pinned goldens in this same commit's parent already hold. examples128 is untouched: no corpus file of its moved. TestCorpusIsCanonical failed on examples/VoidArms.schema: the two typed arms of union VoidSignal carried two spaces in the type column where schemafmt writes one. `make fmt` canonicalizes it. The edit is whitespace, so neither hash moves — verified: the ids above are what the formatted corpus hashes to, and a nine-leg regeneration of generated/ off a rebuilt bin/schema is byte-identical. 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.
docs/SPEC.md §4.8: "All nine backends carry payload-free arms on the packet wire" and "A payload-free arm is the tag alone". The only suite was
test/packet-void/— C and C++, with its ownpacket-void-{c,cpp}-{read,write}controls. No schema underexamples/,examples128/orexamples-wide/declared a bare-name arm, so the construct never entered the golden-source, wire-oracle, cross-language byte-identity or golden-wire gates on Go, Rust, C#, Java, Dart, JS or Elixir. (examples/Clauses.schema'sEmptyUnionis arms-of-empty-types, which §4.8 distinguishes.)What lands
examples/VoidArms.schema— the shared nine-leg corpus (SCHEMAS := $(wildcard examples/*.schema), so it enters generation and the golden pins with no Makefile edit):union VoidSignal { ping; pulse VoidPulse; level VoidLevel; ack }— two payload-free arms bracketing two typed ones, so an emitter that special-cases the first or the last arm is caught.type VoidSignalPacketcarries it behind a 3-bitlead, so the tag is not byte aligned: a union field, a second union field selecting the other bare arm, and a counted array of unions.Its own file, not an arm on
Wire.schema'sProbeShape. That union's 2-bit tag has exactly one out-of-set value,3, and all nine legs use it as the read-refusal negative control. An arm there would make it legal and take the teeth out of nine controls.VoidSignalhas four arms, so its tag is 3 bits for[0, 4]and5..7stay out of set.Per-leg byte identity
No compiler change was needed: every emitter already carries the construct, and each writes the tag in 3 bits and nothing else for
pingandack— the arm costing exactly what tag 0 costs, with the C++ reference as the oracle.VoidSignalMaxBitsgenerated/cpp/VoidArms{,Wire}.hgenerated/c/VoidArms{,Wire}.hgenerated/go/VoidArms.gogenerated/rust/src/voidarms.rsgenerated/cs/VoidArms.csgenerated/java/VoidArms.javagenerated/dart/VoidArms.dartgenerated/js/VoidArms{,Flat}.jsgenerated/elixir/VoidArms.exMaxBits = 19= 3 tag bits + the largest arm (VoidPulse, 16) in every leg — identical across all nine, which is the width half of byte identity.Goldens
go test ./internal/goldens -updatere-pinned. The hunks are only the new construct plus the unit's protocol id: the new unit joinspackage example, so every file's id moves0x8656ae68c06b97a7→0xcaa884d7062cccc8, and the CExampleViewregistry gains the types and the union.testdata/wire/is untouched — no existing fixture's bytes move.Draft: what is NOT in this PR yet
test/main.cpp,test/c/main.c,test/go/main.go, …) are hand-written and none constructs aVoidSignalPacketyet, so there is notestdata/wire/voidarms.binfor the legs to compare against. The byte identity claimed above is over the generated codecs, not over nine executed writers. The oracle case intest/main.cppplus the eight comparisons against its pin are the follow-on.packet-void-c-{read,write}shape for the seven legs (make/negative-controls.jsonuntouched).make testchain needs the sibling runtime checkouts and the pinned toolchains; only the compiler-side gates (./bin/schema check examples,go test ./compiler ./internal/check ./internal/goldens,gofmt -l .) were run on this bench.🤖 Generated with Claude Code
Follow-up 97804e2 — two red gates, found by a DeepSeek read
A DeepSeek read of this branch found two gates it left red, and
97804e2fixes both.TestExportedSurfaceMovesNeitherWire/examplesheld the protocol id and build version as literals (0x8656ae68c06b97a7/0x3084078b2f7d571e) and they were not moved with the corpus. The goldens above were re-pinned; the literals, which exist precisely so a re-pin cannot silence the gate, were left behind. They now carry0xcaa884d7062cccc8/0x68b43963ecc918e3— the values this PR already pinned intotestdata/golden/id.txtandtestdata/golden/build-version/examples.txt. This is the allowance the gate's own comment grants: a change to a projection moves them in the same commit as the goldens.examples128is untouched.TestCorpusIsCanonicalfailed onexamples/VoidArms.schema: the two typed arms ofunion VoidSignalcarried two spaces in the type column whereschemafmtwrites one.make fmtcanonicalizes it. Whitespace only, so neither hash moves — verified by arm -f bin/schemarebuild and a nine-leg regeneration ofgenerated/, which is byte-identical.