原生分类器故障观察器在缺 session header / 反解失败时静默漏检,无任何日志线索
- Dominant language
- TypeScript
- Stars
- 2.7k
- Forks
- 401
- Avg merge
- 21h 48m
- Merged PRs (30d)
- 776
Description
## 现象
原生分类器故障检测依赖两个前置条件,任一不满足就**静默漏检**:故障永远不会升级到 Cindy fallback,会话被留在无限 fail-closed,且日志里连一条 warn 都没有。
## 代码位置
`apps/desktop/src/main/maker-host/claude-auto-permission-fallback.ts:184`:
```ts
const sdkSessionId = ctx.requestHeaders['x-claude-code-session-id'];
if (!sdkSessionId) return undefined;
const sessionId = resolveSessionId(sdkSessionId);
if (!sessionId || !isClaudeAutoClassifierRequest(ctx.requestBody)) return undefined;
```
两个 silent return:
1. **请求头缺失** —— 上游若不回传 `x-claude-code-session-id`(SDK 版本差异、代理链改写、某些错误响应本就不带原请求头),直接返回
2. **反解失败** —— `resolveSessionId(sdkSessionId)` 返回 null(映射尚未建立、会话刚 resume、映射表被清理)时同样直接返回
成功路径 :165 也有同一处依赖,拿不到 header 时连"恢复清零"都不会发生。
此外整个观察器挂在 `anthropic-compat-proxy` 的响应管道上,**不经该 proxy 的路由天然不在覆盖范围内**。
## 为什么值得改
这条链路是 Auto 档唯一的自救通道。它一旦漏检,用户遇到的就是本仓库里已经反馈过的形态:工具一直被拒、没有弹窗、重启无效——而且因为是 silent return,排障时日志里没有任何线索指向这里。
`isClaudeAutoClassifierRequest` 的双判据(system 前缀 + max_tokens 上界)本身有详尽注释和防漏检设计,说明这块的漏检风险已经被认真考虑过;但它前面这两个 early return 没有同等的可观测性。
## 建议改法(保持独立)
1. 两处 silent return 加**限流后的** debug/warn 日志(带 status、是否有 header、反解结果),让"分类器在报错但我们没识别出来"这件事在日志里可见
2. `resolveSessionId` 失败时,考虑用一个二级兜底:若该 proxy 会话只对应唯一活跃 Auto 档会话,可按 fallback 归属;否则维持现状不猜
3. 补一条"分类器错误响应总数 vs 成功识别数"的计数器,挂在已有的 `FallbackCounters`(:241)上,偏差过大即说明识别规则失效
第 1、3 条纯属可观测性,零行为变化,可以先合。
## 独立性
只碰 `claude-auto-permission-fallback.ts` 一个文件,不依赖其他 auto-review issue。
## 验证
- 构造缺失 `x-claude-code-session-id` 的错误响应,确认日志有记录且不刷屏
- 确认计数器能反映识别率
Contributor guide
Assessment
This issue has not been assessed yet.