回收 411 MB(470 M → 58.8 M),全部经回收站,可恢复: - 待清理/(146.2 M,含 relay 分片 128 M 与 42 项过程目录) - tmp/(32.4 M,按接续棒命名的过程临时区) - .workbuddy/tmp/(39.5 M) - 4 份 workbuddy.db 冗余副本(101 M,09-23 事故的坏副本 / 抢救产物) - tmp/im16/gw/centrifugo 二进制(63.9 M,可重下)+ 缓存残留 入库范围:常驻规则(CODEBUDDY.md / README.md / state.py)、在途接续入口与 接续包、docs/、交付物/、交接单/、归档/、scripts/、.codebuddy/、 .workbuddy/memory/;共 398 件,其中 >60 KB 的 26 件全为文档。 排除(.gitignore):tmp/、待清理/、运行态日志与缓存、*.db 与 DB 备份整目录、 打包二进制(*.tar.gz / *.tgz)、记忆修复前备份。
47 KiB
47 KiB
工作日志 · 2026-09(第 11 片)
⚠️ 本目录日志已按【月】分片(2026-09-15 用户定,单文件 ≤50 KB):同月续片
2026-09.md/2026-09-下.md/2026-09-下2.md/2026-09-下3.md/2026-09-下4.md/2026-09-下5.md/2026-09-下6.md/2026-09-下7.md/2026-09-下8.md/2026-09-下9.md/2026-09-下10.md/2026-09-下11.md/2026-09-下12.md/2026-09-下13.md/2026-09-下14.md/2026-09-下15.md/2026-09-下16.md/2026-09-下17.md/2026-09-下18.md/2026-09-下19.md/2026-09-下20.md/2026-09-下21.md/2026-09-下22.md/2026-09-下23.md写入约定:一律 append 到当月最后一片;该片超 50 KB ⇒ 新建2026-09-下N.md;⛔ 不要再按日新建2026-09-DD.md。 覆盖来源:2026-09-12.md、2026-09-13.md 上一片:2026-09-下9.md下一片:2026-09-下11.md
22:3x 用户截图「仍是列表」→ 定位(符合预期:实例比新包早启动 17 分钟)
- 用户 22:34 截图「功能管理」仍是列表(但数据已是新的:
dsh-plugin-mcn-suite v0.3.2✓)。 - 定位三条:① 磁盘包 = 0.2.6、含
gridTemplateColumns✓(新代码在位)② admin 实例当时是 22:12 启动的那个(用户试装那次),早于我 22:29 部署 17 分钟 ⇒ 实例内存里加载的是旧 bundle ✓ ③ 复核时 admin/guest 两个实例均已 inactive(已回收)。 - 机制确认:client bundle 由实例进程提供 ——
/plugins/??<pkgs>&rev=<hash>是实例侧路由(从平台侧请求同一路径返回 404 Route not found)⇒ 改 client bundle 必须重启实例才生效。 - 下一步:用户再访问一次实例(建议硬刷新 Ctrl+Shift+R,防浏览器缓存)→ 实例冷启动即加载 0.2.6 → 可见卡片;顺便可在卡片里启用 mcn-suite 0.3.2。
22:4x 「还是列表」深挖 → 结论:没改错地方(是实例/缓存时序)
- 用户质疑「是不是改错地方了」→ 全面核对三条证据:
① 全盘扫同名
client.js:只有 0.2.6 那份含卡片代码(两个用户 profile 的node_modules/.pnpm/@dsh-local+business-plugins@file+..+..+.dsh-stage+business-plugins-0.2.6.tgz/.../lib/client.js命中 1);0.1.0–0.2.5 的 8 份历史副本全部命中 0。 ②readlink -f确认 profile 的node_modules/@dsh-local/business-plugins软链到的正是 0.2.6 那份 ⇒ 实例读的就是新代码 ✓ ③ ⚠️ 易误判点(记下来):服务器/opt/dshs/poc/business-plugins/lib/client.js是旧的 —— 那只是源码副本,不是实例读取路径;去那里 grep 会误判成"没改"。 - 实例生命周期核对:
POST https://alotbuy.com/api/dsh/enter(注意:/api/dsh/*在门户域,实例子域没有)→{"status":"running","port":44193};实际 scope =dsh-114801-22f3c08d.scope(新 id),旧 id0c033dbe已停 ⇒ 当前实例加载的就是 0.2.6。 - 未完成:
/plugins/??<pkgs>&rev=的 URL 形态没试对(单包 +&token=组合均 404)⇒ 没能直接抓到「HTTP 返回新版」;结论建立在「磁盘命中 + 实例新进程」两条证据上。 - 下一步:请用户用无痕窗口访问(排除浏览器缓存)。
22:5x 决定性验证:位置对 ✓ 服务端对 ✓ ⇒ 是浏览器缓存(且发现平台 rev 缺陷)
- 按项目约定用
-L --compressed -c/-b jar -H "Accept: text/html"取到实例页 HTML(10068 B)→ 抠出真实 bundle URL(HTML 里&被转义成&,还原后请求):HTTP=200 size=3,792,974、gridTemplateColumns命中 1(新版卡片代码在内)、「功能管理」命中 2(确认就是该 section)。 - ⇒ 三条证据闭合:① 位置没错 —— 就是「设置 → 功能管理」那个 bundle(
@dsh-local/business-plugins)② 服务端返回的是新版 ③ 磁盘也是新版(唯一有效副本,软链到.pnpm/…0.2.6…)。 - ⇒ 用户看到旧版 = 浏览器缓存(不是改错地方、不是部署失败)。
- ⚠️ 发现平台缺陷(值得修):资源 URL 的
rev参数没随包更新变 —— 0.2.5→0.2.6 之后仍是rev=03857f16ea9c(与 22:33 日志完全一致)⇒ 浏览器 URL 不变、有理由继续命中共缓存。建议:rev应基于包内容 / 版本计算(当前依据不明)。 - 下一步:用户用无痕窗口访问(排除缓存)。
23:0x rev 深挖结论:服务端给的是新版;是浏览器缓存;rev 在官方包、平台修不了
- rev 的来源(dsh 官方包,只读):
dsh-client-modules/lib/index.js→rev = revision ?? framedHash("combo", [sourceBytes, sourceMap]);注释「sha1 content hash shortened to 12 hex chars」「Versioned code is immutable; mismatched revisions are rejected instead of serving newer bytes」。⇒ rev 由 dsh 官方生成,平台不得改(R2)。 - 排除的两个嫌疑:① nginx 的
expires 30d只作用于location ~* ^/assets/(/plugins/走location /,无缓存头)②profiles/web/.dsh-module-fallback是空目录(只有个空 node_modules);.dsh-biz-plugins.log只记apply pid=2时间戳,非加载日志。 - 决定性事实:我按实例页 HTML 里的真实 URL 请求该 bundle(还原
&)→ HTTP 200 / 3,792,974 B / 「功能管理」命中 2 /gridTemplateColumns命中 1 ⇒ 服务端返回的就是新版。 - ⇒ 根因 = 浏览器缓存:页面 URL 的
rev仍是03857f16ea9c(与 22:33 一致)→ 浏览器认为缓存有效 → 不重新请求。这也解释了"硬刷新前仍是旧的"。 - 提给用户的两个选项:A(0 成本、推荐)无痕窗口 / 清站点数据 → 立刻可见;B(治本、较重)平台代理层给
/plugins/加Cache-Control: no-cache→ 以后 bundle 更新自动生效,代价 = 改平台代码 + build + 重启dshs(全体在线用户断约 10 秒)。
23:0x 治本完成:平台加 Cache-Control: no-cache + 机制固化到 06-工作台UI规范 §7
- 用户要求:「需要治本 所有UI修改相关的任务都要使用这个机制,不然太难排查了」。
- ① 平台侧实现:
src/supervisor/proxy.ts响应头组装处新增 —— 对实例/plugins/(与/assets/)统一加Cache-Control: no-cache(允许缓存但每次回源校验)。已 build + 部署 + 重启dshs(23:04:08;全站断约 10 秒,用户已同意治本)。 - ② 验证:
/plugins/…响应头确带cache-control: no-cache✓(对照/assets/被 nginxexpires 30d覆盖成max-age=2678400—— 但/assets/是 dsh 构建产物、文件名带 hash,30d 合理,无需处理)。 - ③ 决定性验证:实例重启后抓实例页 HTML →
rev由03857f16ea9c变为fa213c11e8aa⇒ 内容确实换新、URL 随之变化 ⇒ 浏览器会自动重新拉,用户无需清缓存/换无痕。 - ④ 机制固化(用户明确要求):
06-工作台UI规范.md新增 §7「UI 改动的生效链路与验收」(生效链路四关 / 平台侧机制 / 三段式验收 / 四个常见误判);项目根CODEBUDDY.md §2加对应指针。 - 备份:服务器
proxy.ts/proxy.js的.bak-cachefix-2305。现场:两把锁已释放、临时脚本已清、三件套 rc=0。
23:2x admin 启用插件失败 → 根因「插件漏声明 xlsx 依赖」→ 修 0.3.3 并真实验证通过
- 现象:用户「用admin账号测试启动插件还是有问题」。
- 取证(journalctl 原文):
failed to import loader entry mcn-suite (dsh-plugin-mcn-suite): **Cannot find package "xlsx**imported from…/lib/host/mcn/imports.js→ 实例exitCode: 1+[crash-restart]⇒ 崩溃重启(与档案 70 anysearch 同型:插件加载失败 → 全或无 → 实例起不来)。 - 根因:
imports.js首行import XLSX from "xlsx",但整合包package.json未声明该依赖(dependencies 只有 react/react-dom)。全包 import 扫描确认:外部依赖仅缺xlsx(react/react-dom 已声明;@deepseek-ai/dsh-llm由平台提供)。 - 修法:
dependencies补"xlsx": "^0.18.5";版本 0.3.2 → 0.3.3;重打包 → 上传 HTTP 200 / replaced:true。 - 止损:admin 的
bundles/dependencies摘掉坏的 mcn-suite(第一次 python 因 ssh 引号失败未生效 → 改 heredoc 脚本后成功)⇒ 实例不再崩。 - ★真实验证(用户已被坑两次,故先验):装上 0.3.3 + 加进 bundles + 拉起实例 → 日志
[mcn-suite] loaded/host 面已注册: mcn, mcn-schedule, voxemw-cloud/skills ensured: 装 [email protected](新装),无 crash-restart、无 failed to import ⇒ 通过 ✓;验后恢复原状(bundles 回 5 个)。 - 遗留小瑕疵:插件内部
console.log的版本字符串仍写v0.3.0(不影响功能)。 - ⚠️ 教训:ssh 内联
python3 -c的引号两次把改动吞掉(第一次止损静默失败)→ 凡带引号的远程改动一律「本地写脚本 → scp → 执行」(档案 70 已记过,本次又犯)。
23:2x 用户问「为什么要删除」→ 认错并修复:rm -rf node_modules/<pkg> 留下孤儿包
- 我的操作:试装验证 0.3.3 后为「恢复原状」,清理时用了
pnpm remove+rm -rf兜底。 - 错在哪:
rm -rf node_modules/dsh-plugin-mcn-suite只删包目录、不删依赖树 ⇒ 留下xlsx的 7 个子依赖(adler-32 / cfb / codepage / crc-32 / frac / ssf / wmf)在顶层 node_modules,与.modules.yaml记录不一致。不致命(实例启动正常)但状态脏。 - 为什么会加
rm -rf兜底:之前pnpm remove报CANNOT_REMOVE_MISSING(那时 package.json 已被恢复、里面没这条依赖)⇒ 我误以为「remove 用不了」而手删。正确动作是pnpm install(按 package.json 自愈,pnpm 自己 prune)。 - 修复:以 admin 身份跑
pnpm install→Packages: -15(自动清掉 15 个孤儿)→ 顶层 node_modules 只剩@dsh-local✓、bundles 5 个 ✓。 - 顺带确认:admin 实例启动正常(
dsh-114801-cdb5d7c0.scope active+dsh web: http://127.0.0.1:46221/),下午那次崩溃是 xlsx 缺依赖所致,与本次删除无关。另:23:23:43 有一次平台服务重启(用户手动点的,成功)。 - 已固化:项目根
CODEBUDDY.md §7补「插件安装 / 卸载 / 清理一律走 pnpm;⛔ 禁rm -rf node_modules/<pkg>」+ 本次实测后果与正确动作。
23:3x 「Failed to load plugins」→ 根因「整合包没按包名注册自己」;修 client 注册 + host 同步 + 工作空间统一 mcn-task(0.3.5)
- 用户给的报错:
bundle …dsh-plugin-mcn-suite/client.js… **loaded without registering "dsh-plugin-mcn-suite" via __ModuleLoader__.load**。 - 根因①(致命):整合包的
client.js是把 6 个原包 client 原样拼接的,那些window.__ModuleLoader__.load({id:"dsh-plugin-mcn",…})注册的是各自的原包 id ⇒ 本包 id 从未注册。而 dsh 按包名找 ⇒ 直接拒载。 - 修法①:改
scripts/build-mcn-suite.cjs加整合包注册层 —— 6 处 load 改写为window.__mcnSuiteCollect({...})(收集),再追加本包的load({id:"dsh-plugin-mcn-suite", factory}),其 factory 驱动 6 个子包 factory 并把inject取并集(硬编码兜底 runtime+sidebar)。自检:整合包 load = 1 / 子包 collect = 6 / 注册 id = 7✓ - 根因②:整合包的 host 面是 T03 时手工复制的旧副本(停在 10:36,原包已到 23:33)⇒ 改原包 host 代码不会进包(本次白打一次包)。修法②:build 脚本增加
[build-host]段,每次从原包同步lib/*.js到host/{mcn,schedule,voxemw}/,排除client.js与*.bak*。 - 顺带完成用户新需求:「MCN 工作台所有功能调用 AI 会话的工作空间统一叫
mcn-task」 —— 改lib/index.js13 处:6 处join(resolveCreativeCwd(), "<旧名>")→"mcn-task"、5 处reg.create(dir, …)、4 处setTitle(…)、1 处cwd:。 - 版本 0.3.5:三重验证 —— ①
client.js含本包注册 =1 ✓ ②host/mcn/index.js含mcn-task=14 ✓ ③ 依赖含xlsx=1 ✓;上传 HTTP 200;更新 admin 已装(pnpm add 指向候选池新 tgz)→ 0.3.5 ✓;重启 admin 实例验证 →[mcn-suite] loaded+ 3 个 host 面注册 +skills ensured✓ 无 crash、无 failed to import。 - 待用户确认:浏览器侧 client 面(刷新后不应再报 Failed to load plugins)。
- 备注:插件内部
console.log仍打印v0.3.0(纯文案,未随包版本更新)。
23:4x 第二轮报错「pending (waiting for services: …)」→ 根因「inject 写成了数组,应为函数」→ 0.3.6
- 用户给的第二个报错:
web boot: 1 entry did not activate+dsh-plugin-mcn-suite: **pending (waiting for services: @deepseek-ai/dsh-client-runtime, @deepseek-ai/dsh-client-ui-sidebar)**。 - 根因:dsh client bundle 的
inject是函数(原包写法inject: () => ({}),返回「要注入的服务映射」);我在整合包注册层里硬编码成了数组["@deepseek-ai/dsh-client-runtime", …]⇒ dsh 把它理解成「在等这些服务」⇒ 条目永远 pending。 - 修法:改为
inject: function () { … }—— 遍历子包,typeof m.inject === "function" ? m.inject() : m.inject取并集后返回对象;并去掉硬编码常量。 - 0.3.6:上传 HTTP 200 /
replaced:true/compat: ok;更新 admin → 0.3.6(inject 是函数=1、mcn-task=14 ✓);重启实例 →[mcn-suite] loaded+ 3 个 host 面注册 +dsh web:✓、无 failed to import。 - 待用户确认:刷新后 client 面(应不再 pending)。
- ⚠️ 教训(值得进规则):给 dsh 写 client bundle 时,
inject必须是函数(() => ({})),不是数组;数组会被当成「等待的服务名」而永久 pending —— 这个坑服务端日志完全看不出来,只在浏览器里暴露。
23:5x 「工作区统一 mcn-task」第二批:修 2 处 Windows 路径 fallback(0.3.7 / 0.3.8)
- 用户追问①:「为什么还是会创建 解析任务 / 计划任务 两个分组」。
- 根因(第二批):两个包各有一份独立的「读 workspace.json 取根工作区」实现,两处都读错路径 + fallback 都是
D://dshworkspace: ·dsh-plugin-mcn/lib/config.js的resolveCreativeCwd()·dsh-plugin-mcn-schedule/lib/index.js的resolveWorkspaceRoot()两者都用homedir()/.dsh/storages/workspace.json(实际在$DSH_HOME/storages/)⇒ 永远读不到 ⇒ 走 fallback"D://dshworkspace"⇒ Linux 下被当成目录名。 - 用户追问②:「工作区目录里面有个 d://dsworkspace 明显不对 这个是之前在windows上的路径」—— 正是同一根因(用户自己看出来 ✓)。
- 修法:两处都改为 多路径尝试(
$DSH_HOME/storages/→homedir()/storages/→homedir()/.dsh/storages/)+ fallback 改为homedir()(实例内 HOME 已由平台指向 ws)。版本 0.3.7(改 config)→ 0.3.8(补 schedule)。 - 进展:0.3.8 部署后
mcn-task → ws/mcnworkspace/mcn-task✓ 新路径正确出现。 - 残留:
计划任务 → ws/D://dshworkspace/计划任务、mcn-task → ws/D://dshworkspace/mcn-task仍在实例启动时被重建 ⇒ 源码里已搜不到D://dshworkspace(两处都改完 ✓)⇒ 判定为旧 workspace 记录/目录被恢复(非源码问题)→ 待清ws/下的带盘符目录 + 重清注册表。 - 期间踩坑:
pnpm add file:首次上传 HTTP 400(内联命令引号问题)→ 改脚本后 HTTP 200;再次验证「带引号的远程操作必须写脚本」。
23:5x 工作区统一 mcn-task —— 收尾状态(新路径已生效,旧记录残留未清净)
- ✅ 已生效:
mcn-task → ws/mcnworkspace/mcn-task(新代码路径正确 ✓);ws/D://dshworkspace目录已删、.node-compile-cache与ws/.cache已清、实例已重启。 - ✗ 残留:注册表里仍有
mcn-task → ws/D://dshworkspace/mcn-task(旧路径),以及计划任务分组。 - 关键判据(本轮最重要的一条):清理动作是在拉起实例之前执行的,当时输出
剩余: [mcnworkspace, mcntimo, mcn-task, mcn-task]⇒ 那两条旧的不是在启动时被重建的,而是历史记录本身没被我的过滤条件删掉(过滤用了"D:////////dshworkspace" not in path,在 heredoc 里经多层转义后没能匹配上)。 - ⇒ 结论修正:不是「实例用旧代码重建」,而是「旧注册记录没清干净」。代码侧两处 fallback 已修完(源码 grep
D://dshworkspace已为空 ✓)。 - 下一步(明确):按 path 精确匹配(不做字符串转义,改从 JSON 解析后
endswith/in判断并打印命中项)重清一次;或最直接:用户在实例里手动删掉「计划任务」分组(UI 一秒)。 - 今日代价提示:这一轮为追这个 bug 连续打了 0.3.5→0.3.8 四个包;根因是「两处独立的 Windows 路径 fallback + 旧注册记录」。
23:5x 「插件已启用但看不到 MCN 工作台入口」→ 定位到两处,暂停等明天
- 已确认正常:host 面
[mcn-suite] loaded+ 3 个 host 面注册;侧边栏入口是 client 面注册的(ctx.slots.inject("sidebar.footer.action", …),见 client.js 3042/3053 行)。 - ⚠️ 发现缺陷①(我引入):生成的
client.js里有两份注册层 —— 第 5522 行还是旧的var inject = ["@deepseek-ai/…"](数组),文件末尾才是新的inject: function()。原因:构建脚本的替换只匹配行首window.__ModuleLoader__.load({,把「上一轮生成时已有的旧注册层」也一并当成子包收集了 ⇒ 新层驱动旧层、旧层再驱动 6 个子包(重复注册)。修法:生成前先剔除文件里已有的注册层标记(或改为「不追加、就地改写」),并在自检里断言「注册层恰好 1 份」。 - ⚠️ 疑问②(待浏览器验证):
inject返回{}(原包写法就是inject: () => ({}))是否足以让ctx.slots可用 —— 若不够,侧边栏注册会失败、入口不显示。只有浏览器控制台能判定(host 日志看不到)。 - 下一步(明天):① 修构建脚本的注册层重复 → 重打包;② 让用户硬刷新看控制台是否仍有
Failed to load plugins/pending;③ 若 inject 语义不足,改为按 T03 单子原设计在package.json的dsh.client.inject里声明[runtime, sidebar](当前已有 ✓)并核对 dsh 对 clientinject的期望形态。 - 暂停理由:已连续打 0.3.5→0.3.8 四个包、跨 5 小时;继续在低质量状态下改会引入新问题(用户偏好里明确「方案规划与落地执行分开、状态不好不硬推」)。
23:47 恢复机制全景梳理 + 现场发现(会话:恢复机制展示)
- 用户问「能否检测用户是否回到 dsh 页面 / 自动恢复进程状态,体验不自然」→ 逐场景梳理线上恢复机制(代码 + 生产日志双向核对)。
- 机制现状(四层,出处见代码/档案):
- 浏览器注入
__dshRecover(proxy.ts L56-287):visibilitychange/focus/pageshow→ 跨域探活/api/dsh/status(15s 节流)→recover();识别 404+not_running(fetchclone().text()/ XHRresponseText);401+/api/→expire()→reload();请求挂起 ≥3s → 覆盖层(SLOW_MS=3000)。 - 代理
proxy.ts:导航 404 → 302/wake.html?next=(不阻塞);非导航 404 →launch()+waitForLaunchTokenForUser(20000)+ 重新 resolve + 转发;实例侧 401 导航 → 302 带新 token;实例侧 401 XHR → 取新dsh-auth-*覆盖 cookie 重放一次 + 回写 Set-Cookie;门户侧 401 导航 → 302 login.html。 - 编排器:崩溃 → 指数退避(1s→30s)重启;
crashStableMs=60s稳定即重置;10 分钟 5 次熔断;插件加载失败自动摘除 + 清计数;cap 4 LRU + 7 天 TTL。
- 浏览器注入
- 重要事实纠正:
/etc/dshs.env未设IDLE_TTL/MAX_IDLE_INSTANCES→ 生效值 = 7 天 TTL + cap 4。全历史idle-reap仅 1 次(09-09)→「空闲回收」基本从未发生;instance-restart106 次 ⇒ 实例中断主因是崩溃/被停,注入脚本文案「实例已休眠(空闲回收)」归因不准。 - ⛔ 现场发现(只报告,未处置):admin 实例(uuid
cce6d1cd/ uid 114801)23:18 起每 2–4 分钟重启一次(23:37:45 / 23:41:06 / 23:45:29 / 23:46:45 / 23:48:45 / 23:50:50…)。每次 scope 均为Succeeded(干净退出,非 OOM/ABRT);crash-restart事件无 exitCode 字段(exitCode = code ?? undefined)。23:18:10 曾因Cannot find package 'xlsx'(dsh-plugin-mcn-suite/lib/host/mcn/imports.js)插件树加载失败并熔断。⇒ 用户体感「不自然」的直接来源 = 恢复流程被反复触发(同期日志/api/dsh/status×19、POST /api/dsh/enter×7、GET /×10)。 - 机制缺口(新发现):
crashStableMs=60s小于崩溃周期(2–4 分钟)⇒ 每次崩溃前都「稳定过」→ 退避步数/streak 被重置(attempt 恒 1、delayMs 恒 1000)→ 周期性死亡永不熔断,恢复流程可以无限反复弹。 - 未改任何文件;未抢锁;未 commit。
- ⚠️ 更正(同日 23:58,同一会话自查):上条「周期性死亡永不熔断」表述有误。实测
stableTimers到点只crashStreak.delete()(只清 streak,不清crashHistory)→ 窗口计数照常累积,熔断会触发(生产日志 23:50:50 已到restartsInWindow:5)。真正的缺口是:熔断后mains.delete+resetCrashState(),而用户下一次launch()/enter(L127)又resetCrashState()→ 计数清零、重新给足 5 次预算 ⇒ 崩溃循环可无限期重复(每轮 ≈10 分钟),且熔断只写 stderr 日志、无告警。
23:54 「回到页面看不到拉起提示」根因定位(用户澄清后的追加排查)
- 用户澄清:不自然之处 = 回到页面从来没看到过「拉起实例」的提示(不是嫌流程慢)。
- 验证 1 · 注入脚本确实在页面上(R4 临时会话 → 用完即删,删除 2 条
poc-curl2历史残留):curl -s -L --compressed -c jar -b jar -b "sid=$TOKEN" -H "Accept: text/html,application/xhtml+xml" https://admin.alotbuy.com/→http=200 size=9994,__dshRecover=7 / __dshAssist=6 / visibilitychange=1 / not_running=3 / SLOW_MS=2。注入正常,脚本在跑。 - 验证 2 · 注入会被跳过的旁证:全历史
[inject-recovery] skip: content-encoding=gzip11 次,最近两次 09-12 22:40:25 / 23:26:55(正落在崩溃循环期间)→ 这些页面加载没有自愈脚本,是次要但真实的洞。 - ★ 根因(代码级,决定性):注入脚本
probe()只在j.running === false时才recover();而running来自dsh.ts的alive(status)——alive()把starting也算活着(status !== crashed/stopped/failed)。 又实测每次崩溃后 新 scope 在同一秒或 1 秒内就起来(23:37:46→23:37:46、23:41:06→23:41:07、23:45:29→23:45:30、23:46:45→23:46:46、23:48:45→23:48:46、23:50:50→23:50:51)。 ⇒ 用户切回标签页时实例几乎总是starting/running→probe()判定「没问题」→ 不提示、不恢复。 用户看到的"死页面"完全没有任何反馈 —— 与他的描述完全吻合。这不是概率问题,是逻辑条件选错了判据。 - 次要根因:即便
recover()真触发,覆盖层只活 600 ms 就location.replace(wake.html);而实例已在跑时 wake.html 的enter立即返回 url → 过渡页一闪而过。两处叠加 ⇒ 提示即便存在也肉眼不可见。 - 修复方案(已定,未实施;需 R8 窗口):改
proxy.ts注入脚本 —— ① 判据从「进程在不在跑」改为「页面还能不能连上实例」(新增同源轻探针,404/405 时降级回旧判据以免官方升级误报);② 提示可见:切回页面先亮顶部轻提示,判定脱节后升级为不自动消失的覆盖层;③ 恢复就地(自己调 enter 拿新 URL + 保留路径),不再跳门户域;④ 文案去掉「空闲回收」归因。改动面 1 个源文件 + build + 重启 dshs(断在线用户数秒)。 - 未改任何代码;未抢锁;未 commit。
00:0x 「看不到 MCN 工作台入口」—— 逻辑层已用模拟验证全对,卡在浏览器侧
- 修正上一条的误判:client.js 里第 5522 行的
var inject = [...]只是我留下的未使用变量(无害),不是"两份注册层"。 - 读官方源码确认契约(
dsh-client-modules): ·package.json的dsh.client.inject= 字符串数组 = 依赖的包名(index.js:145optionalStringArray(pkgName, "dsh.client.inject", decl.inject)); · client bundlefactory()返回的inject= 函数(cordis 服务注入,返回服务映射); · 二者不是一回事 —— 之前报waiting for services: @deepseek-ai/…就是把这个函数写成了包名数组(0.3.6 已修)。 - ★用 node 模拟
__ModuleLoader__跑真实 client.js 的结果(决定性): ·load()调用 1 次(只有整合包)✓; · 收集到 6 个子包(dsh-plugin-mcn/mcn-schedule/voxemw-cloud/douyin-accounts/douyin-account-detail/douyin-video-detail)✓; · 整合包 factory 返回{inject, apply}、inject是函数返回{}、apply是函数 ✓。 · ⚠️ 「apply 期间 slots.inject 调用 0 次」不能作为结论 —— 模拟里 6 个子包 factory 都因假require缺 React 运行时抛错(Cannot set properties of undefined (setting plugin)),是 mock 不够真,非真实故障。 - ⇒ 结论:代码侧(注册层 / inject 形态 / 子包收集)已全对,剩下的是浏览器运行时的真实行为。
- 下一步(唯一缺的一步):在管理员浏览器里 F12 → Console 看真实报错;若不再有
Failed to load plugins,则问题在「入口注册的 slot 位置/可见条件」,需对着sidebar.footer.action的实际渲染确认。 - 期间尝试用
agent-browser直接开实例页(需实例 token)→ 取 token 时node -e引号再次失败,未完成(第 3 次踩同一个坑:一律写脚本,不要内联)。
23:57「现在改」→ 抢锁失败,按 R9 停手(改动已备好)
- 用户答复「现在改」。执行第一步
--claim-exec抢锁失败:两把锁都被占.exec-lock:占用者uv-deploy-2317(09-12 23:17 起,未声明单号)/opt/dsh/state/.op-lock/univer-fork-deploy:占用者同人;摘要 univer-fork-deploy;影响面 「覆盖候选池 dsh-univer-office.tgz(0.2.14→0.2.15)+ guest 实例重装重启」
- 按 R9 停手:不得人工删锁/接管,未动代码仓库、文档库、服务器。
- 顺带核到的实况(只读):近 1 小时 admin(114801) 换了 17 个 scope(= 被重启 17 次),guest(100002) 3 次 —— 与我 23:47 报的「admin 每 2–4 分钟重启一次」一致,可能与该部署会话有关(时间吻合:锁 23:17 → admin 23:18 起崩溃循环),但 op-lock 摘要写的是 guest,需该会话自证。
- 改动已备好(未落地):
_patch77/inplace-recover-patch.md(放在受保护根之外,含 5 处精确编辑的 old/new、落地步骤、回滚、红线)。锁一释放即可机械落地。- 要点:① 判据从「进程在不在跑」→「页面能不能连上实例」(新增同源探针
GET /,2.5s 超时;404/405 →unknown降级回旧判据,绝不误报)② 顶部轻提示条 + 不自动消失的覆盖层(__dshConnBar)③ 就地恢复(自己调/api/dsh/enter+withPath()保留路径,不再跳门户域)④ 去掉「空闲回收」归因文案。
- 要点:① 判据从「进程在不在跑」→「页面能不能连上实例」(新增同源探针
- 未 commit。
00:0x ★用户贴控制台报错 → 一句话定位根因 → 0.3.9 修好
- 用户给的报错(决定性):
[mcn-suite] 子包 apply 失败: Error: **cannot get property "slots" without inject**atModule.apply (client.js:3042)。 - 根因(读子包真身):
dsh-plugin-mcn/lib/client.js的写法是 ——const inject = ["slots", "sessions"]; function apply(ctx){ ctx.slots.inject("sidebar.footer.action", …) } exports.inject = inject;⇒inject是「要注入的服务名」数组,元素是slots/sessions这类服务名。 - 我错了两次(都在这一处):
· 写包名数组
["@deepseek-ai/dsh-client-runtime", …]→pending (waiting for services: @deepseek-ai/…); · 改成函数inject: function(){ return {} }→cannot get property "slots" without inject(ctx.slots 拿不到,入口注册失败 ⇒ 看不到 MCN 工作台入口)。 · 正解 = 子包 inject 的并集(["slots","sessions",…],起点空数组var inject = []+ 合并 6 个子包)。 - 0.3.9 已部署:上传 200 / 候选池 0.3.9 / 已装 0.3.9 /
var inject = []命中 1 / 子包["slots","sessions"]命中 2 / 实例重启[mcn-suite] loaded+ 3 host 面 ✓。 - 教训(已进规则):dsh client bundle 的
inject是服务名数组,与package.json的dsh.client.inject(包名数组)同名不同义 —— 这是本次连续打 5 个包的根因。 - 另一条:浏览器控制台的报错文本是这类问题唯一的定位线索(服务端日志全程显示正常)——用户贴的那两行,比我之前所有服务端排查都有效。
00:03(09-13)「继续修改」→ 锁仍未释放;原地做完两项只读预验证
- 复抢锁:仍失败,
uv-deploy-2317自 23:17 持有.exec-lock+/opt/dsh/state/.op-lock/univer-fork-deploy(已 46 分钟)。按 R9 继续不动代码仓库/文档库/服务器。 - 预验证 1 · CORS 通过(本方案前提):
OPTIONS https://alotbuy.com/api/dsh/enter,Origin: https://admin.alotbuy.com→204+allow-origin: https://admin.alotbuy.com+allow-credentials: true+allow-headers: Content-Type;无 cookie 的 POST →401且带 CORS 头。⇒ 注入脚本跨域调enter合法可用。 - 预验证 2 ·
[inject-recovery] skip: content-encoding=gzip系假警报:两次跳过(09-12 22:40:25 / 23:26:55)的上下文均为[proxy-auth-replay] GET /+remoteAddress= 47.77.182.89(服务器本机)/CF 回源;即我们自己的验证 curl(默认Accept: */*不含text/html→ 代理不覆盖accept-encoding: identity→ 上游 gzip → 跳过注入)。真实浏览器导航必带text/html(三件套 curl 实测__dshRecover=7)。⇒ 不需要为此改动,草案四项编辑已足够。 - 草案已更新:
_patch77/inplace-recover-patch.md(新增 §5 预验证、§6 仍未解决的项)。 - 未改任何受保护资源;未 commit。
00:07(09-13)用户问「uv-deploy-2317 没看到这个会话」→ 查明身份
uv-deploy-2317不是 UI 会话标题,是那个会话 23:17 抢锁时自己填的ME(本项目约定<主题>-<HHMM>)。锁文件路径:dsh-server-docs/交接单/.exec-lock/OWNER(三行:OWNER / 开始 / 在做)。- 从共享日志(同一份
2026-09-12.md)还原出它的轨迹:23:17 先做 univer-office 投放(op-lock 摘要univer-fork-deploy:候选池 0.2.14→0.2.15 + guest 重装重启),23:2x 起一路在做dsh-plugin-mcn-suite插件(0.3.2→0.3.9,最后一条 00:0x「用户贴控制台报错 → 0.3.9 修好」)。 ⇒ 它极可能就是当前仍在交互的那个「插件调试」会话(用户正往里贴控制台报错),按uv-deploy-2317这个名字当然找不到。锁是活的,不是孤儿。 - 同时解开上一个悬案:admin 实例 1 小时内 17 次重启 = 插件会话每升一版就重启实例验证(23:2x 那次
Cannot find package 'xlsx'是 0.3.2 漏声明依赖,0.3.3 已修)。与平台回收机制无关,与本补丁无关。 - 释放命令(只应由用户本人执行;会话仍在跑时释放会破坏互斥):
bash scripts/handoff-guard.sh --release-exec|ME="uv-deploy-2317" bash scripts/op-lock.sh release univer-fork-deploy - 草案 §6 已更新。
00:10-00:20(09-13)档案 77 落地完成:回到页面自检 + 就地恢复(恢复过程可见化)
- 用户授权解锁("看不到还有别的会话执行,批准解锁")→ 按项目章程用
--release-exec+FORCE=1 release univer-fork-deploy处置(用户明确点头,非 AI 单方面接管);随后以recover-inplace-77重占两把锁。解锁前抽查:近 6 分钟无文件写入。 - 改动(唯一文件
D:/github/dsh_shenxian/src/supervisor/proxy.ts,5 处编辑,全在注入脚本SESSION_RECOVERY_JS): ①poke()探针(同源GET /,redirect:'manual'+no-store+2.5s 超时;200→ok,404/405→unknown 降级回旧判据,其余→bad) ②probe(withNotice):门户口running:false直接恢复,否则poke()bad 才恢复 ③ 顶部轻提示条#__dshConnBar(ensureBar/showBar/hideBar,最少显示 900ms) ④recover()就地恢复:跨域POST /api/dsh/enter+withPath()保留 pathname/hash →location.replace();取不到则 reload ⑤ 触发细分:visibilitychange+leftAt(离开 ≥20s 才亮提示条);focus静默;pageshow(persisted)带提示 ⑥ 文案:去掉「空闲回收」归因;expire()文案改「正在重新连接你的工作区…」 - 验证(全绿):
- 本地
npm run buildrc=0;模板字符串反引号 0 /${0(长度 6604→10634) - 编译产物抽
SESSION_RECOVERY_JS/SESSION_ASSIST_JS→new Function()双通过 - CORS 前提实测:
OPTIONS /api/dsh/enter+Origin: https://admin.alotbuy.com→204+ allow-origin + allow-credentials + allow-headers: Content-Type - 传前
diff服务器版 = 本地版(0 行差异,排除带上别人的在途改动);传后md5双向一致、CR 行数=0 - 服务器
npm run buildrc=0 →lib/含新标记;systemctl restart→ active / 门户 200 / 孤儿 scope 0 - 端到端:临时会话
enter200 + 实例running→ 三件套 curl 取实例页 →__dshConnBar/function poke/withPath/rawFetch/leftAt/「正在检查工作区连接」/「工作区正在恢复」全命中;旧文案 0;临时会话deleted_sessions=2 - 回滚点
/opt/dsh/backups/proxy.ts.bak-20260913-0012
- 本地
- 归档:
04-调整方案/77-回到页面自检与就地恢复-恢复过程可见化.md(占号.lock-77,已释放)+INDEX.md加行 +BRIEF.md改「回到实例页面」现行事实行 + 最近动作。四件套:docs-auditrc=0 /docs-manifest刷新 /docs-consistencyrc=0。 - 文档推送:只推我本次碰过的 4 个(77-*.md / INDEX.md / BRIEF.md / docs-manifest.json),chmod 600;复跑对账 125 一致。
⚠️ 如实报告:
BRIEF.md的本地版混有其它会话未推的编辑(T03 候选池状态、待办精简等),随本次一并推上服务器;剩余 6 内容不一致 + 3 仅本地(74/75/76、03-路线图、交接单/README、交接单/T03、06-UI规范、42、67)属其它会话积压,我未动。 - 未 commit / 未 push(用户未要求);本机代码仓与文档库现有未提交项。
2026-09-13 工作日志(append-only)
06:50–07:15 会话 a2665dd3:接管「参考决策方法逐条判断处理」会话的任务(只读 + 配置修复)
- 起因:用户改了工作区路径(
D:\AI技能\aliyun-dsh-server→E:\ProgramData\AI技能\aliyun-dsh-server,D: 旧路径已不存在),要求继续上一会话的任务。
一、目标会话身份已查明
| 项 | 值 |
|---|---|
| 会话 id | b58f0293-d8a6-497d-94d8-af9665553c75 |
| 原始标题 | 「查看dsh项目还有哪些任务待确认和处理」 |
| 09-12 22:55 被自动改名 | 「参考决策方法逐条判断处理」 |
| 生命周期 | 09-12 17:50 建 → 最后活动 09-13 00:09(≈6.3 小时) |
- ⚠️ 本机拿不到该会话转录。桌面版会话内容只在云端(EdgeSync);
~/.workbuddy/projects/最后一份 jsonl 停在 09-12 07:00,之后全部缺席。- 能查到的:元数据在
~/.workbuddy/workbuddy.db(sessions表,但未含本会话,桌面版该库已静态化);标题/创建/重命名/最后活动在~/.workbuddy/logs/<日期>/edge-sync.log。 - ⇒ 复原任务只能靠「共享日志
2026-09-12.md+ 文档库 + 服务端只读实测」三条腿。
- 能查到的:元数据在
二、✅ 修复一个阻断级问题:hooks 路径仍指 D:(本次实测确诊)
- 现象:任何 Write/Edit 都被拒,错误 =
D:\miniconda3\python.exe: can't open file 'D:\AI技能\...\lock-guard-hook.py'(D: 已不存在)。 - 根因:
~/.workbuddy/settings.json的 hooks 两条 command 都是绝对路径,工作区搬迁后失配。 - 修法(只改路径串,未动结构):
sed -i 's#D:/AI技能/aliyun-dsh-server#E:/ProgramData/AI技能/aliyun-dsh-server#g';备份settings.json.bak-pathfix-0655。 - 校验:JSON 顶层键 5 个(
sandbox/claw/enabledPlugins/autoLaunchDesired/hooks)、hooks=PreToolUse+SessionStart均在;写探针文件成功。 - ⛔ 【该结论已被 09-13 07:05 实测推翻——见本文件下方「hooks 语义定论」:hook 命令实为「会话启动时快照」;当时"改完就能写"是被一支临时目录联接掩盖的假象】
- 当时的★结论(修正 09-12 的悬案):hooks 配置是"每次调用现读",不是启动快照 —— 改完立即生效、无需重启;同时
.workbuddy/lock-hook.log有SessionStart/PreToolUse-deny行 ⇒ 桌面版确实加载 hooks(首次正面证据)。- ⚠️ 但钩子只校验「有没有人持锁」,不校验「是不是你」:只要有任一锁存在,任何会话都能写受保护根。
- ⚠️ 副作用(新发现,未处置):无锁时自动化会话(cwd =
D:\github\dsh_shenxian)的 Write/Edit 同样被拒 ——lock-hook.log03:21 / 06:22 两次 deny(.workbuddy/memory/2026-09-13.md)⇒ 「代码仓三方同步」自动化若需提交会被钩子挡住。待用户裁定:给自动化留白名单 or 入disableAllHooks之外的例外。
三、⛔ 未动文档库:全局执行锁被活会话持有
交接单/.exec-lock/OWNER=回到页面实测-0647(09-13 06:51 起),对应会话3c12a818(用户同批开的另一个窗口:继续「检测用户回到dsh页面」)。- 证据:近 20 分钟它已改
BRIEF.md/INDEX.md/README.md/03-路线图/04-73/04-77/06-UI规范/docs-manifest.json/scripts/*,并正在跑浏览器实测(_patch77/shots/:0-初始.png/A-顶部提示条.png/B-恢复后.png/B-恢复覆盖层.png)。 - ⇒ 按 R9 / §6:未抢锁、未改文档库与代码仓、未动服务器(只做只读 ssh)。
四、服务端只读实测(07:01–07:05,bt-server 端口 32022)
| 项 | 实测值 |
|---|---|
| 候选池 | dsh-plugin-mcn-suite.tgz = 0.3.9(09-13 00:02)|dsh-univer-office.tgz = 0.2.15(09-12 23:19,fork 版) |
| admin(uid 114801) | bundles 含 dsh-plugin-mcn-suite(0.3.9 已装);univer 未在 bundles |
| guest(uid 100002) | bundles 无 mcn-suite(⇒ T03 的"guest 启用"仍未做);含 dsh-univer-office 0.2.15(同源代理改造版已上线) |
| guest node_modules | 无 @liustack/modlens 残留 |
| op-lock(服务器侧) | 空闲(仅 README) |
| 实例内存 | guest 208 MiB / admin 210 MiB(上限 384)⇒ 堆限 160 的治理有效 |
| 服务/实例 | dshs active;两个实例 scope 均 running |
五、发现的「账实不符」(只报告,未改)
交接单/README §一T03 行仍写「池内 =0.3.2」→ 实际 0.3.9;BRIEF §3同。03-路线图 §二P1「摘除 guest 仍在启用的@liustack/modlens」→ 实际已完成(guest bundles 与 node_modules 均已无)。03-路线图 §二档案 64/AnySearch 行仍与「已彻底放弃(下架)」并存(BRIEF 已改)。- 档案 76(univer 平台适配)标注状态与「fork 版 0.2.15 已进 guest bundles」的差异 —— 需核该档案是否已含"端到端 400 未闭环"的修正。
六、本次落盘
- 本日志 +
MEMORY.md三处更新(状态表新增「路径迁移」「钩子已实证生效」两行;代码仓/文档库未提交项按 07:0x 复核刷新;§三 改造文档路径改 E:)。 - 探针文件(
_hooktest.txt/dsh-server-docs/_gate_probe.md)已清理。 - 未 commit / 未 push / 未 scp(按 §4,用户未发话)。
06:47–07:10 会话 3c12a818(锁名 回到页面实测-0647):续做「检测用户回到dsh页面」+ 档案 77 浏览器端实测 + 路径全面归位
⚠️ 与上一节(
a2665dd3)同时在跑:它 06:5x 也去修 hooks 路径(sed改 settings.json);我 06:52 先备份、06:53 建了目录联接。两边都改 settings.json 的同一处,结果一致(最终 = E: 路径),无相互破坏(我只做精确 Edit,未整段覆盖)。
一、档案 77 唯一未闭环项 → 已关闭:浏览器端实测 10/10 全绿
- 手段:本机真 Chrome(无头,
playwright-core驱动)+ 临时会话(mksess.cjs,用完即删deleted_sessions=2),未重启服务 / 未停实例 / 未改任何源文件。 - 结果:① 注入落位全中(
__dshConnBar/poke/withPath/LEFT_MS),旧文案「空闲回收」= 0;② 离开 21 s 回来 → 顶部条「正在检查工作区连接…」出现、约 1 s 后自动撤除、未误亮覆盖层;③ 拦截实例侧探针使其失败 → 覆盖层「工作区正在恢复,请稍候…」→POST /api/dsh/enter200 → 就地跳回、仍在admin.alotbuy.com(未跳门户域)。 - 证据截图:
_patch77/shots/(4 张)。结论已回填04-调整方案/77新增 §九(关闭 §四 的 L5)。 - 首次跑的两个 ❌ 是测量脚本的 bug,不是产品问题:① 提示条等待器在 21 s 等待之前启动、被自身 6 s 超时耗光;② 网络过滤写
hostname.endsWith('.alotbuy.com')漏掉裸域alotbuy.com(enter在门户裸域)→ 误报"没调 enter"。 - 环境坑:playwright 装在托管工作区;ESM 不认
NODE_PATH→ 用createRequire;自带 chromium 版本对不上(期望 1210 / 本机 1234)→ 改channel:'chrome';脚本里给 Node 传 bash 风格/e/...路径会在当前盘根建E:\e\...(已删)。
二、hooks 语义定论(含一次自我纠错)
- 起点:工作区一搬,
settings.json里 hooks 的绝对路径失配 → hook 报错 → 本机所有会话 Write/Edit 全被拒(fail-closed)。为不把活断在手上,先建D:/AI技能 → E:/ProgramData/AI技能目录联接救急,同时误以为 hooks 是「启动时快照」。 - 实测结论(2026-09-13 07:05,决定性):hook 命令是「会话启动时快照」。证据链:本会话 06:47 启动(当时配置里仍是 D: 路径)→ 06:55 把配置改成 E: → 07:05 拆掉目录联接后,Write/Edit 报的仍是旧路径
D:/AI技能/...⇒ 改配置对已在跑的会话无效。 - ⚠️ 纠错:中途(07:0x)我曾写成「hooks 每次调用现读、无需重启」,并据此宣布「目录联接多余」——错。真相是联接在 06:53–07:05 期间存在,把"改完就能写"伪装成了现读;同机另一会话(
a2665dd3)独立得出同一错论,可见这就是该误判的成因。 - 正确处置:改完 hook 路径 → 完全重启 WorkBuddy(关窗 ≠ 退出)或新开会话。应急兜底:本钩子不拦 Bash(有意留的安全阀)⇒ 本次余下的文件写入即走 shell 完成。
- 已回填:
CODEBUDDY.md §6、MEMORY.md §五、04-调整方案/73(① 条 + 文末「修正」节)、03-路线图与待办.md。
三、活路径归位到 E:(本次共改 11 个文件;历史档案按「只增不改」保留原值)
| 类别 | 文件 |
|---|---|
| 配置 / 脚本(必须) | ~/.workbuddy/settings.json(hooks×2)、dsh-server-docs/scripts/lock-guard-hook.py(DSH_DOCS_ROOT 默认值)、scripts/docs-sync-check.sh + dsh-server-docs/scripts/docs-sync-check.sh(DOCS_LOCAL_DIR 默认值)、dsh-server-docs/scripts/extract-user-voice.py(目录名示例) |
| 活文档(现行事实) | README.md、INDEX.md、06-工作台UI规范.md(权威源路径×3)、04-调整方案/73(hook 安装片段×5 + 新增「修正」节)、BRIEF.md(新增本机工作区行)、03-路线图与待办.md(新增「工作区迁移 D:→E:」记录) |
| 记忆 | 项目 MEMORY.md(改造文档路径)、用户级 ~/.workbuddy/USER.md(本机工作区) |
- 未改:
01-规划与架构、04-调整方案/11、04-调整方案/12、archive/各篇、历史日志 —— 写于迁移前,属历史(BRIEF/03-路线图 已各加一句"历史 D: 路径 = 迁移前旧值,勿照抄")。 - 代码仓
D:\github\dsh_shenxian未动(不在AI技能之下)。
四、文档库收尾
- 四件套:
docs-auditrc=0 |docs-manifest刷新 |docs-consistencyrc=0 | 对账。 - 只推本次碰过的 11 个文件到
/opt/dsh/docs(档案 600 / README 644)→ 复跑对账:一致 123 → 127。 - ⚠️ 如实报告:其余 4 不一致 + 3 仅本地 是其它会话积压(
交接单/T03、04-42、交接单/README、04-67;04-74/75/76仅本地)——本次未动。 - 未 commit / 未 push。
五、留给用户 / 下一棒
- 历史档案正文里的
D:\AI技能\...未逐处改写(按约定);要连正文一起改,说一声(约 6 个历史文件)。 - 档案 77 §八 遗留 1(崩溃熔断可无限重来 + 无告警)仍待另开档案。
a2665dd3报的 4 条「账实不符」(T03 池内版本 0.3.2→实际 0.3.9 等)未处置。