Files
dsh_ai1net_server/.workbuddy/memory/2026-09-下10.md
T
admin ce8e6ceed9 chore(工作区): 纳入版本控制基线(回收 411 MB 过程产物)
回收 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)、记忆修复前备份。
2026-09-24 07:51:03 +08:00

47 KiB
Raw Blame History

工作日志 · 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),旧 id 0c033dbe 已停 ⇒ 当前实例加载的就是 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 里 & 被转义成 &amp;,还原后请求): 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(还原 &amp;)→ 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/ 被 nginx expires 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.js 13 处: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 对 client inject 的期望形态。
  • 暂停理由:已连续打 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(fetch clone().text() / XHR responseText);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-restart 106 次 ⇒ 实例中断主因是崩溃/被停,注入脚本文案「实例已休眠(空闲回收)」归因不准。
  • ⛔ 现场发现(只报告,未处置):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=gzip 11 次,最近两次 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:145 optionalStringArray(pkgName, "dsh.client.inject", decl.inject)); · client bundle factory() 返回的 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** at Module.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 build rc=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 build rc=0 → lib/ 含新标记;systemctl restart → active / 门户 200 / 孤儿 scope 0
    • 端到端:临时会话 enter 200 + 实例 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-audit rc=0 / docs-manifest 刷新 / docs-consistency rc=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.log 03: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

五、发现的「账实不符」(只报告,未改)

  1. 交接单/README §一 T03 行仍写「池内 = 0.3.2」→ 实际 0.3.9;BRIEF §3 同。
  2. 03-路线图 §二 P1「摘除 guest 仍在启用的 @liustack/modlens」→ 实际已完成(guest bundles 与 node_modules 均已无)。
  3. 03-路线图 §二 档案 64/AnySearch 行仍与「已彻底放弃(下架)」并存(BRIEF 已改)。
  4. 档案 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/enter 200 → 就地跳回、仍在 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-audit rc=0 | docs-manifest 刷新 | docs-consistency rc=0 | 对账。
  • 只推本次碰过的 11 个文件到 /opt/dsh/docs(档案 600 / README 644)→ 复跑对账:一致 123 → 127。
  • ⚠️ 如实报告:其余 4 不一致 + 3 仅本地 是其它会话积压(交接单/T03、04-42、交接单/README、04-67;04-74/75/76 仅本地)——本次未动。
  • 未 commit / 未 push。

五、留给用户 / 下一棒

  1. 历史档案正文里的 D:\AI技能\... 未逐处改写(按约定);要连正文一起改,说一声(约 6 个历史文件)。
  2. 档案 77 §八 遗留 1(崩溃熔断可无限重来 + 无告警)仍待另开档案。
  3. a2665dd3 报的 4 条「账实不符」(T03 池内版本 0.3.2→实际 0.3.9 等)未处置。