boardx / boardx/workspacex

分级表说 write_todos 是 L0,运行时却弹 L2 高风险框——反向门控在这条路径上不生效

Open
#3,404 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
0
Forks
0
Avg merge
1h 7m
Merged PRs (30d)
969

Description

## 分级表说 L0,运行时却弹 L2 高风险框

**实测(手册逐条实跑线,真栈 + 真实 DashScope,实测 SHA `551c8e97f`)**:

发「调研全球电动汽车市场,写一份三千字详细报告」⇒ 弹出:

```
⚠ agent 请求执行一个高风险操作 [L2 · 高风险]
该操作被运行时判定为高风险,可能产生不可逆或外部可见的影响。
具体命令:write_todos(更新待办清单)
```

**而分级表里它是 L0**(`origin/main` 逐字):

```ts
// apps/api/src/domain/agent-run/tool-risk-tier.ts:38
"read_file", "grep", "fetch_url", "list_org_skills", "glob", "ls", "write_todos",
```

同文件 L0 档的注释还专门记着这段历史:

> ⚠ 这段注释曾经**只是注释**:`write_todos` 从引入这条注释的 `5571b867f` 起就从没进过下面的集合,于是落进末尾的默认 L2 —— 每记一次待办弹一次审批框。它还连续误导了两个 agent 的排查(#3132 / #3186)。

**`551c8e97f` 已包含 #3305(分级表补全 + 反向门控)与 #3194。** 所以这不是「旧代码」,是**表与运行时行为分叉**。

## 这是第十三例「同一事实声明在两处」

判据在分级表,**实际放行/拦截的判定在别处**。#3305 的盘点已经点出过一条候选通路:

> `pg-native-session-owner.ts:37` 把 MCP snapshot 的**每个**工具并进准入表且**一律 `interruptOn=true`**,数量不可静态枚举。

⇒ **首要嫌疑(需实测确认,不要直接采信)**:`write_todos` 经由某条**绕过 `classifyToolRisk`** 的通路进入准入表,因而被无条件标成需中断。

其它需排除的可能:deep-agent-service 侧自带的中断配置;`interrupt_on` 在图构建期被另一处覆盖。

## 为什么必须修

- 用户侧:**一个纯内部的规划记账动作,被包装成「不可逆或外部可见」的吓人确认框**。这正是人类反复抱怨的「每个问题都要我确认」的来源之一,而 #3305 本以为已经把它降到 21/45。
- 门控侧:**#3305 新加的反向门控(每个工具必须显式分级,落兜底即红)在这条路径上不生效**——门是绿的,行为是错的。这比缺陷本身更值得修。

## 要求

- **先查清放行/拦截判定的真实通路**(从真实链路取证,不要从代码结构推断):一次 `write_todos` 中断,`interrupt_on` 是谁写的、`classifyToolRisk` 有没有被调用。
- **修法必须收敛**:让「工具的风险档」只有一处权威声明,所有准入判定都读它。**不要在第二处加特判把 `write_todos` 排除掉**——本仓头号病已十二例,这是第十三例。
- **加一条会红的断言**守住「分级表说 L0 的工具,运行时不得触发 L2 审批」。**注意 #3305 的反向门控是静态的、在这条路径上没生效**——新断言必须走**真实中断链路**,否则又是一道绿着的假门。
- **三步反证**:造出缺陷形状(让某条通路绕过分级表)→ 断言变红并贴真实输出 → 撤掉 → 恢复绿。**只贴绿不算数**(本仓已九次「全绿但空转」)。

## 相关

#3305(分级表补全与反向门控)、#3194 / #3186 / #3132(同一工具此前三次误判的历史)、#3221(授权按工具名记而风险按 skill 名判——另一处粒度错配)、#3402(权限模式选择器设计,其中明确 `Accept edits` 是空档,因为 L1 本就自动执行)。

Contributor guide

No contributing guide indexed for this repository

Research direction

Reproduce the write_todos approval at SHA 551c8e97f, then trace the real interrupt path through apps/api/src/domain/agent-run/tool-risk-tier.ts and pg-native-session-owner.ts, checking whether classifyToolRisk is called and where interrupt_on is set or overridden. Add a regression test that exercises the real interruption chain and proves an L0 tool does not trigger L2 approval; validate it with the requested red, then green, counterexample.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend, security, testing-qa
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.