<!-- 受众: AI(直接投喂) | 用途: 排错/自查时发给 AI，让它逐条对照修 -->
<!-- 这些是发给 AI 读的内容。人类查错索引在 ../给人看/排错速查-给人.md 。 -->
# 🐞 错误自查手册 · 发给 AI，让它逐条对照

> 本文件整篇都可直接发给 AI。发给它时说一句：**「对照本手册逐条自审你刚才的改动，命中哪条就修哪条」**，
> 或出错时把最像的那条发给它。每条格式：症状 → 根因 → 定位 → 修复 → 预防。
> 分五类：P(AI流程) / W(小模型专属) / B(代码缺陷原型) / G(网关适配) / E(环境打包)。

---

## §0 改代码前先过这张自查清单

```
动手前逐条确认：
[ ] 我要加的东西，仓库里有没有现成实现？（先 grep，别造第二份真源）
[ ] 我的新逻辑是不是纯叶子？（零IO/确定性/绝不抛/可单测）
[ ] 有没有 KHY_XXX 门控、默认开、登记进 flagRegistry？
[ ] 门控关掉后，行为和改动前逐字节相同吗？异常 fail-soft 回退了吗？
[ ] 我的改动是不是严格超集？（只补漏/补错，没动既有正确输出）
[ ] 它真接到 executeTool/toolUseLoop/aiManagementServer 了吗？（不然不算在产）
[ ] 单文件会不会超 2500 行？
[ ] 我会不会声称"做完了"但其实没交付结论/没接线/没验证？
```

---

## P 类 · AI 做事流程错误（你最容易犯）

**P1 · 声称"已落地"其实是死代码**
症状：报告"已实现并接入"，但线上行为没变。根因：只写了模块+隔离单测，无调用链到达它；隔离单测全绿≠在产。
定位：`grep -rl "require(.*/<模块名>" services/backend/src --include=*.js | grep -vE "/<模块名>/|tests/"`。
修复：接到 executeTool/toolUseLoop/aiManagementServer 之一，接线处 try/catch fail-soft。预防：见 .ai/GUARDS-AI.md §0。

**P2 · 为同一概念建第二份真源**
症状：两套做同一件事的实现，日后改一处漏另一处。定位：.ai/GUARDS-AI.md §2 列了每个概念唯一权威实现。
修复：删新建那份，改 require 既有单一真源。预防：动手前 grep 概念关键词。

**P3 · 忘加门控 / 门控默认关 / 没登记**
症状：新行为硬上无法回退；或父门控关了子还在跑。定位：flagRegistry.js；守卫 check-flag-registry.js。
修复：加 KHY_XXX(default-on)，登记 flagRegistry。预防：铁律 R3/R4。

**P4 · 破坏了"关闭即逐字节回退"**
症状：KHY_XXX=off 后行为和改动前不一致。根因：混进了顺手优化。
定位：置 KHY_XXX=off 跑同输入 diff 新旧输出。修复：新逻辑完全收进门控开分支。预防：每次改完做 gate-off 对比。

**P5 · 跑了工具但没交付结论（静默截断）**
症状：做了一堆 grep/read，最后只说"找到3处，逐个核对，先从第一处"就停了。根因：把进度旁白当交付。
定位：resultGuard.js(progress-only-after-tools)。修复：必须给出结论+具体改动/答案。预防：铁律 R9。

**P6 · 用 --no-verify 跳守卫**：撤销提交，先修红守卫再正常提交。禁止 --no-verify。

**P7 · 猜规范号/撞号**：`find docs -name '*DESIGN-ARCH*' | grep -oE 'DESIGN-ARCH-[0-9]+' | sort -u | tail -1` 取最大值+1。

**P8 · 幻觉引用不存在的文件/函数/flag**：先 grep/find 确认目标真实存在再改；.ai/GUARDS-AI.md §3 列了已删孤儿模块。

**P9 · 写成上帝组件**：抽纯叶子，原文件同名别名 re-export；`npm --prefix services/backend run arch:god`。

---

## W 类 · 小模型/弱模型专属失败（完整设计见 docs/03_DESIGN_设计/[DESIGN-ARCH-013] 弱模型兼容.md）

**W1 · 工具结果过大撑爆上下文**：小窗口(2K–8K)收大结果后截断/幻觉。定位 toolUseLoop.js `_extractToolOutput()`/`_getActiveModelContextWindow()`。现状已按窗口比例缩放(默认32768，硬截断15000)，别破坏。

**W2 · max_tokens 太低中途截断**：已提高冷启动上限，别改回过低。

**W3 · role:'tool' 被无原生函数调用模型拒收**：已改写消息角色，加新适配别绕过这层。

**W4 · JSON 工具调用被包在 markdown 代码块**：解析器已容忍代码块内 JSON，别收窄。

**W5 · 退化 no-op(echo/true/:/裸 cat)**：检测 isDegenerateNoOp(门控 KHY_DROP_DEGENERATE_ECHO)，别破坏。

**W6 · 工具名大小写变体绕过归一化**：BASH/Bash/bash 都要覆盖(门控 KHY_PATCH_TOOLNAME_NORMALIZE)。

**W7 · 空参数工具调用**：已有空参补丁，补丁名集大小写不敏感覆盖(含 BASH/WebSearch)。

**W8 · forward-promise 只承诺不交付**：resultGuard.assessClosure(forward-promise)已检测追加收尾。见 P5。

---

## B 类 · 真实代码缺陷原型（写新代码时对照做边界审查）

**B1 · 裸 startsWith 边界未锚定（目录逃逸）**：proj vs proj-secrets 被误判在界内。修：`p===base || p.startsWith(base+sep)`。

**B2 · 大小写未折叠（denylist 绕过）**：`.SSH/authorized_keys`/`.BASHRC` 变体绕过。修：比较前 toLowerCase()。

**B3 · 正则缺锚点/边界**：glob `**`+`/x` 编 `^.*x$` 误放 backup_x；冒号 KV 未锚把 `https:` 当键。修：加 \b/$/分隔符边界，KV 要求键是合法裸标识符。

**B4 · 越界码点崩溃（不可信输入）**：`&#x110000;` 令 `String.fromCodePoint(cp>0x10FFFF)` 抛 RangeError 崩掉整次抓取。修：`cp<=0x10FFFF` 校验 + 整体 fail-soft。

**B5 · 密钥脱敏漏现代 key（泄漏进用户文案）**：sk-proj-/sk-svcacct-/sk-admin- 不被脱敏。修：脱敏正则覆盖现代前缀与字符集；同缺陷可能多份内联拷贝都要修。

**B6 · cron step=0 死循环(DoS)**：`*/0` 令 `for(i+=0)` 死循环 100%CPU。修：step>0 校验。

**B7 · slice(-0) 语义反转(静默 no-op)**：keepRecent:0 时 slice(-0)===slice(0)，"全压缩"变"全保留"。修：`n===0?[]:arr.slice(-n)`。

**B8 · 闭包捕获过期 resolve / 监听器泄漏**：setTimeout 捕获旧 resolve 致清理不跑；abort 监听器每次正常完成泄漏。修：正确作用域 resolve，正常完成也 removeListener。

**B9 · 字符集解码乱码**：GB2312/GBK 站恒 toString('utf-8') 乱码。修：按声明 charset 用 TextDecoder，异常回退 utf-8(门控 KHY_WEBFETCH_CHARSET，gbk 依赖 full-ICU)。

**B10 · SSRF: IPv4-mapped IPv6 hex 形绕过**：`::ffff:7f00:1`(127.0.0.1)/`::ffff:a9fe:a9fe`(169.254.169.254云元数据)被判 public。修：hex 形归一到 IPv4 再判私网(门控 KHY_SSRF_IPV4_MAPPED_HEX)。

**B11 · 破坏性命令 flag 顺序/大小写/拼写敏感**：`rm -fr ~`/`-r -f`/`-rfv`/`-Rf` 绕过 safe 判定。修：大小写不敏感+顺序无关 lookahead，覆盖长短形。

**B12 · 数值/格式边界错档**：999500 显示"1000k"应"1.0m"。修：先定档再取该档值，别跨档拼接。

**B13 · 上下文告警阈值小窗口下溢为负**：`threshold-20000` 在 8k/16k 窗口变负，从 token 0 就报"100%"。修：阈值 clamp 非负/按比例算。

B 类通用预防：处理外部/不可信输入或安全判定时问自己——边界锚定了吗？大小写折叠了吗？越界/空/0/负会怎样？坏输入崩还是 fail-soft？等价表示形都覆盖了吗？

---

## G 类 · AI 网关 / 模型适配错误

**G1 · 模型名泄漏给不认识它的通道→404冷却**：auto 降级把 A 家模型带给直连 B 家的通道。定位 aiGateway.js normalizeModelForAdapter。修：每通道对非本家族模型做对称防护(非家族→null 用默认)。

**G2 · 模型默认值散落硬编码**：升世代改漏一处。定位守卫 check-model-hardcoding.js。修：收敛单一真源叶子，消费点门控读取。

**G3 · 鉴权形态过时(JWT vs 原始 Bearer)**：新版单段 key 被旧 id.secret 拆分逻辑拒绝。修：按 key 形态选鉴权(含`.`→JWT，否则原始 Bearer)。

**G4 · 请求侧新字段被丢弃**：thinking/reasoning_effort 响应侧读了请求侧没透传。定位 _protocolPipeline._applyOpenAISamplingParams。修：请求侧透传。

**G5 · 视觉模型误判纯文本→无谓退回OCR**：llama-4/gpt-4.1/glm-4.6v/grok-4 名字不含旧片段被判 false。定位 visionCapability VISION_NAME_HINTS。修：补精确族名片段(别裸 4/gemma 免误伤)。

---

## E 类 · 环境 / 打包 / 发布 / 守卫错误

**E1 · Node 版本过低**：需 Node≥20；platform/khy_platform/cli.py 会检查。见 [OPS-MAN-028] 环境要求。

**E2 · 改了仓库源码 pip 用户没变化**：pip 包是打包时快照。修：按 [OPS-MAN-042] 发布手册重新打 wheel 升版发布。

**E3 · 版本号多处不一致**：升版时多处同步改，别只改一处。

**E4 · gbk 解码依赖 full-ICU**：确保 Node 带 full-ICU。见 B9。

**E5 · 守卫红了不知为什么**：看钩子输出指向哪个 scripts/check-*.js，对照 R7 守卫清单修。

**E6 · node:test 传目录幽灵失败 / describe 未定义**：node --test 传具体文件而非目录；jest 用例用 jest 跑、node:test 用例用 node:test 跑，别混。

**E7 · 磁盘膨胀 / 运行时目录当源码找**：.khy/cache/data/.tmp 是未纳入版本库的运行时产物，源码看 .ai/MAP.md；数据主权根是 ~/.khyos/。

---

## 你报错/卡住时先做这三件事（别乱改）
```
1) 只读体检：node services/backend/bin/khy.js maintain freshness
2) 在本手册里找最像的一条，按"根因→修复"做。
3) 还不行就把完整报错、改了哪些文件、跑了什么命令原样告诉我，别臆测硬改。
```
