fix(deps): remove extension-owned deps from root install (#69335)

* fix(deps): remove extension runtime deps from root install

* fix(deps): keep bundled plugin deps local

* test(plugins): assert matrix deps stay plugin-local
This commit is contained in:
Peter Steinberger
2026-04-20 15:03:09 +01:00
committed by GitHub
parent 8642137252
commit f6360da116
9 changed files with 80 additions and 270 deletions

View File

@@ -1503,65 +1503,39 @@
"dependencies": {
"@agentclientprotocol/sdk": "0.19.0",
"@anthropic-ai/vertex-sdk": "^0.16.0",
"@aws-sdk/client-bedrock": "3.1032.0",
"@aws-sdk/client-bedrock-runtime": "3.1032.0",
"@aws-sdk/credential-provider-node": "3.972.32",
"@aws/bedrock-token-generator": "^1.1.0",
"@buape/carbon": "0.16.0",
"@clack/prompts": "^1.2.0",
"@google/genai": "^1.50.1",
"@grammyjs/runner": "^2.0.3",
"@grammyjs/transformer-throttler": "^1.2.1",
"@homebridge/ciao": "^1.3.6",
"@lancedb/lancedb": "^0.27.2",
"@larksuiteoapi/node-sdk": "^1.60.0",
"@lydell/node-pty": "1.2.0-beta.12",
"@mariozechner/pi-agent-core": "0.67.68",
"@mariozechner/pi-ai": "0.67.68",
"@mariozechner/pi-coding-agent": "0.67.68",
"@mariozechner/pi-tui": "0.67.68",
"@matrix-org/matrix-sdk-crypto-wasm": "18.1.0",
"@modelcontextprotocol/sdk": "1.29.0",
"@mozilla/readability": "^0.6.0",
"@pierre/diffs": "1.1.15",
"@sinclair/typebox": "0.34.49",
"@slack/bolt": "^4.7.0",
"@slack/web-api": "^7.15.1",
"@whiskeysockets/baileys": "7.0.0-rc.9",
"ajv": "^8.18.0",
"chalk": "^5.6.2",
"chokidar": "^5.0.0",
"cli-highlight": "^2.1.11",
"commander": "^14.0.3",
"croner": "^10.0.1",
"discord-api-types": "^0.38.47",
"dotenv": "^17.4.2",
"express": "^5.2.1",
"file-type": "22.0.1",
"gaxios": "7.1.4",
"google-auth-library": "^10.6.2",
"grammy": "^1.42.0",
"https-proxy-agent": "^9.0.0",
"ipaddr.js": "^2.3.0",
"jimp": "^1.6.1",
"jiti": "^2.6.1",
"json5": "^2.2.3",
"jszip": "^3.10.1",
"linkedom": "^0.18.12",
"markdown-it": "14.1.1",
"matrix-js-sdk": "41.3.0",
"mpg123-decoder": "^1.0.3",
"node-edge-tts": "^1.2.10",
"nostr-tools": "^2.23.3",
"openai": "^6.34.0",
"opusscript": "^0.1.1",
"osc-progress": "^0.3.0",
"pdfjs-dist": "^5.6.205",
"playwright-core": "1.59.1",
"proxy-agent": "^8.0.1",
"qrcode-terminal": "^0.12.0",
"sharp": "^0.34.5",
"silk-wasm": "^3.7.1",
"sqlite-vec": "0.1.9",
"tar": "7.5.13",
"tslog": "^4.10.2",
@@ -1605,12 +1579,6 @@
"optional": true
}
},
"optionalDependencies": {
"@discordjs/opus": "^0.10.0",
"@matrix-org/matrix-sdk-crypto-nodejs": "^0.4.0",
"fake-indexeddb": "^6.2.5",
"music-metadata": "^11.12.3"
},
"overrides": {
"axios": "1.15.0",
"follow-redirects": "1.16.0"

159
pnpm-lock.yaml generated
View File

@@ -44,42 +44,12 @@ importers:
'@anthropic-ai/vertex-sdk':
specifier: ^0.16.0
version: 0.16.0(zod@4.3.6)
'@aws-sdk/client-bedrock':
specifier: 3.1032.0
version: 3.1032.0
'@aws-sdk/client-bedrock-runtime':
specifier: 3.1032.0
version: 3.1032.0
'@aws-sdk/credential-provider-node':
specifier: 3.972.32
version: 3.972.32
'@aws/bedrock-token-generator':
specifier: ^1.1.0
version: 1.1.0
'@buape/carbon':
specifier: 0.16.0
version: 0.16.0(@discordjs/opus@0.10.0)(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(opusscript@0.1.1)
'@clack/prompts':
specifier: ^1.2.0
version: 1.2.0
'@google/genai':
specifier: ^1.50.1
version: 1.50.1(@modelcontextprotocol/sdk@1.29.0(zod@4.3.6))
'@grammyjs/runner':
specifier: ^2.0.3
version: 2.0.3(grammy@1.42.0)
'@grammyjs/transformer-throttler':
specifier: ^1.2.1
version: 1.2.1(grammy@1.42.0)
'@homebridge/ciao':
specifier: ^1.3.6
version: 1.3.6
'@lancedb/lancedb':
specifier: ^0.27.2
version: 0.27.2(apache-arrow@18.1.0)
'@larksuiteoapi/node-sdk':
specifier: ^1.60.0
version: 1.60.0
'@lydell/node-pty':
specifier: 1.2.0-beta.12
version: 1.2.0-beta.12
@@ -95,9 +65,6 @@ importers:
'@mariozechner/pi-tui':
specifier: 0.67.68
version: 0.67.68
'@matrix-org/matrix-sdk-crypto-wasm':
specifier: 18.1.0
version: 18.1.0
'@modelcontextprotocol/sdk':
specifier: 1.29.0
version: 1.29.0(zod@4.3.6)
@@ -107,21 +74,9 @@ importers:
'@napi-rs/canvas':
specifier: ^0.1.89
version: 0.1.92
'@pierre/diffs':
specifier: 1.1.15
version: 1.1.15(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@sinclair/typebox':
specifier: 0.34.49
version: 0.34.49
'@slack/bolt':
specifier: ^4.7.0
version: 4.7.0(@types/express@5.0.6)
'@slack/web-api':
specifier: ^7.15.1
version: 7.15.1
'@whiskeysockets/baileys':
specifier: 7.0.0-rc.9
version: 7.0.0-rc.9(patch_hash=23ec8efe1484afa57c51b96955ba331d1467521a8e676a18c2690da7e70a6201)(audio-decode@2.2.3)(jimp@1.6.1)(sharp@0.34.5)
ajv:
specifier: ^8.18.0
version: 8.18.0
@@ -140,9 +95,6 @@ importers:
croner:
specifier: ^10.0.1
version: 10.0.1
discord-api-types:
specifier: ^0.38.47
version: 0.38.47
dotenv:
specifier: ^17.4.2
version: 17.4.2
@@ -155,21 +107,12 @@ importers:
gaxios:
specifier: 7.1.4
version: 7.1.4
google-auth-library:
specifier: ^10.6.2
version: 10.6.2
grammy:
specifier: ^1.42.0
version: 1.42.0
https-proxy-agent:
specifier: ^9.0.0
version: 9.0.0
ipaddr.js:
specifier: ^2.3.0
version: 2.3.0
jimp:
specifier: ^1.6.1
version: 1.6.1
jiti:
specifier: ^2.6.1
version: 2.6.1
@@ -185,36 +128,18 @@ importers:
markdown-it:
specifier: 14.1.1
version: 14.1.1
matrix-js-sdk:
specifier: 41.3.0
version: 41.3.0
mpg123-decoder:
specifier: ^1.0.3
version: 1.0.3
node-edge-tts:
specifier: ^1.2.10
version: 1.2.10
node-llama-cpp:
specifier: 3.18.1
version: 3.18.1(typescript@6.0.2)
nostr-tools:
specifier: ^2.23.3
version: 2.23.3(typescript@6.0.3)
openai:
specifier: ^6.34.0
version: 6.34.0(ws@8.20.0)(zod@4.3.6)
opusscript:
specifier: ^0.1.1
version: 0.1.1
osc-progress:
specifier: ^0.3.0
version: 0.3.0
pdfjs-dist:
specifier: ^5.6.205
version: 5.6.205
playwright-core:
specifier: 1.59.1
version: 1.59.1
proxy-agent:
specifier: ^8.0.1
version: 8.0.1
@@ -224,9 +149,6 @@ importers:
sharp:
specifier: ^0.34.5
version: 0.34.5
silk-wasm:
specifier: ^3.7.1
version: 3.7.1
sqlite-vec:
specifier: 0.1.9
version: 0.1.9
@@ -321,19 +243,6 @@ importers:
vitest:
specifier: ^4.1.4
version: 4.1.4(@opentelemetry/api@1.9.1)(@types/node@25.6.0)(@vitest/browser-playwright@4.1.4)(@vitest/coverage-v8@4.1.4)(jsdom@29.0.2(@noble/hashes@2.0.1))(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.7)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))
optionalDependencies:
'@discordjs/opus':
specifier: ^0.10.0
version: 0.10.0
'@matrix-org/matrix-sdk-crypto-nodejs':
specifier: ^0.4.0
version: 0.4.0
fake-indexeddb:
specifier: ^6.2.5
version: 6.2.5
music-metadata:
specifier: ^11.12.3
version: 11.12.3
extensions/acpx:
dependencies:
@@ -8730,26 +8639,6 @@ snapshots:
- opusscript
- utf-8-validate
'@buape/carbon@0.16.0(@discordjs/opus@0.10.0)(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(opusscript@0.1.1)':
dependencies:
'@types/node': 25.6.0
discord-api-types: 0.38.45
optionalDependencies:
'@cloudflare/workers-types': 4.20260405.1
'@discordjs/voice': 0.19.2(@discordjs/opus@0.10.0)(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(opusscript@0.1.1)
'@types/bun': 1.3.11
'@types/ws': 8.18.1
ws: 8.20.0
transitivePeerDependencies:
- '@discordjs/opus'
- '@emnapi/core'
- '@emnapi/runtime'
- bufferutil
- ffmpeg-static
- node-opus
- opusscript
- utf-8-validate
'@cacheable/memory@2.0.8':
dependencies:
'@cacheable/utils': 2.4.1
@@ -8918,25 +8807,6 @@ snapshots:
- opusscript
- utf-8-validate
'@discordjs/voice@0.19.2(@discordjs/opus@0.10.0)(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(opusscript@0.1.1)':
dependencies:
'@snazzah/davey': 0.1.11(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)
'@types/ws': 8.18.1
discord-api-types: 0.38.47
prism-media: 1.3.5(@discordjs/opus@0.10.0)(opusscript@0.1.1)
tslib: 2.8.1
ws: 8.20.0
transitivePeerDependencies:
- '@discordjs/opus'
- '@emnapi/core'
- '@emnapi/runtime'
- bufferutil
- ffmpeg-static
- node-opus
- opusscript
- utf-8-validate
optional: true
'@emnapi/core@1.9.2':
dependencies:
'@emnapi/wasi-threads': 1.2.1
@@ -11016,14 +10886,6 @@ snapshots:
- '@emnapi/runtime'
optional: true
'@snazzah/davey-wasm32-wasi@0.1.11(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)':
dependencies:
'@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)
transitivePeerDependencies:
- '@emnapi/core'
- '@emnapi/runtime'
optional: true
'@snazzah/davey-win32-arm64-msvc@0.1.11':
optional: true
@@ -11053,27 +10915,6 @@ snapshots:
- '@emnapi/core'
- '@emnapi/runtime'
'@snazzah/davey@0.1.11(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)':
optionalDependencies:
'@snazzah/davey-android-arm-eabi': 0.1.11
'@snazzah/davey-android-arm64': 0.1.11
'@snazzah/davey-darwin-arm64': 0.1.11
'@snazzah/davey-darwin-x64': 0.1.11
'@snazzah/davey-freebsd-x64': 0.1.11
'@snazzah/davey-linux-arm-gnueabihf': 0.1.11
'@snazzah/davey-linux-arm64-gnu': 0.1.11
'@snazzah/davey-linux-arm64-musl': 0.1.11
'@snazzah/davey-linux-x64-gnu': 0.1.11
'@snazzah/davey-linux-x64-musl': 0.1.11
'@snazzah/davey-wasm32-wasi': 0.1.11(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)
'@snazzah/davey-win32-arm64-msvc': 0.1.11
'@snazzah/davey-win32-ia32-msvc': 0.1.11
'@snazzah/davey-win32-x64-msvc': 0.1.11
transitivePeerDependencies:
- '@emnapi/core'
- '@emnapi/runtime'
optional: true
'@standard-schema/spec@1.1.0': {}
'@swc/helpers@0.5.21':

View File

@@ -194,7 +194,6 @@ export function collectRootDistBundledRuntimeMirrors(params) {
}
export function collectBundledPluginRootRuntimeMirrorErrors(params) {
const rootRuntimeDeps = collectRuntimeDependencySpecs(params.rootPackageJson);
const errors = [];
for (const [dependencyName, record] of params.bundledRuntimeDependencySpecs) {
@@ -205,25 +204,5 @@ export function collectBundledPluginRootRuntimeMirrorErrors(params) {
}
}
for (const [dependencyName, mirror] of params.requiredRootMirrors) {
const rootSpec = rootRuntimeDeps.get(dependencyName);
const importers = [...mirror.importers].toSorted((left, right) => left.localeCompare(right));
const importerLabel = importers.join(", ");
const pluginLabel = mirror.pluginIds
.toSorted((left, right) => left.localeCompare(right))
.join(", ");
if (typeof rootSpec !== "string" || rootSpec.length === 0) {
errors.push(
`root dist imports bundled plugin runtime dependency '${dependencyName}' from ${importerLabel}; mirror '${dependencyName}: ${mirror.spec}' in root package.json (declared by ${pluginLabel}).`,
);
continue;
}
if (rootSpec !== mirror.spec) {
errors.push(
`root dist imports bundled plugin runtime dependency '${dependencyName}' from ${importerLabel}; root package.json has '${rootSpec}' but plugin manifest declares '${mirror.spec}' (${pluginLabel}).`,
);
}
}
return errors;
}

View File

@@ -130,11 +130,13 @@ export function classifyRootDependencyOwnership(record) {
const sections = new Set(record.sections);
if (record.rootMirrorImporters.length > 0) {
return {
category: "extension_only_root_mirror",
recommendation:
"blocked by packaged host graph: remove root mirror only after bundled runtime resolution stops importing it from root dist",
};
if (!sectionSetContainsCore(sections)) {
return {
category: "extension_only_localizable",
recommendation:
"remove from root package.json and rely on owning extension manifests plus doctor --fix",
};
}
}
if (sections.size === 0) {
@@ -169,7 +171,7 @@ export function classifyRootDependencyOwnership(record) {
return {
category: "extension_only_localizable",
recommendation:
"candidate to remove from root package.json and rely on owning extension manifests",
"remove from root package.json and rely on owning extension manifests plus doctor --fix",
};
}

View File

@@ -6,31 +6,34 @@ const packageManifestContractTests: PackageManifestContractParams[] = [
{ pluginId: "bluebubbles", minHostVersionBaseline: "2026.3.22" },
{
pluginId: "discord",
mirroredRootRuntimeDeps: [
pluginLocalRuntimeDeps: [
"@buape/carbon",
"@discordjs/opus",
"@discordjs/voice",
"@snazzah/davey",
"discord-api-types",
"https-proxy-agent",
"opusscript",
],
mirroredRootRuntimeDeps: ["https-proxy-agent"],
minHostVersionBaseline: "2026.3.22",
},
{
pluginId: "feishu",
mirroredRootRuntimeDeps: ["@larksuiteoapi/node-sdk"],
pluginLocalRuntimeDeps: ["@larksuiteoapi/node-sdk"],
mirroredRootRuntimeDeps: ["@sinclair/typebox", "qrcode-terminal"],
minHostVersionBaseline: "2026.3.22",
},
{ pluginId: "google", mirroredRootRuntimeDeps: ["@google/genai"] },
{ pluginId: "google", pluginLocalRuntimeDeps: ["@google/genai"] },
{
pluginId: "googlechat",
mirroredRootRuntimeDeps: ["google-auth-library"],
pluginLocalRuntimeDeps: ["google-auth-library"],
minHostVersionBaseline: "2026.3.22",
},
{ pluginId: "irc", minHostVersionBaseline: "2026.3.22" },
{ pluginId: "line", minHostVersionBaseline: "2026.3.22" },
{
pluginId: "amazon-bedrock",
mirroredRootRuntimeDeps: [
pluginLocalRuntimeDeps: [
"@aws-sdk/client-bedrock",
"@aws-sdk/client-bedrock-runtime",
"@aws-sdk/credential-provider-node",
@@ -38,34 +41,73 @@ const packageManifestContractTests: PackageManifestContractParams[] = [
},
{
pluginId: "amazon-bedrock-mantle",
mirroredRootRuntimeDeps: ["@aws/bedrock-token-generator"],
pluginLocalRuntimeDeps: ["@aws/bedrock-token-generator"],
},
{
pluginId: "diffs",
pluginLocalRuntimeDeps: ["@pierre/diffs", "@pierre/theme", "playwright-core"],
mirroredRootRuntimeDeps: ["@sinclair/typebox"],
},
{
pluginId: "matrix",
pluginLocalRuntimeDeps: [
"@matrix-org/matrix-sdk-crypto-nodejs",
"@matrix-org/matrix-sdk-crypto-wasm",
"fake-indexeddb",
"matrix-js-sdk",
"music-metadata",
],
mirroredRootRuntimeDeps: ["markdown-it"],
minHostVersionBaseline: "2026.3.22",
},
{ pluginId: "matrix", minHostVersionBaseline: "2026.3.22" },
{ pluginId: "mattermost", minHostVersionBaseline: "2026.3.22" },
{
pluginId: "memory-lancedb",
mirroredRootRuntimeDeps: ["@lancedb/lancedb", "openai"],
pluginLocalRuntimeDeps: ["@lancedb/lancedb"],
mirroredRootRuntimeDeps: ["@sinclair/typebox", "openai"],
minHostVersionBaseline: "2026.3.22",
},
{
pluginId: "msteams",
pluginLocalRuntimeDeps: [
"@azure/identity",
"@microsoft/teams.api",
"@microsoft/teams.apps",
"jsonwebtoken",
"jwks-rsa",
],
mirroredRootRuntimeDeps: ["@sinclair/typebox", "express"],
minHostVersionBaseline: "2026.3.22",
},
{ pluginId: "msteams", minHostVersionBaseline: "2026.3.22" },
{ pluginId: "nextcloud-talk", minHostVersionBaseline: "2026.3.22" },
{ pluginId: "nostr", minHostVersionBaseline: "2026.3.22" },
{
pluginId: "nostr",
pluginLocalRuntimeDeps: ["nostr-tools"],
minHostVersionBaseline: "2026.3.22",
},
{ pluginId: "openshell", pluginLocalRuntimeDeps: ["openshell"] },
{
pluginId: "qqbot",
pluginLocalRuntimeDeps: ["mpg123-decoder", "silk-wasm"],
mirroredRootRuntimeDeps: ["ws"],
},
{
pluginId: "slack",
mirroredRootRuntimeDeps: ["@slack/bolt", "@slack/web-api", "https-proxy-agent"],
pluginLocalRuntimeDeps: ["@slack/bolt", "@slack/web-api"],
mirroredRootRuntimeDeps: ["https-proxy-agent"],
},
{ pluginId: "synology-chat", minHostVersionBaseline: "2026.3.22" },
{
pluginId: "telegram",
mirroredRootRuntimeDeps: ["@grammyjs/runner", "@grammyjs/transformer-throttler", "grammy"],
pluginLocalRuntimeDeps: ["@grammyjs/runner", "@grammyjs/transformer-throttler", "grammy"],
},
{ pluginId: "tlon", minHostVersionBaseline: "2026.3.22" },
{ pluginId: "twitch", minHostVersionBaseline: "2026.3.22" },
{ pluginId: "voice-call", minHostVersionBaseline: "2026.3.22" },
{
pluginId: "whatsapp",
mirroredRootRuntimeDeps: ["@whiskeysockets/baileys", "jimp"],
pluginLocalRuntimeDeps: ["@whiskeysockets/baileys", "jimp"],
mirroredRootRuntimeDeps: ["qrcode-terminal"],
minHostVersionBaseline: "2026.3.22",
},
{ pluginId: "zalo", minHostVersionBaseline: "2026.3.22" },

View File

@@ -1,7 +1,6 @@
import { readdirSync, readFileSync } from "node:fs";
import { createRequire } from "node:module";
import { dirname, join, relative, resolve } from "node:path";
import { fileURLToPath, pathToFileURL } from "node:url";
import { fileURLToPath } from "node:url";
import { describe, expect, it } from "vitest";
import { pluginSdkEntrypoints } from "../../plugin-sdk/entrypoints.js";
@@ -77,10 +76,6 @@ function collectRuntimeDependencySpecs(packageJson: {
]);
}
function createRootPackageRequire() {
return createRequire(pathToFileURL(resolve(REPO_ROOT, "package.json")).href);
}
function collectExtensionFiles(dir: string): string[] {
const entries = readdirSync(dir, { withFileTypes: true });
const files: string[] = [];
@@ -163,7 +158,7 @@ describe("plugin-sdk package contract guardrails", () => {
expect(failures).toEqual([]);
});
it("mirrors package runtime deps needed by bundled host graphs", () => {
it("keeps Matrix runtime deps local to the Matrix plugin", () => {
const rootRuntimeDeps = collectRuntimeDependencySpecs(readRootPackageJson());
const matrixPackageJson = readMatrixPackageJson();
const matrixRuntimeDeps = collectRuntimeDependencySpecs(matrixPackageJson);
@@ -174,21 +169,12 @@ describe("plugin-sdk package contract guardrails", () => {
"fake-indexeddb",
"matrix-js-sdk",
]) {
expect(rootRuntimeDeps.get(dep)).toBe(matrixRuntimeDeps.get(dep));
expect(matrixRuntimeDeps.get(dep)).toBeDefined();
expect(rootRuntimeDeps.has(dep)).toBe(false);
}
expect(rootRuntimeDeps.has("@openclaw/plugin-package-contract")).toBe(false);
});
it("resolves matrix crypto WASM from the root runtime surface", () => {
const rootRequire = createRootPackageRequire();
// Normalize filesystem separators so the package assertion stays portable.
const resolvedPath = rootRequire
.resolve("@matrix-org/matrix-sdk-crypto-wasm")
.replaceAll("\\", "/");
expect(resolvedPath).toContain("@matrix-org/matrix-sdk-crypto-wasm");
});
it("keeps extension sources on public sdk or local package seams", () => {
expect(collectExtensionCoreImportLeaks()).toEqual([]);
});

View File

@@ -170,7 +170,7 @@ describe("collectInstalledMirroredRootDependencyManifestErrors", () => {
writeFileSync(fullPath, `${JSON.stringify(value, null, 2)}\n`, "utf8");
}
it("flags missing root mirrors for bundled plugin deps imported by root dist", () => {
it("does not require root mirrors for bundled plugin deps imported by root dist", () => {
const packageRoot = makeInstalledPackageRoot();
try {
@@ -190,9 +190,7 @@ describe("collectInstalledMirroredRootDependencyManifestErrors", () => {
"utf8",
);
expect(collectInstalledMirroredRootDependencyManifestErrors(packageRoot)).toEqual([
"root dist imports bundled plugin runtime dependency '@slack/web-api' from probe-Cz2PiFtC.js; mirror '@slack/web-api: ^7.15.0' in root package.json (declared by slack).",
]);
expect(collectInstalledMirroredRootDependencyManifestErrors(packageRoot)).toEqual([]);
} finally {
rmSync(packageRoot, { recursive: true, force: true });
}
@@ -226,7 +224,7 @@ describe("collectInstalledMirroredRootDependencyManifestErrors", () => {
}
});
it("flags root mirror dependency version mismatches", () => {
it("does not compare root mirror dependency versions", () => {
const packageRoot = makeInstalledPackageRoot();
try {
@@ -248,9 +246,7 @@ describe("collectInstalledMirroredRootDependencyManifestErrors", () => {
"utf8",
);
expect(collectInstalledMirroredRootDependencyManifestErrors(packageRoot)).toEqual([
"root dist imports bundled plugin runtime dependency '@slack/web-api' from probe-Cz2PiFtC.js; root package.json has '^7.16.0' but plugin manifest declares '^7.15.0' (slack).",
]);
expect(collectInstalledMirroredRootDependencyManifestErrors(packageRoot)).toEqual([]);
} finally {
rmSync(packageRoot, { recursive: true, force: true });
}

View File

@@ -192,7 +192,7 @@ describe("bundled plugin root runtime mirrors", () => {
}
});
it("flags missing root mirrors for plugin deps imported by root dist", () => {
it("does not require root mirrors for plugin deps imported by root dist", () => {
expect(
collectBundledPluginRootRuntimeMirrorErrors({
bundledRuntimeDependencySpecs: makeBundledSpecs(),
@@ -208,12 +208,10 @@ describe("bundled plugin root runtime mirrors", () => {
]),
rootPackageJson: { dependencies: {} },
}),
).toEqual([
"root dist imports bundled plugin runtime dependency '@larksuiteoapi/node-sdk' from probe-Cz2PiFtC.js; mirror '@larksuiteoapi/node-sdk: ^1.60.0' in root package.json (declared by feishu).",
]);
).toEqual([]);
});
it("flags root mirror version drift from plugin manifests", () => {
it("does not compare root mirror versions for plugin manifest deps", () => {
expect(
collectBundledPluginRootRuntimeMirrorErrors({
bundledRuntimeDependencySpecs: makeBundledSpecs(),
@@ -229,9 +227,7 @@ describe("bundled plugin root runtime mirrors", () => {
]),
rootPackageJson: { dependencies: { "@larksuiteoapi/node-sdk": "^1.61.0" } },
}),
).toEqual([
"root dist imports bundled plugin runtime dependency '@larksuiteoapi/node-sdk' from probe-Cz2PiFtC.js; root package.json has '^1.61.0' but plugin manifest declares '^1.60.0' (feishu).",
]);
).toEqual([]);
});
it("accepts matching root mirrors for plugin deps imported by root dist", () => {

View File

@@ -18,16 +18,16 @@ describe("collectModuleSpecifiers", () => {
});
describe("classifyRootDependencyOwnership", () => {
it("treats root-dist bundled runtime mirrors as blocked extension deps", () => {
it("treats root-dist bundled runtime imports as localizable extension deps", () => {
expect(
classifyRootDependencyOwnership({
sections: ["extensions"],
rootMirrorImporters: ["discovery-DZDwKJdJ.js"],
}),
).toEqual({
category: "extension_only_root_mirror",
category: "extension_only_localizable",
recommendation:
"blocked by packaged host graph: remove root mirror only after bundled runtime resolution stops importing it from root dist",
"remove from root package.json and rely on owning extension manifests plus doctor --fix",
});
});
@@ -52,7 +52,7 @@ describe("classifyRootDependencyOwnership", () => {
).toEqual({
category: "extension_only_localizable",
recommendation:
"candidate to remove from root package.json and rely on owning extension manifests",
"remove from root package.json and rely on owning extension manifests plus doctor --fix",
});
});