Repository navigation
ir: assert IRVersion once, against a pin of the encoded shape, instead of in every golden #964
Description
Problem
The IR version is asserted in 115 places and checked against the shape it versions in none.
- Every golden carries it. All 115 golden files hold
"irVersion". 11 of the last 150 PRs bumped the version. Those PRs touched a median of 146 files and 3,437 lines, against 8 files and 590 lines for the rest. Of their 1,069 golden-file edits, 739 (69%) changed only theirVersionline. - Nothing ties it to the shape. ir-design §2.1 bumps
IRVersionon every change to the encoded shape, additive ones included, because the decoder refuses unknown members. Nothing checks it, and parallel PRs each bump from their own base. Four merged PRs had claimed a number another took first and bumped again by hand: fix!: keep the OpenAPI declarations that were dropped #741 claimed 0.6.0 (feat(ir)!: give each provenance locator its own field #549 took it), feat(ir)!: give a tuple a typed rest and collection bounds #734 and feat(ir)!: name a webhook binding's event #735 claimed 0.7.0 (feat(ir)!: identify operation groups and declare ID namespaces #801), and fix!: record an OpenAPI document's $self on its source entry #732 claimed 0.8.0 (feat(ir)!: give parameters and enum members stable IDs #811). - A shape change can pass unseen. Adding a runtime-policy field to
ir.Operation, filling it from anx-retryextension and regenerating the goldens leavesgo test ./..., the harness and archtest green, withIRVersionunchanged.
A missed bump is costly. A build at version N reads only N, so the stamp is all that tells a reader the shape moved.
Direction
A proposal, in two parts that land together:
- Pin the shape. A test derives a canonical description of every type reachable from
ir.Document: JSON member names, Go types,omitemptyandomitzero, and the sealed sums' kind tags. It reads the package throughinternal/decls, hashes the description, and compares against a table keyed byIRVersion.- A shape change with no bump fails, naming the version to add.
- A bump with no shape change fails.
- Two PRs taking one number with different shapes fail on whichever reaches
mainsecond.
- Stop stamping each golden. The golden helper compares documents with the
irVersionmember masked, or writes goldens without it. A bump then touches the constant, the table and the version history, not every golden.
Done when planted mutations redden the pin with IRVersion left as is (a member added or removed, a JSON tag renamed, omitzero changed to omitempty, a TypeKind added), and a version bump regenerates no golden.
Out of scope
What a bump promises consumers (#432).
Related: #432
Priority: P4, rule 1 (a test change with no behaviour change). git log --format=%H -G 'IRVersion = "' -- ir/document.go | wc -l → 14 (the first version and 13 bumps); the last six each rewrote 103 to 115 goldens, 93 to 110 of them only on the irVersion line (morphic @c387e25c).
Activity