Files
admin c1b5e4d966 chore(工作区): 全量入库 + 补齐 .gitignore(以工作区为准)
- 变更规模:新增 514 / 修改 62 / 重命名 155 / 删除 4(归档重组与文档轮次)
- .gitignore 修:`归档/**/db-cwd归一-备份-*/` —— 原规则写绝对层级(归档/db-cwd归一-…),
  目录搬进 归档/配置与备份/ 后**静默失效**,43 MB 的 DB 备份又变成未跟踪
- .gitignore 补:嵌套 git 内部数据(归档/内嵌git-20261008/、归档/skills-git-旧线-20261007/dotgit-原样移出/)
- .gitignore 补:运行态与部署副本(.workbuddy/collab/、.workbuddy/tools/、.workbuddy/.load-pending、.workbuddy/tmp-*)
- .gitignore 补:备份件(*.bak-*)
- 未跟踪文件从 2190 降到 890(其余为 归档/ 归档件与 .workbuddy/memory/ 知识文件,按口径入库)
2026-10-10 23:13:22 +08:00

45 KiB
Raw Permalink Blame History

交接单 · 在册收尾(Q5 + mksess 文档口径 + 技能三处同步 + 幕 4-A 临界项)(2026-09-17)

本单来源:序 ⑯ 规划棒(automation 91c53ef8-c3f0-4bb3-9f0a-943790178176,2026-09-17 16:36 起)。 本单定位:执行单(8 段模板,可直接开工)。把「会合 / 中继拆分复核结论」+「剩余在册项定序」合并为一个执行棒 = 序 ⑰。 本棒只出规划:⛔ 未改任何代码、⛔ 未动 47 / 106、⛔ 未 commit / push;全部取证 = 只读命令(详见 §0.2)。


§0 结论先行

0.1 复核结论(二选一 ⇒ 判「不做」)

「会合 / 中继从 Manager 拆分」—— 判「不做」。原方案 会合中继拆分_取证与改造方案_20260916.md S0–S4 的四个耦合点(C1–C4)与两个改造步骤(S3 / S4)已逐条被后续序次覆盖,未覆盖部分 = 无。

靶子 原方案描述 现状证据(只读取证) 判定
C1 会合地址硬编码在 Worker 的 env(DSHS_TUNNEL_TARGET 写死在 switch-C-worker.sh + /etc/dshs-worker.env) src/config.ts:485-490:DSHS_RENDEZVOUS_URL 优先、DSHS_TUNNEL_TARGET 降为兜底(注释原文:「覆盖网络 S1:会合地址出 env」);src/worker/agent.ts:158、src/worker/tunnel.ts:16 同口径 ✅ 已被 序② P0-2(引导三级链) 覆盖
C2 中继落点 = Manager 的 loopback + 两端同号 ⇒ 第三台机器无法直达、中继不可多实例 src/config.ts:498-500:DSHS_RELAY_DIAL_PORT_BASE=25000 / SPAN=1000 / POOL=64 ⇒ 落点在 Manager 自己本机的回环池;src/net/relay/dialer.ts:11 注释「Manager 也像 worker 一样只拨出一条 wss(RelayClient 的 dialer 模式)」 ✅ 已被 R5(会合可换机) 覆盖 —— 这就是题面给的已知事实
C3 可达性登记把「经谁中转」磨掉了(dsh_hosts.endpoint 语义 ≠ worker 地址) src/net/rendezvous.ts:103-106「按 via 选实现的注册表」+ Reachability.via(:27 / :65 / :98);src/supervisor/remote-spawner.ts:21-48 取址一律走 agentBaseUrlOf() ✅ 已被 S2 / P2(dsh_hosts.via 列) 覆盖
C4 控制面 PG 也走同一条隧道 ⇒ 回滚面含 DB 方案 §8.1 实测:106 与 47 的 worker env 都没有 DSHS_TUNNEL_STATIC_PORTS ⇒ C4 前提不成立 ✅ 前提不成立,无需处理
S0 抽 Reachability / Rendezvous 接口 src/net/reachability.ts(agentBaseUrlOf() = 全仓唯一取址入口,:99)+ src/net/rendezvous.ts 均在册 ✅ 已落地
S1 会合地址出 env 同 C1 行 ✅ 已落地
S2 dsh_hosts 增 via 列 同 C3 行 ✅ 已落地
S3 中继落点命名空间可配(回环别名 127.0.0.2…) 方案 §9.1 实测 gatewayports no ⇒ 别名方案证伪;已改「实例端口区间隔离」(w-47 20000+ / w-106 21000+)⇒ 连「两端同号」这个前提都没了 ✅ 原设计已作废且被更强做法替代
S4 中继独立成单元 + 会合可换机 + 多实例 dshs-relay 独立 systemd 单元已常驻两台(47 / 106,只绑回环 20080);序⑥ S8 把 106 升格为第二中继;序⑦ 切流演练「杀 47 ⇒ 切到 106」实测通过;sshd 反向隧道已下线且不可能重建 ✅ 已被 R2 / 序⑥ S8 / 序⑦ / 序④ 覆盖

⇒ 处置:在 会合中继拆分_取证与改造方案_20260916.md 头部加一行状态标注(已由 R5 + 序②/②P3/④/⑥S8/⑦ 覆盖 ⇒ 仅存档,⛔ 勿再按 S0–S4 开工),正文⛔ 不改(历史档案属性)。 ⚠️ 顺带登记一条观察项(⛔ 本单不处置):SSH 隧道代码路径 src/worker/tunnel.ts 现已是生产死路径(47 同机不建隧道、106 走 wss:// relay),是否删除 = 独立决策(可能保留作 ssh 兜底变体)⇒ 只登记,不定序。

0.2 本棒取证(只读,共 3 条命令族;⛔ 未连任何池口、未动 47/106 配置)

# 命令(cwd = 代码仓 D:/github/dsh_shenxian) 关键输出
1 grep -rn "DSHS_TUNNEL_TARGET|32022" --include=*.ts src + grep -rn "DSHS_RENDEZVOUS_URL" --include=*.ts src C1 现状(config.ts:485-490 新变量优先 / 旧变量兜底)
2 grep -rn "via" src/net/rendezvous.ts + grep -rn "25000|dialer" src/net/relay/dialer.ts + grep -rn "DSHS_RELAY_DIAL" src/config.ts C2 / C3 现状(拨号池 25000..26000、Manager 只拨出)
3 find src test scripts -name "*.bak-*" + git ls-files src/net/relay | wc -l + git ls-files --error-unmatch <bak> Q5 真实范围 5 个(非 3 个);src/net/relay tracked = 0(Q4 自证)

0.3 剩余在册项定序(→ 本单 §5 的 S1–S4)

序 项 类型 为什么排在这个位置
S1 mksess 文档口径(「DB 直插」→「PG 直插」) 文档(操作性载体) 必须最先:它改 skills/** 正文,而 S2 的镜像同步要把 S1 的产物一起带上 ⇒ 二者共用一次 scp(硬顺序)
S2 技能 dsh-auto-handoff-chain 三处同步 文档 + 镜像 紧随 S1(同属 skills/** 面、共用一次 scp);且它是自动接续链路的载体 ⇒ 直接影响本线后续每一棒的可复现性
S3 Q5:.bak-seq7-* 残留清理(范围修正 = 5 个) 清理(零服务副作用) 与 S1/S2 无依赖,但同属「零服务副作用批」⇒ 合在文档批一起做,省一次抢锁
S4 §8.8-2 临界项:幕 4-A 耗时贴近 deadline 演练采样(唯一有副作用项) 放最后:它会把 Manager 通道挪来挪去(幕 4)⇒ 前面三条全部完成后再动,收尾 restart dshs 归零不影响已完成工作

排序一句话:S1 → S2(硬依赖,共用一次镜像同步)→ S3(零风险清理,同批)→ S4(唯一动服务的一项,置末)。

0.4 ⛔ 本单不写进执行范围的项(只登记)

项 登记内容
Q4 代码仓 src/net/relay/** untracked(实测 git ls-files src/net/relay | wc -l = 0)⇒ 序⑭/⑮ 的修复与 test/relay.test.mjs 只存在于工作区、不在版本库。卡在「commit / push 授权」,属待用户拍板 ⇒ ⛔ 本单不执行、⛔ 执行棒也不得动,只报告。
presence / 房间层 / 内容分发定序 属「业务优先级」(§1 边界外 ①)⇒ ⛔ 本单不定序;候选与优缺点登记见 §3.3。
骨干节点服务范围 入口 §4 既有待拍板项(A 只服务自己名下设备 / B 服务全网)⇒ 原样保留,本单不重复上抛。

§1 目标

一次执行棒把四条在册项收干,全部满足「零生产值改动 + 可秒级回滚」:

  1. mksess 口径对齐实现 —— 文档库 / 技能 / 镜像里对 /opt/dshs/mksess{,−guest}.cjs 的「DB 直插(SQLite 旧库)」描述已过期(序⑬ Q1 实测已改 PG)⇒ 改成与实现一致的描述,避免 R4 验收手段被误述。
  2. 技能 dsh-auto-handoff-chain 的「三处同步」从「从未建立」变为「已建立」 —— 现在文档库无副本(实测 ❌)。
  3. 清掉代码仓 .bak-seq7-* 残留 —— 立起「.bak 只在执行期存在」这条规矩(序⑫ 已以身作则、仓内 .bak = 0,但代码仓仍有 5 个历史快照)。
  4. 给「幕 4-A 耗时贴近 deadline」这条临界项落一个判据(三档递进),并采 5 个样本自证是否仍临界。

非目标:⛔ 不 commit / 不 push(Q4 未授权);⛔ 不改任何生产值(RELAY_FAILOVER_* / HB_SEC / burst);⛔ 不做打洞、不改 worker 拨出方向、不重做任何已收官序。


§2 只读前置(S0 必须先核实;任一条不符 ⇒ 停下报告,⛔ 不硬闯)

# 核实项 命令(cwd 见括注) 期望(本单规划时的实测值)
P1 锁空闲 bash dsh-server-docs/scripts/handoff-guard.sh 报「空闲」;抢锁后再开工(抢不到 = 有会话在跑 ⇒ 停手报告)
P2 代码仓基线未漂移 cd D:/github/dsh_shenxian && git rev-parse --short HEAD && git status --porcelain | wc -l HEAD = 640813e;总数 = 43(17 M + 3 ?? + 余)
P3 .bak 真实范围 cd D:/github/dsh_shenxian && find src test scripts -name "*.bak-*" 5 个:src/net/relay/{client,directory,main}.ts.bak-seq7-20260917-112114 + src/web/server.ts.bak-seq7-20260917-112114 + src/worker/tunnel.ts.bak-seq7-20260917-112114(⚠️ 均 untracked,实测 git ls-files --error-unmatch 报 pathspec 不匹配)
P4 Q4 自证(⛔ 只记录) cd D:/github/dsh_shenxian && git ls-files src/net/relay | wc -l 0(untracked 缺口仍在 ⇒ 本棒 ⛔ 不得 commit)
P5 mksess 命中面 cd D:/github/dsh_shenxian && grep -rn "mksess" dsh-server-docs/ | grep -iE "sqlite|直插|dshs\.db|旧库" 命中 4 行:04-调整方案/77-…md:97(档案,⛔ 不改)、skills/dsh-change-workflow/SKILL.md:146/395/495、skills/dsh-env-bootstrap/references/常驻规则-快照.md:55
P6 技能三处现状 ls -d "E:/ProgramData/.workbuddy/skills/dsh-auto-handoff-chain" + ls -d D:/github/dsh_shenxian/dsh-server-docs/skills/dsh-auto-handoff-chain ① 本机 ✅ 存在;② 文档库 ❌ 不存在(与在册项一致);③ 镜像(47 /opt/dsh/docs/skills/)待现取
P7 基线回归值 见 §6-E6 npm test = 162 / 161 pass / 0 fail / 1 skip;--scene all = 12 PASS / 0 SKIP / 0 FAIL;overlay-probe --table "…/参数表_覆盖网络_20260917.md" = 12/12 · rc=0

⚠️ ssh 一律显式 -p 22(别名 bt-server 的 32022 是失效残留口);取证落盘一律 2>/dev/null(ssh 的 PQ 告警会污染行数判据);106 的 ssh 偶发 rc=255(MaxStartups 限流)⇒ 容许单次重试,⛔ 不放宽限流(命中 R5)。


§3 范围

3.1 改哪些(三处文档面 + 一处代码仓清理)

面 具体对象 动作
文档库(代码仓内) dsh-server-docs/skills/dsh-change-workflow/SKILL.md(3 行)、dsh-server-docs/skills/dsh-env-bootstrap/references/常驻规则-快照.md(1 行)、dsh-server-docs/02-运维手册.md(命中处) 口径校正
文档库(新增) dsh-server-docs/skills/dsh-auto-handoff-chain/(新建目录)+ skills/README.md / skills/INDEX.md 登记 新建 + 登记
本机技能 E:\ProgramData\.workbuddy\skills\**(命中 10 行) 口径校正(与文档库同内容)
镜像 47 /opt/dsh/docs/skills/** scp 同步(S1 + S2 产物 一次上)
代码仓 src/{net/relay/web/worker}/*.bak-seq7-20260917-112114(5 个) 删除
观测口径 参数表_覆盖网络_20260917.md §6(仅在 S4 判据落地时) 新增余量判据(⚠️ 会改参数表指纹 ⇒ 必须在 §8.9 记录变更前后值)

3.2 ⛔ 明确不做

  • ⛔ 不 commit / 不 push(Q4 未授权 ⇒ 本棒零提交动作,含"顺手提交 .bak 删除"也不行);
  • ⛔ 不改任何生产值:RELAY_FAILOVER_* / HB_SEC / burst / deadline;
  • 🔴 ⛔ 不许把 RELAY_FAILOVER_COOLDOWN_MS=0 写进任何回滚 / 演练 / 夹具路径(看似合法、实际自锁);
  • ⛔ 不改 04-调整方案/** 历史档案正文(D1 已定:只在操作性载体里写"档案口径已过期"的指针);
  • ⛔ 不动 47 / 106 的 nginx / nft / systemd 单元 / env(唯一例外 = §5 S4 的演练与收尾 restart dshs 归零,与序⑩–⑮ 同口径);
  • ⛔ 不重做任何已收官序(①–⑮);⛔ 不做 presence / 房间层 / 内容分发;⛔ 不做打洞实现;⛔ 不改 worker 拨出方向。

3.3 范围外登记(⛔ 不定序、不决策 —— 属「业务优先级」)

候选 优点 缺点
presence 清单 §五 第 7 步;千台推演里第一瓶颈,做完才能谈"谁在线"类功能 仓库里目前零应用层代码(全仓唯一含 "presence" 字样的是 src/net/relay/placement.ts)⇒ 从零起步、工作量最大
房间层 是 presence 的下游、MMORPG 多人的前置 ⛔ 无 presence 则无输入;依赖链在前
内容分发(块级内容寻址) 与 presence 无依赖、可独立做;直接吃"跨云 ~22 KB/s"这条实测短板 与游戏主线收益关系较远;块级寻址会引入新的存储/校验面

§4 决策点

待拍板项 = 空(本单四条全部落在 §1「边界内自决清单」:实现路径 / 排查方法 / 文档技术内容 / 清理类)。以下为已定项(可推翻):

# 已定项 理由
D1 mksess 口径只改操作性载体(02-运维手册.md + skills/** + 本机技能),⛔ 不改 04-调整方案/*.md 档案正文;在 02-运维手册.md 的 R4 段写一行「档案 77 里的『DB 直插』为当时形态,现实现 = PG 直插」作勘误指针 档案的属性是当时事实,改写 = 销毁溯源;且档案命中面 7 个文件(R7 批量面)。B 方案(只改载体)明显更优 ⇒ 自决
D2 Q5 范围扩到 5 个(含原单未记的 src/web/server.ts.bak-seq7-* 与 src/worker/tunnel.ts.bak-seq7-*) 同类、同批、同为 untracked 过期快照(seq7 11:21 的快照,已被序⑧/⑨/⑭/⑮ 改写作废 ⇒ 无回滚价值);只删 3 个 = 规矩只立一半,下次还要再开一单。R7 透明:本行即"先报告"
D3 幕 4-A 判据取三档递进而非单一阈值:p95 ≤ 24 s(deadline×0.8)= 健康|24–27 s = 临界(记入在册、⛔ 不判 FAIL)|> 27 s = 回头条件触发(停下报告) 观测样本 19.5 / 20.8 / 22.2 s,单阈值 24 s 有假红风险、27 s 又预警太晚 ⇒ 三档把"假红 vs 预警提前量"这个取舍消解掉了(既不失预警、也不误判)
D4 ⛔ 本单不处理 src/worker/tunnel.ts 这条生产死路径(是否删 = 独立决策) 删代码有风险、且它可能作为 ssh 兜底变体保留 ⇒ 只登记(§0.1 末)
D5 S4 若触发回头条件(p95 > 27 s),⛔ 不许自行调 RELAY_FAILOVER_DEADLINE_MS / HB_SEC / burst ⇒ 停下报告,重做四段分解(检测 / 首试 / 白等 / 建连)后定位 沿用序⑨ 已立的三条硬门(D1 / 生产值不可调 / 分解优先)

§5 步骤 S0–S5

S0 · 只读前置 + 抢锁

  • 跑 §2 的 P1–P7 全部核实;任一条不符 ⇒ 停下报告。
  • 抢锁:bash "D:/github/dsh_shenxian/dsh-server-docs/scripts/handoff-guard.sh" --claim-exec "覆盖网络线-序17执行棒"。
  • 抢到后再跑一次信息模式,记下占用与越界改动。

S1 · mksess 文档口径校正(「DB 直插」→「PG 直插」)

  • 先取准实现事实(只读,1 条命令):ssh -p 22 bt-server 'head -40 /opt/dshs/mksess.cjs' ⇒ 确认落点是 PG、连接串来源 = env / dshs.env / dshs.service.d、⛔ 不固化凭据(序⑬ §9.2 已改)。
  • 改哪些行:按 §2-P5 的 grep 结果逐行改(只改断言"存储机制"的行;仅提及文件名、不涉机制的行保持原样)。
    • 统一措辞(示例,⛔ 不写死凭据):node /opt/dshs/mksess.cjs(PG 直插,连接串取自 env / dshs.env / dshs.service.d;10 分钟;user_agent=poc-curl2)
  • 本机 + 文档库两副本同改(内容逐字节一致)。
  • 判据:
    • grep -rn "mksess" dsh-server-docs/ \| grep -iE "sqlite\|旧库" = 0(⚠️ 原本 0 命中的"旧库"也一并核)
    • grep -rniE "sqlite|旧库" <文档库 skills 与 02-运维手册> \| grep -c mksess = 0
    • 两副本 md5sum 逐文件一致
  • 回滚:git checkout -- <改动文件>(文档库)+ 本机技能按 §7 备份还原。

S2 · 技能 dsh-auto-handoff-chain 三处同步建立

  • ① 核本机副本清单:ls -R "E:/ProgramData/.workbuddy/skills/dsh-auto-handoff-chain" ⇒ 记下全部文件(SKILL.md + 可能的 references/、scripts/)。
  • ② 建文档库副本:逐文件复制到 D:/github/dsh_shenxian/dsh-server-docs/skills/dsh-auto-handoff-chain/(逐文件 copy,⛔ 不用 cp -r 整目录覆盖;⚠️ 文档库 .gitattributes = * -text ⇒ 保持纯 LF)。
  • ③ 登记:改 dsh-server-docs/skills/README.md 与 dsh-server-docs/skills/INDEX.md,加上该技能行。 ⚠️ INDEX.md 是混合换行 ⇒ 字节级单行插入,⛔ 不跑 git checkout --、⛔ 不做批量换行符转换。
  • ④ 镜像同步:scp 到 47 /opt/dsh/docs/skills/(连同 S1 的改动物一次上);同步前先抢锁(本棒已持锁)。
  • 判据:
    • diff -r 两副本 = 0 差异;逐文件 md5sum 一致(⚠️ 本机 md5sum 出 hash *path、远端出 hash path ⇒ 先 cut -d' ' -f1 再比)
    • 镜像 /opt/dsh/docs/skills/dsh-auto-handoff-chain/SKILL.md md5 == 文档库 md5
    • grep -c "dsh-auto-handoff-chain" dsh-server-docs/skills/README.md ≥ 1(INDEX.md 同)
  • 回滚:删文档库新增目录 + 镜像改名还原备份(README.md / INDEX.md 用 git checkout --)。
  • ⚠️ 本步自证价值:这一条正是「长期在册」项 —— 此前该技能的"三处同步"从未建立,本步是第一次把它建起来;完成后在 §8.8 明确写"已建立",并在 .workbuddy/memory/MEMORY.md 的对应处("该技能三处同步从未建立(在册未办)")改为已办。

S3 · Q5 清理 .bak-seq7-*(5 个)

  • 前置(缺一不可):① find src test scripts -name "*.bak-*" 逐个确认属 seq7-20260917-112114 批次;② 确认对应源文件存在(client.ts / directory.ts / main.ts / web/server.ts / worker/tunnel.ts);③ 确认 lib/ 内有等价产物;④ ⚠️ 记录一条事实:这些是 11:21 的快照,已被序⑧/⑨/⑭/⑮ 改写作废 ⇒ 他们不是有效回滚点(删除风险 = 零)。
  • 怎么做:逐个 rm(5 个,逐个点名,⛔ 不用通配符 rm src/net/relay/*.bak-*)。
  • 判据:
    • find src test scripts -name "*.bak-*" \| wc -l = 0
    • npm run build RC=0(⛔ 未改任何源文件 ⇒ 产物指纹应与 S0 一致,可对账 lib/net/relay/*.js md5 不变)
    • npm test = 162 / 161 / 0 / 1(不退化)
    • git status --porcelain \| wc -l 只减不增(Δ ≤ 0;⚠️ src/net/relay/ 整体是 ?? 一个条目 ⇒ 不能期望 −5,判据落到 find 结果与 md5 上)
  • 回滚:.bak 不可再生 ⇒ 回滚动作 = 从当前源文件重新 cp 一份快照(⚠️ 语义不等价,仅作备案)。⇒ 故删除前必须完成前置 ④ 的书面记录。

S4 · §8.8-2 临界项 —— 幕 4-A 余量判据化 + 稳定性采样

  • 不改任何生产值;只跑演练 + 落判据。
  • ① 采样:node scripts/overlay-failover-drill.cjs --scene 4 --table "<工作区根>/参数表_覆盖网络_20260917.md"(DRILL_SAMPLE_N = 5)。 ⛔ 只跑 --scene 4(构 A);⛔ 不跑 4b / 4c / ctrl(4c / ctrl 已被序⑩ 整体移除并显式拒绝 —— 那是 COOLDOWN_MS=0 的诱发面)。
  • ② 算判据:对 5 个样本取 p95,按 §4-D3 三档判定:
    • p95 ≤ 24000 ms ⇒ 健康 ⇒ 把判据写进参数表 §6(配套说明:分母 = RELAY_FAILOVER_DEADLINE_MS = 30000 ms);
    • 24000 < p95 ≤ 27000 ⇒ 临界(记录,⛔ 不判 FAIL) ⇒ 写进 §8.8 在册;
    • p95 > 27000 ⇒ 🔴 停下报告(⛔ 不许自行调任何生产值)⇒ 按 §4-D5 重做四段分解。
  • ③ 零回归:--scene all = 12 PASS / 0 SKIP / 0 FAIL(幕 4-A / 4-C 全部 ≤ deadline);npm test 不退化。
  • ④ 收口归零(本步的"回滚"):演练会把 Manager 通道挪到 106 ⇒ 必须 systemctl restart dshs 归零回 47,再跑 overlay-probe 确认 12/12、ss -lntH 'sport >= :25000 and sport <= :25063' | wc -l = 64。 ⚠️ 判"服务是否正常"要 systemctl is-active dshs dshs-relay dshs-pg —— 演练进行中某台 relay 是 inactive,那是幕的正常态。
  • 回滚:本步不改服务配置 ⇒ 回滚 = ① 参数表备份还原(指纹回到现值 8f08e74b026e6e5b5e1b3db813f031ae)② 演练坐标/env 残留清 0(grep -r 'DRILL_' /etc/systemd/system/dshs.service.d/ = 0)。

S5 · 收口(6 件,缺一即算未完成)

① 释放锁 --release-exec;② 陈述句告知用户 + 登记下一棒一次性 automation(scheduledAt = 收口时刻 +2~5 分钟;⚠️ 下一棒 id 只能来自工具返回值:先 create → 取 id → 再落盘);③ 把 接续入口_覆盖网络线_20260916.md §0 + §2 推进到再下一棒;④ 写工作区日志 .workbuddy/memory/2026-09-17.md(append-only);⑤ 在本单追加回报(§8 八小节);⑥ 输出指纹(§8.9)。


§6 验收(逐条命令 + 期望 + 退出码;可被第三方复现)

# 项 命令(cwd 见括注) 期望
E1 S1 口径已对齐 cd D:/github/dsh_shenxian && grep -rn "mksess" dsh-server-docs/ | grep -iE "sqlite|旧库" | grep -v "04-调整方案" 0 行(⛔ 档案除外)
E2 S1 双副本一致 逐文件 md5sum(本机技能 vs 文档库技能,cut -d' ' -f1 后比) 全同
E3 S2 三处同步 diff -r "E:/ProgramData/.workbuddy/skills/dsh-auto-handoff-chain" "D:/github/dsh_shenxian/dsh-server-docs/skills/dsh-auto-handoff-chain" + 镜像 md5sum diff 0 行;镜像 md5 == 文档库 md5
E4 S2 登记 cd D:/github/dsh_shenxian && grep -c "dsh-auto-handoff-chain" dsh-server-docs/skills/README.md(INDEX.md 同) ≥ 1
E5 S3 清理干净 cd D:/github/dsh_shenxian && find src test scripts -name "*.bak-*" | wc -l 0
E6 零回归(三件套) ① cd D:/github/dsh_shenxian && npm.cmd test(必须 Node 22)② node scripts/overlay-failover-drill.cjs --scene all --table "<工作区根>/参数表_覆盖网络_20260917.md" ③ node scripts/overlay-probe.cjs --table "<工作区根>/参数表_覆盖网络_20260917.md" ① 162 / 161 / 0 / 1 ② 12 PASS / 0 SKIP / 0 FAIL ③ 12/12 · rc=0
E7 S4 余量判据 --scene 4 × DRILL_SAMPLE_N=5 ⇒ p95 落 §4-D3 三档之一;> 27000 ms ⇒ 停下报告
E8 越界自证 cd D:/github/dsh_shenxian && grep -c 'COOLDOWN_MS=0' scripts/ + git rev-parse --short HEAD + git status --porcelain | wc -l 0;HEAD 仍 640813e(⛔ 无 commit);总行数 ≤ 43
E9 收口归零 ssh -p 22 bt-server 'systemctl is-active dshs dshs-relay dshs-pg' + ssh -p 22 bt-server "ss -lntH 'sport >= :25000 and sport <= :25063' | wc -l" 三个 active;池口 64

§7 回滚

对象 回滚动作 耗时
S1 文档(文档库) git checkout -- dsh-server-docs/skills/dsh-change-workflow/SKILL.md dsh-server-docs/skills/dsh-env-bootstrap/references/常驻规则-快照.md dsh-server-docs/02-运维手册.md 秒级
S1 文档(本机技能) 执行前逐文件备份到 _中间产物_待清理/seq17/skills-bak/ ⇒ cp 还原 秒级
S2 文档库新增目录 rm -rf dsh-server-docs/skills/dsh-auto-handoff-chain(⚠️ 纯新增 ⇒ 无溯源损失)+ git checkout -- README.md INDEX.md 秒级
S2 镜像 ssh -p 22 bt-server 把 /opt/dsh/docs/skills/ 备份目录改名还原 秒级
S3 .bak 删除 ⚠️ 不可逆(原文件是过期快照、无回滚价值)⇒ 回滚 = 从当前源文件重建快照(仅备案)。故前置 ④ 必须先写 秒级
S4 参数表判据 参数表备份还原 ⇒ 指纹回 8f08e74b026e6e5b5e1b3db813f031ae 秒级
S4 服务态 systemctl restart dshs 归零回 47(⛔ 不删 drop-in、⛔ 不改 cluster 配置) 秒级

§8 回报格式(执行会话按此回填;⛔ 缺一节即算未完成)

8.1 结论(1 行) :四条在册项逐条 ✅ / ❌(S1 / S2 / S3 / S4),+ 是否触发 S4 回头条件

8.2 只读前置 P1–P7 :逐条贴命令与输出(P3 的 5 个 .bak 逐个点名 + git ls-files 的 untracked 自证)

8.3 S1 口径校正 :命中行清单(文件:行 → 改前 / 改后)、0 命中的判据命令原文、⛔ 未动档案的自证

8.4 S2 三处同步 :本机副本文件清单(逐个 md5)+ 文档库 md5 + 镜像 md5(三处对照表)+ README/INDEX 登记原文

8.5 S3 清理 :find 前 / 后计数 + 5 个文件逐个名 + npm run build RC + npm test 计数 + "非有效回滚点"的书面记录

8.6 S4 临界项 :--scene 4 5 个样本原文 + p95 = ? ms ⇒ 落哪一档 + 判据是否落表(落表则给参数表指纹 变更前/后)

8.7 零回归 / 越界自证 :E6 三件套原文(含 --scene all 的幕 4-A / 4-C 两个毫秒值)+ E8(COOLDOWN_MS=0 计数、HEAD、git status 计数)

8.8 未过项 / 在册未办 :逐条写「现象 / 已做到哪一步 / 回头条件」;Q4 原样转下一棒(⛔ 只报告);§0.4 的三项登记原样保留

8.9 指纹(可复现核对口径)

  • 本单前缀:cd "E:/ProgramData/AI技能/aliyun-dsh-server" && sed '/^## §8 回报格式/,$d' 交接单_在册收尾_20260917.md | md5sum
  • 本单全文:md5sum 交接单_在册收尾_20260917.md
  • 参数表(D1 自证):sed '/^## §10 指纹/,$d' 参数表_覆盖网络_20260917.md | md5sum(⚠️ 截断口径,⛔ 不是全文件 md5;现值 8f08e74b026e6e5b5e1b3db813f031ae)
  • 关键产物:src/net/relay/{client,directory,main}.ts + src/web/server.ts + src/worker/tunnel.ts 的 md5(清理前后应不变 ⇒ 自证未改源文件)

§9 执行回报(序 ⑰ 执行棒 · 2026-09-17 16:44–17:3x)

口径 = 按 §8 的九个小节逐条回填;本 §9 位于 §8 之后,不进 §8 前缀指纹。

9.1 结论(对应 §8.1)

四条在册项逐条:S1 ✅ | S2 ✅ | S3 ✅ | S4 ⚠️ 落「临界档」(记录在册,⛔ 不判 FAIL)。 S4 回头条件是否触发:未触发(p95 = 24477 ms < 27000 ms)⇒ ⛔ 未调任何生产值。 范围遵守:⛔ 未改任何生产值;⛔ 未改 04-调整方案/** 档案正文;⛔ 未重做已收官序 ①–⑮;⛔ 未做 presence / 房间层 / 内容分发;⛔ 未超 §3 范围。 追加授权:用户本轮明确「执行完毕后 同步到仓库」⇒ Q4(提交/推送授权)已解除并办结,见 §9.10。

9.2 只读前置 P1–P7(对应 §8.2)

# 核实项 实测 判定
P1 锁空闲 报「空闲」;本棒 --claim-exec "覆盖网络线-序17执行棒" 抢到 ✅
P2 基线未漂移 HEAD = 640813e;git status --porcelain | wc -l = 43 ✅
P3 .bak 真实范围 5 个(逐个点名见 §9.5) ✅ 与单一致
P4 Q4 自证 git ls-files src/net/relay | wc -l = 0 ✅(本轮已解除 → 见 §9.10)
P5 mksess 命中面 grep -rn "mksess" dsh-server-docs/ 筛 sqlite|直插|dshs.db|旧库 = 5 行 ⇒ 落点 = 档案 77(⛔ 不改)+ skills/dsh-change-workflow/SKILL.md:146/395/495 + skills/dsh-env-bootstrap/references/常驻规则-快照.md:55 ✅
P6 技能三处现状 ① 本机 ✅ 存在(SKILL.md + scripts/chain_report.py);② 文档库 ❌ 不存在;③ 镜像 ❌ 不存在(8 个技能、无此项) ✅ 与在册项一致
P7 基线回归值 见 §9.7 ✅

mksess 实现事实(只读,1 条 ssh;-p 22 显式):/opt/dshs/mksess.cjs(74 行)第 2 行即「临时会话直插(PG 版)」;第 4–6 行写明「原版直插 /var/lib/dshs/dshs.db(SQLite)… 集群化后权威库 = 47 的 PG13(DSHS_DB_URL),SQLite 只剩回滚用途」;第 9–10 行「连接串从环境读(DSHS_DB_URL env → /etc/dshs.env → dshs.service.d/*.conf),⛔ 不把凭据固化进本文件」;第 17 行 require('/opt/dshs/node_modules/pg');TTL_MS = 600 * 1000。 ⇒ 文档口径必须改成「PG 直插」,与实现一致。

9.3 S1 口径校正(对应 §8.3)

命中行清单(文件 : 行 → 改前 → 改后) —— 文档库与本机技能同内容逐字节一致:

面 文件:行 改前 改后
文档库 + 本机 skills/dsh-change-workflow/SKILL.md:146 … mksess.cjs\ 直插临时 session,或…` … mksess.cjs\(PG 直插)建临时 session,或…`
文档库 + 本机 skills/dsh-change-workflow/SKILL.md:395 改用 \mksess.cjs` 直插临时 session 或…` 改用 \mksess.cjs` PG 直插临时 session 或…`
文档库 + 本机 skills/dsh-change-workflow/SKILL.md:495 (DB 直插,10 分钟,user_agent=poc-curl2) (**PG 直插**,连接串取自 env / \dshs.env` / `dshs.service.d`;10 分钟;`user_agent=poc-curl2`)`
文档库 + 本机 skills/dsh-env-bootstrap/references/常驻规则-快照.md:55 (\mksess.cjs` 直插)` (\mksess.cjs` PG 直插)`
仅文档库 02-运维手册.md:211–214 # 测试 session 生成(门户 API 直调,10 分钟) 注释行补「PG 直插,连接串取自 env / dshs.env / dshs.service.d;10 分钟;user_agent=poc-curl2」+ D1 勘误指针两行(说明档案 77 与更早文档的描述属当时形态、写 /var/lib/dshs/dshs.db,集群化后权威库 = 47 的 PG13、那份文件仅回滚用)

判据原文:

  • E1 cd D:/github/dsh_shenxian && grep -rn "mksess" dsh-server-docs/ | grep -iE "sqlite|旧库" | grep -v "04-调整方案" | wc -l = 0 ✅(⛔ 档案除外)
  • E1b grep -rniE "sqlite|旧库" dsh-server-docs/skills/ dsh-server-docs/02-运维手册.md | grep -c "mksess" = 0 ✅
  • E2 两副本逐文件 md5:dsh-change-workflow/SKILL.md = 338bf9534e5243f495e7d66f914371bf(本机 = 文档库);dsh-env-bootstrap/references/常驻规则-快照.md = e1a460b53cc4b62466107f8555946496(本机 = 文档库) → 全同 ✅
  • 行尾:5 个文件 CR 计数 全 0(纯 LF)✅

⛔ 未动档案自证:04-调整方案/77-回到页面自检与就地恢复-恢复过程可见化.md:97 原文未改(该行本就不含 sqlite/旧库,属 E1 的排除项)。

⚠️ 一处判据偏差(已按实质落点执行):§3.1 / §5-S2 写的登记文件路径为 dsh-server-docs/skills/README.md 与 INDEX.md,实测 skills/ 下无这两个文件 —— 真实登记文件在文档库根 dsh-server-docs/README.md 与 dsh-server-docs/INDEX.md(内容形态与描述一致:技能表 + 「什么时候查什么」表 + 技能清单表)⇒ 按实质落点执行,判据 E4 落在根文件上。

9.4 S2 三处同步(对应 §8.4)

① 本机副本清单(E:/ProgramData/.workbuddy/skills/dsh-auto-handoff-chain/):

文件 字节 md5
SKILL.md 18926 0c5c4103f8ffa8071ce29434654fa2d3
scripts/chain_report.py 8126 636c4f336864bc99c408e92577516f11

② 文档库副本(新建 dsh-server-docs/skills/dsh-auto-handoff-chain/,逐文件 copy、⛔ 未用 cp -r):

文件 本机 md5 文档库 md5 镜像 md5(47 /opt/dsh/docs/skills/dsh-auto-handoff-chain/) 判定
SKILL.md 0c5c4103f8ffa8071ce29434654fa2d3 同 同 ✅ 三处同值
scripts/chain_report.py 636c4f336864bc99c408e92577516f11 同 同 ✅ 三处同值
  • E3 diff -r "E:/…/skills/dsh-auto-handoff-chain" "D:/…/dsh-server-docs/skills/dsh-auto-handoff-chain" = 0 行 ✅
  • 行尾:两处 CR = 0(纯 LF)✅(文档库 .gitattributes 的 dsh-server-docs/** -text 完好)

③ 登记(字节级单行插入,新行行尾跟随锚点行):

文件:行 内容
dsh-server-docs/README.md:37 技能表新增 skills/dsh-auto-handoff-chain/ 行(v1.3.2 + 六件套骨架 + 登记门禁 + 五条实测防护 + scripts/chain_report.py;同步方向本机 → 此处)
dsh-server-docs/INDEX.md:22 「什么时候查什么」新增 **跑跨会话长任务(自动接力)** 行
dsh-server-docs/INDEX.md:169 技能清单表新增 — / ✅ / skills/dsh-auto-handoff-chain/SKILL.md 行
  • E4 grep -c "dsh-auto-handoff-chain" dsh-server-docs/README.md = 1 ✅;INDEX.md = 2 ✅(≥ 1)
  • ⚠️ INDEX.md 是混合换行(全文件 CR 计数 = 734)⇒ 全程字节级插入、新行行尾跟随锚点(两处锚点均为 LF)、⛔ 未做任何批量换行符转换、⛔ 未跑 git checkout --。

④ 镜像同步(S1 + S2 产物一次上;同步前远端备份):

  • 备份 = /opt/dsh/docs/.bak-seq17-20260917-164809(5 个文件)
  • 上传 7 个文件,md5 逐条与本地一致:skills/dsh-change-workflow/SKILL.md 338bf953…|skills/dsh-env-bootstrap/references/常驻规则-快照.md e1a460b5…|skills/dsh-auto-handoff-chain/SKILL.md 0c5c4103…|…/scripts/chain_report.py 636c4f33…|02-运维手册.md d6627843b67c72ddfd3b62b5cfd5e29f|README.md ddfd4d5fc890af0ee86d5442d8c0d610|INDEX.md 5677883fd3777a225ae85af7c5c79fb7

⇒ 该技能的「三处同步」由「从未建立」变为「已建立」(此前文档库与镜像都无副本)。

9.5 S3 清理(对应 §8.5)

前置四项(缺一不可)全部满足: ① 5 个全属 seq7-20260917-112114 批次; ② 对应源文件 5/5 存在(src/net/relay/{client,directory,main}.ts、src/web/server.ts、src/worker/tunnel.ts); ③ lib/ 内等价比产物 5/5 存在; ④ 书面记录:这 5 个是 seq7 11:21 的快照,已被序⑧/⑨/⑭/⑮ 改写作废 ⇒ 不是有效回滚点、删除风险 = 零。

删除前 → 后:find src test scripts -name "*.bak-*" | wc -l = 5 → 0 ✅(逐个点名 rm,⛔ 未用通配符)

逐个名:src/net/relay/client.ts.bak-seq7-20260917-112114 / src/net/relay/directory.ts.bak-seq7-20260917-112114 / src/net/relay/main.ts.bak-seq7-20260917-112114 / src/web/server.ts.bak-seq7-20260917-112114 / src/worker/tunnel.ts.bak-seq7-20260917-112114

判据:

  • npm run build RC = 0 ✅
  • npm test = 162 / 161 / 0 / 1 ✅(不退化)
  • lib 产物 md5 清理前后零差异 ✅(自证未改任何源文件):client.js b8b29afba06ed6347cbefd29091f8c73/directory.js 3382ae677788d3bd1c026d4c71ca40ee/main.js 7531be9eeba5ced5928ff7747621d512/web/server.js b64fe76500249703e34934d274d0a151/worker/tunnel.js 5f2649b43b072812fbf5d910d91b0c22
  • ⚠️ git status --porcelain | wc -l 不减(这 5 个全 untracked ⇒ 本来就不体现在 git status 里;判据落在 find 与 md5 上,与 §5-S3 的说明一致)

⚠️ 额外兜底(超出单子、零风险):删除前把这 5 份原件复制到 E:/ProgramData/AI技能/aliyun-dsh-server/_中间产物_待清理/seq17/bak-archive/(5 个文件,保持相对路径)⇒ 即使日后需要,仍有字节级副本可查。

9.6 S4 临界项(对应 §8.6)

采样命令:node scripts/overlay-failover-drill.cjs --scene 4 --sample 5 --table "<工作区根>/参数表_覆盖网络_20260917.md"(RC = 0;原文 = _tmp_seq17_scene4.txt) ⛔ 只跑 --scene 4(构 A),⛔ 未跑 4b / 4c / ctrl。

5 个样本(切换耗时,ms):

轮 1 2 3 4 5
耗时 ms 20121 18772 21223 24477 20246

(5/5 全部在 deadline = 30000 ms 内侧;AUTH 就绪 4358 / 2272 / 2846 / 3652 / 2853 ms;目标恒为 wss://106.54.21.172/dshs-relay)

p95 口径(⚠️ 两种口径分档不同,必须点名):

  • nearest-rank(保守,本次采用):k = ceil(0.95 × 5) = 5 ⇒ 第 5 个 = 24477 ms ⇒ 落 临界档(24000 < p95 ≤ 27000)
  • 线性插值:idx = 0.95 × (5−1) = 3.8 ⇒ 21223 + 0.8 × 3254 = 23826.2 ms ⇒ 落 健康档

⇒ 结论(按 §4-D3):临界档 ⇒ 记录在册、⛔ 不判 FAIL、⛔ 不调任何生产值。 ⚠️ 两口径均 < 27000 ms ⇒ 回头条件未触发(§4-D5 未被激活)。 ⇒ 判据未落参数表 §6 —— §5-S4 ② 规定只在「健康」档落表 ⇒ 参数表指纹保持不变(8f08e74b026e6e5b5e1b3db813f031ae,见 §9.9),D1 自证成立。 阈值口径:deadline = RELAY_FAILOVER_DEADLINE_MS = 30000 ms;两档 = deadline×0.8 = 24000 / deadline×0.9 = 27000。

9.7 零回归 / 越界自证(对应 §8.7)

E6 三件套(全绿): ① npm test(Node 22)= 162 tests / 161 pass / 0 fail / 1 skipped,RC = 0 ✅ ② --scene all = 12 PASS / 0 SKIP / 0 FAIL,RC = 0 ✅ —— 幕 4-A 两个毫秒值:20419 ms(停 47 ⇒ 切 106)与 18333 ms(一跳豁免切回 47);幕 4-C 实测 18333 ms / deadline 30000 ms ③ overlay-probe --table "…/参数表_覆盖网络_20260917.md" = 12/12 · rc = 0 ✅(OBS-01…OBS-12 全 PASS;OBS-11 = 必在 7 / 允许 4 / 区间 3 / 派生 2 / 实际 78,多出 0 / 缺失 0;OBS-09 本机:20000=401 w-106:45747=401)

E9 收口归零:ssh -p 22 bt-server 'systemctl is-active dshs dshs-relay dshs-pg' = active / active / active ✅;ss -lntH 'sport >= :25000 and sport <= :25063' | wc -l = 64 ✅

E8 越界自证:

  • COOLDOWN_MS=0 精确计数 = 0 ✅(grep -rn "COOLDOWN_MS" scripts/ 的命中全部是「⛔ 不许置 0」的警示注释,无任何实际赋值 —— 已逐行人工核)
  • HEAD = 640813e(⛔ 本棒零 commit) —— ⚠️ 该判据表内值为基线快照;本节其余项全绿后才按用户追加授权单独提交(§9.10),提交发生在 E8 判据采集之后
  • git status --porcelain | wc -l = 49(基线 43 + 6),逐项可归因,无越界:
    • +4 个 M:本轮 S1/S2 把 4 个原本干净的文档改为 M —— dsh-server-docs/02-运维手册.md、skills/dsh-change-workflow/SKILL.md、skills/dsh-env-bootstrap/references/常驻规则-快照.md、dsh-server-docs/INDEX.md
    • +1 个 ??:dsh-server-docs/skills/dsh-auto-handoff-chain/(S2 计划内新建)
    • +1 个 ??:_中间产物_待清理/(演练脚本落盘产物;⛔ 不在提交范围内)
    • ⇒ M 项逐个都在计划内 ⇒ 无越界改动

9.8 未过项 / 在册未办(对应 §8.8)

  1. S4 落「临界档」(p95 = 24477 ms,nearest-rank 口径)。
    • 现象:5 个样本中 1 个为 24477 ms(超 deadline×0.8 = 24000),其余 4 个 18772–21223 ms。
    • 已做到哪一步:三档判据已立(§4-D3)、--scene 4 × 5 采样已做、零回归三件套全绿、收口归零完成、⛔ 未改任何生产值。
    • 回头条件(一出现必须回头解决):① p95(nearest-rank)> 27000 ms;② --scene all 的幕 4-A / 幕 4-C 出现 FAIL;③ 任何 RELAY_FAILOVER_* / HB_SEC / burst 值被调整。命中任一条 ⇒ 按 §4-D5 重做四段分解(检测 / 首试 / 白等 / 建连)后定位,⛔ 不许自行调生产值。
  2. Q4 —— 已解除(用户本轮授权):原「src/net/relay/** untracked ⇒ commit/push 需授权」由用户原话「执行完毕后 同步到仓库」解除 ⇒ 已 commit + push(§9.10);git ls-files src/net/relay | wc -l 0 → 15。
  3. src/worker/tunnel.ts 生产死路径(§0.1 末 / D4):⛔ 本棒未处置,原样登记(是否删 = 独立决策,可能保留作 ssh 兜底变体)。
  4. presence / 房间层 / 内容分发(§3.3):⛔ 未定序 —— 属业务优先级(§1 边界外 ①)⇒ 需拍板,候选与优缺点登记原样保留。
  5. 骨干节点服务范围(入口 §4 既有待拍板项 A/B):原样保留,本棒未重复上抛。
  6. §8.8-1 106 sshd MaxStartups 限流:本轮 ssh 未遇 rc=255(单次重试机制未触发);⛔ 未放宽限流(命中 R5)⇒ 仍在册。

9.9 指纹(对应 §8.9,可复现核对口径)

对象 值 判定
本单 §8 前缀 bab83b7219b2669d5a6e9f1acf782e1f 回填后未变 ✅(§9 在 §8 之后,不进前缀口径)
本单全文 回填后见下(脚本输出) —
参数表(截断口径 sed '/^## §10 指纹/,$d' … | md5sum) 8f08e74b026e6e5b5e1b3db813f031ae 未变 ✅(S4 落临界档 ⇒ 判据未落表 ⇒ D1 自证)
覆盖网络线入口 接续入口_覆盖网络线_20260916.md(§0 + §2 已推进,见 §9.11) —

三处同步产物(本机 = 文档库 = 镜像):

  • skills/dsh-auto-handoff-chain/SKILL.md = 0c5c4103f8ffa8071ce29434654fa2d3
  • skills/dsh-auto-handoff-chain/scripts/chain_report.py = 636c4f336864bc99c408e92577516f11
  • skills/dsh-change-workflow/SKILL.md = 338bf9534e5243f495e7d66f914371bf
  • skills/dsh-env-bootstrap/references/常驻规则-快照.md = e1a460b53cc4b62466107f8555946496

仅文档库 + 镜像:02-运维手册.md = d6627843b67c72ddfd3b62b5cfd5e29f|README.md = ddfd4d5fc890af0ee86d5442d8c0d610|INDEX.md = 5677883fd3777a225ae85af7c5c79fb7

S3 涉及的源文件(清理前后不变,自证未改码): src/net/relay/client.ts = 6ffb117f3f6df1c2456641e176529ce8|directory.ts = d6dfcf1f1fbf388f994582d43bbb65ec|main.ts = 7d5f915fcf0298e178e910d37863ef1d|src/web/server.ts = 12f8dadd4a2e06ffaed70bddbd719999|src/worker/tunnel.ts = e84c0baab6e96da1208d9512a000cedc

9.10 追加项 —— 同步到仓库(用户本轮明确授权 ⇒ Q4 解除)

授权原话:「执行完毕后 同步到仓库」(本棒执行期间用户明确下达)。

提交清单核对(提交前逐项确认只含本线真实改动) ⇒ 两个 commit:

commit 面 文件数 内容
146c3d2 代码 / 测试 53 relay 子系统 src/net/relay/**(15 文件)+ src/worker/relay-tunnel.ts + src/web/routes/overlay.ts + 8 个 overlay 脚本 + 12 个测试 + package.json 等改动(+16187 / −63)
bc0dd2c 文档库 10 02-运维手册.md、INDEX.md、README.md、scripts/stop-dialog-guard.py、4 个技能文件(含 S1 的两处校正)+ 新增 skills/dsh-auto-handoff-chain/**(2 文件)
  • ⛔ 未用 git add -A:逐路径 git add src/ scripts/ test/ package.json 与 git add dsh-server-docs/;_中间产物_待清理/ 未被提交(提交后仍为唯一的 ??)。
  • 推前判定:git ls-remote origin refs/heads/master 取裸 sha = 640813e84e5e48c56ca39d765d7b195884e58ebc;git merge-base --is-ancestor 640813e… HEAD ⇒ 是祖先(fast-forward,无分叉);git push --dry-run 显示 640813e..bc0dd2c。
  • 推送结果:640813e..bc0dd2c master -> master;推送后 git ls-remote = bc0dd2c96da88b1ee3a8450760b6cbb8ab92d845 = 本地 HEAD ✅
  • Q4 缺口闭合自证:git ls-files src/net/relay | wc -l = 0 → 15 ✅(序⑭/⑮ 的修复与 test/relay.test.mjs 首次进入版本库)
  • 行尾:.gitattributes 的 dsh-server-docs/** -text 完好(文档库保持纯 LF)⇒ ⛔ 未做任何批量换行符转换。

9.11 收口六件核对

# 项 状态
① 释放锁 --release-exec ✅ 本棒收尾第一步执行
② 陈述句告知 + 登记下一棒 ✅ 已陈述句告知;⛔ 未登记下一棒 —— 理由见下
③ 入口 §0 + §2 推进 ✅ 已刷新(§2 的序⑰ 转存档 + 新增收官段)
④ 工作区日志 .workbuddy/memory/2026-09-17.md ✅ append-only 追加
⑤ 本单回填回报 ✅ 本 §9(9.1–9.11)
⑥ 输出指纹 ✅ §9.9

⛔ 为何未登记下一棒(登记门禁):四条在册项清干后,剩余项全部落在「需拍板」区 —— presence / 房间层 / 内容分发定序(= 业务优先级,§3.3)与骨干节点服务范围(入口 §4 的 A/B)。按用户明令的登记门禁(「要用户拍板的,等拍了再登记」,技能 dsh-auto-handoff-chain §3.3),不登记下一棒;拍板到手后再建。 ⚠️ 技能的三处同步(S2)完成后,dsh-auto-handoff-chain 已同时存在于本机 / 文档库 / 镜像 ⇒ 上述门禁在三处都可读取。