diff --git a/CHANGELOG.md b/CHANGELOG.md
index 19ff7e1eb87..6386ac03044 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,7 +4,11 @@ Docs: https://docs.openclaw.ai
## Unreleased
-- UI/chat: replace marked.js with markdown-it so maliciously crafted markdown can no longer freeze the Control UI via ReDoS. (#46707) Thanks @zhangfnf.
+### Changes
+
+### Fixes
+
+## 2026.4.14-beta.1
### Changes
@@ -12,6 +16,7 @@ Docs: https://docs.openclaw.ai
### Fixes
+- UI/chat: replace marked.js with markdown-it so maliciously crafted markdown can no longer freeze the Control UI via ReDoS. (#46707) Thanks @zhangfnf.
- Auto-reply/send policy: keep `sendPolicy: "deny"` from blocking inbound message processing, so the agent still runs its turn while all outbound delivery is suppressed for observer-style setups. (#65461, #53328) Thanks @omarshahine.
- BlueBubbles: lazy-refresh the Private API server-info cache on send when reply threading or message effects are requested but status is unknown, so sends no longer silently degrade to plain messages when the 10-minute cache expires. (#65447, #43764) Thanks @omarshahine.
- Heartbeat/security: force owner downgrade for untrusted `hook:wake` system events [AI-assisted]. (#66031) Thanks @pgondhi987.
diff --git a/apps/android/app/build.gradle.kts b/apps/android/app/build.gradle.kts
index 65dbd2350e7..ff68ed4301f 100644
--- a/apps/android/app/build.gradle.kts
+++ b/apps/android/app/build.gradle.kts
@@ -65,8 +65,8 @@ android {
applicationId = "ai.openclaw.app"
minSdk = 31
targetSdk = 36
- versionCode = 2026041290
- versionName = "2026.4.12"
+ versionCode = 2026041401
+ versionName = "2026.4.14-beta.1"
ndk {
// Support all major ABIs — native libs are tiny (~47 KB per ABI)
abiFilters += listOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64")
diff --git a/apps/ios/CHANGELOG.md b/apps/ios/CHANGELOG.md
index 7c2d0d3f3d4..4c87d107594 100644
--- a/apps/ios/CHANGELOG.md
+++ b/apps/ios/CHANGELOG.md
@@ -1,5 +1,9 @@
# OpenClaw iOS Changelog
+## 2026.4.14 - 2026-04-14
+
+Maintenance update for the current OpenClaw beta release.
+
## 2026.4.12 - 2026-04-12
Maintenance update for the current OpenClaw release.
diff --git a/apps/ios/Config/Version.xcconfig b/apps/ios/Config/Version.xcconfig
index 4d1b39f8ab3..ec3c83c4d54 100644
--- a/apps/ios/Config/Version.xcconfig
+++ b/apps/ios/Config/Version.xcconfig
@@ -2,8 +2,8 @@
// Source of truth: apps/ios/version.json
// Generated by scripts/ios-sync-versioning.ts.
-OPENCLAW_IOS_VERSION = 2026.4.12
-OPENCLAW_MARKETING_VERSION = 2026.4.12
+OPENCLAW_IOS_VERSION = 2026.4.14
+OPENCLAW_MARKETING_VERSION = 2026.4.14
OPENCLAW_BUILD_VERSION = 1
#include? "../build/Version.xcconfig"
diff --git a/apps/ios/fastlane/metadata/en-US/release_notes.txt b/apps/ios/fastlane/metadata/en-US/release_notes.txt
index 99afd00b10b..5090e4186ab 100644
--- a/apps/ios/fastlane/metadata/en-US/release_notes.txt
+++ b/apps/ios/fastlane/metadata/en-US/release_notes.txt
@@ -1 +1 @@
-Maintenance update for the current OpenClaw release.
+Maintenance update for the current OpenClaw beta release.
diff --git a/apps/ios/version.json b/apps/ios/version.json
index 2cbb2769149..4ecad6437ba 100644
--- a/apps/ios/version.json
+++ b/apps/ios/version.json
@@ -1,3 +1,3 @@
{
- "version": "2026.4.12"
+ "version": "2026.4.14"
}
diff --git a/apps/macos/Sources/OpenClaw/Resources/Info.plist b/apps/macos/Sources/OpenClaw/Resources/Info.plist
index f230cf6cbe3..d8da9376896 100644
--- a/apps/macos/Sources/OpenClaw/Resources/Info.plist
+++ b/apps/macos/Sources/OpenClaw/Resources/Info.plist
@@ -15,9 +15,9 @@
CFBundlePackageType
APPL
CFBundleShortVersionString
- 2026.4.12
+ 2026.4.14-beta.1
CFBundleVersion
- 2026041290
+ 2026041401
CFBundleIconFile
OpenClaw
CFBundleURLTypes
diff --git a/docs/.generated/config-baseline.sha256 b/docs/.generated/config-baseline.sha256
index b575aa1bc2c..0b6578e9f22 100644
--- a/docs/.generated/config-baseline.sha256
+++ b/docs/.generated/config-baseline.sha256
@@ -1,4 +1,4 @@
-724be329389b48a3f1697a534722702de294be4605e1d700c16ec6bbc560100d config-baseline.json
-e4f4396307dc84c9f4b5c42280d69b985d8e07869046ca325956fc59a5a9abd0 config-baseline.core.json
+3583489dfebd88a53f1c66c984b16dc5eff752c887d4c582a86753990f1d5b18 config-baseline.json
+a490b20c47a45c3e26b6917eb3e102356698395128aec20b1f4aabb62ca7cad1 config-baseline.core.json
3bb312dc9c39a374ca92613abf21606c25dc571287a3941dac71ff57b2b5c519 config-baseline.channel.json
0471a5bffb213a3829555efe5961f5b5fd5080c1d38b1ac8dd87afaabdb8bdc1 config-baseline.plugin.json
diff --git a/docs/.generated/plugin-sdk-api-baseline.sha256 b/docs/.generated/plugin-sdk-api-baseline.sha256
index b4bfcd6c5aa..23047c9a793 100644
--- a/docs/.generated/plugin-sdk-api-baseline.sha256
+++ b/docs/.generated/plugin-sdk-api-baseline.sha256
@@ -1,2 +1,2 @@
-42a93d8368fd40f6bbe3045ba89b84a28e1131c700d4e57580febd3e773b23a4 plugin-sdk-api-baseline.json
-515333c277b725abaccf4fd5ab8c5e58b2de39b26e1fe4738f31852fcf789c96 plugin-sdk-api-baseline.jsonl
+7003e0d0ba1cddb7eb388204825ac892206209a4a9c795e76c4e34b5fc7b50f0 plugin-sdk-api-baseline.json
+14e39520459abc7db7993a700a4f07adfa0855d9233d123c4725477b91f1cb13 plugin-sdk-api-baseline.jsonl
diff --git a/package.json b/package.json
index a4646197a52..3d59181c34c 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "openclaw",
- "version": "2026.4.12",
+ "version": "2026.4.14-beta.1",
"description": "Multi-channel AI gateway with extensible messaging integrations",
"keywords": [],
"homepage": "https://github.com/openclaw/openclaw#readme",
diff --git a/scripts/stage-bundled-plugin-runtime-deps.mjs b/scripts/stage-bundled-plugin-runtime-deps.mjs
index b13149202ae..419e690c4a9 100644
--- a/scripts/stage-bundled-plugin-runtime-deps.mjs
+++ b/scripts/stage-bundled-plugin-runtime-deps.mjs
@@ -93,6 +93,15 @@ const defaultStagedRuntimeDepPruneRules = new Map([
["matrix-widget-api", { paths: ["src"], suffixes: [".d.ts"] }],
["oidc-client-ts", { paths: ["README.md"], suffixes: [".d.ts"] }],
["music-metadata", { paths: ["README.md"], suffixes: [".d.ts"] }],
+ ["@cloudflare/workers-types", { paths: ["."] }],
+ ["gifwrap", { paths: ["test"] }],
+ ["playwright-core", { paths: ["types"], suffixes: [".d.ts"] }],
+ ["@jimp/plugin-blit", { paths: ["src/__image_snapshots__"] }],
+ ["@jimp/plugin-blur", { paths: ["src/__image_snapshots__"] }],
+ ["@jimp/plugin-color", { paths: ["src/__image_snapshots__"] }],
+ ["@jimp/plugin-print", { paths: ["src/__image_snapshots__"] }],
+ ["@jimp/plugin-quantize", { paths: ["src/__image_snapshots__"] }],
+ ["@jimp/plugin-threshold", { paths: ["src/__image_snapshots__"] }],
]);
const runtimeDepsStagingVersion = 2;
diff --git a/src/canvas-host/a2ui/.bundle.hash b/src/canvas-host/a2ui/.bundle.hash
index 958abf2260c..08f2322179a 100644
--- a/src/canvas-host/a2ui/.bundle.hash
+++ b/src/canvas-host/a2ui/.bundle.hash
@@ -1 +1 @@
-5848c4cb70b4f330875853e1ddb906adb6bde95c6ae531880e2af87b000b4bd9
+fe6c039912decd3f99288b3d1f3dd54723d23b80ba53553ef41d016b81668144
diff --git a/src/config/schema.base.generated.ts b/src/config/schema.base.generated.ts
index 1cb13991876..570e6848d47 100644
--- a/src/config/schema.base.generated.ts
+++ b/src/config/schema.base.generated.ts
@@ -27277,6 +27277,6 @@ export const GENERATED_BASE_CONFIG_SCHEMA: BaseConfigSchemaResponse = {
tags: ["advanced", "url-secret"],
},
},
- version: "2026.4.12",
+ version: "2026.4.14-beta.1",
generatedAt: "2026-03-22T21:17:33.302Z",
};
diff --git a/test/scripts/stage-bundled-plugin-runtime-deps.test.ts b/test/scripts/stage-bundled-plugin-runtime-deps.test.ts
index 9ecf08d4e95..9b5d7d8f857 100644
--- a/test/scripts/stage-bundled-plugin-runtime-deps.test.ts
+++ b/test/scripts/stage-bundled-plugin-runtime-deps.test.ts
@@ -261,6 +261,71 @@ describe("stageBundledPluginRuntimeDeps", () => {
);
});
+ it("applies default prune rules for known heavy non-runtime package cargo", () => {
+ const { pluginDir, repoRoot } = createBundledPluginFixture({
+ packageJson: {
+ name: "@openclaw/fixture-plugin",
+ version: "1.0.0",
+ dependencies: {
+ "@cloudflare/workers-types": "1.0.0",
+ "@jimp/plugin-blit": "1.0.0",
+ gifwrap: "1.0.0",
+ "playwright-core": "1.0.0",
+ },
+ openclaw: { bundle: { stageRuntimeDependencies: true } },
+ },
+ });
+ const rootNodeModules = path.join(repoRoot, "node_modules");
+ const writePackage = (name: string) => {
+ const depDir = path.join(rootNodeModules, ...name.split("/"));
+ fs.mkdirSync(depDir, { recursive: true });
+ fs.writeFileSync(
+ path.join(depDir, "package.json"),
+ `${JSON.stringify({ name, version: "1.0.0" }, null, 2)}\n`,
+ "utf8",
+ );
+ return depDir;
+ };
+ const cloudflareDir = writePackage("@cloudflare/workers-types");
+ fs.writeFileSync(path.join(cloudflareDir, "index.d.ts"), "export {};\n", "utf8");
+ const gifwrapDir = writePackage("gifwrap");
+ fs.mkdirSync(path.join(gifwrapDir, "test", "fixtures"), { recursive: true });
+ fs.writeFileSync(path.join(gifwrapDir, "test", "fixtures", "large.gif"), "fixture\n", "utf8");
+ const playwrightDir = writePackage("playwright-core");
+ fs.mkdirSync(path.join(playwrightDir, "types"), { recursive: true });
+ fs.writeFileSync(path.join(playwrightDir, "types", "types.d.ts"), "export {};\n", "utf8");
+ fs.writeFileSync(path.join(playwrightDir, "index.js"), "export {};\n", "utf8");
+ const jimpDir = writePackage("@jimp/plugin-blit");
+ fs.mkdirSync(path.join(jimpDir, "src", "__image_snapshots__"), { recursive: true });
+ fs.writeFileSync(
+ path.join(jimpDir, "src", "__image_snapshots__", "snapshot.png"),
+ "fixture\n",
+ "utf8",
+ );
+ fs.writeFileSync(path.join(jimpDir, "index.js"), "export {};\n", "utf8");
+
+ stageBundledPluginRuntimeDeps({ cwd: repoRoot });
+
+ expect(
+ fs.existsSync(path.join(pluginDir, "node_modules", "@cloudflare", "workers-types")),
+ ).toBe(false);
+ expect(fs.existsSync(path.join(pluginDir, "node_modules", "gifwrap", "test"))).toBe(false);
+ expect(fs.existsSync(path.join(pluginDir, "node_modules", "playwright-core", "types"))).toBe(
+ false,
+ );
+ expect(fs.existsSync(path.join(pluginDir, "node_modules", "playwright-core", "index.js"))).toBe(
+ true,
+ );
+ expect(
+ fs.existsSync(
+ path.join(pluginDir, "node_modules", "@jimp", "plugin-blit", "src", "__image_snapshots__"),
+ ),
+ ).toBe(false);
+ expect(
+ fs.existsSync(path.join(pluginDir, "node_modules", "@jimp", "plugin-blit", "index.js")),
+ ).toBe(true);
+ });
+
it("falls back to staging installs when the root dependency version is incompatible", () => {
const { pluginDir, repoRoot } = createBundledPluginFixture({
packageJson: {