test(base): 造只读探针端到端验证工具拒绝,并修掉它暴露的一个死分支
**为什么造探针**:ToolExecutor 的四种拒绝在真实链路上很难安全触发——要么改客服、风控的
生效配置,要么动 RBAC,两条路都会影响正在工作的 Agent。platform_probe 是个只读、无副作用
的探针:它只声明 probe 一个意图(所以意图分类只可能返回它)、没有发布工具白名单
(天然处于"未配置"状态)、工具只回显参数不碰业务数据。
**它立刻查出一个死分支**:探针报的是「工具不在当前意图白名单」,而不是我新加的
「该意图未配置工具白名单」。原因是 governance.resolve 会为每个 supported_intents
**预填条目**(governance.py:55-61),未配置时得到的是**空元组**——所以
intent not in configured_tools 在运行期**永远不成立**,那个分支是死代码。
单元测试没能发现它,因为我在测试里手工构造了 configured={},而真实链路不产生这个形状。
**这正是端到端测试的价值**:单元测试验证的是我设想的形状,端到端验证的是真实形状。
修法:改判"白名单为空"而非"缺键",文案改为"该意图的工具白名单为空",并注明经过 governance
装配后"完全没配"与"配了空列表"无法区分、也不假装能区分(两者运维动作相同)。新增一条按
**真实形状**({"faq": ()})构造的用例把它锁住。
实测:探针调用 → failed / AGENT_PERMISSION_DENIED,stderr 为
ForbiddenAgentError: 该意图未配置工具白名单(tool_executor.py:108)。
ruff / mypy(136 文件) / 611 unit+contract 全绿。
This commit is contained in:
@@ -124,5 +124,22 @@ async def test_audit_names_what_to_fix_when_config_is_absent() -> None:
|
||||
await _reject(executor, _context(permissions=(PERMISSION,)), intent="faq", configured={})
|
||||
|
||||
detail = str(audits[0][3])
|
||||
assert "没有任何工具白名单" in detail
|
||||
assert "工具白名单为空" in detail
|
||||
assert "faq" in detail
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_empty_whitelist_is_what_the_real_pipeline_produces() -> None:
|
||||
"""真实链路里拿到的是**空元组**,而不是"缺键"。
|
||||
|
||||
`governance.resolve` 会为每个 `supported_intents` 预填条目(governance.py:55-61),
|
||||
所以 `intent not in configured_tools` 这个判断在运行期**永远不成立** —— 第一版就是
|
||||
那么写的,而这条用例原先用 `configured={}` 手工构造,把它掩盖了,直到端到端跑
|
||||
探针 Agent 才暴露出来。现在按真实形状构造。
|
||||
"""
|
||||
executor, _ = _executor()
|
||||
context = _context(permissions=(PERMISSION,))
|
||||
|
||||
message = await _reject(executor, context, intent="faq", configured={"faq": ()})
|
||||
|
||||
assert "未配置" in message
|
||||
|
||||
Reference in New Issue
Block a user