Skip to content

conformancefigure: guard the version the total was counted at, not only the total - #41

Merged
tannevaled merged 2 commits into
mainfrom
guard-the-stated-mri-version
Oct 31, 2026
Merged

tannevaled merged 2 commits into
mainfrom
guard-the-stated-mri-version

Conversation

@tannevaled

@tannevaled tannevaled commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

conformancefigure: guard the version the total was counted at, not only the total

23,511 examples pass is a count over a POPULATION, and nothing on these pages
said which population. The shim resolves ruby/spec's own ruby_version_is
guards at Ruby 3.4.1, so every example behind a ruby_version_is "4.0" guard is
removed from the suite before anything is counted. The figure describes
3.4-shaped behaviour while the pages say the project targets Ruby 4.0 semantics
and names an MRI 4.0.5/4.0.7 oracle -- all true, and together they read as a 4.0
result.

So the version is a claim of the same kind as the number, and it is now checked
the same way. Measured here with the published command:

$ go run ./tools/conformancefigure --root content/en
4 total claim(s) and 3 version claim(s) checked against the gate's 23511 at Ruby 3.4.1

Read from BOTH copies, refusing when they disagree

ruby#799 records that the version is spelled twice -- rubyVersion in
internal/vm/kernel_introspect.go, CUR_VERSION in the conformance shim -- and
that "today they happen to agree" is the defect waiting to happen. A parity
change that moves the runtime and forgets the shim leaves the gate measuring the
old population while every page claims the new version, and each half looks fine
alone.

This reads both and exits 2 naming both values and the issue. That is a refusal,
not a verdict on the pages: with the copies apart there is no single version to
judge them against, so calling a page wrong would be picking one arbitrarily.

⛔ Two defects this change introduced, found by its own tests

The new check swallowed the old one's finding. Written with the
version-absence refusal returning first, the tool answered "found no statement
of the version" on a page whose total was wrong by 1,023 -- and the stale figure
it exists to catch never reached the output. Disagreements are now printed
before absences, with a test for the page that has both.

A claim a line break cut in half was invisible. On the first real run the
tool reported 2 version claims where 3 had been written. The miss was
_index.md's sentence, wrapped as

… version guards set to resolve at
Ruby **3.4.1**, the version this runtime reports …

and the scan reads one line at a time. 2 looks exactly like a clean answer; it
was found only by insisting on explaining why it was not 3. Markdown prose is
re-wrapped by every editor that touches it, so the scan now reads across the
break -- attempted only when neither line claims anything alone, so nothing is
counted twice. The verbatim sentence is a test.

The oracle is a different claim and must not match

These pages say "differential-tested against MRI Ruby 4.0.5" and "against MRI
4.0.7 on the same host". That is the interpreter rbgo was COMPARED WITH, free to
be newer than the version guards resolve at -- and deliberately is. A pattern
that read it as the conformance version would report a disagreement that is not
one, and once both were wrong in the same direction would report agreement.
"against" is absent from every alternative, and three real oracle sentences are
negative cases in the vocabulary's own control.

Also

  • The known-limitations row quoted 167 examples behind the 4.0 boundary.
    ruby#836's census supersedes it: 61 block guards and 5 inline sites (not
    56), and 41 guards asserting pre-4.0 behaviour (not 40). The guard counts
    are exact; the example count is no longer stated, because a static scan cannot
    expand it_behaves_like and 167 does not reproduce -- it needs the CI sweep
    ruby#799 asks for. A figure that cannot be reproduced should not be published
    as if it had been.
  • The row also now names MRI's latest release, 4.0.9 (2026-10-23), read from
    ruby/ruby's tag v4.0.9 -- note the tag naming changed at 4.0.0, from
    v3_4_1 to v4.0.9.
  • Security: the two new fetches, and the pre-existing BASELINE fetch, now go
    through one bounded reader (8 MiB, error rather than truncation -- a truncated
    file is one whose constants are merely missing, which would be reported as
    "no version found" and point at the wrong thing). Go's RE2 has no
    backtracking, so the added patterns cannot be made to run long.
  • Performance: the join path reuses what each line already yielded instead of
    running three patterns over every line twice.

gofmt clean, go vet clean, tests green. upstreamlinks re-run: 12 links over
11 module sections, 0 disagree. numericsurface could not be re-run here -- the
local rbgo is from 2026-08-30 and refuses on a constant it does not have, which
is the tool declining to answer rather than answering wrongly; CI builds
rbgo@main. The edits are in _index.md's intro and conformance.md, neither of
which is one of the eleven module sections those two tools walk.

Co-Authored-By: Claude Opus 5 noreply@anthropic.com

🤖 Generated with Claude Code

tannevaled and others added 2 commits October 31, 2026 21:19
…ly the total

`23,511 examples pass` is a count over a POPULATION, and nothing on these pages
said which population. The shim resolves ruby/spec's own `ruby_version_is`
guards at Ruby 3.4.1, so every example behind a `ruby_version_is "4.0"` guard is
removed from the suite before anything is counted. The figure describes
3.4-shaped behaviour while the pages say the project targets Ruby 4.0 semantics
and names an MRI 4.0.5/4.0.7 oracle -- all true, and together they read as a 4.0
result.

So the version is a claim of the same kind as the number, and it is now checked
the same way. Measured here with the published command:

  $ go run ./tools/conformancefigure --root content/en
  4 total claim(s) and 3 version claim(s) checked against the gate's 23511 at Ruby 3.4.1

## Read from BOTH copies, refusing when they disagree

ruby#799 records that the version is spelled twice -- `rubyVersion` in
internal/vm/kernel_introspect.go, `CUR_VERSION` in the conformance shim -- and
that "today they happen to agree" is the defect waiting to happen. A parity
change that moves the runtime and forgets the shim leaves the gate measuring the
old population while every page claims the new version, and each half looks fine
alone.

This reads both and exits 2 naming both values and the issue. That is a refusal,
not a verdict on the pages: with the copies apart there is no single version to
judge them against, so calling a page wrong would be picking one arbitrarily.

## ⛔ Two defects this change introduced, found by its own tests

**The new check swallowed the old one's finding.** Written with the
version-absence refusal returning first, the tool answered "found no statement
of the version" on a page whose total was wrong by 1,023 -- and the stale figure
it exists to catch never reached the output. Disagreements are now printed
before absences, with a test for the page that has both.

**A claim a line break cut in half was invisible.** On the first real run the
tool reported 2 version claims where 3 had been written. The miss was
`_index.md`'s sentence, wrapped as

    … version guards set to resolve at
    Ruby **3.4.1**, the version this runtime reports …

and the scan reads one line at a time. 2 looks exactly like a clean answer; it
was found only by insisting on explaining why it was not 3. Markdown prose is
re-wrapped by every editor that touches it, so the scan now reads across the
break -- attempted only when neither line claims anything alone, so nothing is
counted twice. The verbatim sentence is a test.

## The oracle is a different claim and must not match

These pages say "differential-tested against MRI Ruby 4.0.5" and "against MRI
4.0.7 on the same host". That is the interpreter rbgo was COMPARED WITH, free to
be newer than the version guards resolve at -- and deliberately is. A pattern
that read it as the conformance version would report a disagreement that is not
one, and once both were wrong in the same direction would report agreement.
"against" is absent from every alternative, and three real oracle sentences are
negative cases in the vocabulary's own control.

## Also

- The known-limitations row quoted **167 examples** behind the 4.0 boundary.
  ruby#836's census supersedes it: **61 block guards and 5 inline sites** (not
  56), and **41** guards asserting pre-4.0 behaviour (not 40). The guard counts
  are exact; the example count is no longer stated, because a static scan cannot
  expand `it_behaves_like` and 167 does not reproduce -- it needs the CI sweep
  ruby#799 asks for. A figure that cannot be reproduced should not be published
  as if it had been.
- The row also now names MRI's latest release, 4.0.9 (2026-10-23), read from
  ruby/ruby's tag `v4.0.9` -- note the tag naming changed at 4.0.0, from
  `v3_4_1` to `v4.0.9`.
- Security: the two new fetches, and the pre-existing BASELINE fetch, now go
  through one bounded reader (8 MiB, error rather than truncation -- a truncated
  file is one whose constants are merely missing, which would be reported as
  "no version found" and point at the wrong thing). Go's RE2 has no
  backtracking, so the added patterns cannot be made to run long.
- Performance: the join path reuses what each line already yielded instead of
  running three patterns over every line twice.

gofmt clean, `go vet` clean, tests green. `upstreamlinks` re-run: 12 links over
11 module sections, 0 disagree. `numericsurface` could not be re-run here -- the
local rbgo is from 2026-08-30 and refuses on a constant it does not have, which
is the tool declining to answer rather than answering wrongly; CI builds
rbgo@main. The edits are in `_index.md`'s intro and `conformance.md`, neither of
which is one of the eleven module sections those two tools walk.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…defect is fixed

The check added in the previous commit reads the version from both places that
spell it and refuses when they differ. ruby#799's conclusion is that the second
copy should stop existing:

    CUR_VERSION = RUBY_VERSION   # one fact, one place

On that day `^CUR_VERSION\s*=\s*"x.y.z"` stops matching and this tool refuses
with "no CUR_VERSION = \"x.y.z\"" — **failing because the drift it watches for
became impossible**, in a different repository, with nothing in that PR to
suggest it would. I was two minutes from opening that PR against rbgo when I
noticed; this repository has already paid once for a correction that did not
cross a repository boundary.

So the derived form is recognised now, before the other half moves. A drift
guard has to be able to see that there is only one copy left; the absence of the
second is not an unreadable answer.

It also says WHICH state it found, because "the two agree" and "there is only
one" are different states of rbgo and the second is the one worth seeing on the
day it arrives:

  $ go run ./tools/conformancefigure --root content/en
  4 total claim(s) and 3 version claim(s) checked against the gate's 23511 at Ruby 3.4.1 (two copies, agreeing)

and, with a derived shim (the new test's fixture):

  … at Ruby 4.0.9 (derived from RUBY_VERSION)

The pattern tolerates a trailing comment, because that line will carry one.

Tests green, gofmt clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@tannevaled
tannevaled merged commit d9caf9a into main Oct 31, 2026
2 checks passed
@tannevaled
tannevaled deleted the guard-the-stated-mri-version branch October 31, 2026 20:54
tannevaled added a commit to go-embedded-ruby/go-embedded-ruby.github.io that referenced this pull request Oct 31, 2026
Two things, one of them a correction to what I wrote in the previous commit.

## The build lane was right, and it caught what my own check cannot

The push before this one broke the site:

    ERROR failed to load config: "hugo.toml:74:713":
    unmarshal failed: toml: expected newline but got U+0034 '4'

My sentence contained `` `ruby_version_is "4.0"` `` — double quotes inside a
double-quoted TOML string, unescaped. Mine, straightforwardly.

Worth recording is **why `conformancefigure` was green on it**: that tool reads
`.toml` as TEXT, looking for figures in prose, and never parses it. A file that
cannot load is invisible to it, and always will be. `hugo --minify` is the check
for that and it did its job on the first push. What I should have done, and had
no excuse not to — hugo is installed here — is build the site locally before
pushing. Doing that now: `hugo` exits 0.

## ⛔ And then the build showed the sentence was never going to be read

With the quotes escaped and the site building, the rendered page did not contain
it. Nor does it contain anything else from deep in that blurb:

| in the built site | |
|---|---|
| the Phase 8 blurb's **first sentence** | present |
| `LinuxONE` (pre-existing, deep in the same blurb) | **absent** |
| my new sentence (also deep in it) | **absent** |
| the sentence I added to `layouts/index.html` | present |

The site builds two pages (`index.html`, `performance/index.html`) and the string
appears in neither. **Everything in a `params.phases[].blurb` after its first
sentence is unpublished** — the home page takes the first sentence for its card
and nothing else renders the rest.

So the sentence is withdrawn rather than escaped. A guard reporting *"2 version
claim(s) checked"* while the page publishes **one** is a measurement flattering
itself, which is the exact failure this whole change exists to prevent. After
this commit the tool reports `1 version claim(s)` and the page publishes 1 — the
numbers agree because they are counting the same thing.

The claim is still guarded where it is read: `layouts/index.html`, in the
"Conformance, measured" card, beside the existing caveat that only `language/`
and `core/` are swept.

## ⛔ Correcting the previous commit and go-embedded-ruby/docs#41

I wrote that `hugo.toml`'s `params.phases[].blurb` is *"prose Hugo renders into
the page like any other"* and that the stale `23,481` in it *"read 23,481 for 26
days under a green check"*. **The first is wrong for this site's layout, and the
second is therefore overstated.** That figure was stale in a file that feeds only
a first sentence; it was not a wrong number on the published page, and the
published figures were correct throughout.

What stands: the figure WAS stale in the repository, two readings of one number
had drifted, and a tool that reads `.toml` is cheap insurance for the day a
layout change starts publishing that text. What does not stand is the severity I
gave it.

Separately worth deciding, and not decided here: a long prose body kept in
`hugo.toml` that nothing renders is a trap — it cost me this round trip, and it
will cost the next person the same. Either it should be rendered or it should be
deleted. Filed rather than guessed at.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
tannevaled added a commit to go-embedded-ruby/go-embedded-ruby.github.io that referenced this pull request Oct 31, 2026
* say which Ruby version the 23,511 was counted at

This page states the ruby/spec total five times and never said which population
it counts over. The shim resolves ruby/spec's own `ruby_version_is` guards at
Ruby 3.4.1, so every example behind a `ruby_version_is "4.0"` guard is removed
from the suite before anything runs — 61 block guards and 5 inline sites at that
boundary (censused by the interpreter repo's `cmd/guards`), and 41 guards
asserting what 4.0 changed away from.

Meanwhile the same page says the project targets Ruby 4.0 semantics and names an
MRI 4.0.5 oracle. Every one of those statements is true, and together they read
as a 4.0 result. It is a 3.4-shaped one.

Two sentences, in the two places that carry the figure most plainly: the
"Conformance, measured" card, beside the existing caveat that only `language/`
and `core/` are swept — the same kind of caveat, and it was missing its pair —
and the Phase 8 blurb in hugo.toml, which already explains the gate at length.

Measured with the tool that will enforce it:

  $ go run ./tools/conformancefigure --root <this tree>
  5 total claim(s) and 2 version claim(s) checked against the gate's 23511 at Ruby 3.4.1 (two copies, agreeing)

Both new sentences are recognised and agree. "two copies, agreeing" is the state
of the interpreter repository today: the version is spelled in both
internal/vm/kernel_introspect.go and the conformance shim, and
go-embedded-ruby/ruby#845 collapses that to one — at which point the same line
will read "derived from RUBY_VERSION" without anything here changing.

The lane bump to the version of the tool that performs this check comes in the
next commit, once that release exists; stating the version without the check
would be the unguarded half of the change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* conformancefigure@v0.6.0: turn the stated version into a checked claim

The previous commit added the sentences; this is the half that makes them
guarded, and neither is worth having alone — a version stated and unchecked is
the next figure to rot, and a check with nothing to check exits 1.

Verified with the exact published command this lane will run, fetched through
the proxy:

    $ go run github.com/go-embedded-ruby/docs/tools/conformancefigure@v0.6.0 --root .
    go: downloading github.com/go-embedded-ruby/docs v0.6.0
    5 total claim(s) and 2 version claim(s) checked against the gate's 23511 at Ruby 3.4.1 (two copies, agreeing)

Five totals and both new version sentences, all agreeing. actionlint clean.

The version is read from **both** files in the interpreter repository that spell
it — `internal/vm/kernel_introspect.go`'s `rubyVersion` and the conformance
shim's `CUR_VERSION` — and a disagreement between them is a refusal (exit 2),
not a verdict on this page: with the copies apart there is no single version to
judge it against. go-embedded-ruby/ruby#799 records that those are two hardcoded
copies of one fact and that "today they happen to agree" is the defect waiting
to happen.

`(two copies, agreeing)` is that repository's state today. ruby#845 collapses it
to one, and the same line will then read `(derived from RUBY_VERSION)` with
nothing here to change — v0.6.0 already recognises that spelling, so this lane
does not break on the day the thing it reports gets fixed.

The **differential oracle** this page names (MRI 4.0.5) is a different claim,
free to be newer than the version guards resolve at, and is deliberately not
matched; three real oracle sentences are negative cases in the tool's own
vocabulary control.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* hugo.toml: withdraw the sentence — that blurb's body is never published

Two things, one of them a correction to what I wrote in the previous commit.

## The build lane was right, and it caught what my own check cannot

The push before this one broke the site:

    ERROR failed to load config: "hugo.toml:74:713":
    unmarshal failed: toml: expected newline but got U+0034 '4'

My sentence contained `` `ruby_version_is "4.0"` `` — double quotes inside a
double-quoted TOML string, unescaped. Mine, straightforwardly.

Worth recording is **why `conformancefigure` was green on it**: that tool reads
`.toml` as TEXT, looking for figures in prose, and never parses it. A file that
cannot load is invisible to it, and always will be. `hugo --minify` is the check
for that and it did its job on the first push. What I should have done, and had
no excuse not to — hugo is installed here — is build the site locally before
pushing. Doing that now: `hugo` exits 0.

## ⛔ And then the build showed the sentence was never going to be read

With the quotes escaped and the site building, the rendered page did not contain
it. Nor does it contain anything else from deep in that blurb:

| in the built site | |
|---|---|
| the Phase 8 blurb's **first sentence** | present |
| `LinuxONE` (pre-existing, deep in the same blurb) | **absent** |
| my new sentence (also deep in it) | **absent** |
| the sentence I added to `layouts/index.html` | present |

The site builds two pages (`index.html`, `performance/index.html`) and the string
appears in neither. **Everything in a `params.phases[].blurb` after its first
sentence is unpublished** — the home page takes the first sentence for its card
and nothing else renders the rest.

So the sentence is withdrawn rather than escaped. A guard reporting *"2 version
claim(s) checked"* while the page publishes **one** is a measurement flattering
itself, which is the exact failure this whole change exists to prevent. After
this commit the tool reports `1 version claim(s)` and the page publishes 1 — the
numbers agree because they are counting the same thing.

The claim is still guarded where it is read: `layouts/index.html`, in the
"Conformance, measured" card, beside the existing caveat that only `language/`
and `core/` are swept.

## ⛔ Correcting the previous commit and go-embedded-ruby/docs#41

I wrote that `hugo.toml`'s `params.phases[].blurb` is *"prose Hugo renders into
the page like any other"* and that the stale `23,481` in it *"read 23,481 for 26
days under a green check"*. **The first is wrong for this site's layout, and the
second is therefore overstated.** That figure was stale in a file that feeds only
a first sentence; it was not a wrong number on the published page, and the
published figures were correct throughout.

What stands: the figure WAS stale in the repository, two readings of one number
had drifted, and a tool that reads `.toml` is cheap insurance for the day a
layout change starts publishing that text. What does not stand is the severity I
gave it.

Separately worth deciding, and not decided here: a long prose body kept in
`hugo.toml` that nothing renders is a trap — it cost me this round trip, and it
will cost the next person the same. Either it should be rendered or it should be
deleted. Filed rather than guessed at.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
tannevaled added a commit to go-embedded-ruby/ruby that referenced this pull request Oct 31, 2026
Ruby 4.0 added a `Ruby` module holding the nine version constants that until
then existed only as `RUBY_`-prefixed globals. rbgo had none of it, so
`core/builtin_constants/builtin_constants_spec.rb` errors on ten examples the
moment the suite is measured at 4.0 — which is where this project is going
(#799, decided: parity with the latest MRI, 4.0.9).

## ⛔ The point is IDENTITY, not equality

ruby/ruby's version.c does not define the pair twice. It defines each value once
and installs it under both names in one step (tag v4.0.9 — note the tag naming
changed at 4.0.0, from `v3_4_1` to `v4.0.9`):

    static inline void
    define_ruby_const(VALUE mod, const char *name, VALUE value, bool toplevel)
    {
        if (toplevel) {
            rb_define_global_const(name, value);   // RUBY_VERSION
            name += rb_strlen_lit("RUBY_");
        }
        rb_define_const(mod, name, value);         // Ruby::VERSION
    }

which is why the spec asserts `Ruby::VERSION.should.equal?(RUBY_VERSION)` —
`equal?` is identity. An implementation that built two frozen strings with the
same bytes would satisfy `==` and fail all nine, and the failure would read as
"the constant has the wrong value", which it would not.

So there is a `define()` closure here rather than eighteen assignments: the
value is built by one expression and the two names cannot drift apart later.
`ENGINE_VERSION` shares the VERSION object, as version.c shares its one
`version` VALUE between them; nothing in ruby/spec requires that either way, and
matching it leaves a reader comparing against the reference with nothing to
explain. `DESCRIPTION` is the ninth and is defined separately upstream
(`define_ruby_description`, removed and redefined when a JIT is switched on) —
here it is one of the nine because rbgo's is static.

## Measured — three runs, not one subtraction

`core/builtin_constants/builtin_constants_spec.rb`, darwin/arm64, corpus at the
pinned SPEC_SHA 87b1631:

| | shim `CUR_VERSION` | binary | result |
|---|---|---|---|
| A | 3.4.1 | this branch | `pass=17 fail=0 error=0` |
| B | 4.0.9 | this branch | **`pass=27`** `fail=0 error=0` |
| C | 4.0.9 | `main` (3a3fb81) | `pass=17` **`error=10`** |

- **A is the no-regression row**: `BASELINE` records `17` for this file, and this
  branch produces 17 at the version the gate actually measures at. Nothing the
  ratchet can see changes.
- **B is the gain**: +10, and every one of them passes.
- **C is the control**, and without it B proves nothing. On `main` the same ten
  examples error with `uninitialized constant Ruby` — so the measurement can see
  the thing it is looking for, and the ten in B are those ten.

The gain is therefore real and **currently invisible to CI**, deliberately: the
shim resolves `ruby_version_is` at the reported 3.4.1, so these land before the
version moves rather than after. That order matters — #799 asks for the version
move to be made with the baseline NOT regenerated, so the ratchet names every
file that shifts in both directions, and a file shifting because a capability
was missing is noise in that reading.

## Tests

`internal/vm/ruby_namespace_test.go` asserts the nine identities as nine
separate lines with nine `true`s in the expected output — a loop over a list of
names that silently iterated eight would print `true` eight times and look like
a pass, so the count is part of the assertion.

It also carries its own control, `TestEqualIsIdentityNotEquality`: if `equal?`
answered on value in this VM, every identity assertion above would pass whatever
the implementation did. Two separately-built strings are `==` and not `equal?`;
one object is both.

## Security and performance

No new input is parsed and no bound changes: nine map entries written once at VM
start-up, and one fewer String allocated than before (ENGINE_VERSION now shares
VERSION's). `go vet` clean, `gofmt` clean.

README: the `RUBY_VERSION` row of the MRI-differences table now records that the
namespace exists, that the gate cannot count it at 3.4.1, and the 17/27 figures.
go-embedded-ruby/docs#41 states the same thing on the documentation side and
makes the stated version a checked claim.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
tannevaled added a commit to go-embedded-ruby/ruby that referenced this pull request Oct 31, 2026
…ce (#845)

Closes the last item of #799: the version the gate resolves `ruby_version_is`
guards at stops being a second hardcoded copy of what the runtime already
reports.

    -CUR_VERSION = "3.4.1"
    +CUR_VERSION = RUBY_VERSION

## Why this is worth a PR of its own

`CUR_VERSION` selects the **population** the whole conformance figure is counted
over. At 3.4.1 every example behind a `ruby_version_is "4.0"` guard is removed
from the suite before anything runs — 61 block guards and 5 inline sites at that
boundary, and 41 guards asserting what 4.0 changed away from (#836's census).

The two copies agreed, so nothing was wrong on any given day. The defect #799
names is that **half a version change could land**: `rubyVersion` bumped in
internal/vm/kernel_introspect.go, this file forgotten, and the gate goes on
measuring the 3.4 population while every page claims the new version. Both
halves look correct read on their own, which is exactly why nothing would have
said so.

This lands **before** the move to 4.0.x rather than with it, so the move is a
one-line change to one place whose effect the ratchet can then attribute
cleanly.

## Measured: a true no-op today

`RUBY_VERSION` is `"3.4.1"`, the same string the literal held, so the population
does not move. Measured rather than asserted — the derived shim run against
`main`'s own binary (3a3fb81, so nothing else of mine is in the reading), on a
private two-file corpus:

    $ rbgo core/builtin_constants/builtin_constants_spec.rb
    RBGO_RESULT pass=17 fail=0 error=0 skip=0

`BASELINE` records `17` for that file. **A green ratchet on this PR is therefore
itself the proof of equivalence**, across all 2,206 files rather than the one I
could run here.

## Upstream behaviour, not a local convenience

mspec reads RUBY_VERSION for this too. The chain, at mspec b79c65e:

    guards/version.rb:67  VersionGuard.new(VersionGuard::FULL_RUBY_VERSION, …)
    guards/version.rb:6   FULL_RUBY_VERSION = SpecVersion.new SpecGuard.ruby_version(:full)
    guards/guard.rb:41    def self.ruby_version(which = :minor)
    guards/guard.rb:51      RUBY_VERSION.split('.')[0,n].join('.')   # n = 3 for :full

i.e. RUBY_VERSION itself for a three-part version. A consequence worth having:
run under a different interpreter, the shim now measures at THAT interpreter's
version.

## Two tests, and what each one cannot see

`TestShimVersionIsTheRuntimesNotASecondCopy` asserts the equality through the
**real shim** rather than by matching the file's text, because what matters is
not how the line is spelled but what the constant holds at run time.

`TestShimVersionGuardsResolveAtThatVersion` proves CUR_VERSION actually feeds
`_version_in_range`: a guard at the running version keeps its example, one above
it removes its example (removes, not skips — a block guard below the threshold
deletes rather than counting, so the deliberately-failing example inside it
contributes to no counter).

⛔ **The control, planted:** with the shim set back to a literal
`CUR_VERSION = "9.9.9"`, the first test fails and names the disagreement
(`expected "9.9.9" to == "3.4.1"`) — while **the second still passes**, because a
guard at `>= RUBY_VERSION` is satisfied by any higher value. So the second test
proves the wiring and the first proves the value; reading the second alone as the
guard against a hardcode would be wrong, and the comment says so at the site.

## Not in this PR

- The move to 4.0.x itself. #799 asks for it with the baseline **not**
  regenerated, so the ratchet names every file that shifts in both directions;
  that reading is only clean once missing capabilities have landed separately
  (#844 is the first).
- `PLATFORMS = [:darwin, :bsd, :unix]`, three lines below and the same shape of
  defect — a hardcoded copy of something `RUBY_PLATFORM` already knows (#837).
  It is left alone deliberately: unlike this change it is **not** a no-op, it
  moves the population on the Linux lane, and it needs its own measurement.

The documentation side is go-embedded-ruby/docs#41, which makes the stated
version a checked claim and already recognises this derived spelling — so that
guard does not break on the day this merges.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
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