diff --git a/CHANGELOG.md b/CHANGELOG.md index f4f9a84d7dc..24934997d5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ Docs: https://docs.openclaw.ai ### Fixes - Gateway: keep directly requested plugin tools invokable under restrictive tool profiles while preserving explicit deny lists and the HTTP safety deny list, preventing catalog/invoke mismatches that surface as "Tool not available". Thanks @BunsDev. +- Gateway/update: allow beta binaries to refresh gateway services when the config was last written by the matching stable release version, avoiding false newer-config downgrade blocks during beta channel updates. - Channels: keep Matrix and Mattermost bundled in the core package instead of advertising external npm installs before those channels are cut over. Thanks @vincentkoc. - Bonjour: disable LAN mDNS advertising after a repeated stuck-announcing recovery instead of repeatedly restarting ciao and saturating the Gateway event loop. - CLI/plugins: stop treating the non-plugin `auth` command root as a bundled plugin id, so restrictive `plugins.allow` configs no longer tell users to add stale `auth` plugin entries. diff --git a/src/config/future-version-guard.test.ts b/src/config/future-version-guard.test.ts index e71c88f75fa..95216649d70 100644 --- a/src/config/future-version-guard.test.ts +++ b/src/config/future-version-guard.test.ts @@ -51,6 +51,17 @@ describe("resolveFutureConfigActionBlock", () => { ).toBeNull(); }); + it("allows beta binaries to refresh services written by the same stable release", () => { + expect( + resolveFutureConfigActionBlock({ + action: "install or rewrite the gateway service", + currentVersion: "2026.5.2-beta.3", + snapshot: snapshotWithTouchedVersion("2026.5.2"), + env: {}, + }), + ).toBeNull(); + }); + it("allows intentional downgrade override through env", () => { expect( resolveFutureConfigActionBlock({ diff --git a/src/config/version.test.ts b/src/config/version.test.ts index 25343a2d75b..55da0e69117 100644 --- a/src/config/version.test.ts +++ b/src/config/version.test.ts @@ -77,12 +77,19 @@ describe("shouldWarnOnTouchedVersion", () => { expect(shouldWarnOnTouchedVersion("2026.3.23-beta.1", "2026.3.23-1")).toBe(false); }); + it("skips same-base stable configs when current is a beta", () => { + expect(shouldWarnOnTouchedVersion("2026.5.2-beta.3", "2026.5.2")).toBe(false); + }); + it("skips same-base prerelease configs when current is newer", () => { expect(shouldWarnOnTouchedVersion("2026.3.23", "2026.3.23-beta.1")).toBe(false); }); + it("still warns when the touched prerelease is newer", () => { + expect(shouldWarnOnTouchedVersion("2026.5.2-beta.2", "2026.5.2-beta.3")).toBe(true); + }); + it("warns when the touched config is newer", () => { - expect(shouldWarnOnTouchedVersion("2026.3.23-beta.1", "2026.3.23")).toBe(true); expect(shouldWarnOnTouchedVersion("2026.3.23", "2026.3.24")).toBe(true); expect(shouldWarnOnTouchedVersion("2026.3.23", "2027.1.1")).toBe(true); }); diff --git a/src/config/version.ts b/src/config/version.ts index fafda188cb6..f3c183b94ea 100644 --- a/src/config/version.ts +++ b/src/config/version.ts @@ -111,10 +111,11 @@ export function shouldWarnOnTouchedVersion( parsedTouched && parsedCurrent.major === parsedTouched.major && parsedCurrent.minor === parsedTouched.minor && - parsedCurrent.patch === parsedTouched.patch && - parsedTouched.revision != null + parsedCurrent.patch === parsedTouched.patch ) { - return false; + if (!parsedTouched.prerelease?.length) { + return false; + } } if (isSameOpenClawStableFamily(current, touched)) { return false;