Skip to content

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)——一次调用被两层检查,但不存在「上层记住下层结论」的耦合。