Public Access
385 lines
24 KiB
Markdown
385 lines
24 KiB
Markdown
# Minecraft 26.3 port status (issue #96)
|
||
|
||
Checked 2026-10-26. Minecraft Java 26.3 is the newest stable Java release with
|
||
NeoForge support. This is an engineering audit and the start of the port, **not
|
||
a claim that a 26.3 Rivencraft JAR is ready**. The 1.21.1 build remains the
|
||
release target until a separate 26.3 client and dedicated-server build passes.
|
||
The user wants both Minecraft lines maintained after the port, not a one-time
|
||
26.3 release. Gitea milestone "Dual-version support: 1.21.1 and 26.3"
|
||
tracks issues #97–#103 under parent #96.
|
||
|
||
## Version boundary
|
||
|
||
Minecraft 26.3/NeoForge uses Java 25, while Rivencraft 1.21.1 uses Java 21.
|
||
Build and publish separate artifacts; do not widen the Minecraft dependency
|
||
range of the 1.21.1 JAR. The official [26.3 release notes](https://www.minecraft.net/en-us/article/minecraft-java-edition-26-3),
|
||
[NeoForge 26.3 Maven metadata](https://maven.neoforged.net/releases/net/neoforged/neoforge/maven-metadata.xml),
|
||
[NeoForge Java 25 setting](https://github.com/neoforged/NeoForge/blob/26.3.x/gradle.properties),
|
||
and [NeoForge migration primers](https://docs.neoforged.net/primer/docs/)
|
||
are the version sources. NeoForge 26.3.0.99 is the newest listed stable build
|
||
at the time of this check.
|
||
|
||
## Dependency availability
|
||
|
||
The entries below mean that a NeoForge 26.3 version is advertised by the
|
||
project, not that its API or runtime behavior has been validated with
|
||
Rivencraft. Recheck immediately before choosing versions for a port build.
|
||
|
||
| Integration | Role in 1.21.1 | 26.3 availability | Port decision |
|
||
| --- | --- | --- | --- |
|
||
| [Dynamic Dimensions AR Edition](https://modrinth.com/mod/dynamic-dimensions-ar-edition) | Required runtime Age loading | No; 1.21.1 only | Keep it for 1.21.1. Use a Rivencraft-owned runtime-dimension backend for 26.3. |
|
||
| [bad packets](https://modrinth.com/mod/badpackets) | Declared runtime dependency; no direct Java imports in Rivencraft | No advertised 26.3 version | Determine whether the new dimension backend needs it; otherwise remove it from the 26.3 artifact. Use NeoForge's own networking for Rivencraft packets. |
|
||
| [JEI](https://modrinth.com/mod/jei) | Optional recipe/page guides | Yes | Port and test its plugin against the 26.3 API. |
|
||
| [TerraBlender](https://modrinth.com/mod/terrablender) | Optional modded biome support | Yes | Port and verify biome discovery and Age generation. |
|
||
| [Serene Seasons](https://modrinth.com/mod/serene-seasons) and [GlitchCore](https://modrinth.com/mod/glitchcore) | Optional seasons | Yes | Port and repeat the per-Age seasonal matrix. |
|
||
| [Biomes O' Plenty](https://modrinth.com/mod/biomes-o-plenty) | Optional TerraBlender test addon | Yes | Test modded biome registration and decoration. |
|
||
| [Ruins (Structure Spawning System)](https://www.curseforge.com/minecraft/mc-mods/ruins-structure-spawning-system) | Optional authored ruins integration | Yes | Port and verify its generation hooks. |
|
||
| [Create](https://modrinth.com/mod/create) / bundled Ponder | Optional scene renderer | No advertised 26.3 version | Use Rivencraft's existing legacy-animation preview fallback for this target until a compatible release exists. |
|
||
| [Immersive Portals for (Neo)Forge](https://modrinth.com/mod/immersive-portals-neoforge) | Optional live views and portal teleport integration | No advertised 26.3 version | Use the fallback portal surface and normal Rivencraft linking. Do not claim live destination views on 26.3. |
|
||
|
||
Ecliptic Seasons publishes 26.3, but Rivencraft's Ecliptic integration was
|
||
deferred and is not a replacement for the current Serene integration.
|
||
|
||
The alternatives checked for runtime Age loading do not meet the 26.3
|
||
NeoForge requirement: [upstream Dynamic Dimensions](https://github.com/TeamGalacticraft/DynamicDimensions)
|
||
and its [AR fork](https://github.com/dercodeKoenig/DynamicDimensions)
|
||
have no published 26.3 branch or artifact;
|
||
[DimLib](https://modrinth.com/mod/dimlib) is Fabric-only and stops at 1.21.1;
|
||
and [DimensionsCore](https://www.curseforge.com/minecraft/mc-mods/dimensionscore-dynamic-dimension-world-management)
|
||
currently publishes only a Forge 1.20.1 file. Mods that add fixed dimensions
|
||
or portals do not supply the arbitrary per-book runtime worlds Rivencraft
|
||
needs. This is a search result, not proof that no other project exists.
|
||
|
||
## 26.3 backend design
|
||
|
||
The 26.3 port is a **fresh-save target**. It does not need to import 1.21.1
|
||
Age worlds or migrate Dynamic Dimensions' saved registry data. The 1.21.1
|
||
artifact will continue using that library. Within 26.3, however, a created
|
||
Age must retain its identity, seed, chunks and access across save/restart.
|
||
|
||
1. Keep the existing `AgeDimensionService`/`AgeDimensionBackend` boundary.
|
||
Implement a target-specific 26.3 backend without importing Dynamic
|
||
Dimensions or its seed mixin. The backend contract needs registration at
|
||
server start, create/load, unload and delete. Return a failure without
|
||
publishing a half-created Age if any step fails.
|
||
2. At server startup, reconstruct all non-retired Ages from Rivencraft's
|
||
`AgeRegistrySavedData` **before** players can join. For a newly bound book,
|
||
register its unique `rivencraft:age/...` dimension and construct a
|
||
`ServerLevel` from its authored chunk generator, dimension type and saved
|
||
Age seed. The seed must feed chunk random state, not only `getSeed()`.
|
||
3. Register the level with the server's level map and the appropriate
|
||
dimension registries, then synchronize the new dimension definition to
|
||
already-connected clients before sending a travel packet. Handle a
|
||
connecting client receiving every existing Age. Determine the minimal
|
||
26.3 registry and network hooks from the current NeoForge source; do not
|
||
assume `/reload` creates new running levels.
|
||
4. Initialize world border, view/simulation distance, forced chunks, spawn
|
||
settings, per-Age data storage and tick/save lifecycle as a normal level.
|
||
On unload or retirement, refuse while players occupy the Age, move any
|
||
remaining entities safely, flush pending chunk writes, detach the level,
|
||
and synchronize removal. Retirement must not delete another Age's data.
|
||
5. Review the MIT-licensed Dynamic Dimensions code as an implementation
|
||
reference. If any code is adapted, retain its copyright/license notice and
|
||
identify the derived files. Prefer the smallest backend Rivencraft needs
|
||
over a general-purpose library fork.
|
||
|
||
The release gate is a 26.3 integrated-client **and** dedicated-server matrix:
|
||
create two Ages with distinct seeds, explore chunks, travel while another
|
||
client remains online, reconnect, restart, revisit saved chunks, reseed for
|
||
future chunks, unload/reload, retire one Age without harming the other, and
|
||
verify normal travel without optional mods. Then repeat relevant paths with
|
||
available integrations. A failed synchronization must be reported and leave
|
||
the player in their current level, not crash or strand them.
|
||
|
||
## Implementation order
|
||
|
||
1. Keep `AgeDimensionService` independent of a concrete runtime-dimension
|
||
implementation. The 1.21.1 Dynamic Dimensions calls now live in
|
||
`AgeDimensionBackend`; the `AgeDimensionSeedMixin` is 1.21.1-only.
|
||
2. Create a separate 26.3/Java 25 build target. Replace the dimension backend,
|
||
then migrate the main sources through the official NeoForge primers. Do not
|
||
publish a partial JAR with missing Age generation.
|
||
3. Port optional integration classes one at a time. Keep unavailable mods
|
||
optional and preserve their existing fallbacks. Upgrade JEI, TerraBlender,
|
||
Serene Seasons/GlitchCore, Biomes O' Plenty, and Ruins only in the 26.3
|
||
target; do not change the validated 1.21.1 dependency set.
|
||
4. Run compile, data/resource validation, new-world Age generation, Age
|
||
save/restart/reload, direct and portal/book travel, client rendering, and
|
||
dedicated-server tests on both targets. Test without optional mods, then
|
||
with each available integration. Require an in-game check before release.
|
||
|
||
The core blocker is **not** a version number change: 26.3 makes a major API
|
||
jump and the required 1.21.1 runtime-dimension library has no 26.3 build.
|
||
|
||
## Build isolation started in #97
|
||
|
||
The repository root remains the playable 1.21.1/Java 21 build. A separate
|
||
`ports/mc263` Gradle build now resolves NeoForge 26.3.0.99 and compiles with
|
||
Java 25. The build workflow has separate Java 21 and Java 25 jobs. Its JAR
|
||
task remains disabled; this does not satisfy #97's final artifact criteria.
|
||
|
||
## First core slice in #98
|
||
|
||
The 26.3 target now has real Rivencraft metadata and an entrypoint. It
|
||
registers the Crystal Shard and Crystal Block with their reused 1.21.1
|
||
textures/models plus the 26.3 item-model definitions. `build` passed, and a
|
||
dedicated development server loaded the mod and reached `Done` with a new
|
||
world and no optional mods. The server was then stopped. This validates only
|
||
the entrypoint/registry/resource foundation. A development client also loaded
|
||
Rivencraft and reloaded its resources without reported missing models or
|
||
textures. The client logged the host's missing `libflite.so` narrator library;
|
||
this is unrelated to Rivencraft. Both test processes were stopped after
|
||
startup. This does **not** validate in-world client rendering or Age
|
||
functionality. Age generators, data, networking, and client code still
|
||
need migration; #98 remains open.
|
||
|
||
## Runtime-level prototype in #99
|
||
|
||
The 26.3 target has a first-party server-side runtime-level loader and a
|
||
SavedData seed index. It constructs each level with a `LevelStem` seed override,
|
||
publishes the level only after construction, and restores indexed Ages when
|
||
the Overworld loads. A dedicated-server probe created two separate Ages with
|
||
seeds `123456789` and `987654321`; after generating chunks, their terrain
|
||
fingerprints differed (`2865094` and `3227421`). Both levels, their region
|
||
files, seeds, and fingerprints survived a server restart, and the startup log
|
||
shows restoration before `Done`. The temporary operator-only
|
||
`rivencraft_port age` command exists solely to test this non-distributable
|
||
port workspace.
|
||
|
||
This is **not** issue #99 completion. The loader currently reuses the vanilla
|
||
Overworld generator because issue #98 has not ported authored generators or
|
||
Age definitions. The synchronized operator travel probe below does not port
|
||
normal book travel. The 26.3 JAR task remains disabled.
|
||
|
||
## Runtime client-catalog prototype in #100
|
||
|
||
The 26.3 target now sends the current dimension-key catalog to each joining
|
||
client and broadcasts a new catalog when a prototype Age is created or
|
||
retired. Clients update their known-level set and acknowledge a version; the
|
||
server's `rivencraft_port age enter <name>` probe refuses travel until that
|
||
acknowledgement arrives and the target is still loaded. A stale acknowledgement
|
||
does not satisfy the gate. This follows NeoForge's play-payload registration
|
||
and client-handler separation. It is not a general dynamic-registry sync for
|
||
authored dimension types, which have not been ported.
|
||
|
||
The dedicated-server probe used two simultaneous 26.3 clients. Both
|
||
acknowledged a newly created Age without reconnecting; a second client entered
|
||
an existing runtime Age; a player saved inside an Age reconnected after server
|
||
restart and remained there. The operator travel probe searches near origin for
|
||
safe footing and creates a small Crystal Block platform if none is found.
|
||
This probe is not the final book landing implementation.
|
||
|
||
`rivencraft_port age retire <name>` refuses to retire an Age containing a
|
||
player, then saves and closes it, removes it from the active index, and
|
||
broadcasts the reduced catalog. On the dedicated test server, the client
|
||
acknowledged creation and retirement even when they happened back-to-back; a
|
||
late acknowledgement for the intermediate catalog was ignored. Travel to the
|
||
retired Age was refused without moving the player, and retiring an occupied
|
||
Age was refused. The #101 lifecycle slice below now archives exact Age data.
|
||
|
||
This remains a **prototype**, not completion of #100: normal Linking and
|
||
Descriptive Book travel, authored dimension-type/generator registration, full
|
||
client registry synchronization, and an integrated-client regression pass
|
||
must follow the core port. The 26.3 JAR remains disabled. The local test
|
||
server was stopped after verification.
|
||
|
||
## Runtime lifecycle prototype in #101
|
||
|
||
The operator-only backend probe now supports `age unload`, `reload`, `reseed`,
|
||
and `retire` in addition to `create`, `list`, `sample`, and `enter`. Unload and
|
||
retirement refuse a level containing players. A full chunk/entity save and
|
||
close handles other entities; Minecraft's shutdown-style ticket deactivation
|
||
and startup-style activation preserve forced chunks across runtime reloads.
|
||
The loaded-dimension catalog is rebroadcast after unload/reload/reseed and
|
||
retirement, with stale acknowledgements ignored.
|
||
|
||
On the dedicated server, a generated Age unloaded and reloaded with the same
|
||
terrain fingerprint. Reseeding `lifetest` from `24680` to `13579` kept the
|
||
previously generated origin fingerprint `2898472`; previously ungenerated
|
||
chunks at offset 100 produced fingerprint `2897795`, identical to a fresh
|
||
`13579` control Age and different from a fresh `24680` control (`2863099`).
|
||
After restart, `lifetest` still reported seed `13579` and its original origin
|
||
fingerprint. Three consecutive unload/reload cycles with a connected client
|
||
completed; that client acknowledged the final catalog and intermediate stale
|
||
acknowledgements were ignored. Unloading the player's current Age was refused.
|
||
|
||
A force-loaded chunk and a summoned armor stand with UUID
|
||
`[I; -872307724, 883641011, -1239011659, 796091120]` survived repeated
|
||
runtime unload/reload and server restart. The entity could be queried again
|
||
after its chunk finished loading. The probe retired a different Age,
|
||
`seedcontrol`: only its directory moved to the sibling `world-retired-ages`
|
||
archive, other Age directories stayed in place, and reloading/recreating the
|
||
retired ID was refused after restart. A second archival probe exercised the
|
||
tombstone-before-move sequence and again moved only its own directory. The
|
||
tombstone is persisted before the archive move so an interrupted archival
|
||
cannot silently revive an old Age; an ordinary move failure attempts to
|
||
restore the index and level. Ten more consecutive unload/reload cycles
|
||
completed on the dedicated server, with its open file-descriptor count steady
|
||
at 218 before and after. That is a narrow smoke check, not proof of no leak.
|
||
|
||
This still does **not** close #101. The prototype has not been integrated with
|
||
normal books or the full 26.3 Age definition, nor has a long-running resource
|
||
leak test or interrupted-archive recovery drill been completed. Its dev world
|
||
and archive are under ignored `ports/mc263/build`, not a release save.
|
||
|
||
## Optional-integration probe in #102
|
||
|
||
On 2026-10-27, the published NeoForge 26.3 versions checked were JEI
|
||
31.17.0.95, TerraBlender 26.3.0.0.9, Biomes O' Plenty 26.3.0.0.15,
|
||
GlitchCore 26.3.0.0.5, and Serene Seasons 26.1.2.0.7 (its file is labelled
|
||
for Minecraft 26.3). Ruins advertises 26.3.1NF. Create/Ponder and
|
||
Immersive Portals still had no advertised compatible version. These are
|
||
availability checks, not API-compatibility claims.
|
||
|
||
The 26.3 development target now has the operator-only
|
||
`/rivencraft_port compat` command. It reports loaded optional mod IDs and
|
||
the count of registered biome keys by namespace, so integration smoke tests
|
||
can distinguish a missing addon from a missing biome registration. It does
|
||
not change Age generation. A clean dedicated server loaded with no optional
|
||
mods and reported 67 vanilla biomes. A separate dedicated-server launch with
|
||
TerraBlender, Biomes O' Plenty, GlitchCore, and Serene Seasons loaded all four;
|
||
the probe reported 68 `biomesoplenty` biome keys, and TerraBlender logged its
|
||
Overworld and Nether regions. Both launches stopped cleanly.
|
||
|
||
Issue #102 remains open. The 26.3 target still lacks authored Ages, JEI
|
||
guides, per-Age season policy, Ruins hooks, book previews and crystal portals,
|
||
so the relevant integration and fallback acceptance tests cannot yet pass.
|
||
The probe must not be mistaken for feature support. The existing 1.21.1
|
||
integration code and dependencies remain unchanged.
|
||
|
||
## First player-facing bridge in #104
|
||
|
||
The 26.3 port now registers a Descriptive Book with the Legacy item texture
|
||
and a persistent, network-synchronized Age-ID data component. The operator-only
|
||
`/rivencraft_port age book <name>` probe grants a book for an already indexed
|
||
Age; an unbound book does not create a world. Using the bound book calls the
|
||
same server-authoritative, catalog-acknowledged landing path as the existing
|
||
`age enter` probe. A missing or unloaded Age refuses travel. This avoids
|
||
trusting a book-supplied seed or creating a new Age from a forged item.
|
||
|
||
The dedicated-server smoke test still passed after this bridge, and a 26.3
|
||
development client loaded the new item model and texture without a missing
|
||
resource warning. The host still reports a missing Linux `libflite.so`
|
||
narrator library; this is not a Rivencraft item error. The client was stopped.
|
||
The player confirmed right-click travel in game. Book component persistence
|
||
across restart still needs a player test; the headless smoke test cannot
|
||
exercise it. To test the
|
||
bridge in a disposable 26.3 world as an operator:
|
||
|
||
1. `/rivencraft_port age create booktest 123456789`
|
||
2. Wait for the Age catalog acknowledgement, then
|
||
`/rivencraft_port age book booktest`.
|
||
3. Right-click the granted book and verify arrival in
|
||
`rivencraft:age/booktest`. Restart client and server, then use the same
|
||
book again and verify it targets the same saved Age.
|
||
|
||
This is deliberately a **port probe**, not the final book workflow: the Book
|
||
Binder, naming UI, GUI preview, automatic return link, dropped-book entity, authored Age
|
||
plan, and Legacy landing rules are not yet connected. The bound book currently
|
||
remains in hand after travel. Do not distribute this target or mark #104 done.
|
||
For a local player test only, the normally disabled port JAR can be built with
|
||
`./gradlew -p ports/mc263 build -PallowIncompletePortJar=true`; its filename
|
||
retains `26.3-INCOMPLETE` and a `port-dev` version marker. This does not enable the normal
|
||
release artifact or imply that the full mod has been ported.
|
||
|
||
The first Prism test exposed a production-only catalog bug: Minecraft 26.3's
|
||
`ClientPacketListener.levels()` returned an immutable set, and the client
|
||
handler attempted to clear it. That threw `UnsupportedOperationException`
|
||
before the client could acknowledge the Age, so book travel was refused. The
|
||
handler now replaces the entire level set through a narrow access transformer
|
||
and acknowledges only after replacement. The corrected local test JAR is
|
||
`rivencraft-26.3-INCOMPLETE-0.0.0.1-port-dev.jar`. It built successfully;
|
||
the player used that JAR to verify actual travel in game on 2026-10-27.
|
||
|
||
### Linking Book return-path slice
|
||
|
||
The separate 26.3 target now registers a Linking Book using the Legacy bound
|
||
book sprite. `/rivencraft_port link book` grants an operator-only probe book
|
||
bound to the player's exact current dimension, coordinates, and facing. Its
|
||
destination is a persistent data component resolved by the server on use. A
|
||
missing dimension, unacknowledged catalog, same-dimension target without
|
||
Intra-Linking, out-of-bounds target, or obstructed arrival is rejected without
|
||
moving the player. This path does **not** generate a landing platform.
|
||
|
||
For a test, stand at an unobstructed spot in the Overworld and run
|
||
`/rivencraft_port link book`. Create and bind an Age Descriptive Book using the
|
||
steps above, travel into that Age, then right-click the Linking Book. It
|
||
should return to the exact bound spot and facing. Same-dimension use should
|
||
refuse. Repeat after a server restart to check component persistence. This
|
||
slice is `0.0.0.2-port-dev` and remains explicitly incomplete: normal
|
||
crafting/binding, modifiers, book GUI, origin-drop entity, and safe fallback
|
||
are still unported. The probe book remains in inventory after travel.
|
||
|
||
### Age-index durability after the first in-game return-link check
|
||
|
||
The first return-link test exposed a recoverable prototype failure: Seamless
|
||
Portals rejected a newly added runtime Age, the integrated server exited
|
||
abnormally, and a second Age created just before the exit was not present in
|
||
Rivencraft's saved index on restart. Its directory contained no saved chunks.
|
||
The `0.0.0.3-port-dev` slice flushes the index synchronously before announcing
|
||
newly created Ages to clients. It also flushes reseed changes. The dedicated
|
||
server smoke test now checks that both new Age IDs are already in the on-disk
|
||
index **before** it issues `stop`, then verifies both seeds/terrain after a
|
||
restart. This closes the ordinary interrupted-shutdown gap but is not a
|
||
substitute for a power-loss durability test or integration with other mods'
|
||
dynamic-dimension catalogs.
|
||
|
||
### Handheld Linking Book binding slice
|
||
|
||
The `0.0.0.4-port-dev` target adds a client-only book screen using the Legacy
|
||
book artwork. An unbound Linking Book accepts a player-chosen title; a
|
||
serverbound packet binds the held book to the player's *current* dimension,
|
||
coordinates and facing only after checking the book, title length and empty
|
||
target. A bound book opens the same screen and uses a server-validated
|
||
destination-panel click for travel. This replaces the earlier direct item-use
|
||
probe. The panel is a visible placeholder, **not** a live snapshot. The
|
||
rotating preview, completed book behavior (including origin drop), recipe,
|
||
modifiers, stand handling and other port systems remain unported.
|
||
|
||
To test this slice, use `/give @s rivencraft:linking_book` in a 26.3 test
|
||
world, stand at the intended return point, right-click the unbound book, enter
|
||
a name and bind. Travel to an Age, right-click the book again and click its
|
||
right-hand destination panel. Verify the named book persists across restart,
|
||
same-dimension travel is refused, and a replaced/removed held book cannot be
|
||
bound or used by a delayed screen packet. Do not treat this partial target as
|
||
a playable release.
|
||
|
||
The first `0.0.0.4-port-dev` in-game right-click exposed a 26.3 screen API
|
||
mistake: `Screen.extractRenderStateWithTooltipAndSubtitles` already calls
|
||
`extractBackground`, so the screen's second call raised `Can only blur once per
|
||
frame`. The `0.0.0.5-port-dev` fix removes that duplicate background call.
|
||
The next in-game check found that a bound Linking Book's right-hand panel did
|
||
not trigger travel: its target component was persistent but lacked a network
|
||
codec, so the client screen could not identify the book as bound. The
|
||
`0.0.0.6-port-dev` slice adds stream codecs for the Linking Book target and
|
||
Descriptive Book Age ID. Server-side held-item and destination checks remain
|
||
authoritative. This needs another in-game check before considering the slice
|
||
validated.
|
||
The `0.0.0.6-port-dev` retest showed the bound-book panel but left-clicking
|
||
did not even close the GUI. Minecraft 26.3's primary mouse button is
|
||
`InputConstants.MOUSE_BUTTON_LEFT` (value 1), while the port handler still
|
||
checked the 1.21.1 value 0. The `0.0.0.7-port-dev` slice uses the 26.3
|
||
constant. This still requires in-game verification of the full click/travel
|
||
path.
|
||
The player confirmed the `0.0.0.7-port-dev` bound Linking Book click/travel
|
||
path passes in game on 2026-10-27. The 26.3 target remains incomplete and is
|
||
not ready for a public release or closure of the parent port issue.
|
||
|
||
### Explicit technical alpha exception
|
||
|
||
At the player's request, `1.0.1.2-alpha.1` packages this limited 26.3 port as
|
||
an experimental alpha. It is **not** the full mod and does not pass the stable
|
||
release gate above. The alpha label and release notes must state that Ages use
|
||
prototype vanilla terrain, normal authoring and most content are absent, and
|
||
worlds should be disposable or backed up. The 1.21.1 stable release remains
|
||
independent; issues #96–#104 stay open until the full port and validation pass.
|
||
|
||
## Verification of this first slice
|
||
|
||
The 1.21.1 `compileJava` and `build` tasks passed offline after the backend
|
||
extraction. The GameTest server ran 93 tests; 92 passed, while
|
||
`twoblockdeskdropsonce` failed because breaking either desk half dropped zero
|
||
desks instead of one. That desk failure is outside the dimension-backend edit
|
||
and must be resolved or rechecked before a release. The 1.21.1 `build` task
|
||
passed again after the 26.3 registry slice.
|