diff --git a/extensions/qa-lab/package.json b/extensions/qa-lab/package.json index 33162c45437..595906b7c81 100644 --- a/extensions/qa-lab/package.json +++ b/extensions/qa-lab/package.json @@ -27,11 +27,6 @@ "extensions": [ "./index.ts" ], - "install": { - "npmSpec": "@openclaw/qa-lab", - "defaultChoice": "npm", - "minHostVersion": ">=2026.4.10" - }, "compat": { "pluginApi": ">=2026.4.25" } diff --git a/src/plugins/bundled-plugin-naming.test.ts b/src/plugins/bundled-plugin-naming.test.ts index c5087faa867..9a63830fbec 100644 --- a/src/plugins/bundled-plugin-naming.test.ts +++ b/src/plugins/bundled-plugin-naming.test.ts @@ -31,6 +31,7 @@ const DIR_ID_EXCEPTIONS = new Map([ // Historical directory name kept until a wider repo cleanup is worth the churn. ["kimi-coding", "kimi"], ]); +const NON_PACKAGED_BUNDLED_PLUGIN_DIRS = new Set(["qa-channel", "qa-lab", "qa-matrix"]); const ALLOWED_PACKAGE_SUFFIXES = [ "", "-provider", @@ -145,6 +146,18 @@ describe("bundled plugin naming guardrails", () => { `${dirName}: package=${packageName}, npmSpec=${installNpmSpec}`, ), }, + { + name: "keeps non-packaged bundled plugins from advertising npm installs", + message: + "Non-packaged bundled plugins are source-only/private and must not advertise openclaw.install.npmSpec.", + collectMismatches: (records: BundledPluginRecord[]) => + records + .filter( + ({ dirName, installNpmSpec }) => + NON_PACKAGED_BUNDLED_PLUGIN_DIRS.has(dirName) && typeof installNpmSpec === "string", + ) + .map(({ dirName, installNpmSpec }) => `${dirName}: npmSpec=${installNpmSpec}`), + }, { name: "keeps bundled channel ids aligned with the canonical plugin id", message: