Skip to content

fix(profile-compat): 按 generation 目录解析插件同级依赖,消除误报的 blocking 兼容问题 - #566

Open
1kUnD0G wants to merge 1 commit into
dataelement:mainfrom
1kUnD0G:fix/profile-compat-generation-layout
Open

1kUnD0G wants to merge 1 commit into
dataelement:mainfrom
1kUnD0G:fix/profile-compat-generation-layout

Conversation

@1kUnD0G

@1kUnD0G 1kUnD0G commented Sep 25, 2026

Copy link
Copy Markdown

问题

真机复现(DSH Desktop 0.9.2 / 内核 0.1.5-rc.2,Windows 11):安装 dsh-better-sidebar 后,inspectProfileCompatibility 连续报出 35 个 missing-client-module(severity: blocking),日志反复出现:

[plugin-recovery] normal mode remains blocked by 35 profile compatibility issues after upgrade

normal mode 被永久卡在 safe mode,第三方插件全部被封禁。

被判定“缺失”的包全部来自 dsh-better-sidebar → mermaid 的依赖(@types/d3*、@mermaid-js/parser、@chevrotain/types、@upsetjs/venn.js、@types/geojson 等),但它们在磁盘上都存在:

harness/profiles/.generations/live/dsh-better-sidebar+0.21.1+.../node_modules/@types/d3/package.json  ✓

根因

generation 插件的真实目录是 <generation>/node_modules/<plugin>(pnpm 布局),其依赖全部是同级目录,既不嵌套在插件下、也不平铺在 profile 里。而 componentManifest 只查两处:

  1. pluginDir/node_modules/<pkg> — npm 嵌套布局
  2. profiles/web/node_modules/<pkg> — 平铺布局

兜底 resolvesFrom 用 CJS require.resolve(<pkg>) 探测,对两类包必然失败:

  • @types/*:无 JS 入口 → MODULE_NOT_FOUND
  • @mermaid-js/parser / @chevrotain/types:exports 不含 require 条件 → ERR_PACKAGE_PATH_NOT_EXPORTED

于是“明明存在”的同级依赖被判为 not installed in this profile → blocking → 永久 safe mode。

本机实测(直接调用 inspectProfileCompatibility):

activePlugins: ["@liustack/modlens", "dsh-better-sidebar"]
total: 35  blocking: 35  byKind: {"missing-client-module/blocking": 35}
全部 source = "dsh-better-sidebar dependency tree"

对每个包单独验证:require.resolve('@types/d3') 从插件目录 MODULE_NOT_FOUND,而 dirname(pluginDir)/@types/d3/package.json 存在。

修复

新增 componentDirectory() 三段解析:嵌套 → 平铺 → generation 同级(dirname(pluginDir)/<pkg>),componentManifest 与 componentDir 统一复用同一路径。真正缺失的依赖行为不变——三处都找不到时仍回退到平铺路径,readManifest 返回 undefined,原有 blocking 判定照旧。

测试

  • 新增回归用例 accepts generation siblings for a pnpm-laid-out plugin instead of flagging them as missing:
    • 无入口的类型包(同级存在)→ 不再误报
    • 真正不存在的 ghost-kit → 仍报 blocking(防止过度抑制)
    • 修复前红(1 failed),stash 修复后复跑绿(8 passed)
  • test/profile-compatibility.test.ts:8/8 ✅
  • test/plugin-recovery-market.test.ts:8/8 ✅
  • tsc --noEmit -p tsconfig.node.json ✅
  • 全量 vitest run 中另有若干失败(image-generation / feishu-release-notes / github-release-notes / ppt tar 路径 / generation-build-approval),均为 Windows 本地环境既有问题,与本改动无关(这些文件不引用 profile-compatibility)。

关联

同类 generation false-positive 先例:#293

pnpm generation 布局将插件的全部依赖放在 <generation>/node_modules
下作为同级目录,而 componentManifest 只查插件内嵌与 profile 平铺两处,
兜底的 CJS require.resolve 对无 JS 入口的类型包(@types/*)以及 exports
不含 require 条件的纯 ESM 包必然失败,导致本机 dsh-better-sidebar →
mermaid 的 35 个依赖被误报为 missing-client-module(blocking),
normal mode 被永久卡在 safe mode。

新增 componentDirectory 三段解析(嵌套 → 平铺 → generation 同级),
manifest 与 componentDir 统一复用同一路径;真正缺失的依赖仍保持原有
blocking 判定不变。

回归测试覆盖 generation 布局 + 无入口类型包不再误报、幽灵依赖仍报
缺失(修复前红、修复后绿),profile-compatibility 与
plugin-recovery-market 两个测试文件全部通过,tsc --noEmit 通过。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant