4.0.0-rc.1 release ledgerRelease date: 2026-08-24
Canonical tag: v4.0.0-rc.1
Policy: coordinated release runbook
State: in progress; append-only until every intended coordinate is either
published and independently verified or explicitly recorded as deferred.
This train synchronizes seven artifact owners without nesting one owner's packages inside another repository:
| Repository | Owned release surface |
|---|---|
vinary-tree-interop | shared retained-resource ABI and language mirrors |
libdictenstein | dictionaries, collection facades, native SDKs, and language packages |
liblevenshtein-rust | automata, matching, native SDKs, and language packages |
lling-llang | weighted finite-state transducer crate, SDK, and npm facade |
duallity | Levenshtein/WFST bridge crate, SDK, and npm facade |
javascript-runtime | shared native, browser-WASM, and WASI JavaScript runtime |
liblevenshtein-npm | legacy unscoped npm compatibility name only |
The dependency order is interop, libdictenstein, liblevenshtein, lling-llang,
duallity, shared JavaScript runtime and scoped facades, then the legacy npm
compatibility leaf. llattice@0.1.0 is an already versioned prerequisite
outside the synchronized major-version train.
| Owner | Reviewed commit / tag target | Validation evidence | Registry state |
|---|---|---|---|
vinary-tree-interop | d79c97e | tag validation and GitHub prerelease completed | Rust crate and @vinary-tree/interop@4.0.0-rc.1 public and smoke-tested |
javascript-runtime | 576b9c3 | GitHub run 32700242213 succeeded | @vinary-tree/vinary-tree@4.0.0-rc.1 public; CommonJS and ESM installed-byte smokes passed |
libdictenstein | 6335a9d | clean-source tag validation run 32705525805 and publication run 32739936016 succeeded | crates.io artifact independently read back and consumed |
liblevenshtein-rust | release branch includes the clean-source fix d43cd83; final tag awaits the managed-language release-gate correction | local default/all-feature suites passed; 32739900519 proved the registry-dependency gate; 32741417024 then exposed four package-lane dependency defects; corrected exact-tag validation pending | locked crates.io dry-run passes against the public libdictenstein RC; publication pending replacement validation |
lling-llang | 2af235f in isolated release/4.0.0-rc.1 worktree | replacement tag validation run 32741421070 succeeded | publication pending Rust prerequisites |
duallity | f0a644e in isolated release/4.0.0-rc.1 worktree | replacement tag validation run 32741418091 succeeded | publication pending Rust prerequisites |
liblevenshtein-npm | 6e205bb | final exact-tag validation pending scoped facade | publication pending; legacy latest must remain 2.0.4 |
The commit cells identify source commits, not package digests. The immutable registry bytes and their digests are recorded in the registry table only after read-back.
| Coordinate | Public state | Independent verification |
|---|---|---|
vinary-tree-interop@4.0.0-rc.1 on crates.io | published | exact crate resolves; downstream package dry-runs resolve it |
@vinary-tree/interop@4.0.0-rc.1 | published; latest = next = 4.0.0-rc.1; no bootstrap tag | CommonJS and ESM resource-lifetime smoke passed; 0.0.0 deprecated as bootstrap-only |
@vinary-tree/vinary-tree@4.0.0-rc.1 | published; latest = next = 4.0.0-rc.1; no bootstrap tag | CommonJS and ESM dictionary/query smokes passed; SHA-512 integrity begins sha512-oloKdlDk...; 0.0.0 deprecated as bootstrap-only |
libdictenstein@4.0.0-rc.1 on crates.io | published by run 32739936016; publicly readable by 2026-08-24T14:55:27Z | forced crates.io metadata read-back downloaded the public crate; a fresh exact-version binary consumer resolved and compiled it; .crate SHA-256 8c2cf6ce32979447f123bcf9341d84dc410d6621a705f3d4cd1c84310a58bd43 |
liblevenshtein@4.0.0-rc.1 on crates.io | pending | locked dry-run packaged 2,492 files (46.0 MiB; 4.7 MiB compressed), compiled against the exact public libdictenstein RC, verified the crate, and reached the dry-run upload boundary |
lling-llang@4.0.0-rc.1 on crates.io | pending | blocked intentionally until exact prerequisites resolve publicly |
duallity@4.0.0-rc.1 on crates.io | pending | blocked intentionally until exact prerequisites resolve publicly |
| remaining scoped npm facades | 0.0.0 reservations only | publish and installed-byte smokes pending |
legacy liblevenshtein@4.0.0-rc.1 | pending under next | latest remains legacy 2.0.4 |
cargo nextest run --no-fail-fast --workspace --all-features passed
4,903 tests with 5 skipped, without environment-level target flags.32702493249 before the
publication-only Cargo workflow correction.All-feature builds initially failed because Gxhash requires AES plus SSE2 on
x86/x86-64 and AES plus NEON on ARM/AArch64. The portable minimums now live in
target-scoped .cargo/config.toml entries for Linux, macOS, and Windows.
Workflow-level RUSTFLAGS that would override Cargo configuration were removed;
sanitizer jobs explicitly compose their instrumentation with the same portable
baseline. The release never uses target-cpu=native.
The hosted libdictenstein Clojure test failed because clojure.data.json was
used by conformance fixtures but absent from project.clj. The dependency was
declared in commit 0f64b7d. The same audit found liblevenshtein property tests
using clojure.test.check without a manifest entry; commit 2d5d7de declared
it. Both suites then passed from their package-shaped builds.
Libdictenstein crates.io run 32704116534 rebuilt and passed every matrix lane,
then cargo publish rejected dirty Cargo.toml and Cargo.lock files. The
workflow had rewritten valid path + version dependencies into registry-only
dependencies immediately before upload. Cargo already normalizes the supported
multiple-location form by removing path from the packaged manifest.
The correction keeps exact dependency checkouts where local discovery is
needed and invokes cargo publish --locked on the unchanged checkout:
6335a9d — publish exact clean source;d43cd83 — replace the mutating publication action with
exact dependency clones;4fffc88 and duallity 60fb805 — require locked publication.A release workflow must never add --allow-dirty to conceal source mutation.
During release-pipeline bootstrap, the libdictenstein, liblevenshtein-rust,
lling-llang, and duallity RC tags had already been pushed for validation when
the clean-source publication defect, workflow-level target-flag overrides, and
this evidence runbook were corrected. No package registry had accepted those
projects' 4.0.0-rc.1 bytes. Their annotated tags were advanced to the
corrective commits and the complete tag matrices were rerun from scratch.
This is preserved as an incident, not a reusable procedure. The living runbook now requires branch CI and local release gates before the first tag, forbids force-moving a pushed release tag, and requires the next candidate if a defect is discovered afterward. The final tag targets recorded in this ledger are the freeze boundary for this train.
The final documentation audit found release coordinates that were correct in manifests but stale in shipped binding and architecture guides. The fixes were made before the affected packages reached their registries:
4.0.0-rc.1;2af235f updates its JavaScript guide's exact interop
dependency;f0a644e updates its JavaScript and cross-language guides,
describes interop as the actual dependency rather than a peer dependency,
and removes obsolete pre-release wording.Each repository's release-version synchronizer now owns those examples and fails validation if they drift. Because those commits change shipped package bytes, the older successful tag runs are explicitly invalidated in the source table and complete replacement tag validations are required.
Liblevenshtein-rust tag-validation run 32739900519 stopped at the
publish-contract job because it resolved libdictenstein = "=4.0.0-rc.1" from crates.io and that prerequisite had not been published.
This is the intended dependency-order guard, not a source failure. The same tag
must be validated again after independent public read-back of libdictenstein;
only that replacement run can become release evidence.
After libdictenstein became public, liblevenshtein-rust replacement run
32741417024 reached the full package graph and found four independent release
environment omissions. The source contracts themselves passed; the package
lanes had not provisioned everything they exercised:
pytest but omitted hypothesis, although
the wheel test command collects the property suite;io.vinarytree:vinary-tree-interop from
Maven Central before the synchronized interop SDK had been published there;VinaryTree.Interop.The corrections pin Temurin 25 in the npm lane, install both Python test
dependencies in every wheel, stage the exact tagged interop JVM artifact in a
job-local Maven repository, and build .NET through the existing exact interop
project-reference seam. Public package metadata continues to name the exact
4.0.0-rc.1 interop dependency; only validation-time resolution is local.
Before retagging, the corrected contracts were reproduced locally: the
ClojureScript suite passed 2 tests and 4 assertions, Python passed all 14 tests,
the JVM source compiled against the isolated staged artifact, and both net8.0
and net10.0 assemblies built with zero warnings and zero errors. Run
32741417024 remains failed evidence; it is never reclassified as successful.
GitHub Actions publishes with npm trusted publishing, short-lived OIDC
credentials, provenance, and --tag next. The operator's local
npm login --auth-type=web is used only for interactive dist-tag and
deprecation changes after installed-byte verification. No bypass-2FA token is
required or stored.
For each new scoped package, the verified postcondition is:
latest = 4.0.0-rc.1
next = 4.0.0-rc.1
bootstrap is absent
0.0.0 carries a bootstrap-only deprecation
The unscoped legacy package is the exception: it receives the RC under next
while latest remains 2.0.4.
Append one row or subsection when each event completes:
Can you improve this documentation?Edit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |