Phase 29. Runtime matrix CI + dead-code cull (audit-4)
| Field | Value |
|---|---|
| MEP | MEP-56 §Phases |
| Status | LANDED |
| Started | 2026-05-29 14:01 (GMT+7) |
| Landed | 2026-05-29 14:01 (GMT+7) |
| Tracking issue | — |
| Tracking PR | #22510 |
| Commit | e0956a4238 |
Gate
Two orthogonal gates, both audit-driven (no new user-visible Mochi feature, but the CI matrix gate moves the umbrella phase coverage rule forward):
transpiler3-ruby-test.ymlexists and is green on the required CRuby versions. The workflow runsgo test -v -timeout 600s ./transpiler3/ruby/...on a three-entry matrix: CRuby 3.2 on ubuntu (blocking), CRuby 3.4 on ubuntu (blocking), CRuby 3.4 on macos (non-blocking). Each job usesruby/setup-ruby@v1to pin the toolchain, exportsMOCHI_RUBY=$(which ruby)soresolveToolchainpicks up the matrix-installed binary instead of falling through to Homebrew slots, and runs the full Ruby transpiler test suite against that interpreter.go build ./transpiler3/ruby/...andgo test ./transpiler3/ruby/...still pass after removingLambdaandBlockLitfromrtree/nodes.go. The audit-4 dead-code sweep removed tworubyExpr-implementing types thatlower.gonever instantiates:Lambda(intended->(p) { … }lambda emission, never reached becauseMethodDeclis preferred) andBlockLitplus itsMethodCall.Blockfield (block syntax for HOF calls is emitted viaRawExprstrings instead, as documented in the new MethodCall comment). Build- and vet-clean confirms no caller drift.
The MEP-56 umbrella phase coverage rule (feedback_umbrella_phase_targets.md) requires every target in §6's matrix to be exercised before the MEP can close. CRuby 3.2 / 3.4 are now exercised on every PR; JRuby 10, TruffleRuby 33, and mruby 4 remain unexercised and are tracked as sub-phases 29.1, 29.2, 29.3 below.
Build target / audit decisions
This phase does not change the transpiler pipeline, the runtime gem, or any build target. Two surface changes:
.github/workflows/transpiler3-ruby-test.ymladded. Modeled aftertranspiler3-jvm-test.yml: samepaths:filter shape (the new workflow only runs whentranspiler3/ruby/**,mochi-runtime/**,tests/transpiler3/ruby/**, or the workflow itself changes), same Go setup, samecontinue-on-error: ${{ !matrix.blocking }}semantics. The matrix entries are deliberately narrow at first: CRuby 3.2 / 3.4 on ubuntu blocking, 3.4 on macos non-blocking. CRuby 4.0 is not in the matrix becauseruby/setup-ruby@v1does not publish a 4.0 image yet; 4.0 coverage lives in the locally-run developer suite via the existing Homebrew slot detection inbuild.go.transpiler3/ruby/rtree/nodes.goshrunk. RemovedLambda(lines 509 to 519 of the pre-change file) andBlockLit(lines 433 to 438 of the pre-change file). Removed theBlock *BlockLitfield onMethodCalland the block-rendering branch inMethodCall.RubyExprString()(lines 467 to 480 of the pre-change file). The MethodCall comment now explicitly says block-using call sites are emitted viaRawExpr(and that is true: every.map { … }/.select { … }/.inject { … }call site is built as aRawExprinlower.golines 911 / 922 / 937).
Three audit decisions are baked into this phase:
- Delete unused code rather than wire it up. The project rule "Avoid backwards-compatibility hacks. If you are certain that something is unused, you can delete it completely" applies here. Both
LambdaandBlockLithad completeRubyExprStringimplementations but zero call sites inlower.go. Wiring them up would mean reshaping workingRawExpr-based block emission for no user-visible delta. Deleting them is the cheaper choice and removes the risk of a future contributor mistakenly believing the rtree supports first-class lambdas when in fact every lambda flows throughRawExpr. - Block emission stays in
RawExpr. A future audit may want to re-introduce a typedBlocknode so that block bodies can be lowered structurally instead of by string formatting. That is deliberately out of scope for phase 29: the spec change would have to land first (MEP-56 §3 would need a "block syntax" row), and the lower pass would have to migrateListMapExpr/ListFilterExpr/ListFoldlExpr/AsyncExprlowering. None of that is justified by an existing bug. - Non-CRuby runtimes are explicit sub-phases.
index.mdnow lists JRuby 10 / TruffleRuby 33 / mruby 4 as sub-phases 29.1 / 29.2 / 29.3 with a note that container-based toolchain detection inbuild.gois the prerequisite. This makes the umbrella phase rule operational: future contributors can pick up 29.1 (JRuby) without re-reading the audit thread that surfaced the gap.
Files changed
| File | Purpose |
|---|---|
.github/workflows/transpiler3-ruby-test.yml | New CI workflow, matrix CRuby 3.2 / 3.4 on ubuntu (blocking) and CRuby 3.4 on macos (non-blocking) |
transpiler3/ruby/rtree/nodes.go | Removed dead Lambda and BlockLit types plus MethodCall.Block field and block-rendering branch |
website/docs/implementation/0056/index.md | Runtime matrix updated to mark CRuby 3.2 / 3.4 as LANDED via CI; JRuby / TruffleRuby / mruby renamed as sub-phases 29.1 / 29.2 / 29.3 |
website/docs/implementation/0056/phase-29-runtime-matrix.md | This tracking page |
website/sidebars.js | Phase 29 entry appended after phase 28 |
Sub-phases (not yet landed)
| Sub-phase | Target | Status | Prerequisite |
|---|---|---|---|
| 29.1 | JRuby 10 (CRuby-compatible subset) | NOT STARTED | Container image entry in transpiler3-ruby-test.yml plus $MOCHI_JRUBY env var detection in build.go resolveToolchain |
| 29.2 | TruffleRuby 33 | NOT STARTED | Container image entry plus $MOCHI_TRUFFLERUBY env var detection |
| 29.3 | mruby 4 (language subset only, no threads / agents / streams) | NOT STARTED | MRUBY_HOME and MOCHI_MRBC env var detection plus a sub-corpus marker on phases 10 / 11 / 12 / 13 / 21 to opt out |
Each sub-phase keeps the same gate template: the new runtime appears as a continue-on-error matrix entry first (non-blocking), and only promotes to blocking once all per-phase tests pass on it.
Test set
No new Go test functions are added. The phase is validated by:
go build ./transpiler3/ruby/...succeeds after dead-code removal.go vet ./transpiler3/ruby/...succeeds.go test -v ./transpiler3/ruby/...succeeds locally and in CI on CRuby 3.2 / 3.4 / 3.4-macos viatranspiler3-ruby-test.yml.
Closeout notes
Phase 29 is the audit-4 follow-up to phase 28's gap closure. Phase 28 added tests for Driver.Build error paths, edge-case coverage, and emitted-syntax checks; phase 29 closes the umbrella phase coverage rule (CRuby 3.2 / 3.4 in CI) and the dead-code residue (Lambda, BlockLit) that phase 28's emit audit surfaced. The MEP-56 §6 runtime matrix now matches reality: CRuby 3.2 / 3.4 are CI-green; JRuby / TruffleRuby / mruby are sub-phases waiting on a toolchain detection refactor.