Files
dsh_ai1net_server/dsh-server-docs/交接单
admin 09ce76f3af feat(overlay): 内容块级寻址 + 实例逐步拉起 + 骨干选路 + 组密钥加密(序24–㉛ 累积同步)
代码
- 内容分发块级寻址:新增 src/net/relay/content/{chunker,store,runtime,source,peer,crypto}.ts
- 组密钥(C 档)确定性加密:AES-256-GCM,块 id β′ = sha256(密文) 前 32 hex;双 epoch 过渡窗口
- 实例生命周期:三处 teardown() 不再杀实例(local/remote/leased-spawner);启动认领 + TCP 探活判孤儿
- 骨干选路:jitter 选路 + endpoint-target;relay client/server/wire/identity/directory/rendezvous/switcher 调整
- 工作台 src/web/server.ts、src/worker/relay-tunnel.ts 装配与候选链观测

脚本与测试
- scripts/overlay-{probe,keyring,jitter}.cjs 更新
- 探针新增 OBS-21(每连接候选数)/ OBS-22(teardown 静态守卫 + 认领面)/ OBS-23(组密钥加密)
- 新增 test/{orchestrator-teardown,orchestrator-rehydrate,overlay-content,overlay-jitter}.test.mjs;relay 两例更新

文档
- 新增交接单:覆盖网络-序24-内容分发块级寻址 / 序25-实例逐步拉起 / 序26-骨干稳定选路与加密
- INDEX.md、交接单/README.md、skills/dsh-auto-handoff-chain/SKILL.md 同步

验收(零回归,2026-09-18 08:0x 复核)
- npm test           201 tests / 200 pass / 0 fail / 1 skipped
- overlay-failover-drill --scene all --table   12 PASS / 0 SKIP / 0 FAIL
- overlay-probe --table                        23 PASS / 0 SKIP / 0 FAIL (rc=0)
2026-09-18 08:08:51 +08:00
..

交接单(规划会话 → 执行会话)

  • 日期:2026-09-11(2026-09-12 增「待执行清单」)
  • 状态:✅ 启用(本目录是「方案规划」与「落地执行」的唯一传递面)
  • 触发:用户口径「执行任务时间太久 → 一个会话做任务规划,另一个会话执行」

本目录只在「要执行某个任务」时读;日常对齐现状请读 BRIEF.md。 待执行 = 本目录(交接单/*.md);已完成 = archive/交接单-已完成/(首次完成后自动出现)。 完成后:单子头部状态改 ✅ 并附证据 → git mv 归档 → 在 INDEX.md §四 归档表加一行。


一、待执行清单(唯一来源 = 本表)

单子 状态 占用者 / 开始 一句话 冲突域 依赖
T01-档案16阶段3-4-实例内我的技能.md ✅ 已完成并归档(2026-09-15,执行会话 T01我的技能-0825) —(已释放) 实例内「我的技能」(上传/启停/删除);形态修正 = 并入既有「功能管理」内分组(不新开 section)+ 阶段 4 权限收口复核 代码(poc/business-plugins)+ profile 层 + 实例重启;文档 README/INDEX/03-路线图 决策点 1 = A 扩展 business-plugins(已定)|证据:档案 100;插件 0.3.21 已投放两实例;npm run verify 全绿;06 §7 三段式全绿(壳页 combo 含 @dsh-local/business-plugins、rev=533537bbc02b、bundle 200 · 11,363,655 B 含新特征);端到端 19/19(共享技能 409 / 非 zip 400);阶段 4 收口 = 未新增 section、未改角色补丁 ⇒ 可见性不变
T02-文档库收尾-编号消歧与INDEX瘦身.md ✅ 已完成并归档(2026-09-12,并行执行会话) —(已释放) 37a/37b/38a/38b 编号消歧(+ 2 个脚本 8 处正则)+ INDEX 瘦身 + 事实校正 纯文档 — 证据:4 文件已改名;scripts/docs-{audit,manifest}.py 正则已支持 [a-z]?;INDEX 28,805 → 7,468 字符(≤10K 达标);audit【1】冲突 0、【2】标题号不符 0、【6】无悬空;陈旧表述("服务器唯一源"/aliyun-work-space/"下一号 = 20"/8355e99)已归零;已归档 archive/交接单-已完成/
T03-plugin_package整合为单插件并投放.md ✅ 已完成并归档(2026-09-13 18:0x;原状态:🔄 进行中 —— 步骤 1–9 已完成;候选池上传已完成 —— 现行池内版本 = dsh-plugin-mcn-suite @0.3.9(09-13 00:02 上传;历史:22:0x 曾传 0.3.1 → 实例启用失败,根因 = peer 依赖被 pnpm 按公开 registry 解析;22:2x 加 peerDependenciesMeta.optional 修复后重传,HTTP 200 / replaced:true / compat.level=ok)。⚠️ 09-13 07:1x 复核:0.3.2→0.3.9 期间连修:漏声明 xlsx 依赖、client 注册层 id、inject 语义);admin 侧已装 0.3.9 且 host 面 3 个注册加载通过;guest bundles 仍未含 mcn-suite(⚠️ 07:4x 用户尝试启用 → 失败:装上后实例探活不通过(内存不够),失败路径上又触发档案 79 的 P0 缺陷(orchestrator 退出)⇒ 已手工回滚 profile 并验证实例恢复)⇒ 「guest 启用」仍待做,前置 = 先修档案 79 + 解决堆容量(用户已定:暂不改配额档位)) —(已释放;原由 exec-session-B 持有,接管自卡死的 exec-session-A) 7 个自研插件整合成 1 个功能插件包(dsh-plugin-mcn-suite);业务技能随包投放(用户要求「不分开管理」) 代码(新建整合包 + 打包脚本)+ 平台候选池(上传/下架)+ 实例重启;文档 README/INDEX/03-路线图 ✅ 决策已定(2026-09-12 用户拍板):① 不进 social-workbench ② 进 voxemw ③ 多入口并列 ④ 技能随包投放(§4.1)⑤ v0.3.0。进度:产物已出 D:\dshworkspace\plugin_package\dist\dsh-plugin-mcn-suite-0.3.0.tgz(438 条目 / 1.90 MB / md5 f98a3303…);路由 48+6+7 条 ✓;本地 smoke 17 组全绿 ✓;上传扫描 P0=0 ✓;死引用 0 ✓;待执行:用户在实例「功能管理」里启用(用户动作,平台不代劳)→ 启动实例 → §八验收 → 归档。⚠️ 2026-09-13 阻塞:启用会因同堆内存不够致探活失败,并触发档案 79 的 P0 缺陷 ⇒ 先修 79 + 解决容量后再启用
T04-并发治理落地-commit常态化与服务器侧锁.md ✅ 已完成并归档(2026-09-12 15:10,exec-session-C) —(已释放) 并发治理落地:commit 常态化 / 服务器侧操作锁 / 权限统一 700·600 git(本机提交,不 push)+ 服务器(建锁目录 / chmod)+ scripts/ ① 文档库 git 基线提交 + 此后只提自己改的文件 ② 服务器侧操作锁(/opt/dsh/state/.op-lock/)③ 交接单目录权限统一 700/600|决策已定(用户「A 按最佳方案」);基线提交需"静态窗口"
T05-插件兼容性预检.md ✅ 已完成并归档(2026-09-12 16:35,exec-session-D,commit 8d19e89) —(已释放) 插件在导入/上传时即判定与平台 dsh 的兼容性(semver 依赖判据 + 运行时导出符号判据),不再等实例崩 代码 src/web/{plugin-compat.ts,routes/*.ts} + build + 重启;文档 README/INDEX/03-路线图 方案见 04-71;⚠️ 与改 orchestrator.ts 的并行会话冲突域重叠 → 必须串行
T06-模型设置页-多厂家条目可开关.md ✅ 已完成并归档(2026-09-13 23:5x,craft-session-T06) —(已释放) 平台自建「设置 → 模型设置」:条目各自开关、可同时启用 + 官方「模型」分区对全角色隐藏 + spawn 时把「已启用条目」落地到实例 .credentials.yaml / settings.yaml 代码 src/db/*、src/web/{model-landing.ts,server.ts,routes/auth.ts}、ensure-role-profile-patch.cjs、poc/business-plugins(0.3.11) + systemctl restart dshs + ensure-biz-plugins --all --restart;文档 README/INDEX/03-路线图 ✅ 无阻塞(口径用户已定);证据与判据见 04-87;⚠️ 本轮顺手修掉两颗雷:角色补丁脚本的整文件覆盖会抹掉 admin 另两个平台块、verify-mem-model 的陈旧断言
T07-内置dsh安装路径探测.md ✅ 已完成并归档(2026-09-14 05:0x,craft-session-installpath + craft-session-tailclear) —(已释放) 修 P1 静默失效:三处把内置 dsh 安装目录写死 ⇒ 在 npm root -g = /usr/lib/node_modules 的发行版上,厂家目录读空 / 兼容性预检安全网失效 / 目录选择器 import 抛错 代码 新增 src/web/dsh-install.ts + 三处调用点(含 poc/workspace-scoped-picker)+ 插件 business-plugins 0.3.13 / workspace-scoped-picker 0.1.5 + build/restart/铺发;文档 04-88 + README 补 3 个 env ✅ 无阻塞;由开源导出会话提出(它抢不到锁按 R9 停手),源仓独立复核后经用户「确认修改」落地。⚠️ 复核时发现提出方漏了第 3 处、且其 env 名是导出侧的 ⇒ 均已纠正
T08-集群化落地-兼容单例模式.md ✅ 已完成并归档(2026-09-15 18:0x,exec-cluster-1a) —(已释放) 把平台改造成「1 组 Manager(≥2 台,也支持单活)+ N 台 Worker + 共享归属状态」的集群形态;硬约束 = 全程兼容单例模式 + 每步可单独回滚。证据:S0–S7 全绿(冒烟 6/8 与开工基线相同 · 5 个端到端 · lease 单测两后端 10/10)|真跨机演练(47 Manager / 106 Worker,跨云)✅|域名形态访问 ✅|2026-09-15 17:4x 生产整体切换(47=Manager+本地 Worker w-47、106=Worker w-106、控制面库=47 的 PG13;存量用户留 w-47、新用户落 w-106;回滚=删 drop-in)。⚠️ 残留小项(已登记 03-路线图 §二):join-worker.sh 一键装机 · 隧道服务化(心跳重建)· 集中日志/metrics · smoke-domain 定性。详见 §9–§16 代码(src/supervisor/、src/db/、src/cli.ts、src/fs/)+ 服务器(106 另起一套测试环境;47 不动)+ 文档(本单 + 完工时的 04-调整方案/101) 设计单一来源 = 项目根 集群化改造方案_Manager-Worker_20260914.md(19 节);决策 D1–D5 已定(双活+支持单活 / 存储可插拔 / 自建 PG / 跨云只当测试床 / 测试环境用 106);⏳ 仅 D6「生产拓扑最终落点」需用户拍板,且不阻塞 S0–S5
覆盖网络-序24-内容分发块级寻址.md ⏳ 待执行(2026-09-17 20:4x 立单) 🔄 已登记 automation 91251b14-9ee8-42a9-9d89-8559b7af75ed(2026-09-17 20:42 起) 首屏包冷启动改造:块级内容寻址 + 同网段 peer 优先(内容源优先级链 本地→同网段 peer→边缘缓存→分发点→公网源)。主判据 E1 = 版本发布时回源字节数 ≈ 1 份 × 组数。🔴 必须块级,⛔ 绝不做包级(包级 = 版本一发即全量重拉风暴) 代码 src/net/relay/content/{chunker,store,peer,source}.ts + index.ts/web/server.ts/scripts/overlay-probe.cjs/参数表;文档 本单 §8 用户拍板 2026-09-17:「B 内容分发(块级内容寻址)是否立项:做」;依据 覆盖网络_瓶颈落地方案_20260916.md §3;§7 前缀 49d0f405e08c909e18ba6825d1442b9d
覆盖网络-序25-实例逐步拉起.md ⏳ 待执行(2026-09-17 20:4x 立单;待 序㉔ 收口时登记下一棒) ⛔ 未登记(等 序㉔ 收口) Manager(portal)重启后逐步接管既有实例,而不是启动即清空。⚠️ 关键事实:orchestrator.ts:208 构造函数里 cleanAllStaleScopes() ⇒ 现在portal 一启动就把全部实例 scope 清掉 ⇒ 本单 = 把「清空」换成「接管」。主判据 E1 = 重启后实例数不变 代码 src/supervisor/orchestrator.ts(cleanAllStaleScopes / cleanStaleScopes 一带);文档 本单 §8 用户拍板 2026-09-17:「Manager 重启后是否自动拉起既有实例:逐步拉起」;三条硬约束(⛔ 不许删 cleanStaleScopes(uid)/⛔ 不许改成"什么都不做"/⛔ 不许"重启后重新 spawn 一遍");§7 前缀 d9d48121e68faa00e1da17ad8fea36ad
覆盖网络-序26-骨干稳定选路与加密.md ⏳ 待执行(2026-09-17 20:4x 立单;待 序㉕ 收口时登记下一棒) ⛔ 未登记(等 序㉕ 收口) 骨干节点服务范围落地:连接稳定高效(jitter 选路 + 2–3 候选路径 + 中继余量 30%+ + ≤10 成员全互联)+ 数据安全可加密传输(TLS 已在 + 签名/哈希完整性 + 元数据最小化)。主判据 E1 = jitter 更低但 RTT 更高的候选被选中 代码 新增 src/net/relay/jitter.ts + directory.ts/switcher.ts(只加"jitter 劣化即切",⛔ 不改冷却语义)/server.ts/scripts/overlay-jitter.cjs/参数表;文档 本单 §8 用户拍板 2026-09-17:「入口 §4 骨干节点的服务范围:按照连接稳定高效的方式 数据安全可加密传输」;判定 = A 起步、口径按 B 的质量标准建设;§8 前缀 dbcbe633aa1aef92f4c35c77fad3ec11

🔒 占用怎么声明(2026-09-12 新增,防两会话撞车):开工前先原子占位 —— mkdir 交接单/.doing-<单号>(mkdir 原子:成功=你拿到;报 File exists=已有人在做 → 停手,别开工), 回来把本表「占用者 / 开始」填上(会话标识 + HH:MM);完工 rmdir 交接单/.doing-<单号> + 状态改 ✅。 查当前占用:ls -d 交接单/.doing-* 2>/dev/null。标记是纯本机目录(空目录不会 scp 出去),两会话同机所以够用。 ⚠️ 占位与台账必须"同一动作"完成(2026-09-12 实证):T03 10:14 就占了位,但 §一 台账那行直到 12:59 才改成「执行中」→ 中间 2.5 小时里别人看台账会以为没人做,随时可能重复开工。所以:--claim 之后立刻把该行状态改「🔄 执行中」并把「占用者 / 开始」填上。handoff-guard.sh 的 【1b】已能自动检出这种不一致(硬失败)。 🔐 两级锁(2026-09-12 新增,用户建议) —— 一把粗、一把细:

  • 粗 = 全局执行锁 交接单/.exec-lock:同一时刻只允许一个执行会话去动「文档 / 代码 / 服务器」。这是默认工作模式(本库共享入口文件多、且要动生产)。
  • 细 = 单级占用锁 交接单/.doing-<单号>:标记"这个单归谁做",供台账与接管使用(冲突域真不重叠时才允许两单并行)。
  • 顺序:开工 --claim-exec → --claim <单>;完工 --release <单> → --release-exec(锁最后放)。
  • ⚠️ 「无锁」的正确读法 =「你快去抢」,不是「可以开工」(2026-09-12 实证:handoff-guard.sh 输出「无全局锁」被读成"环境干净", 结果两个会话同时改了本库 —— 无实际损害,但属流程失效)。看到"无锁" ⇒ 下一个动作就是 --claim-exec; 抢不到 = 有人在跑 = 停手。抢锁是原子的,抢到才是开工许可。
  • 检查:ME="<你的会话名>" bash scripts/handoff-guard.sh <单号> —— 【1c】会告诉你全局锁在谁手上;不设 ME 时一律按"别人的锁"处理(保守)。

✍️ 写者归属(每个文件只有一个写者;2026-09-12 补) —— 「占用锁」防的是"同一单",下表防的是"跨单撞同一文件":

文件 唯一写者
交接单/<单号>.md 该单的执行会话(规划会话只读)
交接单/README.md §一 状态表 各自只改自己那一行(规划会话加新单 = 新增一行;执行会话改状态 = 改自己那行)
交接单/README.md 其余章节(约定) 谁改谁先读、只用 Edit 精确替换
04-调整方案/、INDEX.md、BRIEF.md、根 README.md、03-路线图与待办.md 执行会话(规划会话只读)
skills/dsh-change-workflow/SKILL.md 其工作副本持有者(单向往本库推进,勿反向覆盖)
scripts/、ops/ 谁新增谁负责(新增文件天然无冲突;改已有文件先跑 guard)

⚠️ 两单必须串行(2026-09-12 更新):T01 与 T03 都要动代码与实例、都要改 README.md / INDEX.md / 03-路线图与待办.md、都要原子占档案号。按 skills/dsh-change-workflow 的「多任务并行调度协议」(并行度由冲突域决定,不由任务数决定)→ 同一时刻只放一个执行会话。(T04 已完成归档,其"基线提交触及所有人文件"的风险已消除。)

建议顺序:T03 → T01(T04 已完成并归档,不再在序列内)。

  • T03 先做:收益最大(7 包归 1),决策已全部拍板,只差"上传候选池 → guest 启用 → 验收 → 归档"。
  • T01 最后:依赖 T03 之后的候选池 / 实例状态;决策点 1 已定,无阻塞。

分工边界(防双源漂移):03-路线图与待办.md 管「平台还没做、也还没规划的事」;本表管「已经规划成单、等执行的事」。同一个事项在两边都出现时,状态以本表为准,03-路线图 那行只保留指针。


二、单子必填 8 段

# 段 写法要求
1 目标 一句话,可判定"做完了没有"
2 只读前置 执行前必须先核实的 3–5 条事实,给命令与期望输出,不让人推断
3 范围 改哪些文件;并明确"不动什么"(防止顺手扩大)
4 决策点 已定的写「已定(谁定的/依据)」;未定的写「开跑前问用户」
5 步骤 有序编号,每步自带一次可执行的验证
6 验收 命令 + 期望输出(含退出码),可被第三方复现
7 回滚 具体命令或副本路径
8 回报格式 执行会话必须回填的证据(命令、输出、commit)

判断标准:执行会话不读规划会话的上下文也能开工。凡需要"你懂的"才写得通的句子,都是没写清。

⚠️ 写引用/数字的两个坑(2026-09-12 三次实证,写单子时必看)

  1. 不要在「档案」二字后面直接跟一个字符类(例:写成 档案 + 3[78]、档案 + 6[01])—— docs-audit.py 的引用正则会把它们读成裸旧号(3 / 6)→ 永久悬空、audit 退出码非 0(T02 执行会话踩 1 次、规划会话踩 2 次,连本条警告的第一版也踩了)。要举例请写 档案 (37|38),或在中间加反斜杠阻断匹配。
  2. 基线/阈值数字必须带"取数时间 + 复核命令",不写死绝对值 —— 会被并行改动打穿(实证:T02 里写死的 INDEX=25,581 在 40 分钟内变成 28,805)。

三、执行会话的硬要求

  1. ⚠️ 先确认没有别的会话在写同一文件(2026-09-12 新增):本库多个会话并行工作已是常态(实证:同日 T01 被两会话先后编辑、T02 与 T03 由两会话同日产出、交接单/README.md 被双方先后改动)。冲突域重叠的单子必须串行(§一),但跨单子仍会撞同一批文件(INDEX.md / README.md / BRIEF.md / 03-路线图 / 本 README / skills/…/SKILL.md)。开工前必须:
    • ① git -C dsh-server-docs status --short + bash scripts/docs-sync-check.sh(退出码 0)→ 看清有没有不属于你的未提交改动;
    • ② ls -la --time-style=+%H:%M <要改的文件> → mtime 比你上次看到的新 = 别人刚动过 → 先读最新内容再改;
    • ③ 共享文件只用 Edit 做"精确片段替换",禁止整文件 Write 覆盖 —— 别人改了同一处时 Edit 会失败,这就是天然的冲突检测;确需整文件重写(如 INDEX 瘦身)→ 先确认无人在改 + 先留回滚点(cp x x.bak-<ts>,或先 git commit 留下 HEAD)+ 改完立即 commit。注意 Write 覆盖是静默的、没有检测能力,这类操作是并行期最危险的一步。
    • ④ 改完立即 git commit(本机,不 push) —— 本库目前长期不提交,等于没有冲突检测能力(无法靠 pull/merge 发现撞车)。提交是"给下一个会话留路标",与"推送上线"是两件事(推送仍需用户明确说)。
    • ⑤ 推服务器前必须复跑 docs-sync-check.sh;报「仅本地」的文件若不在你本次改动清单里 → 立刻停手(2026-09-12 事故实证:我把已被对方归档移走的 T02 单子又推回服务器,制造出"幽灵文件",靠对方后续同步才清掉)。这类"迟到的推送"是本库最容易发生的并行事故。
    • ⑥ 不要"重放"别人的文件:只推你自己本次生成/修改的文件。看到别人的新文件想"顺手一起推" → 先问,对方可能正处在半成品状态。
  2. 开跑前拉齐:bash scripts/docs-sync-check.sh(退出码 0);读单子「只读前置」与 §一 的冲突域/依赖。
  3. 新增档案必须原子占号:mkdir <目录>/.lock-<NN> 再写("先 ls 再写"两次撞号实证 → skills/dsh-change-workflow/SKILL.md:250)。
  4. 收尾四件套:python3 scripts/docs-audit.py(退出码 0)+ python3 scripts/docs-manifest.py(刷新机读清单)+ bash scripts/docs-sync-check.sh(0)+ 推送前 MINE="<我改的文件...>" PUSH=1 bash scripts/handoff-guard.sh(幽灵文件硬判定,2026-09-12 因漏此步把已归档文件推回服务器)。
  5. 回填:§一 本行状态改 ✅;勾销 03-路线图 对应行;更新 INDEX.md §二 状态行与 README.md 的「下一号」。
  6. 提交边界:推送需用户明确说"推送"(沿用既有红线,见 README §红线 第 3 条与用户约定)。
  7. 单子归档:git mv 交接单/<单> archive/交接单-已完成/<单>(archive/交接单-已完成/ 首次完成时创建)。
  8. 服务器镜像:本目录新增/修改的文件同样要 scp 到 /opt/dsh/docs(root 600,README 类保持 644)——规划会话不 scp,这一步一律由执行会话做。
  9. 预检工具(2026-09-12 新增,把上面 0–② 变成一条命令):scripts/handoff-guard.sh(只读)
    • 占位 / 释放:bash scripts/handoff-guard.sh --claim T03 "exec-session-A" / --release T03
    • 开工检查:MINE="交接单/README.md 交接单/T03-*.md" bash scripts/handoff-guard.sh T03
    • 推送前检查:同上再加 PUSH=1(启用【4】的幽灵文件硬判定:对账结果里「仅本地」的文件若有未声明的 → 直接失败)
    • 判据与设计:mtime 只作提示(分不清谁改的);硬判定只有两处 —— ① 别人的占用锁;④ 「仅本地(待推送)」清单里含未声明文件(= 幽灵文件风险,2026-09-12 就是这么把已归档的文件推回服务器的)。② 越界改动只作提示(本库长期脏,无法作为判定依据)。退出码 1 = 不可放行。
  10. 会话生命周期 = 一个单(2026-09-12 新增):一个执行会话只做一个单;该单 ✅ + 归档 + 双端一致之后,就地结束这个会话,新任务开新会话。 理由(实证):会话越长寿,越容易拿过期快照当事实 —— 同一天里,T02 单子写死的 INDEX=25,581 在 40 分钟内变成 28,805;BRIEF.md 至今仍写 512M 而实际已是 384 MiB。新会话用交接单冷启动,比老会话带着旧上下文续跑更准。
  11. 🔒 执行中冻结单子(2026-09-12 新增):单子被 .doing-<单> 持有期间,只有持有者可以改该单子文件;规划会话与其它执行会话一律只读。需要补充意见 → 写进 .doing-<单>/OWNER 的"待并入"段,或等锁释放后再改。今天实测过这个风险面:规划会话 09:20–09:45 在改 T03,执行会话 10:14 才锁它 —— 时序上是安全的(先改完再开工),但反序就会撞。
  12. 接管必须无损:OWNER 是交接凭证(2026-09-12 新增,来自 T03 的 A 卡死 → B 接管 实战;⚠️ 「接管」这个动作本身现已受 R9 限制 —— 见第 13 条末,不得由 AI 自行发起):OWNER 至少写四项 —— ① 占用者 ② 开始时间 ③ 进度(做到第几步 / 已完成哪几段) ④ 产物位置与 md5 + 下一步。接管者先读 OWNER 与单子回报段,再续做,不要从头重来。示范(T03 实际写的):exec-session-B(当前会话,接管自 exec-session-A),台账里补了"步骤 1–9 已完成、产物 dsh-plugin-mcn-suite-0.3.0.tgz(438 条目 / 1.90 MB / md5 f98a3303…)、待执行 = 上传→启用→验收→归档"。
  13. 并行干活、串行登记(收口单点):确有多单并行时,各自的档案占号(.lock-<NN> 原子)与各自 §一 行可以并行;但 INDEX.md、03-路线图与待办.md、根 README.md 的"登记动作"由单一收口会话统一做(沿用 skills/dsh-change-workflow 的"收口在主会话"规则)—— 因为这几个入口文件是全库唯一的双写热点。
  14. 🔐 全局执行锁:一次只允许一个执行会话(2026-09-12 新增,用户建议) —— 单级锁只管"同一单别被两人做",管不住跨单撞共享文件、更管不住服务器态并行(重启/drain/改 env 会让在线用户掉线)。所以补一把全局粗锁:
    • 开工:bash scripts/handoff-guard.sh --claim-exec "exec-session-B" T03(抢不到 = 已有会话在跑 → 停手,输出会直接告诉你占用者/开始时间/在做哪单);
    • 完工:bash scripts/handoff-guard.sh --release-exec(放在最后:回填 → 改自己 §一 行 → commit → 推服务器+対账 → 归档 → 再放锁);
    • 检查:ME="<会话名>" 时 guard 会区分"自己的锁"(提示别忘释放)与"别人的锁"(硬失败);不设 ME 一律按别人的处理(保守);
    • ⛔ 接管:AI 不得自行接管,更不得删锁(R9,2026-09-12 用户明令「严格禁止这类操作」)—— 抢不到锁 ⇒ 停手 + 报告用户;锁的处置权只属于用户本人(要撤也只能用户自己动手)。 下条的「读 OWNER + 台账进度」只用于「用户已点头、且用户自己撤锁之后」的续做; 不得以「持有者疑似已死 / 卡住 / 太久没动 / 只在只读分析没产出」为由单方面撤锁 —— 平台无心跳机制,AI 没有任何判据。(本条原文为「读 OWNER → 人工删锁 → 自己 --claim-exec」,已作废。)
    • 它同样覆盖服务器操作:任何要重启 / drain / 改 env·quota / 铺插件 / 改 nginx·nft 的动作,都先持这把锁(与 §六 的服务器侧锁是同一件事的两种落地,先做哪个都行,别两套并存)。

四、规划会话的边界(本目录的作者)

  • 只读本地文档与本地只读命令;不 ssh、不改码、不重启服务、不 scp。
  • 产出后必须自检:python3 scripts/docs-audit.py 退出码 0(交接单自身也是被扫描的 md)。
  • 事实一律标注单一来源(档案号 / 文件:行),不写"我记得"。

五、为什么这样分(2026-09-11 实证)

原因 证据
上下文挤 一次改造的规划要读 5–10 万 tokens,执行要读源码 + 日志 + 复跑;同一会话混做,两头都慢
并行踩坑 同一天两次「两通道并行改同一批文件」造成损失:03-路线图 被旧快照覆盖跳号;两个编号各被两份档案占用(37/38,→ T02)
交付面单一 单子成为唯一传递面,两边都不需要对方的历史;也让"做没做"可被第三方核对

与既有机制的关系:skills/dsh-change-workflow 的六阶段中,阶段 0–2(需求/调研/规划)留在规划会话,阶段 3–5(开发/验证/归档)交执行会话;冲突域与并行度规则仍按该 skill 的「多任务并行调度协议」执行。

六、服务器侧也要锁(2026-09-12 新增;比文档冲突严重,待落地)

前面 §一–§三 治的是文档冲突(丢的是文字,可重写)。但所有会话共用一台服务器,且下面这些操作跨会话没有任何互斥:

高危操作 影响 现状
systemctl restart dshs / drain / 停 dsh-*.scope 在线用户当场掉线(档案 58/59 已两次引发报障) ✅ 已加锁(须先占位)
改实例 env / MemoryMax / bwrap 参数 全部实例行为变化,用户无感知到异常 ✅ 已加锁(须先占位)
批量铺插件 / 改 profile patch / /opt/dsh/docs 之外的生产文件 可能触发崩溃循环(档案 25 前例) ✅ 已加锁(须先占位)
改 nginx vhost / 证书 / nft 全站可达性 ✅ 已加锁(须先占位)

✅ 已实施(2026-09-12,见 交接单/T04-*.md 与 scripts/op-lock.sh):加第二把锁,粒度到"平台操作"而不是"文件":

  • 约定文件 <repo>/.doing-platform(或服务器侧 /opt/dsh/state/.op-lock,取"跨机可见"之利);
  • 内容 = 占用者 + 操作摘要 + 影响面(谁会被断、断多久)+ 预计时长;
  • 凡 §六 表里任一类操作,开工前必须先占位;占位失败 = 有别的会话正在动线上,停手;
  • 与 §三 第 0 条的差别:文档冲突靠 git status/mtime 能看出来,服务器态变更看不出来(systemctl 不会告诉你 10 分钟前谁重启过)→ 只能靠显式锁。

✅ 落地记录(2026-09-12 15:07,T04):锁根 /opt/dsh/state/.op-lock/(root 700,内含使用约定 README)已建立;工具 bash scripts/op-lock.sh {claim|release|status} 已就位并实测往返通过(占位 → status 显示 🔴+OWNER → 释放 → 无人占用 ✓)。 开工前必做:bash scripts/op-lock.sh status 无人占用才继续;占位失败 = 有会话在动线上 → 停手。 顺序仍为:先抢文档库全局锁 --claim-exec → 再占服务器侧锁 op-lock.sh claim;完工反序释放。