Liking cljdoc? Tell your friends :D

Vinary Tree 4.0.0-rc.4 release ledger

Train opened: 2026-08-24
Canonical tag: v4.0.0-rc.4
Policy: coordinated release runbook
Predecessor evidence: 4.0.0-rc.3
State: dependency-ordered publication in progress. The root crate and the interop and libdictenstein managed-language packages recorded below are public and independently consumed. The interop opam contribution passes all upstream checks and awaits review/merge. Go publication remains stopped at protected-tag creation. The first LuaRocks revisions are public but fail a clean source-rock link; installable packaging-revision-2 corrections are being validated. Both historical Maven notices are externally blocked because Central has not granted the exact legacy com.github.* namespaces to the current account.

This append-only ledger is the operational source of truth for RC.4. It records the clean-build corrections after RC.3, exact source commits and workflow runs, registry digests, and independent installed-byte proofs. The living runbook defines reusable procedure; this ledger records observed facts.

Why the train advanced

RC.3 root validation exposed two hidden prerequisites: a JavaScript test job loaded a native addon that it never built, and a JVM collection test used a native dictionary provider that it never staged. The RC.4 correction closes those defects and the version-drift weakness found while reproducing them:

  1. The npm package job invokes the shared runtime's existing local configuration, native SDK bootstrap, and release addon build against exact RC.4 siblings.
  2. The JVM job stages exact RC.4 interop and libdictenstein sources, builds libdictenstein with its ffi contract, publishes the interop JAR to an isolated staging repository, and passes the provider directory explicitly.
  3. Gradle canonicalizes both default and caller-supplied native directories to absolute paths before tests fork.
  4. Each Rust owner synchronizer now writes and validates its own family package entries in Cargo.lock. Native SDK bootstrap passes --locked and executes Cargo from each crate owner, preventing a runtime-only patch overlay from leaking patch.unused metadata into independent lockfiles.
  5. The root JavaScript facade removed unused @cljs-oss/module-deps. The actual ClojureScript compiler path does not use it; removal eliminates its obsolete Babel/core-js dependency graph and the three critical clean-install advisories it introduced.

These are release-reproducibility repairs. They do not change dictionary or matching semantics.

Clean-layout reproduction evidence

A build-clean family was created under a unique /tmp/vinary-release-family-rc4.* directory by cloning each current owner through Git's shared-object mechanism and applying only its tracked RC.4 working diff. No target, Gradle build, native addon, npm installation, or runtime SDK output existed at the start.

ContractClean-layout observationResult
seven-owner identityall seven owner synchronizers accepted RC.4; the root train checker accepted seven standalone owners, exact edges, npm next, Hackage/fpm embargoes, and legacy latest protectionpassed
runtime bootstraplocal interop types installed with zero advisories; configure/bootstrap compiled libdictenstein, liblevenshtein, lling-llang, and duallity; node-gyp produced native/build/Release/vinary_tree_native.nodepassed
locked SDK rebuildall five owner lockfiles were copied from source, native bootstrap rebuilt with --locked, and byte comparison proved every lockfile remained unchangedpassed
root npm facadenpm ci installed only three local family packages with no obsolete bundler graph; build, TypeScript contract tests, three runtime facade tests, and two ClojureScript tests/four assertions passedpassed
JVM dependency stagingexact interop 4.0.0-rc.4 staged locally; exact libdictenstein 4.0.0-rc.4 built with ffi; root tests received absolute native directoriespassed
JVM collection/resource behaviorclean Gradle test javadoc completed successfully, including DictionaryCollectionsTest; local JDK 26 compiled Java 22 bytecode, while the tag workflow remains pinned to JDK 25passed
workflow syntaxevery YAML workflow/action in all seven repositories parsed successfullypassed

The temporary family is retained only until commits and local tags have been verified, then removed explicitly together with older RC rehearsal directories.

Local release-gate evidence

The clean-layout reproduction was followed by the owner-native gates below. Every command used Rust 1.95 where the owner declares that MSRV. Generated artifacts were rebuilt before package inspection rather than accepted from a prior candidate.

Owner or surfaceLocal observationResult
vinary-tree-interopfull verifier passed Rust layout/evolution tests, C17 and C++23 headers, JavaScript, Python, Go, .NET, JVM/Javadoc, Swift, Fortran, OCaml, and Haskell; cargo package --locked built and verified the crate archivepassed
javascript-runtimesource and built verifiers passed native, leak, property, browser-WASM, WASI, and package-shape tests; a full npm prepack rebuilt both WebAssembly targets and produced the expected 15-file archivepassed
libdictenstein862 default tests, 3,046 debug all-feature tests, and 3,046 release all-feature tests passed; the exact FFI suite passed 97 tests and the query-start snapshot contract passed 7; binding, documentation, ABI, MathJax, Clippy, npm prepack, and native staging gates passedpassed
liblevenshtein-rust1,775 default tests, 4,903 debug all-feature tests, and 4,903 release all-feature tests passed with five intentional skips in each all-feature run; the exact snapshot contracts passed 7, 10, and 5 tests; binding, ABI, MathJax, Clippy, npm/TypeScript/ClojureScript, JVM/Javadoc, and native staging gates passedpassed
lling-llang2,567 default and 2,841 release all-feature tests passed; both release-workflow FFI matrices, binding/documentation/ABI/MathJax, Clippy, npm prepack, native staging, and installed shared/static CMake consumers passedpassed
duallity257 default and 374 release all-feature tests passed; the FFI-only workflow matrix passed 152 unit, 33 integration, and 10 documentation tests; binding/documentation/ABI/MathJax, Clippy, npm prepack, native staging, and installed shared/static CMake consumers passedpassed
scoped and compatibility npm facadesall seven prepack lifecycles passed and exposed exact 4.0.0-rc.4 identities, exact family pins, and the intended archive file setspassed
repository policyall seven workflow trees parsed as YAML, all synchronizers and the aggregate train checker accepted the graph, formatting and whitespace checks passed, and all seven pgmcp bug-gate invocations reported no open bug anchored to a changed filepassed

Cargo fully verified the dependency-free interop crate archive. Packaging each downstream crate then stopped at its first exact, intentionally unpublished RC.4 crates.io edge. This is the expected dependency barrier, not a substituted source dependency: each downstream cargo package/cargo publish verification is repeated only after its exact upstream registry version resolves.

RC.4 source freeze

Populate this table only after each worktree is clean, every local gate passes, and the enumerated commit has been created. Tags are annotated locally only after the complete source graph is frozen. No branch or tag is pushed without a fresh, explicit operator approval naming the exact repositories and refs.

OwnerRC.4 commitLocal gatesImmutable-tag runState
vinary-tree-interopcanonical crate/npm source 1614a522172ca33c90815920c82c5e07afec6918; first corrective source 3cb6165d44cc908d1da639788dd7677d458cec42 at remote v4.0.0-rc.4-release.1; final registry/provenance source d95ab52e031851d2810c95e4b9006324a0acb22e at remote v4.0.0-rc.4-release.2full platform verifier, crate/npm package, docs, lock, policy gates, exact JReleaser configuration, opam provenance, and corrective-ref authority tests passedcanonical validate-only 32794787058 and first corrective validate-only 32865676284 passed; final corrective run 32895741481 in progresscrate and npm public; final corrective source remote for remaining registries
javascript-runtimefirst corrective source ea1549a4283b102dc3ad8eab96d9f8342bf2c20e at remote v4.0.0-rc.4-release.1; topology correction 68ca91ddf555cc015e20d7984f1db631e4c27ac2 at local v4.0.0-rc.4-release.2immutable-source and hostile-input contracts, exact locked owner builds, native behavior/leak tests, browser-WASM, WASI, YAML, JavaScript syntax, and whitespace gates passed locallyfirst corrective run 32895741974 failed before artifact assembly because nested owner builds inherited the runtime Cargo overlayfirst corrective tag immutable; second corrective source awaiting remote validation
libdictensteinpublic crate source 085f61c22f714f6a9c2aee528077be180b9545d4; binding/fpm sources through remote release.2; uploader corrections 31e3954ffc6f9687045cd596288b420dfd68a3ef and 85af1fe2d2a808a628d3032c1ea2573bdddb3aaa at remote release.3 and release.4; renderer-independent diagram source 9a8dd1e64ee84065061bee378cda8dfb53758dec; installable LuaRocks correction 9ca3418e33e10a5b691264866e127205d7adc040 at remote v4.0.0-rc.4-release.5prior owner gates plus staged native-SDK rock build, isolated Lua 5.4 conformance, release synchronization, YAML, binding docs, MathJax, whitespace, and bug gates passedrelease-5 validate-only 32950358421 and revision-2 publication 32952621821 passed from exact commit 9ca3418e33e10a5b691264866e127205d7adc040crate and prior bindings public; LuaRocks revision 1 superseded; revision 2 public and clean-consumer verified
liblevenshtein-rustcanonical source b81b5516d956775def69f2010e61738522d83003; corrective sources through remote release.6 at 0bc8d938f7c08e1396042f63d66ec9d7d6dbe323; purpose-oriented Maven metadata 0988c7e78e1669437d65fb0c03477ea09cbcc706; installable LuaRocks correction 7fa8ebbfa3d80f18b54a5a66c93482aea1f5c73a at remote v4.0.0-rc.4-release.7prior root gates plus staged native-SDK producer/consumer rock builds, isolated Lua 5.4 snapshot behavior, generated shared-header mirrors, per-owner Lua revision invariants, YAML, docs, MathJax, release-train, whitespace, and bug gates passedrelease-7 validate-only 32950359638 and revision-2 publication 32955830880 passed from exact commit 7fa8ebbfa3d80f18b54a5a66c93482aea1f5c73acrate and prior bindings public; LuaRocks revision 1 superseded; revision 2 public and clean dependency-chain verified
lling-llang20329d8e31f22ec4afc36736d686122133bd38c9 at remote v4.0.0-rc.4-release.1default/all-feature, FFI, binding, native/npm package, docs, lock, policy, protected-release, and corrective-ref gates passedcorrective run 32895771279 in progresscorrective source remote; validation in progress
duallityce2e56b7e13a69b097cefb05dfce0b661ec5ee91 at remote v4.0.0-rc.4-release.1default/all-feature, FFI, binding, native/npm package, docs, lock, policy, protected-release, and corrective-ref gates passedcorrective run 32895770587 in progresscorrective source remote; validation in progress
liblevenshtein-npm9171d6e87d6be58a65c2a1692147374a581fe592 at remote v4.0.0-rc.4-release.1compatibility, delegation, npm package, full-license, legacy-channel, protected-release, and corrective-ref gates passedcorrective run 32895743642 in progresscorrective source remote; validation in progress

Root JVM staging failure and corrective source

The canonical root dispatch ran from exact commit b81b5516d956775def69f2010e61738522d83003. Its binding contract, four native targets, four Python wheels, npm package, NuGet package, RubyGem, SwiftPM, LuaRocks metadata, opam source package, Hackage candidate, and fpm candidate all passed. The only failed job was JVM FFM Maven package 97657829090. All jobs dependent on JVM staging, including every root registry upload and the GitHub release, were skipped; no liblevenshtein RC.4 coordinate became public.

The failure occurred before Gradle started. That job cloned libdictenstein and its path dependencies below .release-deps/, but Cargo resolves this root's development paths in the established repository-sibling topology. Cargo therefore sought ../libdictenstein/Cargo.toml outside the nested checkout and failed with No such file or directory. Other release jobs already used the shared checkout-dev-siblings action and proved the correct topology on all four native runners.

The correction in 38935dd507ce7171d76b388a0345ed32e016a7bb reuses that action, builds ../libdictenstein, stages the exact interop Maven artifact from ../vinary-tree-interop, and deliberately points vinaryTreeInteropRoot at a nonexistent directory while testing so Gradle cannot replace the staged artifact with a composite source build. A clean /tmp/vinary-jvm-rc4-topology.* reproduction cloned the four exact tags, compiled libdictenstein with ffi, staged interop, and passed root test, javadoc, verifyNativeResources, and Maven staging. The generated POM retained the exact io.vinarytree:vinary-tree-interop:4.0.0-rc.4 dependency and the test JAR contained the expected Linux x86-64 native resource.

The recovery source also makes io.vinarytree:liblevenshtein:4.0.0-rc.4 the official Maven coordinate. It generates POM-only relocation releases at com.github.dylon:liblevenshtein:4.0.0-rc.4 and com.github.universal-automata:liblevenshtein:4.0.0-rc.4, pointing both historical lineages to the Vinary Tree group. Canonical and historical inputs are isolated into three namespace-specific JReleaser deployers and selected one per dispatch. The canonical upload is blocked only until the Central Portal token can publish io.vinarytree; each historical notice has its own later namespace gate and cannot cause JReleaser to retry the immutable canonical coordinate. The Java package namespace remains io.vinarytree.liblevenshtein throughout. An isolated local Maven repository smoke resolved each historical RC.4 coordinate with maven-dependency-plugin:3.9.0; both traversed their relocation POM into the canonical liblevenshtein JAR and its exact io.vinarytree:vinary-tree-interop:4.0.0-rc.4 dependency. JReleaser remains the authority that signs and adds release checksums to the three staged inputs.

Because this repository published no RC.4 coordinate and the correction does not change the public API, ABI, or runtime implementation, the first authoritative recovery source was the append-only tag v4.0.0-rc.4-release.1. Package versions remain 4.0.0-rc.4; the failed v4.0.0-rc.4 tag is not moved. The workflow derives Go and opam versions from Cargo.toml, accepts only positive numbered corrective tags, and subjects the corrective source to the complete validation and publication sequence. This avoids an unnecessary train-wide RC.5 while preserving exact provenance.

First corrective validation and Clojure dependency closure

The interop corrective source passed its complete validate-only graph in run 32865676284 at exact commit 3cb6165d44cc908d1da639788dd7677d458cec42. Every package job passed, every registry mutation was skipped, and the checksummed GitHub release job passed. The interop Maven source is therefore validated independently of the still-pending Central publication authorization.

The root's first corrective source then ran from exact commit d8ab2e6cce1095b5f9259f209601ee7b2f5a90aa in run 32865692165. Its JVM package successfully built the exact sibling topology, staged interop, passed Gradle tests and Javadoc, and produced the canonical and relocation inputs. Every other independent package job also passed. Only the downstream Clojure package failed: project.clj directly requires both io.vinarytree:vinary-tree-interop:4.0.0-rc.4 and io.vinarytree:liblevenshtein:4.0.0-rc.4, while the job transported and installed only the latter. Because neither coordinate was public, Leiningen correctly refused to substitute an external version.

Correction b7039543f5409f70036f5b60f95ef392e94f48fd transports the interop staging tree as a second, explicitly named workflow artifact and installs the exact JAR/POM pair for each direct dependency before Leiningen starts. The interop tree remains separate from root maven-staging: the canonical JReleaser deployer still downloads only the root-owned input, so an interop artifact cannot enter the root deployment bundle. A local reproduction began with both RC.4 entries absent from the Maven cache, installed only the two staged pairs, and passed 9 Clojure tests containing 19 assertions before generating the POM and JAR.

The remote v4.0.0-rc.4-release.1 tag remains immutable. The complete root validation and any later root publication therefore use the next append-only source tag, v4.0.0-rc.4-release.2; all package coordinates remain 4.0.0-rc.4.

Second corrective validation and sibling-source provenance

The second corrective validation ran from exact commit fbb2ddb12a936ea2dbd6c1022cf12b27ab657831 in run 32895742927. Its first aggregate binding-contract job failed before any package job or registry mutation. The root checker correctly required libdictenstein's pinned RubyGems OIDC exchange, but checkout-dev-siblings had cloned the immutable canonical libdictenstein tag, whose older workflow predates that hardening. Local validation had used the current sibling worktrees and therefore did not reproduce the clean runner's source selection.

The correction makes release/version.json the single release-train lock for all seven sibling refs. The shared checkout action reads its sourceRefs map, fails when any owner is absent or empty, and clones those exact immutable tags. Both release validators require the complete owner set and reject branch names, arbitrary commits, mismatched versions, and unnumbered corrective suffixes. The aggregate contract consumes the manifest rather than duplicating seven YAML literals. The already-pushed release.2 tag remains immutable; validation and publication continue from append-only v4.0.0-rc.4-release.3, while every package coordinate remains 4.0.0-rc.4.

JavaScript runtime corrective source topology

The JavaScript runtime's first corrective validation ran from exact commit ea1549a4283b102dc3ad8eab96d9f8342bf2c20e in run 32895741974. All six native matrix jobs rejected their owner Cargo lockfiles before artifact assembly. The workflow had cloned each family repository under the runtime checkout. Cargo therefore discovered the runtime's ancestor .cargo/config.toml while building libdictenstein and applied a patch graph that the owner lockfile does not contain. No npm or other package-registry job ran.

Runtime correction 68ca91ddf555cc015e20d7984f1db631e4c27ac2 moves every family checkout beside the runtime, records its exact immutable tag in the runtime release manifest, verifies that each tag peels to the checked-out commit, and rejects nested component roots before generating a Cargo overlay. The same helper protects all six native targets plus browser-WASM and WASI; development CI uses the same external topology with explicitly selected branch refs. Local regression validation rebuilt all four native owner libraries with --locked, proved their lockfiles unchanged, passed 10 native behavior tests, 7 steady-state leak tests, and 10 browser-WASM/WASI tests. Recovery proceeds from append-only runtime tag v4.0.0-rc.4-release.2; package identity remains 4.0.0-rc.4.

Libdictenstein fpm corrective source

Libdictenstein's first corrective validation ran from exact commit 208d9cd6ccfc4993acddd3c166bb314049dfb258 in run 32895771744. All artifact lanes except the numeric fpm candidate passed. fpm 0.12 enforced its optional package-name module convention and correctly rejected public module vinary_tree_libdictenstein for package libdictenstein; all protected publisher jobs were skipped, so no additional registry received bytes.

Correction 4b9a75b55cfd4e8b7f10b048d139e324150dfbc8 retains that intentional language-facing module and disables only the optional convention in both development and staged manifests. The binding contract now rejects a regression. Local validation reproduced the complete candidate lane: the Rust FFI library and interop Fortran dependency built, fpm compiled the namespaced module and collection example, and the registry-shaped package staged at numeric version 4.0.0. Recovery proceeds from append-only libdictenstein tag v4.0.0-rc.4-release.2; its RC package coordinates remain unchanged.

Dependency-ordered publication barriers

Every stage begins only after the exact public bytes from the preceding stage resolve and pass an independent consumer:

  1. interop crate and @vinary-tree/interop;
  2. libdictenstein crate, followed by its registry-shaped bindings;
  3. liblevenshtein crate, followed by its registry-shaped bindings;
  4. lling-llang crate, then duallity crate;
  5. @vinary-tree/vinary-tree native/WASM/WASI runtime;
  6. scoped libdictenstein, liblevenshtein, lling-llang, and duallity npm facades;
  7. unscoped liblevenshtein under next only; and
  8. scoped npm dist-tag normalization after an all-package installed-byte smoke.

Each GitHub dispatch uses one registry selector and a tag-restricted protected environment. Owners use refs/tags/v4.0.0-rc.4; the unpublished root recovery uses refs/tags/v4.0.0-rc.4-release.3 as recorded above. A downstream dispatch never substitutes a source checkout for a required public dependency.

Registry evidence

CoordinateWorkflow/protected environmentPublic digestIndependent consumerState
vinary-tree-interop@4.0.0-rc.4crates.io 32795964511SHA-256 431dff0a1c1adb8008800224978aa25f1d386d1ffba5456b5b575d29ff57dd5dexact registry lock; ABI/interface constants, null resource, and all ten status valuespassed
@vinary-tree/interop@4.0.0-rc.4npm 32797056140SHA-512 integrity w5lkouGm8rkkiFB+8gcVasdBwqUqZpgQLnjzbZ70aeoAbHFUuYkzH2dIXcVS5CSAoolXj26IDXF4R6tN6Kfd4A==; tarball SHA-256 1f2be5c342a88e54545b033ab032e4e5a1fa07b58b7afe2e22300305573df310exact install; CommonJS and ESM resource acceptance/rejection guardspassed under next
io.vinarytree:vinary-tree-interop:4.0.0-rc.4pending from interop v4.0.0-rc.4-release.1pendingJava/Kotlin/Scala resource-layout consumer pendingblocked on verified io.vinarytree namespace, corrective tag, and protected dispatch
libdictenstein@4.0.0-rc.4crates.io 32798222309SHA-256 3107cc65fec16a66624be386df12a0c8f4786c665c2088124bccc63350587842exact registry lock; valued CRUD and pre-mutation snapshot isolationpassed
@vinary-tree/libdictenstein@4.0.0-rc.4pendingpendingCRUD/traversal/batching/disposal smoke pendingnot published
liblevenshtein@4.0.0-rc.4 cratependingpendingconstruction/query smoke pendingnot published
io.vinarytree:liblevenshtein:4.0.0-rc.4pending in protected maven-central environmentpendingcanonical Java consumer pendingblocked on verified io.vinarytree namespace and canonical release dispatch
com.github.dylon:liblevenshtein:4.0.0-rc.4 relocation POMpending after canonical Central read-backpendingMaven relocation warning/resolution locally passedblocked on canonical publication and verified historical namespace
com.github.universal-automata:liblevenshtein:4.0.0-rc.4 relocation POMpending after canonical Central read-backpendingMaven relocation warning/resolution locally passedblocked on canonical publication and verified historical namespace
@vinary-tree/liblevenshtein@4.0.0-rc.4pendingpendingquery/stream/disposal smoke pendingnot published
lling-llang@4.0.0-rc.4 crate and facadependingpendingautomata/traversal smoke pendingnot published
duallity@4.0.0-rc.4 crate and facadependingpendingWFST/bridge/disposal smoke pendingnot published
@vinary-tree/vinary-tree@4.0.0-rc.4pendingpendingnative CJS/ESM, browser-WASM, and WASI smoke pendingnot published
liblevenshtein@4.0.0-rc.4 compatibility facadepending under next onlypendingCommonJS/ESM delegation smoke pendingnot published

The two Rust consumers were created under /tmp, outside every family workspace and therefore outside all sibling [patch] configuration. Each locked registry checksum matched the archive Cargo downloaded. The interop npm tarball downloaded from the registry was byte-for-byte identical to the validate-only GitHub release asset; both module systems then exercised the actual public guards, including rejection of wrong-runtime and wrong-interface resources.

Publication continuation, public-byte evidence, and Lua recovery

The observations in this section occurred after the initial registry table and supersede its pending cells without erasing that earlier release state. Every upload was dispatched independently from its ledgered immutable source, passed its protected environment, and was followed by a registry read-back.

CoordinateExact workflowPublic-byte evidenceIndependent consumerState
vinary-tree-interop==4.0.0rc4PyPI 32910364615wheel SHA-256 8c349f9e2a833877592c0633d2d98ea12782277508d708580ca063031605839a; sdist SHA-256 934e578ddaef27950647371a52ee80bf8790bfa11364a00ca577505782f404aafresh virtual environment imported the public wheel and checked UnitDomain.UNICODE_SCALAR == 2passed
io.vinarytree:vinary-tree-interop:4.0.0-rc.4Maven Central 32910366837public JAR SHA-256 9471b8221f022396706cfa42b2971afab9b17c478e0b9bbf7c3801e178338e93canonical POM and JAR resolved from Centralpassed
VinaryTree.Interop@4.0.0-rc.4NuGet 32910369154public nupkg SHA-256 d7f64a79723fd84593fe9596a4a33495dce62c063ceaf1b47bf2f89e72bf7df6fresh .NET 10 project constructed a Unicode DictionaryKeypassed
libdictenstein==4.0.0rc4PyPI 32913323744exact PyPI wheel installed with its public interop dependencyfresh virtual environment performed DynamicDAWG update, snapshot, lookup, and deterministic closepassed
io.vinarytree:libdictenstein:4.0.0-rc.4Maven Central 32913325678public JAR SHA-256 4632e82192408d6f69578be2aef78c3bbced0a77a8503be5c45a18cbb91368d7fresh Maven/JDK 26 project compiled at Java 22, used try-with-resources, batch insertion, lookup, and snapshot collectionpassed
Libdictenstein@4.0.0-rc.4NuGet 32913329142public nupkg SHA-256 83c2259b997e4ab64eb6b6f368e2c1058a9c0782bcf81b81a8460f59d70c29d0fresh .NET 10 project performed PutAll and Get through DynamicDawgpassed
libdictenstein-4.0.0.rc.4RubyGems 32913331042public gem SHA-256 27930ba23812594437fff931517e3755313e465f6fb80d0e1ababfcf5fb43832isolated gem home loaded vinary_tree/libdictenstein, performed put/get, and closed the dictionarypassed
io.vinarytree/libdictenstein-clojure@4.0.0-rc.4Clojars retry 32917209119public JAR SHA-256 7670b8fe50863d6e24f1d095b2d85843b916f1434aa260aa897ec5f08b9f7307; POM retains exact interop, libdictenstein, and liblevenshtein dependenciespublic POM and JAR resolved after the canonical Maven artifact indexedpassed
liblevenshtein@4.0.0-rc.4 cratecrates.io 32915965982public crate SHA-256 016fea81cd6ac523e7c1321a920c8c22044dcc1be5b3440d9faaf7566fb070aafresh Cargo project resolved only registry dependencies, built a DAT/transducer, and checked the expected fuzzy matchpassed
lling-llang@4.0.0-rc.4 cratecrates.io 32918156799public crate SHA-256 c827b5417a0ad3bf2e45ee98ce198c12cb2bbdca6243beff020924909f8871aefresh Cargo project built a correction lattice and verified its tropical-semiring Viterbi pathpassed
duallity@4.0.0-rc.4 cratecrates.io 32919377497public crate SHA-256 1864da0aa5bd1cada68bafa1c9ae160001ba93eab39b221f393a15323edb02f9fresh Cargo project resolved the complete public family, constructed a Levenshtein WFST, and exercised lazy start-state expansionpassed
io.vinarytree:liblevenshtein:4.0.0-rc.4Maven Central 32919679316public JAR SHA-256 af55e27520375c6b9465f765a4d9e8facd221f5fbfadd72c37cbb34b285b210bfresh Maven/JDK 26 project compiled at Java 22 and exercised try-with-resources, dictionary collections, retained-resource handoff, and a fuzzy querypassed
Liblevenshtein@4.0.0-rc.4NuGet 32919681588public nupkg SHA-256 662e231a4b7d619913406bed4549db5e0c0cac51f3cc46270a12c1bceb419a18fresh .NET 10 project exercised standard/Damerau/Unicode distances and deterministic phonetic-pattern disposalpassed
liblevenshtein-4.0.0.rc.4RubyGems 32919682753public gem SHA-256 3c64af580113357176374c1ce775b78419d953db0ebf2cc5636330b893934212isolated gem home exercised standard/Unicode distances, phonetic matching, and explicit closepassed
io.vinarytree/liblevenshtein-clojure@4.0.0-rc.4Clojars 32922464481public JAR SHA-256 bcaffc0227c3d91496995c20947f57aafaa9937ab5c2cf12f75688c4a3f67a26; POM SHA-256 b7a349fbd4934d7ea7f2baf30ec6f5e7a8d270bd35b30860cd522cb7858ddfabfresh tools.deps consumer resolved only public Clojars/Central coordinates and exercised a native phonetic-pattern resource under Java native-access containmentpassed
@vinary-tree/interop@4.0.0-rc.4npm 32797056140public tarball SHA-256 1f2be5c342a88e54545b033ab032e4e5a1fa07b58b7afe2e22300305573df310installed with all other scoped packages; ESM/CommonJS guards shared one runtime identitypassed under next; scoped tag normalization pending
@vinary-tree/vinary-tree@4.0.0-rc.4npm 32921548502public tarball SHA-256 7819f82552d1ad830d820290d57e3382bc3ad8b4ebe00e37e3b0342b63081a67clean native ESM, native CommonJS, browser-WASM bytecode, and Node WASI execution passedpassed under next; scoped tag normalization pending
@vinary-tree/libdictenstein@4.0.0-rc.4npm 32923611461public tarball SHA-256 ee0e9efffa433338d8f0b9132cb8f2ebdcb302266bb081daeff3542323b671f1combined clean consumer exercised collection CRUD and passed its dictionary directly to liblevenshtein and duallitypassed under next; bootstrap cleanup pending
@vinary-tree/liblevenshtein@4.0.0-rc.4npm 32923610561public tarball SHA-256 4094e77c3b86a9c2e0d7b94c96e3853eebf702771086be3a9a489bc55210d665combined clean consumer ran a ranked fuzzy query over the shared dictionary in ESM and verified CommonJS identitypassed under next; bootstrap cleanup pending
@vinary-tree/lling-llang@4.0.0-rc.4npm 32928888404public tarball SHA-256 0989c414f6200d175d2acdb224941eec1364142a1d166af6a9c8e8499a938fd0combined clean consumer built and finalized a vector WFST with the shared native runtime identitypassed under next; bootstrap cleanup pending
@vinary-tree/duallity@4.0.0-rc.4npm 32928886512public tarball SHA-256 31b3c45e9cb9eb11326d079c23add5edab1ce70f330ef543738a0e525c414c90combined clean consumer constructed a lazy edit WFST from the same dictionary and verified runtime identitypassed under next; bootstrap cleanup pending
liblevenshtein@4.0.0-rc.4 compatibility facadenpm 32929518360public tarball SHA-256 a3849cffe718289ce1d354c48190123a74272c750ee055b85caa5255048afb50exact ESM/CommonJS installs delegated to the scoped facade without changing runtime identity; phonetic API executedpassed under next; legacy latest=2.0.4 preserved

The interop opam dispatch 32910373279 opened upstream pull request ocaml/opam-repository#30559. It is a successful submission, not yet a registry publication. As of 2026-08-26, correction commit be33bb2d41e35d7d267a140233d3c1cee89b05d3 pins the public source archive's actual SHA-256 aff48f131e23c19171dce0a75404ec1c8093bdc3cd2264bc150ce1663d86e66c. Analysis, the opam-repository linter, Cygwin, msys2, and all 73 applicable opam-ci jobs pass; 79 non-applicable jobs are skipped. Dependent opam packages remain correctly blocked until the pull request is reviewed and merged and the exact public package passes a fresh-switch consumer.

The interop Go dispatch 32910371203 failed closed when GitHub rejected creation of protected tag bindings/go/v4.0.0-rc.4 with Resource not accessible by integration. No Go proxy version was published. The workflow token had contents: write; the remaining issue is protected-ref authority, not compilation or module content. Do not weaken tag immutability or create the tag manually without a fresh, exact-ref operator approval.

The root PyPI dispatch 32919683159 built its wheels and reached the protected uploader, but PyPI refused the OIDC exchange with invalid-publisher. The authenticated claims were repository vinary-tree/liblevenshtein-rust, workflow release.yml, environment pypi, and tag v4.0.0-rc.4-release.5; no liblevenshtein PyPI file was uploaded. The retry is blocked until the pending/trusted publisher for project liblevenshtein matches those four claims exactly. This is external package authority, not a source, wheel, or runtime defect.

The first libdictenstein Clojars dispatch 32913327427 failed before publication because Central had not yet indexed its exact Maven artifact. Retry 32917209119 ran only after public read-back and succeeded. This is the intended dependency barrier, not a source correction.

The libdictenstein LuaRocks dispatch 32913332742 failed before upload because a clean runner's LuaRocks installation contained no JSON decoder. Commit 31e3954ffc6f9687045cd596288b420dfd68a3ef installs dkjson explicitly and adds a cross-owner release gate; local append-only tag v4.0.0-rc.4-release.3 preserves that first correction. Pre-push validation then found that its release model and rockspec still named release.2. Rather than move the local tag, the complete libdictenstein recovery advances in commit 85af1fe2d2a808a628d3032c1ea2573bdddb3aaa at v4.0.0-rc.4-release.4, with a generalized numbered-correction invariant and an exact rockspec source. The corresponding root publisher correction, family-wide gate, pinned libdictenstein source ref, and this evidence are frozen by the ledger's containing commit and designated v4.0.0-rc.4-release.6. That root model also pins the canonical public Maven JAR SHA-256, af55e27520375c6b9465f765a4d9e8facd221f5fbfadd72c37cbb34b285b210b, so migration notices cannot target an unverified rebuild. Neither final corrective tag may be pushed without fresh, exact repository/ref approval. Each Lua upload is retried only after its new tag passes validate-only; package versions remain unchanged.

Both historical Maven-relocation dispatches reached the canonical-publication barrier and then failed before upload: 32922400401 for com.github.dylon and 32922398859 for com.github.universal-automata. The public POM matched, but the barrier compared two independently built JARs byte for byte. Direct inspection found the differing member was the rebuilt META-INF/native/windows-x86_64/liblevenshtein.dll, demonstrating native-build non-reproducibility rather than an altered public coordinate. The release.6 correction retains byte-exact POM comparison and verifies the downloaded public JAR against the canonical digest recorded above. It does not compare a rebuild that is never uploaded by the POM-only relocation lane. The two relocation uploads must be retried independently from validated release.6.

Post-recovery read-back and packaging-revision evidence

Root validate-only run 32933305806 and libdictenstein validate-only run 32933307261 passed from immutable release.6 and release.4, respectively. Their GitHub releases contain checksum manifests generated over the flattened upload set. The subsequent LuaRocks uploads also succeeded:

Public rockWorkflowPublic rockspec SHA-256Read-back result
liblevenshtein 4.0.0rc4-132934557951a336cf22ec659d5990b00d8f95cf7d6da88816fc2387a623b4585a75c072b7f2registry bytes equal the tagged rockspec; clean install fails at link time
libdictenstein 4.0.0rc4-13293456041294d8a74d5c91d8f006a861c2823adb634cc2e1fecc790b4e23d6fd1ca68a54bdregistry bytes equal the tagged rockspec; clean install fails at link time
libdictenstein 4.0.0rc4-2validate 32950358421; publish 32952621821c577b5773ed9ec5ff87560c8921f64032016055206c413d590502b86c7d0f2dcregistry bytes equal the tagged rockspec; checksum-verified SDK a6591065839527dba4081d5a05f5e5e7668cd8ac4b8f76386567b3ab7267779e; clean public-source install and complete Lua conformance passed
liblevenshtein 4.0.0rc4-2validate 32950359638; publish 329558308807c6efb2e8bb29bb42d30500940a0c97bb66af153fdb6d5ad32a9527270dae826registry bytes equal the tagged rockspec; checksum-verified SDK cc6ff7e81f94b049d5dcc403b6c26e6272de781fa399d77e28cc5ea165f33a3b; fresh tree resolved public revision-2 libdictenstein and passed snapshot integration

The independent command luarocks install --tree DIR --only-server=https://luarocks.org libdictenstein 4.0.0rc4-1 downloaded the public source rock and failed with Could not find library file for LIBDICTENSTEIN. Supplying LIBDICTENSTEIN_LIBDIR passed dependency discovery but still failed because the rockspec explicitly linked -Ltarget/release. A LuaRocks variable cannot override an explicit module libdirs entry. The same construction defect exists in the dependent liblevenshtein rock, which also referenced sibling headers absent from its source archive. Upload success and lint success were therefore false proxies for consumer usability.

The correction separates LuaRocks' numeric packaging revision from the Rust release candidate. Root and libdictenstein release models now derive 4.0.0rc4-2 from positive publication.luaRocksRevision = 2; other owners retain their own default revision 1. The release-train checker validates each owner's local revision instead of forcing one family-wide Lua revision. Both rockspecs consume LuaRocks' detected INCDIR and LIBDIR variables, and the root source archive carries generated copies of the two shared Lua/interop headers it compiles against. Package jobs now build into an isolated rock tree against an exact staged native SDK and execute the installed facade before the protected uploader can run.

The first local external-directory test passed against checkout headers. A stricter staged-SDK test then failed because libdictenstein's standalone native archive correctly omits the separately owned vinary_tree_interop.h, while the rockspec had also stopped searching its source package's generated header mirror. The final include order is external project SDK, source include, then Lua facade headers: the external project header wins, and the exact source supplies shared ABI declarations. With that correction, both revision-2 rocks compiled against staged native SDK directories, installed into one isolated Lua 5.4 tree, the complete libdictenstein Lua conformance suite passed, and bindings/lua/tests/snapshot.lua completed with Lua binding snapshot integration passed. The remote validate-only and protected publication runs then repeated those installed-package gates from immutable release.5 and release.7. Independent registry read-back downloaded each public rockspec, proved it byte-identical to the tagged source, verified each native SDK against its GitHub SHA256SUMS, and installed the public source rocks into fresh Lua trees. The dependent proof began with an empty tree, resolved public libdictenstein 4.0.0rc4-2 through public liblevenshtein 4.0.0rc4-2, and passed the snapshot integration program.

After the immutable RC.4 Maven artifact was already public, libdictenstein commit 62e489b0d83ced995b177d51968473b90f0e0b1f replaced its vague future Maven description with “High-performance dictionaries and trie-maps for approximate string matching” in both Gradle POM generation and JReleaser, and added a contract check preventing drift. Maven Central artifacts are immutable, so this metadata correction applies to the next publication; RC.4 was not silently replaced.

The corrected Maven relocation runs reached farther than the earlier rebuild gate and isolated the remaining blocker. Dylon run 32934559301 uploaded signed deployment 2c034894-a403-41a5-a00f-9b0172d99230; Central rejected it with Namespace 'com.github.dylon' is not allowed. Universal-automata run 32934559486 was rejected with Namespace 'com.github.universal-automata' is not allowed. The verified io.github.* namespaces do not authorize historical com.github.* coordinates, and publishing notices under new group identifiers would not relocate old consumers. Sonatype must grant or transfer the two exact legacy namespaces before either immutable run can succeed.

Root PyPI retry 32943019358 was dispatched from validated release.6 after the trusted-publisher setup was reported complete. All four wheel jobs passed, but protected publisher job 98100122514 again failed the PyPI OIDC exchange with invalid-publisher: PyPI found no publisher matching repository vinary-tree/liblevenshtein-rust, workflow release.yml, and environment pypi. No file was uploaded. The project-level trusted publisher must match those case-sensitive claims exactly before this same immutable dispatch is retried.

RC.4 GitHub checksum-manifest limitation

The interop validate-only run uploaded 41 non-manifest assets. GitHub exposes release assets in a flat basename namespace, but the tagged workflow computed SHA256SUMS before flattening Maven and Fortran paths. Consequently, sha256sum -c SHA256SUMS cannot find 31 entries immediately after a flat gh release download.

This is a path-encoding defect, not content corruption: all 41 manifest paths have unique basenames, every basename exists in the release, every expected hash equals the downloaded flat file, and GitHub's independent per-asset digests agree. RC.4 therefore remains immutable. A post-tag local workflow correction at 89ff866d018095d3ad38d2986ec327d1977a0cab stages separately, flattens with duplicate-basename rejection, hashes exactly the upload directory, and passed both positive verification and collision fixtures. It is not part of the RC.4 source tag and must receive separate push approval.

npm postconditions

Only after all exact RC.4 tarballs pass the combined installed-package smoke:

  • the six scoped coordinates must report latest = next = 4.0.0-rc.4;
  • no scoped coordinate may retain bootstrap;
  • every immutable 0.0.0 namespace reservation must carry the documented bootstrap deprecation;
  • rejected @vinary-tree/libdictenstein@4.0.0-rc.1 must direct users to RC.4 or newer; and
  • unscoped liblevenshtein must report latest = 2.0.4 and next = 4.0.0-rc.4.

Interactive web authentication is used for dist-tag and deprecation mutations. Publishing uses the repository workflow's provenance-bearing trusted publisher; no long-lived 2FA-bypass token is required.

The combined exact-package smoke above has passed. Registry read-back currently shows next=4.0.0-rc.4 everywhere, but the four newly claimed scoped names still have latest=bootstrap=0.0.0; interop and the umbrella runtime still have latest=4.0.0-rc.1. Those states are safe for prerelease consumers but do not satisfy the scoped postcondition. The operator must use interactive web authentication to move each scoped latest to RC.4, remove every remaining bootstrap tag, and deprecate each immutable 0.0.0 placeholder. No workflow or long-lived token should be introduced solely to bypass that account-level 2FA operation.

Explicit post-RC.4 completeness follow-up

RC.4 publishes the surfaces that passed the release gates recorded above. It does not treat the existing repository-local binding manifests as proof that the family is complete. Two pgmcp work items preserve the mandatory next-release scope:

  • complete-family-language-and-feature-parity requires the generated, family-wide project/language/capability matrix and closes every applicable implementation, idiom, test, benchmark, and packaging gap.
  • audit-and-complete-family-language-binding-documentation, with child publish-and-verify-language-package-documentation, requires complete API documentation for native Rust and every supported binding, validated common or intended usage examples for every API, conformance with all pgmcp documentation guidelines, and deployment/readback from each ecosystem's canonical documentation service, including docs.rs and cljdoc.
  • expose-host-implementable-lattice-and-lling-llang-interfaces requires idiomatic target-language providers for llattice algebra and the richer lling-llang semiring, backend, WFST, and extension contracts. It includes batch-amortized native callbacks, browser/Node WebAssembly import trampolines, WASI Component Model/WIT resources, algebra-law checks, lifecycle and hostile provider tests, and native-specialization performance preservation.

These are explicit next-release requirements. Their deferral does not classify an absent binding, API document, usage example, or documentation deployment as inapplicable.

Historical Maven relocation retry after namespace verification

On 2026-08-26, the exact v4.0.0-rc.4-release.6 source was dispatched again after the operator verified io.github.dylon, io.github.universal-automata, and io.vinarytree in Maven Central. Both protected relocation environments were explicitly approved after their complete package graphs and staging jobs passed:

Historical coordinateWorkflow runCentral deploymentResult
com.github.dylon:liblevenshtein:4.0.0-rc.432990895611a64ed21b-e94f-4533-8ef5-037429ddfa69rejected: Namespace 'com.github.dylon' is not allowed
com.github.universal-automata:liblevenshtein:4.0.0-rc.43299089627102514956-536d-4271-a32e-26f3b9f5eb5arejected: Namespace 'com.github.universal-automata' is not allowed

This is not a build, signature, staging, authentication, or canonical-artifact failure. Central accepted both bundles, then rejected the exact historical com.github.* namespaces. Verification of io.github.* does not grant the reverse-domain com.github.* coordinates used by the legacy artifacts. Do not retry either deployment until Central explicitly grants the exact historical namespace or provides a supported migration mechanism. The canonical io.vinarytree line remains independent of these optional notices.

Operator checklist

  • [x] RC.3 failure is closed with exact run/job evidence and no moved tag.
  • [x] All seven canonical models and generated dependency edges identify RC.4.
  • [x] Synchronizers own and validate every primary Cargo lockfile family entry.
  • [x] Clean JavaScript and JVM reproductions close both RC.3 defects.
  • [x] Complete every pre-publication default/all-feature, FFI, binding, documentation, registry-shape, native/npm package, and pgmcp bug-gate validation; retain downstream Cargo package verification at its exact public-dependency barrier.
  • [x] Render every changed PlantUML diagram headlessly and validate MathJax.
  • [x] Create seven descriptive, enumerated commits and seven local annotated tags; verify every tag peels to its intended commit.
  • [ ] Request and receive explicit approval naming every branch/tag push before using any remote push command.
  • [ ] Dispatch remaining validate-only workflows in dependency order and record exact run URLs, commits, job conclusions, and GitHub release checksums.
  • [ ] Publish each authorized registry coordinate only after its public upstream dependencies resolve; verify exact downloaded bytes independently.
  • [ ] Normalize npm metadata, update this ledger and pgmcp with final evidence, clean all temporary release directories, and prove every worktree clean.

Completion condition

RC.4 is complete only when all intended coordinates have exact source, workflow, digest, and clean-consumer evidence; every npm tag/deprecation invariant holds; all documentation and pgmcp records agree; temporary evidence has been removed; and every release worktree is clean. A local pass, tag, upload, or registry metadata listing alone is not completion.

Can you improve this documentation?Edit on GitHub

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close