回收 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)、记忆修复前备份。
54 KiB
接续入口 · 插件投放与分库线(2026-09-22 开线)
工作区:
E:/ProgramData/AIProject/aliyun-dsh-server(本入口只此一份) 开线棒:会话aliyun-dsh-server2026-09-22 13:2x(用户当场提要求后收口) 代码基线:D:\github\dsh_shenxian= 生产口径dshs;⚠️ 另有一份开源导出物dsh_ai1net(/opt/dsh_ai1net·/etc/dsh_ai1net.env·DSH_AI1NET_*)是另一套命名、另一个部署,⛔ 两者不要混用(本会话已实测踩过这个坑)。 上游上下文:同工作区.workbuddy/memory/2026-09-22.md的10:0x节(carbon 线"两处平台侧阻塞"判定)+07:5x节(一插件一库拍板)。
§0 状态(最新一行 = 执行依据)
- 2026-09-22 13:2x|开线 —— 规划棒①收口(出交接单
①共享只读包库与插件数据面.md)。 - ✅ 2026-09-22 17:0x|执行棒①完成(S1/S2 全绿) —— 共享只读包库已在 47+106 上线并真机取证;实投 mcn-suite + storyforge。S3/S4/S5/S6 未做。
- 🔴 2026-09-22 18:1x–21:1x|编码与设计(受 IM 线锁占用,只出件不动服务器) —— 用户追加口径「admin 全流程自闭环」(上传 → 检测通过 → 点建库按钮 → 建库成功才能开启 → 更新按钮 → 更新也检测 → 告知数据库改动 → 确认执行按钮)。产出设计件
交付物/数据面管理面-建库与更新流程-20260922.md(7 态状态机 / 检测第 3 项 /dsh.data声明 / API 契约 / 两段式预演-确认 / 门户改动清单)。 - ✅ 2026-09-22 19:3x|用户拍板建库权限 = D,产出 D 档 Runbook。
- 🔴 2026-09-23 05:2x|D 档实测被证伪(重大反转) —— PG 显式禁止从函数内执行
CREATE DATABASE(cannot be executed from a function;另一层是「不能在事务块内」,而 PL/pgSQL 函数体恒在事务内)。同姿势下CREATE SCHEMA/CREATE ROLE均成功 ⇒ 语句级内核限制。旁路dblink/postgres_fdw均不可用。已回滚,服务器零残留。判定件 ⇒交付物/建库权限-D档被证伪与修正判定-20260923.md。 - ✅ 2026-09-23 05:4x|用户拍板建库权限 = B,并已在 47 落地 ——
ALTER ROLE dshs CREATEDB;+ 11 条验收全过(核心断言:权限精确false|true|false,未要CREATEROLE/ 未要超管)。🔴 B 档真实缺口:PG 无「只允许dshs_pl_*前缀」的原生机制(实测建evil_probe成功)⇒ 白名单只能靠平台代码兜住三点(库名单点生成 + 正则复校 + 每次建库落台账审计)。落地件 ⇒交付物/插件建库权限-B档落地-20260923.md。 - 🔴 2026-09-23 05:5x|排期调整:本线代码面现在开工 —— 原拍板「A = 等 IM 线整阶段收官后一次性跑完」的前提已变化:IM 线因 E 单 UI 落点待拍板而停下(A–D 四单已落地、E 单未开工、未登记接续棒 ⇒ 整阶段收官无时点),本线继续空等已不成立。故改为:不依赖拍板的部分(设计件 §八 除建库口以外的全部)即刻推进;建库口与三份文档回写另行安排。
下一棒(唯一) = 第 3 棒 · 执行棒 = automation
fe16b14a-cd7e-424d-99b0-37a21972365a(一次性 ·scheduledAt = 2026-09-23T05:55)。 ⛔ 拍板项(不得自动跨过):无新增;建库通路已定 = B 档。 - ✅ 2026-09-23 06:0x|第 3 棒 · 执行棒完成(设计件 §八 除建库口外全部落地) —— 7 项全做完:
src/db/plugin-data/schema.ts(新建 · 声明解析校验 9 中性类型 ·pluginDbNameOf/assertPluginDbName)|src/db/plugin-data/diff.ts(新建 ·diffDecl/planHashOf/forbidden只增不减)|v15 迁移plugin_datastores×plugin_data_audit(台账 = B 档白名单第三点兜底)|检测第 3 项「数据面声明校验」|三处门禁(enableDenialOf/ 检测不过不许建库 /planHash未确认不许迁移)|门户「数据面」列 + 7 态徽章 + 预演清单面板 + 状态驱动按钮|版本回读校验(只认内容指纹,漂移写plugin_version_drift审计)。 验证:npm run buildrc=0 |npm test=391/389 过 / 0 败 / 2 跳过(基线 366/364 过 / 2 跳过,本棒 +25 条)|check-layering✅ 无新增违规(added: 0)。⛔ 未做(属下一棒):建库口接线 / 三份文档回写 / S3·S5-a·S6 / 跨节点内容分发。 下一棒(唯一) = 第 4 棒 · 执行棒 = automation6e8cedcd-f426-4390-9460-937573d93f7d(一次性 ·scheduledAt = 2026-09-23T06:27,约 8 分钟后);接续点 = 建库口接线(调 B 档CREATE DATABASE、单语句不走事务、落台账 + 审计)。 - ✅ 2026-09-23 07:0x|第 4 棒 · 执行棒完成(建库口接线 · B 档全部兑现) —— §5 的 5 项全做完:
src/db/plugin-data/datastore.ts(新建 479 行 ·CREATE DATABASE单语句非事务 /readCurrentSchema真读information_schema+p_meta_schema/executePlan建库项非事务+表级 DDL 同事务 /reconcilePluginDatabases对账 / 错误码映射PG_CREATEDB_MISSING·invalid_plugin_db_name)|currentSchemaOf去占位|路由POST /datastore(建库)+GET /datastores/reconcile(对账告警)+/datastore/plan的executable真判据 +/datastore/migrate去 503 真执行|门户「建库」按钮接真实路由(原"尚未接线"禁态已去掉)。 验证:npm run buildrc=0 |npm test= 426/424 过 / 0 败 / 2 跳过(基线 391 过 ⇒ 本棒 +35)|check-layering✅ 无新增违规(added: 0)。47 真机取证通过(真实编译产物走建库口):建库created71 ms/幂等exists/非法名invalid_plugin_db_name未下发 PG/库内台账真读exists:true, schemaVersion:7/planHashPreserved:true(COALESCE 语义)/对账抓出 orphandshs_pl_borphan4。清理后零残留(pluginDbs:[]· 控制面表回到 13 张 ·dshsactive)。落地件 ⇒交付物/建库口接线-B档落地-20260923.md。 ⚠️ 本棒记的已知缺口(⛔ 未假装做了):① 迁移前结构备份(设计件 §七-3 的pg_dump)属运维面,归 S5-a 棒;② 47 控制面仍停在迁移 v13 ⇒ v15 两张台账表要平台启动时runPgMigrations才落,部署本棒代码时随restart dshs自动补。 - ✅ 2026-09-23 07:2x|第 5 棒 · 执行棒完成(三份文档回写 · 纯文档零代码) —— 共享文件持锁成批做,全部落笔:
①
DEPLOY-本部署.md新增 §6.4 数据库初始化(PG13 / 47 本机进程):建角色建库 + 🔴ALTER ROLE dshs CREATEDB;(标用途 = 插件建库,⛔ 未给CREATEROLE/SUPERUSER)+ 回滚句 + 权限校验判据(f|t|f)+ 白名单只能靠代码 + v15 迁移表随restart dshs自落。 ②交接单/…①共享只读包库与插件数据面.md:§五 S4-2改写为 admin 显式按钮(上传只检测 ⇒pending⇒ 点[建库]⇒ 成功才能开启;两道后端门禁;单语句非事务;两重防线;错误码)|§十-D1表格行同步改并标注原写法作废。 ③数据库/DB-03-插件数据面规范.md:执行状态块整块重写(🔴 受阻 ⇒ ✅ 已落地;仅剩"跨节点身份通道为 0"一条真缺口)|§三新增 「三·补 谁建库、什么时候建」|§四执行时机改两步(建库 / 迁移都是插件级一次性)+ 表级同事务 / 建库不可回滚 /planHashCOALESCE语义|§六-2补两张台账表结构(plugin_datastores/plugin_data_audit)。 ④ 顺带核对交付物/数据面管理面-建库与更新流程-20260922.md §十一:D 档段已作废(头部 + §十一 末尾均已有更新说明)⇒ ⛔ 未改动其历史结论文本,核对通过。 验证:npm run buildrc=0 |npm test= 426 tests / 424 过 / 0 败 / 2 跳过(与基线一致,纯文档零变动)|git diff --stat本次改动 =DEPLOY-本部署.md+21(唯一 tracked 的直接证据;另两份在未跟踪路径下:交接单/被.gitignore:45排除、数据库/整个目录仍是??未跟踪 ⇒ 改动落地但不出现在 tracked 清单,属既有仓库形态,⛔ 与本棒无关)。锁已--release-exec。 下一棒(唯一) = 第 6 棒 · 执行棒;接续点 = S3 跨机装配(POST /plugins/apply+remote-spawner.applyPlugins+mine/apply改走台账裁决)。 - ✅ 2026-09-23 08:1x|第 6 棒 · 执行棒完成(S3 跨机装配 · 真机 S3-E 全过) —— §5 的 4 项全做完:新建
src/supervisor/plugin-assembly.ts(约 400 行,两台机共用的唯一实现)|worker/agent.ts新增POST /plugins/apply(同族于/restart-probe,⛔ 不新增入站口)|remote-spawner.applyPlugins(按hostIdFor定位机器)|mine/apply改只做清单裁决(⛔ 不再本机runPnpmAs)。 验证:npm run buildrc=0 |npm test= 439/437 过 / 0 败 / 2 跳过(基线 426/424 ⇒ +13)|check-layering✅ 无新增违规(added: 0)。 S3-E 真机取证(106 · 非 Manager worker · 用户4092b965uid 100002 · 包@dsh-local/storyforge0.1.0)①–⑦ 全过:applyOk:true|file:/var/lib/dshs/bundled-plugins/_dsh-local_storyforge|node_modules/<pkg>软链 ✓|实例内ls可见 +touch=Read-only file system+ mountinforo,nosuid,nodev|反证plugin_bundle_missing报错可读、实例不崩|⛔ 47 的users/下该用户零storyforge命中(连软链都没有,目录 8.0K 空壳)= D2 主判据过。停用腿同验;用户面零残留(profile 已复原)。 附带修正(真机暴露的既有缺陷,两条):①pnpm install --ignore-workspace-root-check—— pnpm 9 不认该 CLI 选项(只当 config 项)⇒Unknown option直接失败(旧代码一直裸写,2026-09-13 07:43:58 曾因此把平台带崩、当时只加 try/catch 兜住进程)⇒ 改-w(与scripts/ensure-biz-plugins.cjs既有正确姿势一致)+ 回归测试钉住;② 启用项先落盘再 pnpm ⇒ 失败留半装状态(依赖已声明、实际未安装)⇒ 改先解析全部包(失败即抛、profile 未改)+ pnpm 失败回滚。另修RemoteSpawner.call()既有 4xx 重试 bug(4xx 的 throw 被 catch 吞掉、循环跑满 4 次)。 部署:两机lib/同批(plugin-assembly.jsmd5134b5704…逐字一致)+ 备份lib-pre-s3-*.tgz;47restart dshs后 v15 两张台账表已落;106 共享层已同步(storyforge + mcn-suite);relay-dialer实测连到ops/w-106。落地件 ⇒交付物/S3跨机装配落地-20260923.md。 🔴 本棒抓出 1 条口径级缺陷(已取证 · ⛔ 未擅改 ⇒ 待拍板):D-h 拍板的file:协议在 pnpm 9 下会把插件包整份复制进每用户.pnpm/(实测 6.5 M/用户/包、116 文件、links=1、inode 与源不同),不满足 D2「实体一份、链接多份」;根因 = pnpm 对file:(目录型)走复制、⛔ 不硬链(同 profile 普通依赖links=9可证)。已实测替换方案link:= 4.0 K 纯软链直达共享层,且抗 reconcile(加依赖 /remove后软链仍在,即 D-h 当初选file:的唯一理由仍成立)。⇒ 因涉及已拍板项 D-h,交用户拍板(候选 A 维持file:/ 候选 B 换link:,优缺点见落地件 §六),倾向 B。⛔ 拍板前不得改协议写法。 下一棒(唯一) = 第 7 棒 · 执行棒 = automation9cf7c353-415d-4347-9b59-7ae4449ae986(一次性 ·scheduledAt = 2026-09-23T08:23,约 6 分钟后);接续点 = S5-a 兼容矩阵 + 迁移前结构备份 + S6 门户三段式 UI。⛔ 该棒不得碰装配协议(见上「待拍板」)。 🔴 新登记待拍板项(唯一):装配协议file:(现状)vslink:(实测 4 K)。拍板落地位置 =src/supervisor/plugin-assembly.ts的协议写法 + 交接单 8 处file:描述。 - ✅ 2026-09-23 08:4x|第 7 棒 · 执行棒完成(S5-a + 迁移前备份 + S6 三段式 UI) —— §5 的 3 项全做完,文件面 8 改 2 新:
① S5-a 兼容矩阵落定稿
数据库/DB-03-插件数据面规范.md新增 §四·补(6 行场景表:首次装 / 升级 / 等价换包 / 降级 / 幂等重传 / 同名异内容冲突;三条硬规则;B 档两条前置;4 条可复现验证)—— 核心口径 = 两个版本号是两件事,判"库该不该动"只看schemaVersion。 ② 迁移前结构备份(第 4 棒记下的缺口):datastore.ts新增backupSchemaOnly()(pg_dump --schema-only→<backupRoot>/plugin-db/<pkg>/<v>-<ts>.sql)+ 接进datastore/migrate路径:非首次建库 ⇒ 先备份,ok=false⇒500 schema_backup_failed且不执行(设计件 §七-3 原文落地)。三条纪律:失败即不执行 / 只导结构 / 口令走PGPASSWORDenv ⛔ 不进 argv。两处自决:只在!isFirstCreate时备份(否则首次建库全堵死)· 0 字节视为失败(空库也会写头部 ⇒ 空文件=静默失败,不判它就把纪律绕过去了)· 包名路径折叠(先折分隔符再折连续点)。 ③ S6 门户三段式 UI:web/portal.html新增第 3 个 tab「用户可见性(三段式)」+.sec-head等分段样式 +loadVisibility();三段数据来源分两路不混——① 平台共享只读 ← 新增GET /api/plugins/shared/catalog,②③ 已启用/已停用 ←/api/plugins/mine(该路由保持原样,⛔ 未顺手加过滤),另附「⋯ 暂不可用」把"池里有没发布"与"用户没开"分开(混讲会误导 admin)。 🔴 新增开关DSHS_SHARED_CATALOG_PUBLIC(默认false):新路由是用户可见面变化(此前登录用户无任何共享清单口子)⇒按 §1「扩大可见面」红线默认关,关着 = 404(⛔ 不是空列表:空列表会被读成"共享层是空的")。未擅自开。 ④DB-03新增 §八·补 端侧边界声明:端侧走同一个平台 API ⇒ 只保证「能看见 + 能开通」;⛔ 不要求本地装包 / ⛔ 不下发平台级凭据 / ⛔ 端侧不落插件数据。 验证:npm run buildrc=0 |npm test= 447 / 445 过 / 0 败 / 2 跳过(基线 439/437 ⇒ +8:新文件 5 条 +plugin-data追加 3 条)|check-layering✅ 无新增违规(added: 0)|verify-inject全合格。落地件 ⇒交付物/S5-S6落地-20260923.md。 ⚠️ 本棒记的已知缺口(⛔ 未假装做了):未部署到 47/106(deploy-deferred-to-next-step)⇒ S5-E / S6-E 的真机 E2E 未跑(须部署 + 先开可见面开关);跨节点内容分发仍无平台侧通路(可立独项)。 ⛔ 本轮严格未碰装配协议:plugin-assembly.ts零改动、交接单file:相关描述零改动。 下一棒(唯一) = 第 8 棒 · 执行棒 = automation87c8221c-a7ce-41e2-b5fa-e56fc0c8c929(一次性 ·scheduledAt = 2026-09-23T08:49,约 7 分钟后);接续点 = 部署到 47/106 + S5-E / S6-E 真机 E2E。 🔴 待拍板项仍是同一条(唯一,⛔ 未变):装配协议file:(现状)vslink:(实测 4 K)。拍板落地位置 =src/supervisor/plugin-assembly.ts的协议写法 + 交接单 8 处file:描述。 🔴 下一棒新增红线:可见面开关DSHS_SHARED_CATALOG_PUBLIC属红线门禁(CODEBUDDY.md §1扩大可见面)⇒ ⛔ 下一棒不得擅自打开;S6-E ② 若要跑,要么先向用户取得开启许可,要么只跑不需要该开关的部分(E ①③)。 - ✅ 2026-09-23 09:5x|第 8 棒 · 执行棒完成(部署 + S5-E / S6-E 全绿) —— §5 的 4 项全做完:
① 部署:
npm run buildrc=0 ⇒ 产物 scp 到 47/opt/dshs+ 106/opt/dshs-cluster,三机 md5 逐字一致(db/plugin-data/datastore.js9fedd77c…/web/routes/business-plugins.jsfe456d60…);47restart dshsrc=0;重启后plugin_datastores+plugin_data_audit仍在(v15 未丢)。部署前备份/opt/dsh/backups/lib-s5s6/{47,106}-pre-s5s6-20260923-085319.tgz。 ② S5-E ①–⑤ 真机 E2E 全 PASS:① v1→v2 加列升级,升级前后均 3 行(存量原样)|② 强行降级 ⇒items=[]+forbidden=[drop_column p_s5probe_notes.pinned]+executable=false+state=blocked⇒409 plan_blocked,列与行数一字未动|③ 同名同版本重传http=200、tgz md5 与源一致(幂等)|④/opt/dsh/backups/plugin-db/<pkg>/2 个.sql(v0-…643B/v1-…1344B)、0 字节文件数 = 0、台账datastore_migrate_backup_ok x2|⑤ 对照 200 + 反证 500schema_backup_failed(mkdir_failed: EPERM)、库结构未变,环境已原样还原。 ③ S6-E ①③ PASS:① admin 池 5 = guest/mine5|③ admin 新增@dsh-local/s6newprobe⇒ guest 5 → 6、无需管理动作。② 只记事实 ⇒DSHS_SHARED_CATALOG_PUBLIC未设置(默认 false)⇒404;🔴 开关全程未开(红线门禁遵守)。 🔴 本棒抓出并修复 1 条真实缺陷(真机专属 —— 本机测不出):datastore.ts里pgEnvFrom(baseUrl)的返回值被展开在execFileSync的 options 层(与env:同级)⇒PGHOST/PGPORT/PGUSER没下发到pg_dump子进程 ⇒ 退回 Unix socket:5432⇒ 47 上No such file or directory⇒ 结构备份在生产上根本跑不通。修法 = 新增pgDumpEnv()并合进env;另修business-plugins.ts里第 4 棒遗留的backup:'not_implemented'不实文案 ⇒ 改真实值(skipped_first_create/taken+backupPath)。回归钉住+2用例(⚠️ 首版用 PATH 假pg_dump桩在 Windows 上失败(.cmd/.bat无法解析 ⇒ENOENT/EINVAL)⇒ 改为直接断言 env 不变量:四个 PG 变量必须存在、且 ⛔ 不得混进stdio/timeout/cwd/encoding)。重部署后 ④ 腿备份成功落盘 ⇒ 闭环。 验证:npm run buildrc=0 |npm test= 449 / 447 过 / 0 败 / 2 跳过(基线 447/445 ⇒ +2)|check-layering✅ 无新增违规(added: 0)。落地件 ⇒交付物/S5-S6真机E2E验收-20260923.md。 ⚠️ 本棒记的已知缺口 / 未做项(⛔ 未假装做了): ① S6-E ② 字面判据(/mine返enabled:true)未闭合 —— 不是代码缺陷,是拓扑形态的必然:客实例(uid100002)在 106(worker),而/mine读的是平台本机 profile 快照(47 上为空)⇒ 本机快照反映不了远端装配。实测 enable 已正确落到实例所在机 106(node_modules/@dsh-local/storyforge软链 09:43 建立、可解到package.json、package.json写入file:/var/lib/dshs/bundled-plugins/_dsh-local_storyforge)⇒ 判据用 106 侧文件证据闭合。旁证:dsh-100002-9648cef4.scope沙箱命令行含--ro-bind-try /var/lib/dshs/bundled-plugins(S1 共享只读层挂载成立)。🔴 ⇒ 暴露一条缺失能力:平台侧"用户可见启停状态"没有跨机回流通路(现在只有单向 apply) —— 建议单独立项,本棒只记录、未改架构。 ② 门户三段式 UI 的 CSS 视觉渲染 / tab 点击 未验(本机agent-browser每次调用均挂死,属环境限制 ⇒ fail-fast;已清理 chrome 进程)⇒ 改用等价判据ui-logic-check.mjs复跑portal.html的loadVisibility()逻辑:7/7 断言通过(互斥 / 完备6 vs 6/ 语义正确 / 开关关 ⇒ ③=0)。 ③ 跨节点内容分发仍无平台侧通路 ⇒ 需单独立项。 清理:探针库 / 候选池行 / 账本行 / 审计行 / 备份目录 / 共享层探针 tgz 全清,零残留(%probe%三处计数全 0、池子恢复原始 4 个);platform-dirs.conf原样还原(DSH_PLATFORM_DIR=/opt/dsh+ 无.bak-s5e);106 客实例storyforge启用已回退(回到 4 依赖原始态:business-plugins/portal-entry/workspace-scoped-picker/dsh-file-preview),106dshs-worker+dshs-relay均 active。 ⛔ 本轮严格未碰装配协议:plugin-assembly.ts零改动、交接单file:相关描述零改动;⛔ 未开可见面开关;⛔ 未 commit / 未 push / ⛔ 未引新依赖 / ⛔ 无 merge。 下一棒(唯一) = 第 9 棒 · 规划棒 = automation9028a886-6b79-497e-a57c-1a33dcd796c3(一次性 ·scheduledAt = 2026-09-23T09:59,约 7 分钟后);接续点 = 跨机可见性状态回流(缺口立项)+ 三门一致性复验。⛔ 三条硬禁止:⛔ 不碰装配协议(D-h 待拍板)· ⛔ 不开可见面开关 · ⛔ 不改plugin-assembly.ts。 🔴 待拍板项仍是同一条(唯一,⛔ 未变):装配协议file:(现状)vslink:(实测 4 K)。拍板落地位置 =src/supervisor/plugin-assembly.ts的协议写法 + 交接单 8 处file:描述。 🔴 待拍板项(本轮新增 · 第 ② 条):平台侧"用户可见启停状态"的跨机回流通路要不要立 —— 现状是单向 apply、无状态回流 ⇒ 实例在 worker 上的用户,平台侧/mine恒显enabled:false。候选 A:立专项做状态回流(优点:平台侧启停状态全域准确、admin 与用户看到同一事实;缺点:新增一条控制面回传链路、要定拓扑与重试语义)|候选 B:维持现状、把"跨机时/mine的enabled语义明确为「本机快照、可能滞后」并在 UI 上标注(优点:零改动、立刻可交付;缺点:admin 侧看到的启停状态在跨机场景下永远是错的,会误导管理动作)。 - ✅ 2026-09-23 10:0x|第 9 棒 · 规划棒完成(跨机可见性状态回流设计件 + 三门基线复验 + 交接单登记) —— §5 的 3 项全做完,只出设计件 · 零代码改动 · 未动服务器:
① 设计件 ⇒
交付物/跨机可见性状态回流-设计件-20260923.md(10 节):问题定义(4 条影响面 + 3 条排除项)|事实基础 13 条(现读代码,带行号)|🔴 三条硬约束(C1「worker 主动上报」在"只拨出"形态下物理走不通;C2「Manager 主动拉」的骨架reportHost()已在跑、增量只是把返回值加宽;C3 读路径必须与响应路径同源)|通路形态三候选(A 主动拉/B 共用台账/C worker 上报,逐条优点+缺点 + 一张对比表)|写入时机 T1(apply 完成后)+ T2(实例启动 reconcile,由 worker 本机驱动、Manager 不在场)|陈旧度语义(asOf必带 +stale现算不落库 + 阈值 = 3×心跳周期)|失败重试与不可达降级(5 场景表,核心 = ⛔ 不许把"未知"显示成"未启用")|与 v15 台账的关系(粒度不同塞不进去;A 案不建表、B 案才建且必须落控制面)|"不做会怎样"四尺度(长期越晚越贵:多 Manager 联邦下每个区都要各造一套)|落地轮廓 + 附复核命令。 🔴 本件的关键否证:候选 B 不能单独成立 ——reconcile的驱动点在 worker(agent.ts20 s 本地定时器),Manager 不在场 ⇒ "apply 时写台账"覆盖不到该路径 ⇒ 台账只能当缓存、⛔ 不能当权威。候选 C 要新开一条 worker→Manager 入站口 ⇒ 撞 §1「扩大可见面」红线。 技术倾向(可推翻 · ⛔ 未替拍):A 为骨架 + B 降级为可选缓存;C 需用户先授权新开入站口。 ② 三门一致性复验(基线记录 · 未改代码 ⇒ 确认第 8 棒部署未引入漂移):npm run buildrc=0(tsc -p tsconfig.json无输出)|npm test(Node 22)= 449 tests / 447 过 / 0 败 / 2 跳过(与第 8 棒基线逐字一致)|node scripts/check-layering.mjs= ✅ 无新增违规(现存 5 条全在基线内;⚠️ 报「未归类 1 =src/platform-paths.ts」属既有状态,非本棒引入)。 ③ 交接单登记:交接单/插件投放与分库线-①共享只读包库与插件数据面.md§五 S6 新增「🔴 已知边界」小节(成因代码位置 + 106 真机实证 3 条 ✅ / 1 条 ❌ + 影响面 3 条 + ⚠️ 区分响应路径与读路径 + 状态=缺失能力已立项);§六 验收表第 8 行同步加注(② 的字面判据仅同机形态成立)。 ⛔ 本轮严格未碰装配协议:plugin-assembly.ts零改动、交接单file:相关描述零改动;⛔ 未开可见面开关;⛔ 未改任何生产代码、未动 47/106 服务器。 下一棒 = ⛔ 未登记(拍板项未定 ⇒ 按用户级记忆「要用户拍板的,等拍了再新建接续会话」)。接续点 = 用户对通路形态拍板后,排「跨机可见性状态回流」执行棒。 🔴 待拍板项 = 两条(⛔ 未变 + 新增): ① 装配协议file:(现状)vslink:(实测 4 K)。落地位置 =src/supervisor/plugin-assembly.ts协议写法 + 交接单 8 处file:描述。 ② 跨机可见性回流的通路形态(A 主动拉/B 共用台账/C worker 上报,逐条优缺点见设计件 §三)。落地位置 =worker/agent.ts的/healthz+leased-spawner.ts的reportHost()+business-plugins.ts的/mine。 - ✅ 2026-09-23 15:4x–16:2x|A 线收口 · 装配协议
link:全落地(① ② ④ ✅ · ③ 实测撤销) —— 用户口令「先把 a线做完,处理完成后在做b线」,本段为 A 线(插件投放与分库线) 的收口: 代码:plugin-assembly.ts新增depRefOf()(+pnpmExecDisabled()/runPnpm()测试缝)|business-plugins.ts4 处fileRef同步为depRefOf。三门全绿:npm run buildrc=0|npm test= 450 / 448 过 / 0 败 / 2 跳过|check-layering✅ 无新增违规(added: 0)。 部署:lib/supervisor/plugin-assembly.js+lib/web/routes/business-plugins.js已 scp 两机 —— 🔴 47 =/opt/dshs/、106 =/opt/dshs-cluster/(106 上没有/opt/dshs,这是本轮新查实的事实);两机 md5 逐字一致(fe5162ec…/ed507b7a…);restart47dshs+dshs-worker、106dshs-worker;门户 3080 → 200、worker 19100 → 401;旧产物备份/opt/dsh/backups/plugin-assembly-20260923/。 真机复验(47):软链 54 B +.pnpm8.0 K(对照file:6.5 MiB/116 文件 ⇒ 约 1000 倍差距)、目标回溯直达共享层、用户身份下可读、反证原子抛错;探针用户已回滚。 🔴 ③ 存量用户迁移实测撤销(本轮最重要的否证):全平台只有 1 个带依赖实例,5 条依赖全.tgz型(目录型 0 条),只有 1 条在共享层有目录 ⇒ 原迁移方案会让 4 条悬空 ⇒ 实例崩。成因 = 那 4 个包是平台自研核心组件、从不进共享层。⇒ 已从待落地清单撤下,交接单 §9.3 整节改写。 文档:交接单该文档 —— 状态行(S3 → 全绿已上线)|§五 S3-E 新增真机复验表 + 部署状态段|§五 S4-2 无改|§9.3 整节改写(含"dsh-file-preview已指向共享池"的误读纠正)|§十二 执行回报第 1 行(S3 → 已做)。入口 §5 待落地块 + 本线后续第 4 条同步。 ⚠️ 残留一条待补(不阻塞):106 侧跨机腿 —— 106 现无带插件用户实例可复验,等有用户启用时按 S3-E ④⑤⑥ 补一次。 ✅ 2026-09-23 18:3x|用户拍板 —— 跨机可见性形态 = D「按需定向拉(主)+ worker 变更上报(辅·后置)」 —— 用户原话「可以 worker 上报,具体要管理那个用户的时候 manager 针对性的去查」。原 A / B / C 三候选作废;设计件 §十 已整节改为定稿。 🔴 本棒(设计阶段)拿到的最有价值事实:fenceOnAgent()(src/supervisor/leased-spawner.ts:144-155)里已经有「findUserInstance(userId)→agentFor(hostId)→ 带 token 定向POST到那台 worker」的完整三步定位链 ⇒ 主路径=只把目标端点从/fence换成新只读口(建议/profile-bundles)。⇒ 零新增监听口 · 零新增凭据体系 · 零广播,且天然覆盖reconcile路径(原 B 案的死结,因为查的是对端现算真值而非历史快照)。 ⛔ 两条硬约束(写码前必守):① 新端点必须带 token(与/fence同级)—— ⛔ 绝不可挂到免凭据的/healthz上,否则等于开匿名任意读口;② 查不到须返回not_here,⛔ 不等于"零插件"(两者语义不同,混用即复制本缺陷)。 📌 落地登记 = 下方「⏭️ 本线后续」第 1 条(本条为设计与拍板落定,⛔ 未写一行生产代码、未动 47/106)。 🔴 下一棒(automation)本轮排不出来 ——automation_update创建时返回file is not a database:宿主活动库E:\ProgramData\.workbuddy\workbuddy.db(以CODEBUDDY_CONFIG_DIR = E:\ProgramData\.workbuddy判定)第 1 页 header 已丢失 ⇒ 全机 automation 功能不可用。⚠️ 与拍板结论无关,⛔ 不要因为排不出棒而认为形态没定;库修复后按本条与设计件 §十 直接排。 下一步 = B 线(IM 线):按用户口令「处理完成后在做b线」,接续点 =接续入口_IM线_20260922.md(推荐先做 ①档位重写,它是全部 E2EE 代码的硬前置)。 - ✅ 2026-09-23 20:5x|carbon 线「两问」答辩(纯文档 · 零代码 · 未动 47/106) —— 触发 = 用户口令「看插件会话的问题反馈
dsh-plugin-carbon/对接文档_carbon插件-平台侧两处阻塞_20260922.md」⇒ 读 carbon 线回执 §H–§K,在该对接单追加 §L 答辩,逐条裁定: ① 凭据落点 → 迁 D4 目录(<userRoot>/home/.dsh/plugins/dsh_plugin_carbon/mcp.json;判据 = 清理单元一致 / 一处约定 / 暴露面不变 ⇒ 不触发 R5);并将目录名口径定死 =pluginId(去 scope·小写·非[a-z0-9_]折_,与库名dshs_pl_<pluginId>同 token ⇒ carbon =dsh_plugin_carbon,⛔ 不是carbon)。 ② 零数据面插件 ⛔ 不要显式提交空声明:无dsh.data⇒none⇒ 放行;tables: []⇒invalid⇒ 状态恒blocked、永远发不出去;单放一个dsh.data.yaml根本不被读取(不自动探测)。⇒ carbon 现状即合规,什么都不用加。 ③ 🔴 自纠(我上一轮写错的一处):§C-2 D4 里的「只能走 SDK 的im.paths.pluginData()」是错的 —— 该 API 三处零命中(源仓src// 宿主仓deepseek-harness/node_modules)⇒ 正确姿势 =join(process.env.DSH_HOME, '.dsh', 'plugins', pluginId)(DSH_HOME由平台注入、必存在),⛔ 删homedir()回退(HOME=<userRoot>/ws,而ws会被平台按产物清理 ⇒ 回退 = 写到会被清掉的位置)。 ④ 另抓一条(对方没问、但会咬人):跨机投递 —— 用户实例在 worker 上时,管理机直写<userRoot>/home/…= 静默空操作(user-fs.ts:122-124,档案 138 §五)⇒ 投递须落在hostIdFor(userId)那台机。⚠️ 平台侧无「插件凭据投给用户」通路(home 白名单仅 3 个裸文件名)⇒ 凭据仍带外投递;要自动化须立项,建议并进 worker/plugins/apply同一条腿(零新增入站口)。 文档落笔:DB-03新增 §六·补 插件文件落点与凭据投递(8 行口径表 + 现状缺口)|交接单 ①…md三处同步更正(状态行「S5-b 口径已更正」· §四 路径段「SDK 口不存在、改DSH_HOME拼法」· §五 S5-b 五条改写含pluginId口径/凭据同目录/跨机/零数据面)。 ⛔ 本棒零平台代码改动、⛔ 未动 47 / 106、⛔ 未 commit / push。 下一棒 = ⛔ 未登记(本棒为即席应答、非接续棒;且 B 线(IM 线)第 15 棒正在跑,按用户口令 A→B 的顺序,本线不与 B 线并行抢资源)。⚠️ 本线两项可排(均非阻塞):a) 跨机可见性回流的执行棒(形态 D 已拍板 2026-09-23 18:3x ⇒ 按用户级「等拍板」纪律,条件已满足、随时可排);b) 可见面开关DSHS_SHARED_CATALOG_PUBLIC的开启决策(红线门禁 · 待用户拍板)。 - ✅ 2026-09-23 21:3x|插件对接文档落库 + 仓库清理清单(纯文档 · 零代码 · 未动 47/106) —— 触发 = 用户口令「需要一份插件对接文档,给插件开发会话按照文档规范开发插件」+「放到
D:\github\dsh_shenxian\dsh-server-docs中长期维护」+「清理这个文件夹中过时和临时以及不需要的文件」。 ① 新规范(长期维护 ⇒ 落文档库、不带日期) ⇒dsh-server-docs/规范/08-插件开发与对接规范.md:§0 一句话 / §1 开工四问 / §2 包形态 / §3 数据面(含「零数据面 ⛔ 不要写空声明」+ 声明唯一入口澄清)/ §4 文件落点 D4 / §5 投放链路(谁做什么)/ §6 错误码表(判归属) / §7 提包前自测清单 / §8 端侧边界 / §9 回报格式 / §10 别做清单 / §11 变更记录。INDEX.md §一已加一行索引(「写一个业务插件」→ 指向 08)。 ⚠️ 该件顺带纠正一处口径分叉:DB-03 §三与平台回复里的「在im.data上声明表」是运行时对象的措辞;声明的存放位置只认package.json的dsh.data.schema(内联对象或指向包内文件),且不自动探测包内dsh.data.yaml(源码src/db/plugin-data/schema.ts:701-746现读)。 ② 仓库清理(D:\github\dsh_shenxian) ⇒交付物/清理候选清单-dsh_shenxian-20260923.md(只读扫描报告):P0 明确垃圾 9 项 / 2.5 MiB(dsh-server-docs/scripts/__pycache__、_tmp_seq40/*.out)· P1 疑似一次性 91 项 / 2.6 MiB(_tmp_seq40/(36) ·_tmp_seq24/(8) ·poc/**/*.tgz20 个旧版本 ·_中间产物_待清理/·tmp-e9*.txt·tmp/seq46s0/)· §四 假阳性 10 项(⛔ 别删:scripts/overlay-probe.cjs等 6 个在册工具、archive/存档、过程档案、poc/carbon-mcp-probe/(carbon 线归属)、.workbuddy/lock-hook.log(hook 正在写))· §五 五批次处理顺序(每批 ≤10、跟踪文件走git rm、每批复核)。 🔴 ⛔ 本棒未删 / 未移 / 未改名任何文件 —— 批量删除属红线(用户长期规则「任何可能影响 >10 文件的操作用前必须先出受影响清单并取得确认」+「未明确要求不 commit / push」)⇒ 先出清单、等逐项点名确认。 ⚠️ 遗留(不阻塞):新增规范尚未进全文检索(docs-manifest.json未重生成;生成器 =dsh-server-docs/scripts/docs-manifest.py,⛔ 本棒未擅自跑生成物)。 下一棒 = ⛔ 未登记(同前:即席应答 + IM 线第 15 棒在跑)。 - ✅ 2026-09-23 21:5x|仓库清理执行(用户口令「按照建议清理」· 先备份后删 · 零代码影响) —— 备份 ⇒
归档/dsh_shenxian-清理-20260923/deleted-20260923.tar.gz(1.23 MB / 36 条目 +MANIFEST.txt)。实删:批3 = 26 个 POC 历史 tgz(1.15 MiB) + 批4 =_中间产物_待清理/(5 文件) + 批2 = 2 项;批1/批2 的多数目标在动手前已被清掉(非本次动作,备份包可证);P0 类残留复扫 = 0。守卫全绿:.workbuddy/lock-hook.log(hook 在写)/scripts/overlay-probe.cjs(在册探针)/poc/carbon-mcp-probe/(carbon 线)/poc/im-conversation-tabs/(IM 线)健在,备份包内 0 条他人路径。⛔ 未 commit / push。回报已落交付物/清理候选清单-dsh_shenxian-20260923.md §六。 - 📌 用户问「仓库根
docs/有什么用 / 何时建 / 要不要留」—— 判定 = 全部保留(2026-09-23 21:5x 取证):docs/= 仓库自带的 7~8 篇安装向文档(blueprint/deployment/hard-isolation/domain-config/troubleshooting/k8s-deploy/k8s-deployment/architecture),建于 09-13~09-16(项目最早文档批次);README.md:5明文「docs/(本仓库内)= 仓库自带 7 篇 …… ⛔ 不要往这里写我们的改造记录」+ README 表格逐篇索引 ⇒ 职责与dsh-server-docs/(平台文档库)分离。其中k8s-*两份对应 2026-09-15 已下线的模式 B,但README.md:55明写「保留作为未来可选路线」⇒ 属有意留档,不列可清理项。 ⚠️ 同时澄清「仓库只有代码和文档」不成立:实存非源码内容 =lib/(构建产物 3.5 MiB,服务器跑的就是它)·node_modules/·.workbuddy/(钩子日志,正在写)·config/·poc/(各线 POC 源码)·deploy/assets/.github/·dsh-server-docs/(文档库,含scripts/ ops/ skills/ archive/ tmp/)· 根级Dockerfile*cordis.patch.ymltsconfig.jsonpackage*.jsonmksess.cjs等 ⇒ ⛔ 均在用,不属可清理项。
§1 用户原话(目标,⛔ 不得改写、不得替拍)
「插件由admin上传后,应该是建独立库据库进行对接(需考虑更新插件的情况),然后分发到服务器worker,或端侧设备上,任何登录用户都可以访问才对」
拆成四条判据:
- P1 admin 上传插件 ⇒ 建该插件独立的库并完成对接
- P2 插件更新的情形要有定义(升级后库/表/元数据/存量数据怎么办)
- P3 分发的终点面 = 服务器 worker + 端侧设备(不止 Manager 本机)
- P4 任何登录用户都可以访问
§2 现状(本会话已核实 / 已定稿,执行棒复核时只读)
| # | 事实 | 来源 |
|---|---|---|
| 1 | 一插件一库已拍板:库名 dshs_pl_<pluginId>,全部建在同一个 PG 13.23(47 · 127.0.0.1:15432);库内归属列 user_id / room_id 强制 |
定稿 dsh-server-docs/架构设计/数据-分库与权威存储架构.md;2026-09-22 用户拍板 |
| 2 | 插件数据面实现为零:47 的库内 13 张表全是内核表,p_* 零命中;src/db 无对应模块 |
2026-09-22 实测 |
| 3 | 分发现状 = admin 导入候选池 → 用户在实例「功能管理」自助启用;安装动作 = 实例内 pnpm add file:<tgz> |
src/web/routes/business-plugins.ts:625-651 |
| 4 | 跨机那条腿是断的:/api/dsh/restart 的 handoff 已停写(只留日志)⇒ 装不到 worker 上实例 |
src/web/routes/dsh.ts:149-175(本会话核实) |
| 5 | 端侧(桌面壳 / 设备)没有插件投放通路,目前只有"设备登录接入" | 序㊻ 范围 |
| 6 | 版本一致性已有档案:候选池同名替换 + 版本对账 | 调整方案/144-插件规模化投放与版本一致性.md |
| 7 | 多节点投放与数据面已有档案:路 A / 路 B、worker 自举、目录权限 711 | 调整方案/147-多节点形态下的插件投放与数据面.md |
⚠️ 与既有硬说明的关系:记忆里那条「投放业务插件只有一种方式:admin 导入候选池 → 用户自助启用(不铺 profile)」说的是启用语义;本线的 P3 是包分发面(把包铺到各节点 ≠ 替用户铺 profile)。规划棒须把这两层分清,⛔ 不要当成"推翻既有说明"。
§3 技术方向 · 已拍板口径(用户原话,2026-09-22 13:2x,⛔ 不得改写)
「c 全员默认可见,需自己开通,服务器上所有用户共享只读插件库,不会每个用户分发一份,使用中数据入库,文件保存到用户插件文件夹下对应插件名称的路径中」
拆成四条硬口径(规划棒 ⛔ 不得自行改档):
- D1 可见性:候选池里的插件对所有登录用户默认可见;开通由用户自己点(沿用
/api/plugins/mine/apply)⇒ ⛔ 不采用"默认安装到所有实例" - D2 包共享:服务器上一份只读插件库供所有用户共享,⛔ 不给每个用户复制一份
- D3 数据:使用中产生的数据走库(按插件分库
dshs_pl_<pluginId>,见 §2-1 定稿) - D4 文件:用户侧文件落 「用户插件文件夹 / <插件名称> / …」(目录真身须现场核实,见 §5-3)
📌 2026-09-22 16:3x 补(只记实况,⛔ 未改上面口径):两条待拍板已闭合 —— ① 共享包库版本策略 = 只保留最新一版(用户原话「1 B」)② D4 落点 =
<userRoot>/home/.dsh/plugins/<pluginId>/(口径已对齐:用户说的就是平台用户自己的目录;落点由规划棒自决,可推翻)。详见交接单 §4.1D-i/D-j与 §4.2 注;执行棒以交接单 §五 为准。
技术方向(可推翻,逐条对应上面):
- 包分发:admin 上传后由平台/worker agent 铺到每个节点的共享只读包点;实例侧只引用、不复制。
- 首选实现 = 共享只读 pnpm store(节点级
store-dir,o+rX;node_modules走硬链/符号链接)⇒ 实体一份、链接多份,天然满足 D2;注意硬链要求同一文件系统。 - 备选 = 解包到共享目录后 symlink 进 profile。
- ⛔ 禁止把 tgz 实体复制进各用户 profile(这正是 D2 明令否掉的形态)。
- 首选实现 = 共享只读 pnpm store(节点级
- 不依赖 handoff:包已在节点本地 ⇒ 安装动作不需要"重启后执行命令"那条链(跨机 handoff 已停写,见 §2-4)⇒ 也⛔ 不必给登录用户开命令口。
- 建库是平台侧动作(不在实例内):上传钩子里
CREATE DATABASE dshs_pl_<pluginId>+ 迁移登记;粒度沿用定稿(默认独立 database,schema 档留作备选)。 - 端侧先只做可见性:端侧设备访问同一个平台 API ⇒ 只管"访问得到",不要求端侧本地装包。
§4 P4 粒度:已拍板 = 候选 C(2026-09-22 13:2x)
原三案存档(供追溯):A 全员默认安装 | B 逐用户自助启用 | C 折中。
定案 = C,且用户把 C 的语义收窄为「全员默认可见、需自己开通」:
- ⛔ 不采用 A 的"默认安装"(不把内存/磁盘代价摊到所有实例)
- ⛔ 不加 admin 侧的"默认启用"标记(用户未要求,开线棒提过,已按用户口径去掉)
⇒ 规划棒:这一项不再出候选,只管把 C + §3 的 D1–D4 落成可执行方案。
§5 下一棒要做什么
🔄 2026-09-23 更新:本节原有内容(规划棒口径)已由规划棒①执行完毕(交接单已产出并跑完执行棒①的 S1/S2)。当前执行依据改看 §0 最新一行 + 下方「⏭️ 本轮动作」。
⏭️ 本轮动作(第 9 棒 · 规划棒 · ✅ 已收官 2026-09-23 10:0x)= 跨机可见性状态回流(缺口立项)
✅ 第 9 棒已收官(设计件
交付物/跨机可见性状态回流-设计件-20260923.md+ 三门基线复验全过 + 交接单 §五 S6 已知边界登记,见 §0 2026-09-23 10:0x 行)⇒ ⛔ 不要重做。 ✅ 第 8 棒已收官(部署 47/106 + S5-E ①–⑤ 全 PASS + S6-E ①③ PASS/② 只记事实 + 修掉pg_dumpenv 真实缺陷,见 §0 2026-09-23 09:5x 行;落地件交付物/S5-S6真机E2E验收-20260923.md)⇒ ⛔ 不要重做。 ✅ 第 7 棒(S5-a + 迁移前备份 + S6 三段式 UI)、第 6 棒(S3 跨机装配)、第 5 棒(三份文档回写)、第 4 棒(建库口接线)同样已全部落地 ⇒ ⛔ 不要重做。
⏭️ 下一棒(⛔ 未登记 —— 等用户拍板):
🔴 接续点 = 用户对「跨机可见性回流的通路形态」拍板(候选 A 主动拉/B 共用台账/C worker 上报,优缺点见设计件 §三)。拍板到手后,排**「跨机可见性状态回流」执行棒**。 ⛔ 本轮不登记下一棒:拍板项未定 ⇒ 按用户级记忆「要用户拍板的,等拍了再新建接续会话」——先判"是不是要拍板",命中即停,⛔ 不得因"候选排序看起来有优劣"就自决登记。 ✅ 已解决的待拍板项(装配协议)见本节末「⚠️ 已拍板待落地」 —— ⛔ 该条退出待拍板清单,拍板前禁令随之解除(禁令仅针对"未拍板就改",不针对落地)。
⛔ 执行棒开工前仍须遵守:⛔ 不开可见面开关 DSHS_SHARED_CATALOG_PUBLIC · 不做跨节点内容分发(需单独立项)。
要求:判据给「命令 + 期望输出 + 退出码」。
⚠️ 已拍板待落地(用户 2026-09-23 拍板 · ① ② ④ 已落地 ✅,③ 已实测撤销)
🔴 装配协议 = 采用
link:(推翻原 D-hfile:)。用户原话:「按照建议处理」。 落地范围(4 处)现状: ① ✅ 已落地 ——src/supervisor/plugin-assembly.ts新增depRefOf()(file:→link:)+business-plugins.ts4 处fileRef同步;npm run buildrc=0 |npm test= 450/448 过 / 0 败 / 2 跳过 |check-layering✅ 无新增违规。两机已部署(47/opt/dshs+ 106/opt/dshs-cluster,md5 逐字一致fe5162ec…/ed507b7a…)+restart完成(门户 200 · worker 401)。 ② ✅ 已落地 —— 交接单该文档file:描述已改(含 §9.3 整节改写 + 新增 S3-E 真机复验段)。 ③ ⛔ 已撤销(实测证伪,⛔ 别再做) —— 全平台扫描:带依赖的实例只有 1 个,5 条依赖全是file:…tgz(.tgz型 0 条目录型),且只有 1 条能在共享层找到对应目录 ⇒ 原「把 4 条改写成共享层引用」会让 4 条依赖悬空 ⇒ 实例崩。成因 = 那 4 个包是平台自研核心组件、从不进共享层。⇒ 迁移在真实数据上不成立,等这些包进共享层再议。详见交接单 §9.3。 ④ ✅ 已落地 —— 47 真机复验(applyProfileChanges真实入口):profile 写入link:/var/lib/dshs/bundled-plugins/dsh-plugin-mcn-suite✓|node_modules/<pkg>= 软链 ✓|软链目标回溯直达共享层(非复制)✓|软链本体 54 字节 +.pnpm8.0 K ✓|用户身份下可读 ✓|反证plugin_bundle_missing原子抛错 ✓。对照file:的 6.5 MiB / 116 文件 ⇒ 量级差约 1000 倍。探针用户已回滚(dependencies回空、软链已移除)。 ⚠️ 残留一条待补(不阻塞):106 侧跨机那条腿 —— 106 上当前无带插件的用户实例可复验(其用户 profile 无依赖),等 106 有用户启用插件时按 S3-E ④⑤⑥ 原命令补一次即可。装配实现两机共用同一份 md5,不因此判 S3 未完成。 ⚠️ 跨机前提:软链目标必须是两机同路径的共享层(现为/var/lib/dshs/bundled-plugins/<flat>,两机同名 ✓);⛔ 若将来两机路径分叉,link:会比file:更脆 —— 已写进depRefOf()注释。⚠️ 注意/opt/dshs(47 代码根)与/opt/dshs-cluster(106 代码根)两机不同名不影响link:—— 共享层路径才是link:的目标。
⏭️ 本线后续(⛔ 本棒不预登记队列)
- ✅ 跨机可见性状态回流 —— 形态已定稿(2026-09-23 18:3x 用户拍板 = 形态 D「按需定向拉(主)+ worker 变更上报(辅·后置)」) —— 用户原话「可以 worker 上报,具体要管理那个用户的时候 manager 针对性的去查」。原 A / B / C 三候选作废(§三 仅存为决策过程)。设计件 §十 已整节改为定稿(10-1 形态 / 10-2 关键发现 / 10-3 两条硬约束 / 10-4 五步落地轮廓 / 10-5 四条真机验收)。
🔴 关键发现(写出这条是为了让下一棒不用重查):
src/supervisor/leased-spawner.ts:144-155的fenceOnAgent()已经实现了完整三步定位链 ——findUserInstance(userId,'main')拿 hostId →options.agentFor(hostId)拿{agentUrl,token}→post('/fence', body, target)带 token 定向 POST 到那台 worker ⇒ 主路径只需把目标端点从/fence换成新的只读口(建议/profile-bundles)。⇒ 零新增监听口 · 零新增凭据体系 · 零广播,且天然覆盖reconcile(查的是对端现算真值,不是历史快照 —— 这正是原 B 案的死结)。 ⛔ 两条硬约束:① 新端点必须带 token(与/fence同级)—— ⛔ 绝不可挂到免凭据的/healthz上(那等于开匿名任意读口);② 查不到该 userId 必须返回not_here,⛔ 不等于"零插件"、⛔ 不许把"未知"显示成"未启用"。 落地位置:src/worker/agent.ts(新端点)|src/supervisor/leased-spawner.ts(复刻定位链)|src/web/routes/business-plugins.ts:1648-1670的/mine(先判本机 ⇒ 本机直接读盘零网络,非本机才定向查)。 ⚠️ 下一棒 = 待排(原记「automation 不可用,见 §0 末行」—— 🔻 该前提已于 2026-09-23 19:4x 作废,见本节末「状态更正」)—— 本项未开工,⛔ 不要当成已落地。 - 跨节点内容分发(后续棒 · 需单独立项)—— 平台侧把共享层铺到各节点的通路;第 8 棒 106 的共享层是手工同步的。
- 可见面开关的开启决策(红线门禁 · 待拍板)——
DSHS_SHARED_CATALOG_PUBLIC开与不开会让"用户能看见什么"变化 ⇒ 需用户拍板后才开。 装配协议✅ 已完成(2026-09-23) —— 见上方「⚠️ 已拍板待落地」;③ 存量迁移已实测撤销。link:落地- 🔴 E 单(
im-conversation-tabs)的线上可见面投放 —— 此前无归属,2026-09-23 19:4x 由 IM 线第 12 棒显式登记到此(登记依据 =接续入口_IM线_20260922.md第 136 行的收口要求)。- 是什么:IM 线 E 单的 UI 落点(用户已拍板 C 案 = 实例内 dsh 会话页 tab);代码面已完成(
poc/im-conversation-tabs/)。 - 为什么以前没人做:本入口此前对
im-conversation-tabs零命中 ⇒ IM 线以为"投放线会接力"、投放线没登记 ⇒ 两不管。 🔴 硬阻塞(⛔ 未解,先别投):IM 线查出一处 P0 协议不一致 ……✅ 已解(2026-09-23 19:5x,IM 线第 13 棒) —— 客户端已对齐平台的 op 制(出站收敛到subscribe / ping / resume,入站switch (msg.op)全量 9 分支),并新增两侧源码机械对账用例E-14守着;⛔ 不再有type:出站帧。- ✅ 投放已执行(2026-09-23 20:2x,IM 线第 14 棒):按本线既有流程走完 —— admin
POST /api/plugins/business(http=200,池 4→5,trustedOverride:false)→POST /api/plugins/business/share(http=200action:"created",fileRef = link:/var/lib/dshs/bundled-plugins/_dsh-local_im-conversation-tabs)→ 回滚素材/opt/dsh/backups/plugins/_dsh-local_im-conversation-tabs/0.1.0.tgz;审计audit_logid 360 / 361。⛔ 未铺 profile、未 commit、未改动本线任何代码。⚠️ 「共享层发布」这一步是link:装配协议的必需项(只进池不发布 ⇒ 用户启用撞plugin_bundle_missing)—— 本线后续给任何插件投放时都要带上这一步。 - 📌 归属 = IM 线自行认领完结(2026-09-23 20:2x 第 14 棒):投放的可自动部分由 IM 线做完;剩余唯一未闭合项 = 用户在实例「功能管理」启用(用户动作,属投放语义),操作单 ⇒
E:\ProgramData\AI技能\aliyun-dsh-server\交付物\IM群组-ui投放与线上取证操作单-20260923.md。⇒ 本线不再有该条的待办,⛔ 不要重复认领。⚠️ 一条留在本线名下的关联缺口:目标实例若在 106,其共享层缺该包 ⇒ 与本入口 §5-2「跨节点内容分发(需单独立项)」是同一件事,操作单里给了手工同步命令。
- 是什么:IM 线 E 单的 UI 落点(用户已拍板 C 案 = 实例内 dsh 会话页 tab);代码面已完成(
📌 状态更正(2026-09-23 19:4x,IM 线第 12 棒顺带核对 ⇒ ⛔ 未替本线排棒):§0 末行「
automation_update返回file is not a database⇒ 全机 automation 功能不可用」的前提已消失 —— 宿主活动库已由 app 自动重建(2026-09-23 18:55;坏库改名workbuddy.db.corrupt-2026-09-23T10-55-47-845Z留档,代价 = 历史 automation 记录全丢)。本会话实测mode=list/mode=create均可用 ⇒ 本线「下一棒」可以正常登记了。⚠️ 排棒时机仍由本线收口时自行决定(⛔ 不预登记队列)。
§6 开工校验(新会话先跑这三条)
- 口径门禁:本入口 md5 见启动棒 prompt(开工时现算比对;不符 ⇒ 先读最新版再动手)
- 源仓 HEAD:
git -C D:/github/dsh_shenxian log --oneline -1(以实跑为准) - 相关口径复核:
/etc/dshs.env无DSHS_ENABLE_PATCH(47 / 106 于 2026-09-22 实测)—— 本线 §3.2 正是为绕开它而设计
⛔ 不要重做:carbon 线两处阻塞的定位(memory
10:0x节已判完);一插件一库是否分库(已拍板,见 §2-1)。