Files
dsh_ai1net_server/交付物/插件数据面取数口-真机验收与接线缺陷-20260925.md
T
admin 318430c9e9 chore(工作区): 插件投放与分库线收口入库(第 35 棒 + 22:44 拍板落盘)
范围 = 本线(插件投放与分库线)产物 + 记忆类,共 27 件:
- 接续入口_插件投放与分库线(1 件):§0 新增 22:44 拍板行;§2 第 36 棒范围改 5 步、条件步转无条件
- 交付物(22 件):MCN 数据面接入阶段一/阶段二系列(含 B 案落地与 shadow 读数)、
  P0 修通与移动端真机验收、pnpm-EPERM、两机 lib 差异、共享层台账语义、
  基础插件身份与回滚、插件接入验收、插件数据面取数口、移动端迁包与字号扩面、跨机错误消息
- 记忆(4 件):2026-09-24 / 2026-09-25 日志、MEMORY.md、本棒 automation 执行记录

⛔ 未含他线在途改动(只报告、不代提交):机制层 CODEBUDDY.md / state.py /
.codebuddy/rules/server-ops.md、接续入口_IM线、接续入口_StoryForge验收线、
其余 29 个 automation 目录、docs/规则与载体/、归档/、接续包_*。
2026-09-25 23:06:29 +08:00

10 KiB
Raw Blame History

插件数据面取数口 · 47 真机验收 + 抓出接线缺陷(2026-09-25 · 第 15 棒)

一句话:把第 14 棒落地的「运行时取数口」部署到 47 并真机跑通(四拒一空 + 回读 7/7 PASS), 过程中抓出一条会让取数口对全部插件失效的接线缺陷(已修 + 已复验); 第 2 件(MCN 移动端视觉验收)未通过 —— 前提不成立:移动端修复落在未投放的包里。 归属线:插件投放与分库线|会话:插件投放与分库线-第15棒|交接单:无(本棒为执行棒)


一、本轮做了什么

# 事项 结果
0 开工门禁 + 域锁 preflight 判【D】2 个 → 归类后抢锁成功(域 aliyun-dsh-server/接续入口_插件投放与分库线_20260922.md + aliyun-dsh-server/.workbuddy)
1 部署取数口到 47 ✅ 5/5 md5 逐字一致 + restart dshs + 服务 active、门户 200
2 数据面取数真机验收 ✅ 7/7 PASS(四拒 + 一空 + insert→find 回读;归属列真值直连核)
3 抓出并修复接线缺陷 ✅ 已修 src/web/routes/plugin-data.ts + 重投 + 复验
4 MCN 移动端视觉验收 🔴 未通过 —— 前提不成立(修复不在已投放的包里,详见 §五)
5 夹具清理 ✅ 零残留(池 5 / 插件库 0 / 台账 0 / 会话 0 / tgz 已删)

二、部署面证据(47 · /opt/dshs)

文件 47 与本地 md5 说明
lib/web/server.js fcbbb9b3476499ba2d97841f0e6ebaed 与 47 原版只差 7 行(就是 pluginDataRoutes 的 import + register +注释)—— 已逐行 diff 确认
lib/db/plugin-data/runtime.js 45daf7c5b2b6163e3d1e1fd110dca36d 新增
lib/db/plugin-data/registry.js 44d3b5c424f7bc27a930454a945f6f06 新增
lib/web/routes/plugin-data.js a03394088f4ad90e571d4b5ede7a5f95 → 修复后 fac8f4dfe0d5710705de6d614275c77e 新增 → 修复
sdk/im-plugin-client/index.mjs 4a1a160156a90cc07696332fcc99d0cd 新增(落 /opt/dshs/sdk/)
  • 备份:/opt/dsh/backups/lib-p15/47-pre-p15-20260925-074345.tgz(投放前)。
  • 重启:systemctl restart dshs → active、NRestarts=0、门户 200。
  • 部署前先做了漂移比对(避免把别的棒的东西带上线):business-plugins.js / worker/agent.js / leased-spawner.js / config.js 四件与本地逐字一致 ⇒ 只投必要项。
  • ⚠️ 106 未部署(本轮范围 = 47;取数口是 Manager 侧路由 ⇒ 106 不影响本轮验收)。

三、真机验收读数(47 · 调用者 = guest,插件身份头 = 包名)

夹具 = 一次性探测包 dsh-plugin-pdprobe(user 域 + room 域各一表;声明过平台真校验器 → level=ok)。

断言 期望 实测(HTTP 200 + 契约体)
① 写他人 user_id 拒 ok:false, reason:bad-args,detail=不得写入他人的 user_id(归属列由内核注入)
② room 表缺 room_id 拒 ok:false, reason:bad-args,detail=房间维度表必须带 room_id
③ 缺主键列 拒 ok:false, reason:bad-args,detail=缺少主键列「probe_key」(它是本表的行标识)
④ 带 created_at 拒 ok:false, reason:bad-args,detail=审计列「created_at」由内核维护,⛔ 不可自写
⑤ 非成员读 room 表 0 行 ok:true,value:[] ⇒ 0 行
⑥ insert 正常行 ok ok:true
⑦ find 回读一致 1 行且字段一致 ok:true,value 1 行,note='v1'、payload={a:1}

归属注入直连核(不靠响应自证):p_dsh_plugin_pdprobe_probe_user.user_id 全部等于 调用者本人 4092b965-…;probe_room 行数 = 0。

DDL 侧证(迁移回显):PRIMARY KEY ("user_id", "probe_key") ⇒ id = 声明第一列、归属列 + 第一列 复合键 (无代理自增 id)—— 与 DB-03 §五 口径一致,首次在真机上被看见。

对照(负例):给无声明的真插件取数 ⇒ 409 plugin-data-unavailable / no-declaration(不是 500,不是"假装成功")。


四、🔴 抓出的接线缺陷(P0 级 · 已修 + 已复验)

现象:库建好(state=ready)、插件身份头合法、鉴权通过 —— 但取数一律 409 no-declaration:插件「dsh_plugin_pdprobe」不在候选池或包内无数据面声明。

根因(两个名字空间被混用):

名字空间 取值 谁在用
池键 / 台账键 原始包名:dsh-plugin-pdprobe、@dsh-local/storyforge business_plugins.id、plugin_datastores.plugin_id(建库口、门户都用它)
pluginId(归一化) 去 scope + 下划线化:dsh_plugin_pdprobe pluginIdOf();用于算库名/表名前缀

取数口把归一化后的 id 交给了 PluginDataRegistry,而 registry 内部拿这个值去 findBusinessPlugin / findPluginDatastore 精确查这两张表 ⇒ 永远查不到 ⇒ 任何插件调取数口都只会得到 no-declaration(不是这一个夹具的问题)。

为什么单测没抓到:test/plugin-data-runtime.test.mjs 用假执行器,直接构造声明对象, 绕过了路由层的 id 归一化 ⇒ 这条路径只有在真机上才会被走到。

修法(最小):src/web/routes/plugin-data.ts 两处

  • resolvePluginPort:pluginId: pluginIdOf(pkgName) → pluginId: pkgName(原始包名)
  • /plugin-data/status:查表用原始包名,对外仍回归一化 pluginId(响应契约不变)

复验:npm run build rc=0|node --test test/plugin-data-runtime.test.mjs test/im-plugin-client.test.mjs → 24/24 过 |重投 + 重启 → 7/7 PASS(同 §三)。

⛔ 未 commit / 未 push(遵守本棒约束);改动留在 D:/github/dsh_shenxian 工作树(plugin-data.ts)。


五、🔴 第 2 件(MCN 移动端视觉验收)—— 未通过:前提不成立

验收目标(入口 §2 原文):D:/dshworkspace/plugin_package/dsh-plugin-mcn/lib/client.js 的 mcn-mobile 样式段 → 375×667 下工作台独占、能退出、无横向溢出、聚焦不缩放、横屏可用。

真机取证(为什么做不了):

检查 结果
线上真身是哪个包 池与共享层里的都是 dsh-plugin-mcn-suite v0.3.13(/var/lib/dshs/bundled-plugins/dsh-plugin-mcn-suite)
该真身含修复吗 否 —— lib/client.js 里 mcn-mobile 命中数 = 0(mcnNav_split = 4)
本地 suite 含修复吗 否 —— 本地 dsh-plugin-mcn-suite/lib/client.js(0.3.13 · mtime 09-20 22:12)mcn-mobile = 0
修复改在哪个包 dsh-plugin-mcn v0.1.0(本地 lib/client.js mtime 09-25 05:18)—— 该包从未投放

⇒ 移动端修复改在了「不是线上真身」的包里。所以"重投插件 + 实例重启"无从生效: 线上跑的一直是 suite,它里面没有这段样式。故本件不做视觉验收,也不宣称通过(无真机读数不得宣称)。

整改路径(可机械执行 —— 已核对可移植性): mcn-mobile 段是一段运行时注入的 <style>(document.head.appendChild,data-plugin-css="mcn-mobile"), 选择器全部是 .mcnNav_* / vvModal 族。已逐个核对它在 suite 里的存在性:

.mcnNav_split .mcnNav_panel .mcnNav_resizer .mcnNav_close .mcnNav_btn .mcnNav_mask .mcnNav_modal .mcnNav_stats .mcnNav_input vvModal
4 3 3 2 12 3 10 2 2 2

⇒ 类名齐备 ⇒ 可整段平移(把同一段注入进 suite 的 lib/client.js,dataset.plugin 改成 suite 名)。 ⚠️ 重投前必须先验本地 suite 与线上 suite 逐字一致(否则会把别的漂移一起发出去); ⚠️ 版本要自增(0.3.13 → 0.3.14)并同步 lib/skills-installer.js 的 SUITE_VERSION 与 skills/.manifest.json(该包「版本号唯一真源」口径)。


六、第 3 件(可选 · MCN 数据面接入改造)—— 未做

超本轮范围(lib/db.js 红线扫描 21 处、且须「先建库再投放」)。按入口 §2 的口径留给后续棒。


七、清理与零残留(夹具全清)

项 清理后读数
候选池 5(回到原值,夹具行 0)
插件库 dshs_pl_* 0
plugin_datastores 0
plugin_data_audit(夹具) 0
临时会话(poc-curl2) 0
夹具 tgz / 备份目录 已删
服务 active

⚠️ 夹具在池内存活约 2 分钟(07:56–07:59 量级),期间登录用户理论上可在「功能管理」看到它 —— 已删除,无残留。这是本轮唯一一处对线上可见面的临时触碰,主动记录。


八、未闭环 / 下一棒

  1. 🔴 MCN 移动端修复的「迁包 + 重投 + 375×667 视觉验收」(见 §五)—— 本线唯一排定的下一棒。
  2. 跨节点形态:worker 上的实例 → Manager 侧数据面仍缺「实例→控制面」身份通道 (本轮验收是同机/本机形态)⇒ 属既有缺口(DB-03 §六 自认),未动。
  3. 106 未部署本轮产物(Manager 侧路由,不影响本轮验收)。

九、可复现命令

# 部署(三件产物 + server.js)
scp lib/web/server.js bt-server:/opt/dshs/lib/web/server.js
scp lib/db/plugin-data/{runtime,registry}.js bt-server:/opt/dshs/lib/db/plugin-data/
scp lib/web/routes/plugin-data.js bt-server:/opt/dshs/lib/web/routes/
ssh bt-server 'systemctl restart dshs'

# 验收(夹具搭建 + 7 条断言 + 零残留清理)
scp tmp/15棒-夹具/dsh-plugin-pdprobe-0.0.1.tgz bt-server:/var/lib/dshs/business-plugins/
scp tmp/15棒-夹具/pd-probe-47b.mjs bt-server:/tmp/   # 或第 15 棒工作区 tmp/15棒-夹具/
ssh bt-server '/usr/local/bin/node /tmp/pd-probe-47b.mjs'
ssh bt-server 'bash -s' < tmp/15棒-夹具/remote-cleanup.sh