Skip to content

feat(debugging-network-issues): 补上「一切正常只是慢」这个失败家族 (v1.6.0) - #292

Merged
daymade merged 1 commit into
mainfrom
feat/dni-throughput-collapse
Aug 17, 2026
Merged

feat(debugging-network-issues): 补上「一切正常只是慢」这个失败家族 (v1.6.0)#292
daymade merged 1 commit into
mainfrom
feat/dni-throughput-collapse

Conversation

@daymade

@daymade daymade commented Aug 14, 2026

Copy link
Copy Markdown
Owner

为什么

这个 skill 原本会主动把降速类故障劝退:Step 0 写着「'Slow' is not a symptom」,把「用户说慢」列为不合格前提,全仓 throughput / MB/s / goodput / iperf 命中 0 个文件

但存在一整类故障没有任何 error string 可抓——每个请求返回 200,每项健康检查都绿,系统却因为字节以应有速率的几分之一到达而不可用。整套 error-driven 工具链在它面前无处下嘴。

加了什么

Step 0.7 — 决定性实验:两条共享网络路径、但不共享任何应用代码的通道,同方向、同时间预算测速率

A B 结论
链路。两个不相干的栈不会以同一速率同时变慢。停止调应用
应用。你现在有了可用的对照组
还不能下结论——对照组本身是异常。换第三个栈重测
探针没复现症状。不得据此结案

命令是时间预算制而非固定字节:固定 8MB 在健康链路上不到一秒、在降级链路上约 90 秒,更深的降级会无界放大等待。判据前有强制自检——「探针根本没连上」会读出低/零速率,被表读成「慢」,直接推向错误结论。

原则 3 加容量变体(换的是「栈」不是「跳数」);原则 5 加量级轴:探针在链路成为限制因素之前就结束,就测不到链路(案例里健康端点全天 40ms 不变,横跨容量 100× 的摆动)。

陷阱 16–18 — 把路径类型读成路径容量(同一个 direct、同一个字段,0.09 和 14 MB/s 读数一样;RTT 反向);把自己探针的锅算到远端头上;错误的容量假设静默产出损坏产物并通过成功检查。

新 case study 按本 skill 体例:四个错误转弯逐个列出,每个都是合理的推断 + 真实的测量 + 量错了东西

质量证据

两轮独立审阅(fresh-context,非 fork),共 15 条 findings 全部处置,档案在私有知识库。

  • 轮一的一条修复建议被拒绝:它让我用 dd 自报速率,实测那量的是「写进管道」不是网络(同一次传输 dd 自报 54.9 MB/s、端到端 44.26 MB/s)。findings 是假设不是判决。
  • 轮二 7 条里 4 条是轮一修复自己引入的,含两个我编的数字(「8MB 要十分钟」实为 73–89 秒;「慢到一分钟挪不动 4MB」实为 36–44 秒),和一条 blocking:判据表扩到 4 行后,前面那句为 2 行写的压缩公式变成了矛盾,方向恰好是鼓励过早结案。

顺带修正一处既存缺陷:「详见 cognitive-traps.md」的指针在基线里就已部分失效(该文件只有 Trap 1–12,而 SKILL.md 基线已有 13–15)。改为如实指路,未擅自迁移 6 条 trap。

闸门quick_validate ✅ | security_scan 无 secret ✅(1 条 MEDIUM 为内网服务占位符误报,基线本有同类)| 回归审计 829 项精确保留、4 候选全分类 ✅ | description 1013/1024 ✅

description 达 1020/1024 后新增触发词是零和交易:删掉结尾一句纯方法论摘要(不承担触发职能,内容在正文原则 2/3 里更完整),并放弃一条候选触发词,压回 1013。

未做的事(如实标注)

  • Tier 3 的配对 A/B 评测经用户明确豁免,记为 user-waived,不冒充通过
  • 触发词有效性未测:新增的 throughput collapse / "it works, it's just slow" 等短语能否赢得路由,未跑 run_loop 也未用 claude -p 实探
  • 两条命令只在 macOS + Linux 上验过,timeout 在部分 BSD 需 gtimeout,未在真 BSD 复验

这个 skill 原本会主动把降速类故障劝退:Step 0 写着「'Slow' is not a symptom」,
第 107 行把「用户说慢」列为不合格前提,全仓 throughput / MB/s / goodput / iperf
命中 0 个文件。但存在一整类故障没有任何 error string 可抓——每个请求都返回 200,
每项健康检查都绿,系统却因为字节以应有速率的几分之一到达而不可用。

新增内容,全部来自一次实测过的真实事故:

Step 0.7 —— 决定性实验是「两条共享网络路径、但不共享任何应用代码的通道,同方向、
同时间预算测速率」。两条一致地慢 → 瓶颈在链路,别再调应用;A 慢 B 快 → 在应用。
两条命令都是时间预算制而非固定字节:固定 8MB 在健康链路上不到一秒、在降级链路上
约 90 秒,而更深的降级会无界放大等待,恰好在最耗不起的时候。

原则 3 加容量变体(同一技术,换的是「栈」不是「跳数」);原则 5 加量级轴——
探针在链路成为限制因素之前就结束,就测不到链路。案例里健康端点全天 40ms 不变,
横跨链路容量 100× 的摆动。

陷阱 16-18:
- 把「路径类型」字段读成「路径容量」。同一个 direct、同一个字段,在 0.09 和
  14 MB/s 两种状态下读数完全一样;RTT 更是反向指标(慢的那次 12ms,快的 4ms)。
- 把自己探针的锅算到远端头上。损坏的 key 走的是更慢的路径(索引未命中 → 全表扫描
  → 报错),完美伪造出「对端吃力」的 signature。判据是载荷大小:21 秒送 17 字节
  不是带宽症状。
- 错误的容量假设会静默产出损坏产物并通过成功检查。真实的检查是
  `HTTP 200 && bytes > 1000`,听起来像个正经完整性检查,却放过了 35 个下载里的
  14 个截断文件——被砍断的多兆文件轻松超过任何你想得到的阈值。没有任何字节下限
  能区分「完整」和「大部分」,那是文件格式的属性。

新 case study 按本 skill 自己的体例写:四个错误转弯逐个列出,每个都是合理的推断 +
真实的测量 + 量错了东西。

---

两轮独立审阅,共 15 条 findings 全部处置(档案在私有知识库,非本仓)。其中:

- 轮一给的一条修复建议被拒绝。它让我用 dd 自报速率作为 channel B 的读数,实测那
  量的是「写进管道」不是网络——同一次传输 dd 自报 54.9 MB/s、端到端 44.26 MB/s。
  改用「固定时间预算 + 接收端计数」,两条命令均已实验验证(含 curl --max-time
  中途被砍时仍打印 -w 速率,exit 28)。
- 轮二 7 条里有 4 条是轮一修复自己引入的,含两个我编的数字(「8MB 要十分钟」实为
  73-89 秒;「慢到一分钟挪不动 4MB」实为 36-44 秒),以及一条 blocking:判据表从
  2 行扩到 4 行后,前面那句为 2 行写的压缩公式「agreement implicates the path」
  就成了矛盾,且矛盾方向恰好是鼓励过早结案。
- 判据表补上「探针根本没连上」的自检:SSH 免密没配好会静默读到 0,被表读成「慢」,
  直接推向「是链路」——这正是本 skill 陷阱 17 在配方内部的复现。

顺带修正一处既存缺陷:「详见 cognitive-traps.md」的指针在基线里就已部分失效
(该文件只有 Trap 1-12,而 SKILL.md 基线已有 13-15)。改为如实指路,未擅自迁移。

description 达 1020/1024,新增触发词是零和交易:删掉结尾一句纯方法论摘要
(不承担触发职能,内容在正文原则 2/3 里更完整),并放弃一条候选触发词,压回 1013。

闸门:quick_validate 通过;security_scan 无 secret(1 条 MEDIUM 为内网服务占位符
的误报,基线本有同类);回归审计 829 项精确保留、4 候选全分类;脱敏后真实 IP/主机名/
内网段零命中,另经逐字语义复核抓出一处无关键词的指纹并改为中性示例。

Tier 3 的配对 A/B 评测经用户明确豁免,记为 user-waived 而非冒充通过;触发词有效性
未测。两项均在审阅档案的「未能核查」节列出。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019oKLM3zqoWUFAH6wY5W199
@daymade

daymade commented Aug 15, 2026

Copy link
Copy Markdown
Owner Author

Small cross-reference drift worth folding into this PR while it's open — not a blocker, and not worth its own PR.

debugging-network-issues/SKILL.md:19 (unchanged on both main and this branch) routes with the symptom label "TUN DNS hijack":

| macOS Tailscale ⨯ proxy/VPN conflict ... Connection closed by 198.18.x.x, TUN DNS hijack, ~60s getaddrinfo resolver stall | **tunnel-doctor** |

That phrasing was retired in tunnel-doctor by #294 (merged). The reason it went: under TUN every hostname resolves to a fake IP — on success as well as on failure — so "DNS hijack" describes the normal operating mode, not a diagnosis, and 198.18.x.x appearing in an error line carries no diagnostic signal. Step 2H now names two candidate mechanisms and hands the reader a discriminating test instead of asserting one.

Low severity: a reader who follows the routing lands on the corrected Step 2H, so nothing here misleads them for long. It's just that the router still uses the retired vocabulary.

Suggested edit to that row, if you're touching the file anyway — drop the label and keep the observable symptom:

... `tailscale ping` works but SSH/curl/git fails, `Connection closed by 198.18.x.x`, ~60s `getaddrinfo` resolver stall ...

Flagging rather than editing because this file has an open PR (this one) and uncommitted local changes, so it has an owner already.

@daymade
daymade merged commit 06fa225 into main Aug 17, 2026
4 checks passed
@daymade
daymade deleted the feat/dni-throughput-collapse branch August 17, 2026 07:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant