# v0.5.20 > 子代理限流器从单门改双门:cap 放宽 + 连续 FAIL 流式阻断,正常多步工作不再被误杀。 ## 修复 - **子代理限流器双门**(#78)。原 `verification` 类子代理 cap=5,5 个连续 PASS 的 PR 验证后第 6 个就被硬阻断——即使每次都成功。源码注释承诺「only fires on pathological loops, not on normal multi-step work」,实际行为违背了这条契约。本版把单门改成双门: - **总 cap 放宽**:`verification` 5 → 12。日常多 PR 工作有充足预算。 - **连续 FAIL streak 门**:新增 `noteOutcome(agentType, verdict)`。3 次连续 FAIL(无 PASS 中断)立即 cap,**与总数无关**。任何 PASS / UNKNOWN 清零 streak。这才是真正抓 verifier-loop 的语义。 - **保守 verdict 解析**:`parseVerdict(text)` 解析子代理输出的 `VERDICT: PASS|FAIL|CHANGES_NEEDED|APPROVE|UNCONFIRMED` 行,附带 `SECURITY:` `PLAN_REVIEW:` `ROOT CAUSE:` 同义词。**UNKNOWN 当 soft-PASS** ── 一次性研究类子代理(如 Explore)没有 verdict 结构的输出不会被误杀。 - 错误文案区分 `cappedReason: 'total' | 'streak' | 'none'`,用户能看到具体哪个门触发。 - 环境变量出口保留:`CLAUDE_CODE_AGENT_LIMIT_=N` 调高 total cap、`CLAUDE_CODE_AGENT_LIMITER_OFF=1` 整体禁用。 ## 测试 - `src/tools/AgentTool/invocationLimiter.test.ts`:28 cases / 153 expects 全过。 - 14 个原测试按新 cap=12 适配 - 5 个 streak 行为新测试:3 FAIL trip / PASS clears / UNKNOWN soft-PASS / per-agent-type 隔离 / 12 PASS 触 total cap not streak - 9 个 parseVerdict 测试:empty / 标准 VERDICT 行 / FAIL 同义词 / APPROVE / 专家技能同义词 / 无 verdict / markdown 容忍 / 长 input tail - 验证子代理独立 PASS,含 8 个对抗性场景:5 PR PASS 序列、verifier loop 模拟、PASS 中断 streak、跨 type 隔离、真实子代理输出、UNKNOWN soft-PASS、orphan FAIL、12 PASS 后 total cap。 ## 设计审查 - **UNKNOWN 当 soft-PASS 的攻击面**:恶意子代理可省略 VERDICT 行避开 streak,但 total cap=12 仍兜底;且子代理 prompt 由调用方完全控制,不是普通输入面。 - **throw / abort 场景的 streak 状态**:`noteInvocation` 已增计数但 `noteOutcome` 不跑——streak 保持原值不偏移,下次调用基于既有 streak 起步,PASS 仍能清零。 - **接入点对称性**:`AgentTool.tsx` 中 `noteOutcome` 与 `noteInvocation` 用完全相同的 guard `(!toolUseContext.agentId && isBuiltInAgent(selectedAgent) && !isLimiterDisabled())`,避免 streak/total 计数不同步。 ## 范围 - `src/tools/AgentTool/invocationLimiter.ts`:核心改造,加 streak 状态、noteOutcome、parseVerdict、双门判定。 - `src/tools/AgentTool/AgentTool.tsx`:completed 分支加 `noteOutcome` 调用。 - `src/tools/AgentTool/invocationLimiter.test.ts`:14→28 测试。