From dc898013a65dbb99dcffdef3609306b9f419006c Mon Sep 17 00:00:00 2001 From: Andrew Plaza Date: Tue, 25 Aug 2026 17:20:26 -0400 Subject: [PATCH 1/3] chore: sort the unified pre.* prerelease timeline (drop followTag) Drop "followTag": "nightly" so default npm semver sorting picks the newest @xmtp/node-sdk / @xmtp/node-bindings prerelease, and widen the lockstep guard to accept libxmtp'''s unified pre... suffix alongside the legacy nightly.. / dev. shapes. ignoreUnstable: false and respectLatest: false are unchanged, so prereleases stay eligible. --- .github/renovate.json | 1 - test/xmtpLockstep.test.ts | 16 +++++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/.github/renovate.json b/.github/renovate.json index 66dff0f..ffba415 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -17,7 +17,6 @@ }, { "matchPackageNames": ["@xmtp/node-sdk", "@xmtp/node-bindings"], - "followTag": "nightly", "ignoreUnstable": false, "respectLatest": false } diff --git a/test/xmtpLockstep.test.ts b/test/xmtpLockstep.test.ts index adfe77e..d0e9e8d 100644 --- a/test/xmtpLockstep.test.ts +++ b/test/xmtpLockstep.test.ts @@ -13,13 +13,18 @@ import { describe, expect, it } from "vitest"; * * Nightlies of both packages are published together from a single libxmtp * commit, and dev releases likewise publish both from one libxmtp run — so - * the pins are in lockstep exactly when they share the same - * `nightly..` or `dev.` suffix. Renovate bumps nightlies - * as one grouped PR (see .github/renovate.json) and libxmtp's dev-release + * the pins are in lockstep exactly when they share the same suffix: the + * unified `pre...` shape that main-cut dev and + * nightly releases now share (one release run stamps one timestamp, so both + * packages carry an identical suffix), or the legacy + * `nightly..` / `dev.` shapes, which are kept because + * branch-cut dev releases still use them. Renovate bumps nightlies as one + * grouped PR (see .github/renovate.json) and libxmtp's dev-release * automation opens dev bumps the same way; this test fails if anything * desyncs them. */ -const PRERELEASE_SUFFIX = /-(nightly\.\d{8}\.[0-9a-f]+|dev\.[0-9a-f]+)$/; +const PRERELEASE_SUFFIX = + /-(pre\.\d{12}\.(?:dev|nightly)\.[0-9a-f]+|nightly\.\d{8}\.[0-9a-f]+|dev\.[0-9a-f]+)$/; describe("xmtp node-sdk / node-bindings lockstep", () => { const pkg = JSON.parse( @@ -46,7 +51,8 @@ describe("xmtp node-sdk / node-bindings lockstep", () => { bindingsSuffix, `@xmtp/node-sdk ${nodeSdk} and @xmtp/node-bindings ${nodeBindings} ` + "must come from the same libxmtp commit (matching " + - "nightly.. or dev. suffix); a skewed pair breaks inbox-id " + + "pre..., nightly.., or dev. " + + "suffix); a skewed pair breaks inbox-id " + 'derivation with "Inbox ID doesn\'t match nonce & address"', ).toBe(sdkSuffix); }); From 2991722416516e2bcb10bf683bfdb2235777226c Mon Sep 17 00:00:00 2001 From: Andrew Plaza Date: Tue, 25 Aug 2026 17:37:22 -0400 Subject: [PATCH 2/3] chore(renovate): keep xmtp pins on the prerelease timeline Dropping followTag left this rule sorting the whole @xmtp/node-sdk / @xmtp/node-bindings version list for the highest candidate, and rc/final releases are numerically higher than any prerelease of the same X.Y.Z -- so a stable release would have become the update candidate. allowedVersions pins the rule back to the prerelease timeline: - unified pre..., both channels: main-cut dev and nightly are one ordered timeline now; - legacy nightly.., kept for the transition so a cross-X.Y.Z move off the current legacy pins is still offered; - legacy dev. deliberately excluded -- branch-cut devs stay renovate-invisible and are delivered by bot PRs. Stable adoption therefore stays a deliberate human change. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01QF99maZfAqQ5onTGatgDvy --- .github/renovate.json | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/renovate.json b/.github/renovate.json index ffba415..2ea4bd1 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -17,6 +17,7 @@ }, { "matchPackageNames": ["@xmtp/node-sdk", "@xmtp/node-bindings"], + "allowedVersions": "/-(?:pre\\.\\d{12}\\.(?:dev|nightly)\\.[0-9a-f]+|nightly\\.\\d{8}\\.[0-9a-f]+)$/", "ignoreUnstable": false, "respectLatest": false } From 5f5e082f4a6ecd9274c8b412722ddb3de0be0db8 Mon Sep 17 00:00:00 2001 From: Andrew Plaza Date: Tue, 25 Aug 2026 22:16:18 -0400 Subject: [PATCH 3/3] chore: widen prerelease timestamp to seconds precision (14 digits) Tracks xmtp/libxmtp#4048's same-minute-collision fix: the prerelease timestamp widened from YYYYMMDDHHMM to YYYYMMDDHHMMSS, so releases minted in the same minute no longer tie and fall back to channel-word ordering. --- .github/renovate.json | 2 +- test/xmtpLockstep.test.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/renovate.json b/.github/renovate.json index 2ea4bd1..5853807 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -17,7 +17,7 @@ }, { "matchPackageNames": ["@xmtp/node-sdk", "@xmtp/node-bindings"], - "allowedVersions": "/-(?:pre\\.\\d{12}\\.(?:dev|nightly)\\.[0-9a-f]+|nightly\\.\\d{8}\\.[0-9a-f]+)$/", + "allowedVersions": "/-(?:pre\\.\\d{14}\\.(?:dev|nightly)\\.[0-9a-f]+|nightly\\.\\d{8}\\.[0-9a-f]+)$/", "ignoreUnstable": false, "respectLatest": false } diff --git a/test/xmtpLockstep.test.ts b/test/xmtpLockstep.test.ts index d0e9e8d..6b7e3ea 100644 --- a/test/xmtpLockstep.test.ts +++ b/test/xmtpLockstep.test.ts @@ -14,7 +14,7 @@ import { describe, expect, it } from "vitest"; * Nightlies of both packages are published together from a single libxmtp * commit, and dev releases likewise publish both from one libxmtp run — so * the pins are in lockstep exactly when they share the same suffix: the - * unified `pre...` shape that main-cut dev and + * unified `pre...` shape that main-cut dev and * nightly releases now share (one release run stamps one timestamp, so both * packages carry an identical suffix), or the legacy * `nightly..` / `dev.` shapes, which are kept because @@ -24,7 +24,7 @@ import { describe, expect, it } from "vitest"; * desyncs them. */ const PRERELEASE_SUFFIX = - /-(pre\.\d{12}\.(?:dev|nightly)\.[0-9a-f]+|nightly\.\d{8}\.[0-9a-f]+|dev\.[0-9a-f]+)$/; + /-(pre\.\d{14}\.(?:dev|nightly)\.[0-9a-f]+|nightly\.\d{8}\.[0-9a-f]+|dev\.[0-9a-f]+)$/; describe("xmtp node-sdk / node-bindings lockstep", () => { const pkg = JSON.parse(