交接单按归属约定(正文落文档库、工作区只放指针)归档至 归档/交接单-20260924-归档/,含逐件判定 README: - 16 件已被文档库正式版取代(T09–T21 + 覆盖网络-24/25/26) - 4 件主题已被覆盖网络线入口汇总 - 7 件历史接续包/规划件 CODEBUDDY §9:收口清本棒 tmp、tmp 保留期 7 天、禁「待清理」中间态、 工作区入库只放文档与文件、不保留脚本副本、>60 KB 单文件须逐个判。
455 lines
45 KiB
Markdown
455 lines
45 KiB
Markdown
# 交接单 · 在册收尾(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` 已同时存在于本机 / 文档库 / 镜像 ⇒ 上述门禁在**三处都可读取**。
|