345 lines
41 KiB
Markdown
345 lines
41 KiB
Markdown
# T03 · 把 `plugin_package` 7 个自研插件整合为 1 个功能插件并投放
|
||||
|
|
|
|||
|
|
- 日期:2026-09-12
|
|||
|
|
- 状态:✅ **已完成并归档(2026-09-13 18:0x)** —— 投放链路全通(上传 → admin 装 → **guest 启用** → 实例重启探活成功);主体验收通过。收尾记录见 **§十**
|
|||
|
|
|
|||
|
|
> ⛔ **2026-09-13 09:4x 现场取证:这一步已被试过,但被平台自动回滚了。**
|
|||
|
|
> guest 在 **07:42:52** 通过「功能管理」提交了启用(`POST /api/plugins/mine/apply`,任务 `c8ac2686539aeb7c`),
|
|||
|
|
> 随后实例 **07:43–07:45 连崩 5 次**(`exitCode=134`,栈 = V8 `JsonParser`/`HeapAllocator` ⇒ **V8 堆打满 abort**),
|
|||
|
|
> 07:46 触发熔断,平台**自动回滚**(`package.json.bak-rollback-20260913T0748`)⇒ 现在 guest bundles 里**没有** mcn-suite。
|
|||
|
|
> **根因指向 `--max-old-space-size=160` 太紧**(档案 74 的下调)+ guest cgroup 峰值已 **382/384 MiB**
|
|||
|
|
> ⇒ **先把内存预算调上去(需重启窗口),再重试启用**。详见 `04-调整方案/74` 文末「现场反证」。
|
|||
|
|
|
|||
|
|
**原状态行**:⏳ **待续做(2026-09-13 07:3x 复核更正)** —— **步骤 1–9 已完成,且「上传候选池」亦已完成**(现行池内 = `dsh-plugin-mcn-suite @0.3.9`,09-13 00:02 上传;**admin 侧已装 0.3.9 且 host 面 3 个注册加载通过**),**剩**:**`guest` 侧在实例「功能管理」启用**(`POST /api/plugins/mine/apply` —— **用户动作,平台不代劳**)→ 重启实例 → §八验收 → 归档。**2026-09-12 14:55 已释放占用锁**(原 `exec-session-B`),接手者**直接续做**;产物与验收证据见 `交接单/README.md §一` 的 T03 行。
|
|||
|
|
|
|||
|
|
> **🔎 只读核查结论(2026-09-12 20:2x)—— 执行前的三个事实**
|
|||
|
|
> ① **候选池里只有 `dsh-univer-office`(39.9 MB)** ⇒ §七 防线②"下架旧 7 包"**实际无需做**:那 7 个包**从未上架过候选池**,不存在新旧并存。
|
|||
|
|
> ② **guest 的 `profile/web` bundles = `base / dsh-web-app / business-plugins / portal-entry / workspace-scoped-picker / @liustack/modlens / dsh-univer-office`** ⇒ **不含任何旧包** ⇒ §七 头号风险(新旧并存 → `duplicate loader entry id` 崩实例)**在本单不成立**,切换顺序可简化。
|
|||
|
|
> ③ **时机未到**:guest 活动实测 —— `ws/MCN短视频创作` mtime = **20:06**、`sessions` mtime = **20:02**(距核查 13–17 分钟)⇒ 判定**活跃中**,按 **R8「能避开活跃时段就避开」** 暂缓"启用 + 重启"。上传(零影响)与启用(断 guest ~1 分钟)**同窗口做更安全**(避免为"上传"单独占一次 op-lock),故**整体等待空闲窗口**(判据:最近 30 分钟无活动)。
|
|||
|
|
>
|
|||
|
|
> ⚠️ **同窗口须一并处理**:guest 的 bundles 里仍挂着 **`@liustack/modlens`** —— 该包今天已从候选池下架(档案 70 收尾),但用户 profile **仍启用它**(包文件尚在 `node_modules/@liustack/modlens`,故当前不致命)。这是"**已下架却仍启用**"的不一致态 ⇒ **与 T03 共用同一次重启窗口摘除**(从 bundles 移除 + 重启),避免两次中断用户。
|
|||
|
|
|
|||
|
|
### ✅ 上线进展(2026-09-12 22:0x)
|
|||
|
|
|
|||
|
|
| 步 | 结果 |
|
|||
|
|
|---|---|
|
|||
|
|
| ① 首传 0.3.0 | ❌ **被 T05 兼容性预检拒收**(HTTP 409 `compat_incompatible`)—— 判据 `@deepseek-ai/dsh-client-ui-sidebar@^0.1.0-rc.5` vs 平台 `0.1.2-rc.1`。**根因是 semver 的 prerelease 规则**:带 prerelease 的版本只能被「**同 major.minor.patch 且带 prerelease**」的比较器匹配,`^0.1.0-rc.5` 里没有 tuple `(0,1,2)` 的比较器 ⇒ 判不满足。**不是误报,是声明写窄了**(且 T05 16:35 才上线,而包 11:15 打的,单子当时没这道关) |
|
|||
|
|
| ② 修正 + 重传 | ✅ **HTTP 200**,`compat.level = ok`、`findings[]` 空。改法:3 个 `dsh-client-*` peer 范围 → **`^0.1.2-rc.1`**(跟随平台版本);版本号 **0.3.0 → 0.3.1**;`npm pack` 重打包 → md5 **`adcb134e…`** / 322 条目。**内容与 0.3.0 逐项对齐**:`SKILL.md` 18=18、`lib/` 文件 19=19、`web/` 1=1(条目数差异纯属 `npm pack` 不写目录条目) |
|
|||
|
|
| ③ 候选池 | 现 **2 条**(09-13 07:3x 复核):`dsh-plugin-mcn-suite @0.3.9`(09-13 00:02;admin 已装并验通,**guest 未启用**)+ `dsh-univer-office @0.2.15`(09-12 23:19,fork 版)|历史:曾为 `@0.3.1` + `@0.2.14`,`@liustack/modlens` 与 `anysearch` 已下架 |
|
|||
|
|
| ④ 剩余 | **`guest` 在实例「功能管理」里启用**(`POST /api/plugins/mine/apply` —— **用户动作,平台不代劳**)→ 重启 → §八 验收 → 归档。~~同窗口一并摘 `@liustack/modlens`~~ **已消解**(09-13 07:0x 实测:guest `bundles` 与 `node_modules` 均已无该包)|
|
|||
|
|
|
|||
|
|
> ⚠️ **给接手人的两条提醒**
|
|||
|
|
> 1. **上传前必过兼容性预检**(`POST /api/plugins/business` 会 409);`trust` 只用于"已人工确认后放行",别拿它盖住声明问题。
|
|||
|
|
> 2. **peer 版本范围必须跟随平台 dsh 版本**(当前 `0.1.2-rc.1`)—— 平台升版时同步改,否则 prerelease 规则会再次拒收。插件源码**并不 import** 这些包(只靠 `dsh.client.inject` 注入点),所以放宽范围无功能风险。
|
|||
|
|
- 触发:用户「**规划 `D:\dshworkspace\plugin_package` 整合成一个插件,可打包后由 admin 整体上传到 dsh 服务器插件,用户可以启用进行使用**」
|
|||
|
|
- 关联:档案 16(插件三层归属 + 投放/启停流程)、27(MCN 插件平台化评估,P0 清单来源)、34(启用探活 + 快照回滚)、36/38(铺开链路)、41(技能启停 API)、58(实例内存配额)、60(分区改名「功能管理」)、19 §C6 + 41(上传安全扫描)
|
|||
|
|
- 规划会话边界:本单由**规划会话**产出,只读普查了本机 `D:\dshworkspace\plugin_package`(未 ssh、未改码)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 一、目标
|
|||
|
|
|
|||
|
|
把 `D:\dshworkspace\plugin_package` 下的 **7 个自研插件整合成 1 个功能插件包**:admin 在门户一次性上传候选池 → 用户在实例设置「**功能管理**」分区启用一次 → 重启实例 → **全部功能可用**。
|
|||
|
|
|
|||
|
|
**做完的判定**:一个**全新用户**启用该整合包并重启后,侧边栏入口 + 工作台各功能页逐个可用,journald 无 `duplicate loader entry id`、无崩溃循环;**并且业务技能随包自动就位**(见 §4.1)—— `$DSH_HOME/skills/` 出现 `mcn-short-video` 与 4 个业务子技能,**用户不需要另外上传或启用技能**。
|
|||
|
|
|
|||
|
|
## 二、现状(2026-09-12 只读普查结论)
|
|||
|
|
|
|||
|
|
| 包 | loader id | 体积 | client 行 | host 行 | 角色 |
|
|||
|
|
|---|---|---|---|---|---|
|
|||
|
|
| `dsh-plugin-mcn` | `mcn-nav` | 945K | **3045** | 3095 + 9 模块 | **宿主壳**(唯一声明 `dsh.client.inject=[runtime, sidebar]`) |
|
|||
|
|
| `dsh-plugin-douyin-accounts` | `douyin-accounts` | 55K | 666 | **9(空壳)** | 功能页 |
|
|||
|
|
| `dsh-plugin-douyin-account-detail` | `douyin-account-detail` | 67K | 877 | **9(空壳)** | 功能页 |
|
|||
|
|
| `dsh-plugin-douyin-video-detail` | `douyin-video-detail` | 39K | 496 | **9(空壳)** | 功能页 |
|
|||
|
|
| `dsh-plugin-mcn-schedule` | `mcn-schedule` | 54K | 253 | 483 | 功能页 + 定时任务 |
|
|||
|
|
| `dsh-plugin-social-workbench` | `social-workbench` | 37K | 150 | 218 | 外部服务守护(**Windows 本地**) |
|
|||
|
|
| `dsh-plugin-voxemw-cloud` | `voxemw-cloud` | 77K | 134 | 233 + 6 模块 + `web/app.html` | 云 API 面板 |
|
|||
|
|
|
|||
|
|
### 2.1 结构性结论(**这是"必须整合"的真正理由**)
|
|||
|
|
|
|||
|
|
**它不是 7 个平行插件,而是「1 个宿主壳 + 6 个功能页」。**
|
|||
|
|
|
|||
|
|
- `dsh-plugin-mcn` 注册了 **25+ 条 `/mcn/api/*` HTTP 路由**、`inject = ["slots","sessions"]`、在 `sidebar.footer.action` 注册唯一入口,并提供两个**全局扩展点**:
|
|||
|
|
- `window.__mcnEntries` —— **功能页注册表**(工作台首屏图标网格读它渲染,源注释写明"外部插件注册的功能入口,即插即用")
|
|||
|
|
- `window.__mcnNav` —— **页内路由**(`open(entryId, params)` / `openView(id)` / `back()`)
|
|||
|
|
- 其余 6 个包**全靠往 `__mcnEntries` 注册 + 被 `__mcnNav.open()` 打开**;三个 douyin 包的 host 面只有 **9 行空壳**,注释原文写着"数据复用 `dsh-plugin-mcn` 服务端注册的 `/mcn/api/*` 路由"。
|
|||
|
|
- ⇒ **拆开的状态下"逐个启用"本身就违背设计**:缺了 mcn,其余 5 个只是死链;反过来只启用 mcn 则功能残缺。**整合是回归正确形态,不只是图省事。**
|
|||
|
|
- 附注:`dsh-plugin-mcn` **没有** `defineTool` / `tools.register`(`grep` 实证 = 0)→ 它是 UI + HTTP 插件,**不给 agent 注册工具**;agent 侧能力只来自技能与 prompt。
|
|||
|
|
|
|||
|
|
### 2.2 打包链路现状:**不存在,要新建**
|
|||
|
|
|
|||
|
|
7 个包均**无 `scripts` 字段、无 build 脚本、无 `package/` 目录、无 tgz 产物**;`lib/*.js` 是**直接维护的产物**(client.js 顶部自带 `var module = {exports:{}}` 的 bundle 外壳)。→ 整合包必须**新建打包脚本**。
|
|||
|
|
|
|||
|
|
### 2.3 需要一并处置的残留
|
|||
|
|
|
|||
|
|
`dsh-plugin-mcn/lib/` 内有 **2 个 `.bak`**(`index.js.bak-20260906`、`index.js.bak3-20260906`)→ 会被打进包、加重体积并可能触发上传扫描告警。`docs/ui-check-home-fix/`(1.6M)与插件无关,不进包。
|
|||
|
|
|
|||
|
|
## 三、范围
|
|||
|
|
|
|||
|
|
| 区 | 对象 | 动作 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 新建 | `D:\dshworkspace\plugin_package\dsh-plugin-mcn-suite\`(**7 个原包原地保留**作回滚参照) | 整合包源码 |
|
|||
|
|
| 新建 | 整合包内 `skills/`(**技能原文 + `.manifest.json`**,来源 `C:\Users\Administrator\.dsh\skills\mcn-short-video`,11 MB / 711 文件) | 随包投放的业务技能,**按 §4.1 取舍表挑选**(不整包照搬) |
|
|||
|
|
| 新建 | 打包脚本(`scripts/build-mcn-suite.cjs` 或等价) | 产出 `dsh-plugin-mcn-suite-<ver>.tgz`(**tgz 内需 `package/` 前缀**,档案 25/28 教训) |
|
|||
|
|
| 改 | 整合包内的 host/client 代码 | §五 的 P0 适配 |
|
|||
|
|
| 平台侧 | 门户候选池 | 上传新包 + **下架旧 7 包**(防并存,见 §七) |
|
|||
|
|
| 文档 | 新建档案 + `INDEX §二` + `03-路线图` + `交接单/README §一` | 归档 |
|
|||
|
|
|
|||
|
|
**明确不动**:❌ dsh 官方包与缓存(红线 R2)❌ 平台自建三 bundle(`portal-entry` / `business-plugins` / `workspace-scoped-picker`)❌ `/opt/dsh` 权限 ❌ 7 个原包源码(保留)❌ 不新增平台侧权限能力(不触发 R5)
|
|||
|
|
|
|||
|
|
## 四、决策点(**已由用户 2026-09-12 拍板**)
|
|||
|
|
|
|||
|
|
> 用户口径:「**A 按照最佳方案处理;B 按照你的建议处理 —— 业务技能能否打包到插件中一起安装和使用,不要分开管理!;C、D 按照最优方案处理**」
|
|||
|
|
|
|||
|
|
| # | 决策 | 定稿 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 1 | `dsh-plugin-social-workbench` **进不进包** | ✅ **不进包**(采纳建议 A)。实测是 **Windows 本地服务守护**:`EASEL_DIR` 默认 `D:\dshworkspace\Easel`、可执行文件 `.venv/Scripts/easel.exe`、探针打 `127.0.0.1:7860`/`:18789`;平台实例里 ① 该 exe 不存在 ② `127.0.0.1` 已被档案 39 封(实测 BLOCKED)→ **必然不可用**。该入口在平台不投放,原包源码保留 |
|
|||
|
|
| 2 | `dsh-plugin-voxemw-cloud` 进不进包 | ✅ **进包**。凭据全程走 env(**无硬编码** ✓、`getPublicConfig` 已剥离 apiKey ✓),平台实例无该 env → 入口显示「未配置」,不崩 |
|
|||
|
|
| 3 | 整合后的入口形态 | ✅ **A=保留 `__mcnEntries` 机制、多入口并列**(工作台首屏图标网格),client 面行为与现状一致 |
|
|||
|
|
| 4 | **业务技能投放** —— 用户明确要求 **打进插件包、一起安装使用、不分开管理** | ✅ **改为「技能随包投放」**,实现见 **§4.1**。**这推翻了规划会话原先"走门户技能管理分开投"的建议**,据此重设计 |
|
|||
|
|
| 5 | 包名与版本 | `dsh-plugin-mcn-suite` **v0.3.0**。**版本号必须每次递增**:同名同版本 tgz 即使内容变了,pnpm 也复用旧包(档案 18 踩坑 1) |
|
|||
|
|
|
|||
|
|
### 4.1 技能随插件包投放(**用户要求:不分开管理**)
|
|||
|
|
|
|||
|
|
**为什么可行**:技能发现位在**实例内** —— `dsh discoverRoot` 只扫 `$DSH_HOME/skills`(档案 41 §B 实测:启用/禁用靠目录 rename 即可**即时生效、无需重启**);而插件的 host 面代码**就跑在实例内、以该用户 uid 运行** → **插件完全有能力自己把技能装到位**,不需要平台技能管理面参与。
|
|||
|
|
|
|||
|
|
**机制(建议,执行会话按此实现)**:整合包内置 `skills/`(技能原文)+ `skills/.manifest.json`(技能名 → 版本 / 文件数 / sha256)。host 面在**每次实例启动**调用 `ensureSkills()`:
|
|||
|
|
|
|||
|
|
1. 读 `.manifest.json`;对每个技能比对 `$DSH_HOME/skills/<name>/.installed.json` 记录的版本;
|
|||
|
|
2. **幂等**:版本一致 → 跳过(不重复写盘);
|
|||
|
|
3. 版本不一致 → **全量替换**(先删后放,旧版已删除的文件一并清除 —— 与档案 11「apply 全量替换」同语义);
|
|||
|
|
4. **不覆盖用户自建的同名技能**(目录存在但无 `.installed.json`)→ 跳过 + 写日志 + UI 提示"被同名技能占用";
|
|||
|
|
5. 写加载标记 `[mcn-suite] skills ensured: [email protected], …`(回归看日志即可,档案 26 §建议)。
|
|||
|
|
|
|||
|
|
**备选(更省事,但必须先实测)**:若 dsh 的 skill 扫描**认得目录软链**,可改用软链 `<DSH_HOME>/skills/<name>` → `<profile>/node_modules/dsh-plugin-mcn-suite/skills/<name>`,**升级插件即升级技能、零对账**。风险:symlink 是否被扫描/读盘正常要**实测**(档案 39 的教训:symlink 行为必须 realpath 级实测,别假设)。→ 执行会话先试软链,不行再退回"复制 + 版本对账"。
|
|||
|
|
|
|||
|
|
**投哪些 / 不投哪些 —— 按「引用驱动」裁剪,不按"看着像资料"裁**(用户 2026-09-12 定「参考资料不需要」;规划会话随后实测引用关系,**发现三类"像资料"的其实是被引用的功能件**,故按下表执行):
|
|||
|
|
|
|||
|
|
| 内容 | 体积 | 引用实测 | 定稿 |
|
|||
|
|
|---|---|---|---|
|
|||
|
|
| 主技能 `mcn-short-video`(`SKILL.md` + `references/` + `references-add/` + `scripts/` + `帮助文档.md`) | ~1.3 MB | — | ✅ **投** |
|
|||
|
|
| 子技能 `mcn-dou-analysis` / `mcn-script-review` / `mcn-video-prompt` / `mcn-data-insight` 主体 | 主体 | 插件 prompt 正是引用这 4 个 | ✅ **投** |
|
|||
|
|
| **`mcn-data-insight/` —— 它本身是"技能集索引",下挂 12 个二级子技能**(`douyin-top-account`(140K) / `douyin-account-diagnosis`(136K) / `douyin-rise-ranking`(76K) / `douyin-hot-trend`(72K) / `douyin-ai-feed` / `douyin-prohibited-word` / `playlet-douyin-feed` / `douyin-weekly-surge` / `douyin-works-crawler` / `douyin-content-surge` / `douyin-daily-hot` / `douyin-search`,**全部带 `SKILL.md`**) | **869 KB** | 插件的「榜单更新」任务依赖其中的 `douyin-top-account`;`workshop.js` 的赛道白名单同源 | ✅ **整块投**(这是"技能树"的第二层,**不是参考资料**;`find -maxdepth` 容易漏它,核对时注意层级) |
|
|||
|
|
| `mcn-dou-analysis/references/样例/`(`模板_旧梦留声机账号设定卡.svg` 19 KB + `参考_旧梦留声机_账号设定卡_长图版.png` **994 KB**) | 992 KB | **`references/feature/06_生成账号设定卡片.md:67` 写明"动手前必须先读"这两份** → **功能件,不是资料** | ✅ **保留**。用户说的"参考资料不需要"**不覆盖这一项**;若你仍要剔,则必须同改那条指令,否则留下死引用 |
|
|||
|
|
| `nuwa-skill-main/` **主体**(去掉 `examples/`) | **104 KB / 11 文件** | **被引为"主方法论"**:`feature/03_提炼账号设定.md:81`、`references/人设卡生成方法.md:186` | ✅ **保留** |
|
|||
|
|
| `nuwa-skill-main/examples/`(`trump-perspective/` 英文研究文档等) | ≈ **2.4 MB** | `人设卡生成方法.md:187-188` 引了 `examples/mrbeast-perspective/`(**未引 `trump-perspective`**) | ❌ **剔**。精确做法:只剔未被引的 `trump-perspective/`;若要连 `mrbeast-perspective` 一起剔,**必须同改那两行引用** |
|
|||
|
|
| `mcn-video-prompt/参考skills/`(seedance2.0-prompt-skill、script-writing-studio 上游全文) | **2.0 MB** | **实测 0 引用**(`grep` 命中 0)→ 纯资料 | ❌ **剔** ✓ —— 用户"参考资料不需要"指的就是这类 |
|
|||
|
|
| `browser-harness/`(整包 Python + 自带 venv + docs/png) | **2.3 MB** | **多篇 feature 要求"浏览器优先"**(`feature/01_获取账号信息.md:12`、`feature/02_获取视频.md:10`)+ 主 `SKILL.md` 有专章(L88/105-112) | ❌ **剔目录**,但**必须同步改文档**:写明「平台无浏览器(档案 38a 实测 Playwright 装不起来)→ 改走 MCP / 其它路径」,否则留下死引用,agent 会像档案 55 那样反复撞墙 |
|
|||
|
|
| `scripts/mcp-config.json` | 16 KB | 插件 MCP 依赖(功能必需部分 = URL) | ⚠️ **剔 `MYAI_FEISHU_APP_ID`(`cli_a84d0a47f93e1013`)、保留 URL**(`maiya-trans.youmanvideo.com`);再按 §五#7 过扫描 |
|
|||
|
|
|
|||
|
|
**裁剪后体积预期**:11 MB → **≈4.3 MB**(剔掉 6.7 MB:`参考skills` 2.0 + `browser-harness` 2.3 + `nuwa/examples` 2.4)。
|
|||
|
|
⚠️ **投的是整棵技能树,不是一个技能**:全树 **36 个 `SKILL.md` / 711 文件**(主技能 1 + 一级子技能 5 + `mcn-data-insight` 下 12 个二级子技能 + 更深层的参考技能目录)。**核对层级时别用浅 `find`**(规划会话首轮就是这么误判 `douyin-top-account` "缺失"的)。
|
|||
|
|
|
|||
|
|
**裁剪必须机械校验(新增,防"剔完留死引用")**:剔完跑一次**死引用扫描** ——
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
grep -rIn -E "参考skills|browser-harness|nuwa-skill-main/examples/trump|参考_旧梦留声机" <整合包>/skills/ \
|
|||
|
|
| grep -v -E "已移除|无浏览器|不再使用"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
期望:**只剩"已移除 / 已改走 X"这类说明行**(即上面要求改写的指令),**没有一条指向已删文件的活引用**。
|
|||
|
|
|
|||
|
|
**⚠️ 与共享技能层互斥**:本单走"插件内投"后,**不要再把 `mcn-short-video` 投到平台共享技能层**(`bundledSkillDir`,档案 10/40)—— 两条通道同名会按 rank 抢,行为不可预测。详见 §七。
|
|||
|
|
|
|||
|
|
**禁用 / 卸载语义(取舍,已定)**:插件被禁用(`disabled: true`)时**不删**已装技能(用户可能正在用),只在下次启用时按版本对账;**卸载插件**会留下技能残留 → 记为已知残留(清理走实例内「我的技能」或目录手工删)。
|
|||
|
|
|
|||
|
|
### 4.2 技能落地方式(装到哪)与撞名规则(2026-09-12 用户提问定稿)
|
|||
|
|
|
|||
|
|
**问题一:装到 `$DSH_HOME/skills/`,还是"就在插件内目录使用"?**
|
|||
|
|
|
|||
|
|
关键事实:**dsh 的技能扫描根是一个固定集合**(个人 `~/.dsh/skills` rank300 / 项目级 `.dsh/skills` rank100 / `.agents/skills` rank200 / 平台注入的 `bundledSkillDir`,档案 10 §Skill 装载机制 / 档案 41 §B),**插件包目录(`profile/node_modules/<pkg>/skills/`)不在其中**。
|
|||
|
|
⇒ **"就在插件内目录使用"意味着 agent 无法按技能名加载**(skill 机制发现不了),只能靠 prompt 给绝对路径让它自己读 `SKILL.md`。
|
|||
|
|
|
|||
|
|
| 方案 | 能否按技能名加载 | 副本/维护 | 备注 |
|
|||
|
|
|---|---|---|---|
|
|||
|
|
| **A 复制**到 `$DSH_HOME/skills/<name>` | ✅ 能 | 每用户一份 ≈4.3 MB;需版本对账 | 最简单确定;用户能在「我的技能」看到(但归插件管) |
|
|||
|
|
| **B 软链** `$DSH_HOME/skills/<name>` → 插件包内目录 | ✅ 能(**前提:实测 dsh 跟随 symlink**) | **零副本**;**升级插件即升级技能**,零对账 | 副作用:用户在「我的技能」里删/禁 → 断链或删链,需处理;**必须先实测**(档案 39 教训:symlink 行为必须 realpath 级实测,不许假设) |
|
|||
|
|
| **C 不落扫描根**,prompt 给"包内绝对路径"(插件运行时用 `import.meta.url` 算出) | ❌ 不能 | 零副本零对账 | 兜底方案:agent 用不了 skill 名;用户不可见、不可管理;每次 prompt 都要注入路径 |
|
|||
|
|
|
|||
|
|
→ **定稿:B 优先(一条实测命令即可确认);B 不通退回 A;C 仅作最终兜底。**
|
|||
|
|
|
|||
|
|
**问题二:同名技能怎么处理(三层,按优先级)**
|
|||
|
|
|
|||
|
|
| 场景 | 处理 | 理由 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 插件技能 ↔ **用户自建**同名 | **让位**:不覆盖,跳过 + 日志 + UI 提示"被你的同名技能占用" | 用户的东西优先;档案 41 已有"同名 409"的先例,不静默覆盖 |
|
|||
|
|
| 插件技能 ↔ **平台共享技能层**同名 | **互斥**:本单不投共享层;若共享层已有同名,插件让位并提示 | 共享层 rank 更高会压住个人层,静默失败比明说更糟(§4.1 互斥条) |
|
|||
|
|
| 插件技能 ↔ **另一个插件**同名 | **owner 标记 + 先到先得 + 冲突报错**:每份由插件装的技能写 `.installed.json`(`owner: <包名>@<版本>`、`skillVersion`、`sha256`);安装前查目标目录 —— 无标记=用户自建→让位;`owner`=自己→按版本对账;**`owner`=别的插件→拒绝写 + 明确提示** | 多插件共存时行为可预测、冲突可见;**不建议给技能名加命名空间前缀**(要改所有 prompt,且用户看到怪名字) |
|
|||
|
|
|
|||
|
|
**判定顺序(实现时按此写)**:`目标目录不存在` → 装;`存在且 .installed.json.owner == 本包` → 比版本,不同则全量替换;`存在但无 .installed.json` → 用户自建,让位;`存在且 owner == 其他包` → 拒绝 + 报错。
|
|||
|
|
|
|||
|
|
## 五、平台化 P0 清单(**不修则"传上去也不能用"**)
|
|||
|
|
|
|||
|
|
| # | 问题 | 实测位置 | 改法 |
|
|||
|
|
|---|---|---|---|
|
|||
|
|
| **1** | **`homedir()/.dsh` 硬编码** —— 平台实例的 DSH 家目录是 `$DSH_HOME`,不是 `~/.dsh` | `mcn/lib/config.js:6,28,68`;`mcn/lib/index.js:733,771,865,881,935,964,978,1124,1167,1496,1565,1630,1969,2143,2840`;`mcn-schedule/lib/index.js:11,27,84` | 统一 `const DSH_HOME = process.env.DSH_HOME` → `join(DSH_HOME, …)`。**注意三处子路径**:`storages/workspace.json`、`sessions/`、`profiles/`,都在 DSH_HOME 下 |
|
|||
|
|
| **2** | **技能路径硬编码** `~/.dsh/skills/mcn-short-video/subskills/<x>/` | `mcn/lib/index.js` 多处:1255、1565、1798、1813、1834、2078、2313、2364、2491、2546、2984、2986… | 改成**只报技能名**(`mcn-dou-analysis` 等),由 agent 自行解析(档案 27 P0-2);技能**随包投放**(见 §4.1),prompt 里不再出现任何绝对路径 |
|
|||
|
|
| **3** | **`spawn("powershell", …)` 杀进程树 = Windows only** | `mcn/lib/index.js:919`(两个 `.bak` 同位置) | 平台是 Linux → 改 `process.kill(-pid, …)` / `pkill -P`,或直接删掉该清理分支(评估残留影响) |
|
|||
|
|
| **4** | **MCP `spawn(npx -y myai-mcp)` 每次现拉包** | `mcn/lib/mcp.js:21`、`config.js:14` | 平台侧**预装成包**(档案 27 P1),并确认实例内 **npm registry 可达**(档案 38a:仅云元数据端点被封,其余放行但只记日志) |
|
|||
|
|
| **5** | **`.bak` 混在 lib/** | `mcn/lib/index.js.bak-20260906`、`index.js.bak3-20260906` | 打包前剔除(构建脚本过滤 + `files` 白名单) |
|
|||
|
|
| **6** | **上传扫描可能误伤**(P0 阻断 / P1 告警) | 整包 | **打包后先本地 dry-run `src/web/security-scan.ts` 的规则**(P0:`/etc/shadow`、base64 解码执行、`nc -e`、`/dev/tcp` 反弹、fork 炸弹、给系统二进制加 setuid;P1:`child_process`、`vm`/`eval`/`new Function`、敏感 env、超长 base64、外部网络、隐藏目录)。已知 `child_process`(mcn spawn、social-workbench spawn)只会触发 **P1 告警、不阻断**,但要确认整包 **P0 = 0**。**注意技能原文里有大量代码示例/脚本,P0 风险比插件本身高** |
|
|||
|
|
| **7** | **技能原文里的凭据 / 平台情报**(随包投放新增) | `mcn-short-video/scripts/mcp-config.json`(实测含 `MYAI_FEISHU_APP_ID=cli_a84d0a47f93e1013` + 私域 URL `maiya-trans.youmanvideo.com`)、`scripts/MCN_CYLG_API.py`(命中 `key/token` 模式,**需逐个核对**)、`subskills/browser-harness/.env.example` | 入包前对 `skills/` 整目录做**凭据扫描**:`grep -riE "api[_-]?key|access[_-]?token|secret|password|passwd" skills/` → **真密钥一律剔除**(改 env 注入);非密钥的平台情报(app id、私域域名)按最小必要原则剔除;结论写进档案 |
|
|||
|
|
| **8** | **插件 prompt 里的技能路径层级不符**(2026-09-12 复核,**更正规划会话先前的误判**) | 插件 prompt 写的是 `subskills/douyin-top-account`(`mcn/lib/index.js:3085`、`3086`;`mcn/lib/workshop.js:9,22`),**真实路径是 `subskills/mcn-data-insight/subskills/douyin-top-account/`**(少了一层)。技能本身**完整存在**(36 个 `SKILL.md` / 711 文件)—— 规划会话首轮的"缺失"结论是**搜索深度不够(`-maxdepth 5` 差一层)导致的误判,已更正** | 无需补文件;**并入 #2 一起修**:所有 prompt 改成**只报技能名**(`douyin-top-account`),由 agent 自己解析 → 层级问题自然消失。**打包前必跑**:`grep -rn "subskills/" lib/` 逐条核对是否与技能实际层级一致 |
|
|||
|
|
|
|||
|
|
## 六、步骤(每步自带验证)
|
|||
|
|
|
|||
|
|
1. **前置只读核查**:`git -C <平台代码> log -1`(取当前 HEAD 备写档案)/ `ls /opt/dsh/artifacts/`(看版本命名与 `package/` 前缀)/ 门户 `#/plugins` 候选池现有 7 包的实际状态(是否有人已启用)。
|
|||
|
|
*验证*:拿到"候选池里有哪几个、谁在用"的事实清单。
|
|||
|
|
2. **决策与技能完整性**:§四 五个决策点已定稿;**另需向用户确认 §五#8 —— `douyin-top-account` 子技能的去向**(补进包 / 已废弃改 prompt / 走 MCP)。**该项未确认前不要打包**。
|
|||
|
|
3. **建包骨架**:`package.json`(name `dsh-plugin-mcn-suite`、version、`type: module`、`exports {".", "./client"}`、`dsh.bundle.patch`、`dsh.client.inject` = mcn 的 `[runtime, sidebar]` 并集)+ `cordis.patch.yml`(**只 1 条 `insert`**:`id: mcn-suite`)+ `lib/{index.js, client.js, host/*}`。
|
|||
|
|
*验证*:`node --check` 全通过;`cordis.patch.yml` 里 insert 条目数 = 1(防 duplicate,档案 25)。
|
|||
|
|
4. **移植 host 面**:把 mcn 的 9 个模块 + mcn-schedule + voxemw(+决策 1 的 social-workbench) 收进 `lib/host/`,**保持路由前缀不变**(`/mcn/api/*`、`/voxemw/api/*`)→ client 面零改动。
|
|||
|
|
*验证*:路由清单 diff:改前 25+ 条 vs 改后逐条一致(只增不减)。
|
|||
|
|
5. **合并 client 面**:一个 `client.js` 内注册全部 `__mcnEntries` 条目;`inject` 取并集;**确认无 `exports.default`**(红线 R3,实测 7 个原包全部合规 ✓,合并时别引入)。
|
|||
|
|
*验证*:`grep -c "exports.default"` = 0。
|
|||
|
|
6. **P0 适配**(§五 1–5)+ 按需加**加载标记**:`console.log("[mcn-suite] loaded …")`(把回归从"看 UI"变成"看日志",档案 26 §建议)。
|
|||
|
|
*验证*:`grep -n "homedir()" lib/**/*.js` = 0;`grep -n "powershell"` = 0;`grep -rn "\.dsh/skills"` = 0。
|
|||
|
|
7. **本地 smoke**:参考 `dsh-plugin-voxemw-cloud/tests/smoke.mjs` 的写法,跑一遍 host 面(路由注册、DB 建表幂等、无 env 时降级不崩)。
|
|||
|
|
*验证*:smoke 全绿;无 env 情况下进程不抛。
|
|||
|
|
8. **打包**:产出 `dist/dsh-plugin-mcn-suite-<ver>.tgz`,**内含 `package/` 前缀**,**不含 `.bak` / `node_modules`**。
|
|||
|
|
*验证*:`tar tzf` 清单人工核对(顶层只有 `package/`);体积与 `du` 对照;`md5sum` 记档。
|
|||
|
|
9. **扫描 dry-run**:按 §五#6 规则跑一遍 → **P0 必须为 0**;P1 告警逐条判断是否误报。
|
|||
|
|
10. **上传**:admin 门户 `#/plugins` 上传 tgz → 进候选池(默认禁用)。**产物不要复制进用户 ws**(档案 28 平台污染教训)。
|
|||
|
|
*验证*:候选池列表出现该包 + 版本号正确。
|
|||
|
|
11. **切换(关键,防并存)**:① 先在候选池**下架旧 7 包** ② 用户实例「功能管理」启用新包 ③ 确认弹窗 → 重启实例 ④ 走 `restartAndProbe` 探活(档案 34)。
|
|||
|
|
*验证*:§八 C–F。
|
|||
|
|
12. **实测验收 + 资源**:逐功能页点开;用 `scripts/probe-instance-mem.cjs` 量**私有内存与启动时间**(档案 58 预算:`MemoryMax 384 MiB` / 堆 256)。
|
|||
|
|
*验证*:§八 D、G。
|
|||
|
|
13. **归档**:新建档案(**原子占号** `mkdir 04-调整方案/.lock-<NN>`)→ 更新 `INDEX §二` / `03-路线图` / `交接单/README §一` → 本单 `git mv` 到 `archive/交接单-已完成/`。
|
|||
|
|
*验证*:`docs-audit.py` 退出码 0。
|
|||
|
|
|
|||
|
|
### 6.1 技能随包的额外步骤(并入上面第 3、6、8、10 步,不另起编号)
|
|||
|
|
|
|||
|
|
- **建包阶段(并入第 3 步)**:按 §4.1 **引用驱动**裁剪(不是"看着像资料就删")→ 放整合包 `skills/<name>/`;生成 `skills/.manifest.json`(名称 / 版本 / 文件数 / sha256);剔完跑 §4.1 的**死引用扫描**。
|
|||
|
|
*验证*:`du -sh skills/` ≈ **4.3 MB**(而不是 11 MB);`tar tzf` 确认**没有** `参考skills/`、`browser-harness/`、`nuwa-skill-main/examples/trump-perspective/`;**确认有** `mcn-dou-analysis/references/样例/`(含 994 KB 长图)、`nuwa-skill-main/SKILL.md`、**`mcn-data-insight/subskills/douyin-top-account/`**(这三块都是被引用的功能件,不能剔)。
|
|||
|
|
- **改码阶段(并入第 6 步)**:实现 `ensureSkills()`(§4.1 五步)+ 加载标记;把 `mcn/lib/index.js` 的 13+ 处**技能绝对路径改成技能名**。
|
|||
|
|
*验证*:`grep -rn "\.dsh/skills" lib/` = 0;`grep -rc "ensureSkills" lib/` ≥ 1。
|
|||
|
|
- **打包阶段(并入第 8 步)**:`skills/` 整体进包(`package.json` 的 `files` 白名单必须包含 `skills`)。
|
|||
|
|
*验证*:`tar tzf dist/*.tgz | grep -c "package/skills/"` ≈ 技能文件总数(数百)。
|
|||
|
|
- **上线阶段(并入第 10 步)**:上传 → 用户启用 → 重启 → 按 §八 J/K 验技能就位。
|
|||
|
|
|
|||
|
|
### 6.2 收尾顺带(D 组:两处文档漂移 —— 用户已定「并进 T03 收尾」)
|
|||
|
|
|
|||
|
|
- **`BRIEF.md:20`**:`scope(512M / 150% / TasksMax 128)` → **`384M`**,并补 `NODE_OPTIONS=--max-old-space-size=256` 与 `NODE_COMPILE_CACHE`(档案 58 实测)。
|
|||
|
|
- **`03-路线图与待办.md`**:头部仍是 09-11 21:20 合并版、**档案 57-61 完全未登记** → 补登记 + 刷新头部状态行;`BRIEF §3` 待办同步。
|
|||
|
|
*验证*:`grep -n "384M" BRIEF.md` 命中;`grep -nE "档案 (60|61)" 03-路线图与待办.md` 命中(**写成 `(60|61)` 而不是字符类**:`档案\s*6[01]` 这种写法会被 `docs-audit.py` 的引用正则匹配成裸旧号 `6` → 永久悬空,T02 已踩过一次)。
|
|||
|
|
|
|||
|
|
## 七、风险与红线
|
|||
|
|
|
|||
|
|
**🔴 头号风险:新旧包并存 → 实例崩**
|
|||
|
|
若某用户同时在位"旧 7 包"与"新整合包",会出现:`/mcn/api/*` 路由**重复注册**、`sidebar.footer.action` **重复注册**、`__mcnEntries` **重复条目**;严重时 `duplicate loader entry id` → **崩溃循环**(档案 25 有真实前例,靠档案 20 熔断才拦住,但用户会看到死页面)。**四道防线必须全做**:
|
|||
|
|
1. 新包用**全新 loader id**(不复用 `mcn-nav` 等 7 个旧 id);
|
|||
|
|
2. 门户候选池**下架旧 7 包**(或标 deprecated,并在包描述写明替代关系);
|
|||
|
|
3. 切换按 §六 步骤 11 的顺序执行(先禁用旧 → 再启用新);
|
|||
|
|
4. 新包 host 面加**防御**:启动时检测旧 id 是否同时在位 → 命中则**拒绝启动并写明确日志**(宁可这个包不工作,也不要崩实例)。
|
|||
|
|
|
|||
|
|
**其余**
|
|||
|
|
- 内存/启动(档案 58):合并后单实例加载模块更多,**必须实测**,超预算就按需懒加载或砍 social-workbench。
|
|||
|
|
- 网络(档案 38a):实例出网只记日志不拦(元数据端点已封)→ MCP `npx`、voxemw 云调用可达性要用**实测**确认,别假设。
|
|||
|
|
- **技能同名互斥**(§4.1):插件投的技能、平台共享技能层、用户自建技能**三方可能同名** → ① 本单**不投共享技能层**;② 用户自建同名时插件**跳过并提示**;③ 若日后要改投共享层,必须先撤掉插件内投放。
|
|||
|
|
- **技能随包的体积成本**:约 1.5–2 MB × 每用户一份(用户已明确"不分开管理",接受该冗余);日后要省可改软链方案(§4.1 备选)。
|
|||
|
|
- 红线:R2 不改官方 dsh 包(只走 bundle + patch)✓;R3 client 禁 `exports.default` ✓;R5 本单不扩大平台权限 ✓;不自动升级 dsh ✓;**未获明确授权不 commit / push**。
|
|||
|
|
|
|||
|
|
## 八、验收
|
|||
|
|
|
|||
|
|
| # | 命令 / 动作 | 期望 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| A | `tar tzf dist/*.tgz \| head` ;`md5sum` | 顶层只有 `package/`;无 `.bak`、无 `node_modules`;md5 记档 |
|
|||
|
|
| B | 上传扫描 dry-run | **P0 = 0**;P1 逐条有结论 |
|
|||
|
|
| C | 门户 `#/plugins` 上传 | 进入候选池、默认禁用、版本号正确 |
|
|||
|
|
| D | 全新用户:启用 → 确认弹窗 → 重启 | 侧边栏入口出现;工作台首屏功能入口**逐个可打开** |
|
|||
|
|
| E | `journalctl -u dshs --since '10 min ago' \| grep -E "mcn-suite\|duplicate"` | 有 `[mcn-suite] loaded`;**无** `duplicate loader entry id`;无崩溃重启 |
|
|||
|
|
| F | 启用探活(档案 34) | 探活通过;失败时快照回滚不误伤好插件 |
|
|||
|
|
| G | `scripts/probe-instance-mem.cjs` | 私有内存 + 启动时间在档案 58 预算内(写实测值) |
|
|||
|
|
| H | 候选池 | 旧 7 包已下架/标 deprecated;**不存在"新旧同时可启用"的状态** |
|
|||
|
|
| I | **技能随包就位**(§4.1) | 全新用户启用 + 重启后:`ls $DSH_HOME/skills/` 出现 `mcn-short-video` 与 4 个业务子技能;`journalctl` 有 `[mcn-suite] skills ensured: …` |
|
|||
|
|
| J | 技能可用(agent 侧) | 实例内让 agent **按技能名**加载(如「调用 mcn-dou-analysis」)→ 能解析到,**无需给绝对路径** |
|
|||
|
|
| K | 幂等 / 不覆盖 | 再重启一次 → 技能**不被重复写**(`.installed.json` 版本一致则跳过);人为放一个同名自建技能 → 插件**跳过并提示**,不覆盖 |
|
|||
|
|
| L | 凭据(§五#7) | `skills/` 凭据扫描:**真密钥 0 命中**;app id / 私域域名的处置有明确结论并写进档案 |
|
|||
|
|
| M | D 组文档(§6.2) | `BRIEF.md` 已更正为 384M;档案 57-61 已在 `03-路线图` 登记 |
|
|||
|
|
| N | **裁剪后引用完整性**(§4.1 死引用扫描) | 只剩「已移除 / 已改走 X」的说明行;**无一条指向已删文件的活引用**(`browser-harness` 相关的"浏览器优先"指令必须已改写) |
|
|||
|
|
| O | 包体积与技能树 | `skills/` ≈ **4.3 MB**(已剔 6.7 MB);含全部 **36 个 `SKILL.md`**(主技能 + 5 一级子技能 + `mcn-data-insight` 12 个二级子技能);**保留了** `references/样例/`(992 KB)、`nuwa-skill-main/SKILL.md`、`mcn-data-insight/subskills/douyin-top-account/` |
|
|||
|
|
| P | 技能落地方式(§4.2) | 按 B(软链)先实测;不通则用 A(复制)。**两种都必须能被 skill 机制按名加载**(不是靠 prompt 给绝对路径) |
|
|||
|
|
| Q | 撞名处理(§4.2) | 用户自建同名 → 让位并提示 ✅;平台共享层同名 → 互斥并提示 ✅;别的插件已占 → **拒绝写并报出 owner** ✅(验证:人为造这三种场景各跑一次) |
|
|||
|
|
|
|||
|
|
## 九、回滚
|
|||
|
|
|
|||
|
|
- **包级**:候选池删新包 → 重新上架旧 7 包 → 用户逐个启用 → 重启(**这是为什么原包源码与 tgz 都要留档**)。
|
|||
|
|
- **实例级**:走档案 34 的 `restartAndProbe` 快照回滚;或直接禁用新包重启。
|
|||
|
|
- **本单不改平台代码** → 无平台侧回滚;若为铺开改了 `ensure-*` 脚本,按 `.bak-<ts>` 还原 + 重启。
|
|||
|
|
|
|||
|
|
## 十、回报格式(执行会话填)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
## T03 执行回报
|
|||
|
|
- 决策 1–5 选定:<逐条,谁确认的>
|
|||
|
|
- 整合包:name/version = ? 体积 = ? 路由数 25+N 入口数 = ?
|
|||
|
|
- P0 适配:homedir() 残留 0 ✅ / powershell 残留 0 ✅ / .dsh/skills 硬编码 0 ✅ / .bak 已剔 ✅
|
|||
|
|
- 打包与扫描:tgz md5 = ? P0 = 0 P1 = ?(逐条结论)
|
|||
|
|
- 上传与切换:候选池版本 ? 旧包下架 = 是/否 启用+重启 ✅ 探活 ✅
|
|||
|
|
- 实测:私有内存 ? MiB / 启动 ? s(对照档案 58 预算)
|
|||
|
|
- 验收:A–I 逐项 ✅(未过项写现象)
|
|||
|
|
- 证据:<journald loaded 标记 + duplicate 检查输出 + 内存采样>
|
|||
|
|
- 偏离:<…;无则写"无">
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 十一、不在本单
|
|||
|
|
|
|||
|
|
- 业务技能内容本身的维护/改版(只做"投放到位")
|
|||
|
|
- voxemw 云链路接线(档案 12 的 M1 后段)
|
|||
|
|
- Easel / social-workbench 的平台化改造(决策 1 选 C 才需要,另立单)
|
|||
|
|
- 平台「功能管理」分区的其它 UI 调整(档案 57/60 已闭环)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 九、验收结果(2026-09-13 09:5x · **只读取证,服务器实测**)
|
|||
|
|
|
|||
|
|
> 口径:§八 逐项核对;能只读证的全跑了,需要浏览器/造场景的明确标出。
|
|||
|
|
|
|||
|
|
| # | 项 | 结果 | 实测证据 |
|
|||
|
|
|---|---|---|---|
|
|||
|
|
| A | 包结构 | ✅ | 池内 tgz md5 `2ff1a2fa775891085949d50452394fa0` / 1,953,267 B / **v0.3.9**;顶层仅 `package/`;`node_modules` **0**、`.bak` **0** |
|
|||
|
|
| B | 上传扫描 | ✅(P0) | `[upload-scan] blocked=0 warnings=118`(**warnings 逐条结论未做**) |
|
|||
|
|
| C | 候选池上传 | ✅ | 池内 `dsh-plugin-mcn-suite @0.3.9`(09-13 00:02) |
|
|||
|
|
| D | 启用→重启→入口 | ⚠️ **未验**(需浏览器逐个点开入口) | — |
|
|||
|
|
| E | 加载日志 | ✅ | `[mcn-suite] loaded v0.3.0(host 面 3 个:mcn, mcn-schedule, voxemw-cloud)`;**`duplicate loader entry id` = 0**;同期无崩溃 |
|
|||
|
|
| F | 启用探活 | ⚠️ 未单独验(但**平台已自动回滚过一次** ⇒ 该链路是活的,见 07:42–07:46 事故) | — |
|
|||
|
|
| G | 内存 | ⚠️ 偏紧 | guest 峰值 **382 / 上限 384 MiB**;admin 峰值 321 / 384(档案 74 采样) |
|
|||
|
|
| H | 旧 7 包下架 | ✅ | 池内只剩 `mcn-suite` + `univer-office` 两个;无新旧并存 |
|
|||
|
|
| I | 技能随包就位 | ✅ | 落点 = **`<home>/skills/mcn-short-video`**(4.6 MB,含 4 个一级子技能);journal `[mcn-suite] skills ensured …` |
|
|||
|
|
| J | agent 按技能名加载 | ⚠️ 未验(需实例内跑一次 agent) | — |
|
|||
|
|
| K | 幂等/不覆盖 | ✅ | `skills ensured: 跳过 [email protected](版本一致)` |
|
|||
|
|
| L | 凭据扫描 | ⚠️ 未验 | — |
|
|||
|
|
| M | D 组文档 | ✅ | `BRIEF.md` 已是 384M(档案 58 收尾时改) |
|
|||
|
|
| N | 裁剪后引用完整性 | ⚠️ 未验(需跑死引用扫描) | — |
|
|||
|
|
| O | 包体积与技能树 | ⚠️ **口径待核** | 实测 **4.4 MB / 18 个 SKILL.md**(主 1 + 一级 4 + `mcn-data-insight` 下 13);§八 原文期望 **36 个 SKILL.md** ⇒ 差异需确认为"包被裁剪"还是"口径过时" |
|
|||
|
|
| P/Q | 软链落地 / 三种撞名场景 | ⚠️ 未验(需造场景) | — |
|
|||
|
|
|
|||
|
|
**结论**:**主体已通过(8 项实证)**;未验的 6 项(D/J/L/N/P·Q)都属"需浏览器或需造场景",可以另找时间补,**不阻塞投放**。
|
|||
|
|
|
|||
|
|
**⚠️ 一条必须记的事实(guest 那次尝试)**:2026-09-13 **07:42:52** guest 在「功能管理」提交启用 →
|
|||
|
|
实例 **07:43–07:45 连崩 5 次**(`exitCode=134`,栈 = V8 `JsonParser`/`HeapAllocator` ⇒ **V8 堆打满**)→ 07:46 熔断 →
|
|||
|
|
平台**自动回滚**(`package.json.bak-rollback-20260913T0748`)⇒ 现在 guest bundles 里**没有** mcn-suite。
|
|||
|
|
根因指向 `--max-old-space-size=160` 太紧(档案 74)+ guest cgroup 峰值贴顶 ⇒ 详见 `04-调整方案/74` 文末「现场反证」。
|
|||
|
|
**admin 侧**自 09-13 00:02 起一直启用且各项实证通过(上表 A/E/I/K 均取自 admin)。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 十、收尾记录(2026-09-13 18:0x)
|
|||
|
|
|
|||
|
|
### 本轮补齐的 gap
|
|||
|
|
|
|||
|
|
| 项 | 结果 |
|
|||
|
|
|---|---|
|
|||
|
|
| **guest 启用**(原「剩余」第 1 条,单子长期卡点) | ✅ **已完成** —— `POST /api/plugins/mine/apply` `{id: dsh-plugin-mcn-suite, enabled: true}` → 任务 **`c20739a6dbe8975c`** → `status=success` / `stage=完成` / **`restarted=true`**;启用后 bundles 含 `dsh-plugin-mcn-suite` ✓ |
|
|||
|
|
| 容量前置(07:4x 崩溃的根因) | ✅ **已解除** —— 档案 79 两处 P0 已修;R1-④ 动态配额生效(guest 装前 672 MiB → 装后 **800 MiB**)⇒ 「V8 堆打满 abort → 自动回滚」不再复现 |
|
|||
|
|
| §八 **L** 凭据扫描 | ✅ **通过** —— `ak_`+32hex **0**、`sk-` **0**、`app_id=` **0**、`*.alotbuy.com` **0**;125 处命中均为变量名/文档说明;唯一 32+hex 是 `.manifest.json` 的**文件哈希** |
|
|||
|
|
| §八 **O** 包体积与技能树 | ✅ **通过(口径澄清)** —— SKILL.md 实测 **18** 个;§八 原文期望「36」系**笔误**(主 1 + 一级 4 + `mcn-data-insight` 下二级 13 = 18,与文字描述完全吻合)。包总 4.27 MB / skills 3.55 MB |
|
|||
|
|
| §八 **P** 技能落地形态 | ✅ **通过** —— admin 实例 `skills/mcn-short-video` = **实体目录**(18 个 SKILL.md / 4.6 MB)⇒ 走 §4.2 的 **A(复制)兜底路径** |
|
|||
|
|
| §八 **N** 死引用扫描 | ⚠️ **未定判** —— 自动扫描出 63 处「包内路径对不上」,但抽样 8 个里 **5 个是误报**(引用省略 `references/` 前缀,文件其实在);**内容基本齐全**(16 个 `scripts/` 目录、27 个 `.py`、263 个 `.md`,知识库 12 类齐全)⇒ **不能判不合格**,需人工逐条读;**不阻塞投放** |
|
|||
|
|
| §八 **D / J / Q** | ⏸ **未验**(需浏览器或造场景);按 §九 口径 **不阻塞投放** |
|
|||
|
|
|
|||
|
|
### 归档
|
|||
|
|
|
|||
|
|
- 本单主体目标已达成 ⇒ 按流程移入 `archive/交接单-已完成/`,并在 `INDEX.md §四` 与 `交接单/README.md §一`、`03-路线图与待办.md §二` 三处同步状态。
|
|||
|
|
- **遗留(可选,不阻塞)**:D(实例内入口逐个点开)/ J(agent 按技能名加载)/ Q(三种撞名场景)/ N(死引用逐条人工判定)。
|