外观
04 · approval/request 终局裁决管线
The Lone Adjudicator
这是整个插件的心脏。以下决策顺序与 index.ts:L"anyCtx.on('approval/request', async"(answerer 注册体;互斥器/askHuman/learnAttempt 等前置件自节注释 index.ts:L"approval/request answerer (returns an outcome" 起)逐行一致,红色 = 拒绝、蓝色 = 转人工/面板、绿色 = 放行。G0 判据是 durable raw identity(permissionState().preset),不是会被 approval override 折叠掉的 current()。
🟢 LOW 低风险
- 不送评审 → 直接 auto-allow 放行(记录
auto-allow) - 送评审 → 阻塞等 LLM 结论:ALLOW→放行(不清零熔断,只有人工决定清零);DENY→拒绝并计数;评审失败→拒绝不计熔断;ESCALATE→转人(带倒计时)
- ALLOW+CRITICAL → 不放行,转人(矛盾输出不信任)
🟡 MEDIUM 中等
- 弹面板 + 倒计时,并行跑 LLM 复审(fire-and-forget)
- 若属于
llmTakeoverScope或 unattended,且 LLM 给明确 ALLOW/DENY(非 CRITICAL-ALLOW)→handle.claim抢占竞速,立即按 LLM 结论结案(source=llm-*) - 否则 LLM 结论只是建议(
🤖 Review suggestion刷新在面板上),最终听人/超时/接管
🔴 HIGH 高危
- 弹面板 + 倒计时(10s 默认)
- LLM 复审永远只当建议(
🤖 Review suggestion),绝不接管 - unattended 模式下 HIGH 超时强制转人/失败关闭,方向正确性不让步
askHuman 内部做了同一件事
(index.ts:LaskHuman):把状态写进 reviewStates(客户端轮询用)→ 组装 notes(评审建议 / 「⚠️ Breaker」原因列表 / 「⏳ will auto-X in Ns」)→ 追加到 req.reason → 走 raceHumanDecision(§07)→ 计算诚实来源(approvalSource)→ applyBreaker 更新熔断 → pushHistory 落盘 → 学习层记账(human-allow 计数、human-deny 清零,见 §18)。任何一环抛错(会话销毁/请求取消)→ 标记 abort、清残留、rethrow —— 绝不伪造裁决。
类别层有第二个接线点
tools/pre-execute 侧另有一段独立的类别收紧(index.ts:L"Category tightening"):只做收紧(deny 终端拒 + ask 跳过分类器快径),不产放行。它与 answerer 侧两个接点各自从零重算类别与指令,无任何状态跨越(categoryDirectiveFor 注释明言,category.ts:LcategoryDirectiveFor)——一次调用被两层检查,但不存在「上层记住下层结论」的耦合。