jruby/02: the jruby runtime feedstock (spec 33; the first universal runtime image) - #1
Merged
Merged
Conversation
…untime image)
tebako-packages/jruby scaffold: jruby 10.1.1.0 (ruby 4.0.0, Build-Jdk-Spec 21)
on the 2.5.0 owner line.
- The first UNIVERSAL runtime image: jruby-dist ships ~26 platforms' jffi
(probed), so ONE image tebako-runtime-2.5.0-10.1.1.0-universal.tfs is built
once by ROLE=image; the per-triplet ROLE=pair legs pair the 2.5.0 launcher
exe + write shards whose image.filename names the universal asset
(tpkg::runtime_store::entry_asset_names flows the shard's image.filename
verbatim — zero product change).
- L1 manifest in the one-or-many provides form (tpkg::manifest::RuntimeProvides
is Vec<EngineProvides> — the model's own multi-platform shape).
- Owner edge `java >= 21` with NO implementation key (jruby brings its own
JIT; temurin default, graalvm legal). owner_smoke pins the openjdk v2.5.0
temurin pair.
- argv_template carries -Djruby.home={mount}: LOAD-BEARING, probed on the
bare host — without it `require "json"` fails ("`RubyGems' were not
loaded"); with it JSON.generate works (same shape as truffleruby's
llvm.home token).
- Shard carries "abi": "none" so native-ext payloads fail at dispatch with
the resolver's named abi-mismatch instead of crashing late; the cext
negative cell in tools/build proves it.
- Windows leg: named follow-up (the universal image already serves it; it
lands with its CI leg).
- Tools block: tfs + tebako-shim pins from the v2.5.0 monolith; NO link-unit
(the jvm layout grants no preload).
Local gate green: image leg (fetch, two-anchor sha256 vs the upstream
Maven Central sidecar, stage, symlink dereference, manifest+layout embed,
mkimage, read-back) + pair leg (wrapper exe, shard, composed smoke through
the shim: "hello from jruby 4.0.0" + JSON.generate OK + the cext negative
cell).
ronaldtse
marked this pull request as ready for review
September 7, 2026 13:33
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.
jruby/02 — the jruby runtime feedstock (spec 33; the FIRST universal runtime image)
Scaffolds
tebako-packages/jrubyas a working runtime feedstock: the env image is theJRuby home, composed ON the published temurin java owner at dispatch (spec 33's
on_runtimeform, second feedstock instance after truffleruby's jvm flavor).The universal-image design (TODO.jruby/02 item 4 — pinned here)
The JRuby dist is genuinely universal: bytecode + the ruby home, and
lib/jni/ships ~26 platforms' jffi stubs (probed 2026-09-07 — record:
TODO.jruby/02-probe-2026-09-07.mdat the ecosystem root). So:…-universal.tfs), built once by theimageleg (mkimage is not byte-reproducible across legs — the createdtimestamp — so one leg's image IS the published asset).
per-triplet). The release still carries the per-triplet wrapper exe (the 2.5.0
launcher, byte-identical to tamatebako/tebako's asset) — it keeps the store
entry well-formed (the scan requires the exe) and serves the spec 33 §5
standalone fail-closed smoke; it is never the composed process's owner.
image.filenamenames the universal asset —tpkg::runtime_store::entry_asset_namesflows it verbatim (verified againstv2.5.0 sources), so no tebako product change was needed.
providesis the one-or-many form — oneEngineProvidesper covered platform, the model's own multi-platform shape(
tpkg::manifest::RuntimeProvides, "one entry per platform the imagecovers").
platform row (the grammar consequence item 4 asked to pin).
What lands
recipe.yml— the SSOT:flavors.jvm(the only mode; the flavor shape mirrorsthe sibling feedstocks), the owner edge
java >= 21with no implementationkey (unlike truffleruby-jvm: jruby brings its own JIT, the graalvm compiler is
not needed — temurin is the default and legal),
mount: /__runners__/jruby,argv_template: ["-Djruby.home={mount}", "-jar", "{mount}/lib/jruby.jar"]—-Djruby.homeis load-bearing: the jar'sMain-Class: org.jruby.main.Mainself-locatesjruby.homefrom the code-source path forbin/jrubyitself, but RubyGems (require "json") needs the real home —probed on the bare host: without the flag
require "json"fails with"
RubyGems' were not loaded"; with itJSON.generateworks (same shape as truffleruby'sllvm.hometoken), entrypoints[jruby, jgem, jirb], the platform coverage list, the universal upstream source (Maven Central, upstream-published.sha256sidecar cross-checked at fetch — the two-anchor rule), and theowner_smoke` pins (the openjdk v2.5.0 temurin pair — 2.5.0 is the firstspec-33-capable owner line, tebako#552).
manifests/runtime.yaml/layout.yaml/registry.yaml— the L1 authority(one-or-many provides, the
java_homewhole-tree annotation, the on_runtimeblock), the pair contract (NO interpreter, NO preload — spec 33 §5), the L3
registry template (universal artifact under every platform row).
tools/build— two roles:ROLE=image(fetch → two-anchor verify → stage →dereference symlinks → embed manifests → mkimage → read-back gates) and
ROLE=pair(per triplet: wrapper exe + sidecar + shard withimage.filename→universal + the smokes).tools/pins.rb— same shape as the sibling feedstocks (recipe → env),emitting the universal image stem beside the per-triplet one.
build-payload.yml—image(once, ubuntu) →pairmatrix (macos-arm64 +linux-gnu-x86_64 — mirrors the recipe's coverage list; windows-ucrt64 is a
named follow-up, the universal image already serves it) → publish on tags
(the tag IS the wrapper line).
The smokes (acceptance, TODO.jruby/02)
"declares no layout.interpreter" message (spec 33 §5).
payload prints
hello from jruby 4.0.0and loadsjson(jruby's ownjava-backed default gem) — asserted
"engine":"jruby".runtime_requirementdeclares anative-extension abi NEVER boots on jruby — the shard carries
abi: "none",so the resolver's named abi-mismatch error fires at dispatch (the absent-field
compat window would otherwise match and crash late). Named error, never a boot.
Local gate (pre-CI proof, macos-arm64)
Ran end-to-end with the real 2.5.0 release binaries (tfs / launcher / shim,
sha256-verified against the v2.5.0 monolith) and the PUBLISHED openjdk v2.5.0
temurin pair (two-anchor verified): universal image built + read-back green,
wrapper paired, shard written (universal image.filename), standalone exit 65,
composed smoke green, cext cell refused by name.
Depends on: tebako v2.5.0 (spec 33), tebako-packages/openjdk v2.5.0 (the temurin
owner line). Refs: TODO.jruby/02, spec 33, tebako#552, truffleruby#3 (the
machinery template).