fix(auto-review): Auto 档降级后 SDK 档位缺补推点,控制通道被占时与逻辑状态分叉
- Dominant language
- TypeScript
- Stars
- 2.7k
- Forks
- 401
- Avg merge
- 21h 48m
- Merged PRs (30d)
- 776
Description
## 现象
Auto 档下原生分类器被判定不可用、Cindy 接管审阅之后,如果**那一刻控制通道正被占住**(rewind / bridge 重建 / plan 档 / plan turn 进行中),SDK 会一直停在 `auto` 档,而 Cindy 侧已经认为自己接管了。结果是 Claude 原生 auto reviewer 继续被调用去撞那个正在抽风的分类器——降级形同没做。
## 代码位置
`packages/maker-core/src/agents/claude-code/index.ts`
1. **:4549** `nativeAutoReviewUnavailable = true` **无条件**置上(逻辑状态 = 已降级)
2. **:4551-4558** 但 `await q.setPermissionMode('default')` 被四个条件守卫——`mutablePermissionMode === 'auto' && !mutablePlanMode && !planTurnActive && !controlRequestsBlocked()`——任一不满足就跳过推档
3. **:1828-1829** `effectiveSdkPermissionMode()` 只读 `mutablePlanMode / planTurnActive / mutablePermissionMode`,**不读 `nativeAutoReviewUnavailable`**。所以 bridge 重建、rewind 后 buildQuery 重新起 turn 时仍然算出 `auto`,**没有任何补推点**
4. **:1756-1757** 而 `usesNativeClaudeAutoReview()` 已因该标记返回 `false`
`nativeAutoReviewUnavailable` 在全文件只有 4 个读写点(`:1753` 声明、`:1757` 读、`:4548` 早退、`:4549` 置位),可确认不存在补推路径。
## 为什么这是漏洞,不是设计如此
同一文件里另外两个改档入口都**显式配了补推点**,并在注释里写明时机:
- `setPlanMode` **:4568-4574**:「补推时机:send 消耗武装态时(!sdkInPlanMode → push plan)」
- `setPermissionMode` **:4583-4586**:「重建时 buildQuery 以 effectiveSdkPermissionMode() 起档并回写 sdkInPlanMode」
只有降级这一处「置了标记就走」,没有配对的补推。
## 影响面
故障窗口内(分类器瞬时故障 与 控制通道被占 同时发生)用户的工具调用仍走原生审阅路径。命中概率取决于 rewind / bridge 重建的发生频率,不需要用户做特殊操作。
## 期望方案
二选一:
- 让 `effectiveSdkPermissionMode()`(或 buildQuery 起档路径)消费 `nativeAutoReviewUnavailable`,使「重建」本身成为补推点;
- 或在 `useCindyAutoReviewFallback` 跳过推档时记一个待补推标记,由 send / 重建路径消费——与 `setPlanMode` 的武装态补推同构。
## 验收标准
- 回归测试:`controlRequestsBlocked()` 为真时调用 `useCindyAutoReviewFallback()`,随后触发一次 bridge 重建 / buildQuery,断言 SDK 档位为 `default` 而非 `auto`
- `mutablePlanMode` / `planTurnActive` 为真的同一路径同样覆盖
## 来源
从已关闭的 #1612 中剥离。那个 PR 试图用「档位写入串行队列」一并解决它,但与 #1581 的代际号机制在解同一个问题(两套语义会在同一文件里打架),且违反仓库「禁止先合并地基抽象、后做验证性接线」。本 issue 只记录 main 上这一处真实缺陷,用独立小 PR 修。
Contributor guide
Research direction
Start in packages/maker-core/src/agents/claude-code/index.ts, tracing useCindyAutoReviewFallback(), effectiveSdkPermissionMode(), buildQuery, and the bridge-rebuild path. Reproduce the fallback while controlRequestsBlocked(), mutablePlanMode, or planTurnActive prevents the immediate mode update. Add regression coverage showing that a later rebuild or buildQuery uses default rather than auto.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100