chore(工作区): 纳入版本控制基线(回收 411 MB 过程产物)

回收 411 MB(470 M → 58.8 M),全部经回收站,可恢复:
- 待清理/(146.2 M,含 relay 分片 128 M 与 42 项过程目录)
- tmp/(32.4 M,按接续棒命名的过程临时区)
- .workbuddy/tmp/(39.5 M)
- 4 份 workbuddy.db 冗余副本(101 M,09-23 事故的坏副本 / 抢救产物)
- tmp/im16/gw/centrifugo 二进制(63.9 M,可重下)+ 缓存残留

入库范围:常驻规则(CODEBUDDY.md / README.md / state.py)、在途接续入口与
接续包、docs/、交付物/、交接单/、归档/、scripts/、.codebuddy/、
.workbuddy/memory/;共 398 件,其中 >60 KB 的 26 件全为文档。

排除(.gitignore):tmp/、待清理/、运行态日志与缓存、*.db 与 DB 备份整目录、
打包二进制(*.tar.gz / *.tgz)、记忆修复前备份。
This commit is contained in:
admin committed 2026-09-24 07:51:03 +08:00
commit ce8e6ceed9
396 files changed
+66045

No files matched your search

@@ -0,0 +1,45 @@
# 覆盖网络线 · 序 ⑮ 执行棒(automation `1933b18a`)— 运行记忆
> 用途:下一棒开工前扫一眼,确认本棒没有遗留「未落盘的状态 / 未告知的拍板」。
> ⛔ 只记高层结论与指针,不复制正文。
---
## 2026-09-17 16:14–16:3x · 第 1 次运行 —— ✅ 全部完成(收官)
**任务**:序 ⑮「修掉缺陷 B = 拨号池**未分配槽位被任意一条连接永久杀死**」**执行棒**,按入口 §2 + `交接单_观测口径与在册缺陷_20260917.md` §10.8 开工。
**结果**:✅ **缺陷已修并端到端验收**;改动只有 **2 个文件**、**未改任何生产值**、零 commit / push、零上抛;收口 6 件全办。
**核心成果(一句话)**:`src/net/relay/dialer.ts#onConn` 撞到未分配槽位时只做 `slot.server.close()` —— 关掉的是**这个口的服务器**,而槽位**仍留在 `slots` 里、`key` 仍是 `undefined`** ⇒ `localPortFor()` 的 `slots.find(s => s.key === undefined)` **下次还会选中它** ⇒ 把**没人听的口号**当落点发出去 ⇒ `ECONNREFUSED`(47 上实测:`16:00:27 落点 127.0.0.1:25000` 紧接 **16:00:31/35/40 三条 `POST /api/dsh/enter` → 500**)。**改法 = 只 `tcp.destroy()`(槽位原样保留)+ `stray` 计数 + 点名日志**,再加纵深防御(`localPortFor`/`lruIdle` 只认 `server.listening`)+ `status().pool` 改报"实际在听"。⛔ **不取"把槽位从 `slots` 摘掉"那条**:那等于让任意本地连接**永久**蚕食池容量(R11)。
**关键指针**:
- 证据 = 交接单 **§11**(11.1–11.10 全节);`--scene all` 原文 = `_中间产物_待清理/seq15/scene-all.txt`。
- 验收原文(⚠️ 顺序**就是缺陷 B 的复现顺序**):**先故意对未分配池口 25000 发一条连接** ⇒ 打后池口仍 **64**、stray 日志 1 行 ⇒ guest `enter` **200/200** ⇒ 该口同连接连发 3 次 **200/200/200** ⇒ `sessions` 回基线 2。落盘 = `verify-47.txt` / `verify-47-final.txt`;`npm test` **162/161/0/1**;`--scene all` **12 PASS / 0 SKIP / 0 FAIL**;探针 **12/12 · rc=0**。
- 指纹:`dialer.ts` = **`f3a608a75f7edd0aa0de8cceb4de5615`**|`test/relay.test.mjs` = **`587f9d80e9330e33badb281e6bd6c719`**(1318 行,含 **T24**)|部署产物 = **`6446fe9b23bca2649137adcbf4bf9d1f`**(五处同值)|参数表 **`8f08e74b…`(未变 ⇒ D1)**|交接单 §8 前缀 **`3ece0f87…`(未变)**。
- 部署备查:远端各留 `.bak-20260917-1621xx`;**只重启了 47 的 `dshs`**(拨号方专属改动)。
**🔴 本棒留给下一棒的三条硬事实**:
1. **对 47 / 106 的 ssh 必须显式 `-p 22`** —— ssh 别名 `bt-server` 里的 `32022` 是**失效残留口**(47 的 sshd 只监听 22)。本棒为此多花了 3 次调用。
2. **`ssh` 的 stderr 会带 PQ 告警行** ⇒ 取证一律 `ssh … > f 2>/dev/null`(否则污染行数判据)。
3. **参数表指纹的既有口径是 `sed '/^## §10 指纹/,$d' <表> | md5sum`(截断口径),⛔ 不是全文件 md5** —— 用全文件 md5 会得到完全不同的值(本棒差点把 D1 误判成"参数表被改")。
**下一棒登记**:automation id **`91c53ef8-c3f0-4bb3-9f0a-943790178176`**「覆盖网络线-序16规划棒-会合中继拆分复核与在册收尾定序」(一次性,`scheduledAt` = 2026-09-17 **16:36** = 收口 +~5 min,`nextRunAt` = 1789634160000)。已用**陈述句**告知用户,并落盘到入口 §0 / §2 与 `.workbuddy/memory/MEMORY.md` 在途单。
**边界遵守**:⛔ 未 commit / 未 push(`git status` 43、`src/` 20 均为既有基线 Δ0)|⛔ 未改参数表 / `package.json`|⛔ 未动 `RELAY_FAILOVER_*`·`HB_SEC`·burst|🔴 `COOLDOWN_MS` 赋 0 —— 远端**严格判据 0 命中**(⚠️ 宽松正则 `"\?0"\?` 会**误报** `switcher.js:53` 的默认值 `300_000` 里的 `0`)|⛔ 未动 **Q4 / Q5**(只报告)|⛔ 未重启 106 worker / relay|R4:`sessions` 回基线 **2**。
**收口清单核对**:① 释放锁 ✅ ② 陈述句告知 + 登记下一棒 ✅ ③ 入口 §0 + §2 推进到序 ⑯ ✅ ④ 工作区日志 `.workbuddy/memory/2026-09-17.md` ✅ ⑤ 交接单追加 §11 ✅ ⑥ 本文件 ✅。
---
## 运行须知(给后续复跑的同类棒)
- 本 automation **是一次性的**,已执行完毕 ⇒ ⛔ 不要重启它;若需再跑,另建新棒。
- 开工前先跑 `state.py` + 扫最新两条 automation memory(防漏掉别人留下的拍板)。
- 🔴 **`--scene all` 与 `overlay-probe` 都必须带 `--table "<工作区根>/参数表_覆盖网络_20260917.md"`** —— 不带会报「找到 0 个参数表」而直接失败(演练脚本同因,本棒踩过一次)。
- 🔴 **演练会把 Manager 挪来挪去**(幕 1 切到 106、幕 4 切回 47)⇒ 跑完务必 `systemctl restart dshs` 归零,再跑探针,否则 OBS 会红。
- 🔴 **判定"服务是否正常"要看 `systemctl is-active dshs dshs-relay dshs-pg`** —— 演练进行中某台 relay 是 `inactive`,那是**幕的正常态**,不是故障。
- 🔴 **池口自证**:`ss -lntH 'sport >= :25000 and sport <= :25063' | wc -l` 应恒为 **64**。修复后**打未分配池口不再有害**(它只丢连接、槽位保留);`status().pool` 现在恒等于这个数。
- 🔴 **对 106 的 ssh 偶发 `rc=255`**(MaxStartups 被外部爆破限流)⇒ 脚本里的 ssh 一律 `2>/dev/null` 并容许单次重试;⛔ 放宽限流命中 R5 ⇒ 只报告。