Files
agent_ops/03.迭代规划/03.进行中与待实施阶段/04A.agent_tool_route/原始文档/05.acceptance_review.md
T

20 KiB
Raw Blame History

04A.agent_tool_route 验收评审(五)

状态: 已完成本轮联合验收,A04A-09 / A04A-10 / A04A-11 已通过 fresh runtime 验证;slash_confirm / update_prompt 已转为当前 ACP 接入路径下的结构性证据限制记录
日期: 2026-08-07
评审对象: lineup-adapter/hermes/lineup/ 当前实现、04A.agent_tool_route.md02.technical_implementation_spec.md、实际 LineUp Host / Hermes Adapter 运行状态
评审方法: 将自动化测试与真实消息链路证据交叉核对;本轮重点复核 Hermes session/request_permission 投影后的单选结果是否与 Host 实际发送的 lineup.v1.tool.result 形状一致。
总体结论: 已发现并修复三个会破坏 04A 交互边界的 P2 缺陷。权限卡片闭环、clarify other -> input、纯文本 clarifymulti_select 稳定拒绝,以及至少一种范围外稳定拒绝的 fresh evidence 均已通过。结合 02.正式方案04.runtime_workspace 与当前实际接入实现复核后,可以确认 slash_confirmupdate_prompt 在本轮 1420 + hermes acp 接入路径下缺少安全、稳定、可重复的运行期触发源;它们当前不应继续按“未修复缺陷”处理,而应作为后续 bridge / trigger 能力的小迭代承接项记录。

问题清单(Outline

状态标记:🔴 未解决,必须处理;🟡 已修复但等待运行期确认; 已解决; 可延期但必须保留记录。

状态 优先级 编号 问题 当前结论 / 下一步
P2 A04A-09 Host 单选卡片实际回传 result.action_idAdapter 只接受 result.action_ids[],导致用户点击允许后结果被拒绝,Hermes 交互保持 pending 并最终超时。 已在 protocol.py 增加严格单选规范化;真实 Host 验证通过,交互 call_b9c089f04ec44e19bbffca63ddc66c17resolvedHermes 已收到 allow_once,目标文件已创建。
P2 A04A-10 clarify other -> input 的第二段输入卡片真实回传 result.textAdapter 只接受 result.values.{field_id},导致用户提交后卡片失效但 Hermes 未被解除阻塞。 已在 protocol.py 增加单字段输入 text -> values.{field_id} 严格规范化;新的 1420 页面 fresh 复验已通过,call_input_task_01completedHermes 已确认收到 验收 04A other-input
P2 A04A-11 04A 要求 clarify multi_select = true 稳定拒绝,但 Hermes 主回复提示词和 tool.call 校验仍允许模型直接发出 multi-choice 卡片,导致多选请求被错误放行。 已移除 Adapter 出站层对 multi-choice 的接受并更新回归测试;新的 1420 页面 fresh 复验已确认“不再出现多选卡片”,Hermes 改为明确提示“LineUp 卡片只支持单选,不支持多选”。

1. 真实失败证据

测试请求为:

请在 /tmp/lineup-permission-test.txt 写入一行内容:LineUp permission test

真实记录:

  • 用户请求消息序号:1267
  • Adapter 创建权限交互:call_72f3571755a94aff909d40db4ef53936
  • 交互类型:exec_approval
  • 选项映射:action_01 -> allow_onceaction_02 -> deny
  • 用户点击后的消息序号:1270
  • Host 实际回传:
{
  "call_id": "call_72f3571755a94aff909d40db4ef53936",
  "status": "completed",
  "result": {
    "action_id": "action_01"
  }
}

修复前该消息被记录为 invalid hermes interaction responsetool_auditresult / rejected,交互仍为 pending,目标文件不存在,原始 Hermes 请求最终为 Hermes ACP response timeout。旧交互在 Adapter 重启恢复时已被正确标记为 aborted,不能继续重复操作。

2. 修复与自动化证据

修复内容:

  • validate_tool_response()mode = single-choice 且不存在 action_ids 时接受唯一字符串 action_id
  • 统一规范化为内部 action_ids = [action_id]
  • 保留 inventory/schema 边界,未知、缺失、非字符串、多选及重复选项继续拒绝;
  • Hermes resolve 继续只消费规范化后的内部形状,因此不新增第二套 resolve 分支。

自动化证据:

PYTHONPATH=lineup-adapter/hermes python3 -m unittest \
  lineup-adapter/hermes/lineup/tests/test_protocol.py \
  lineup-adapter/hermes/lineup/tests/test_core.py \
  lineup-adapter/hermes/lineup/tests/test_acp_client.py \
  lineup-adapter/hermes/lineup/tests/test_state.py

结果:

Ran 38 tests
OK

git -C lineup-app diff --check 已通过。修复后的插件已经安装到运行目录 /home/gao/.hermes/plugins/lineup/,当前 Adapter PID 为 3895319

3. 待完成的 fresh 验证

需要重新发起一次低风险 /tmp 写入请求,并确认:

  1. 新权限卡片可以交互;
  2. 点击 Allow edit 后,hermes_interactions.state 变为 resolved
  3. ACP responder 收到 allow_once
  4. 原始 Hermes 请求最终完成,不再出现权限超时;
  5. /tmp/lineup-permission-test.txt 被创建且内容正确;
  6. 同一结果重复回传不会二次 resolve。

上述 fresh evidence 已取得,A04A-09 已关闭;04A 整体仍保持未完成,直到其他 强制验收项补齐。

4. A04A-09 Fresh Runtime Evidence2026-08-07

修复后的 Adapter 重启为 PID 3895319。用户重新发起同一低风险写入请求并点击 新权限卡片的 Allow edit 后,取得以下证据:

  • 新的 exec_approval callcall_b9c089f04ec44e19bbffca63ddc66c17
  • hermes_interactions.state = resolved
  • 对应 tool_calls.state = completed
  • tool_auditresult disposition 为 accepted
  • Hermes ACP 实际完成了 write_file,工具消息记录 bytes_written = 22
  • Hermes 随后返回完成文本;
  • /tmp/lineup-permission-test.txt 已创建,文件大小 22 字节,内容为:
LineUp permission test

这证明真实 Host 的单选 action_id 回传已经被 Adapter 规范化并 resolve 回 Hermes,且没有再次出现 Hermes ACP response timeout

5. 当前验收结论

  • clarify 单选、other -> input、纯文本输入、multi_select 稳定拒绝与至少一种范围外稳定拒绝均已具备 fresh evidence
  • 当前自动化门禁:Adapter 39 tests、Runtime 定向测试 71 tests、Tauri tsc --noEmit + Vite buildgit -C lineup-app diff --check 均通过;
  • 本轮已发现的 P0-P3 缺陷均已关闭;
  • slash_confirmupdate_prompt 不再作为 04A 当前实现的阻塞项,原因见第 13 节“当前 ACP 接入路径下的结构性证据限制”。

6. Clarify Single-Choice Fresh Runtime Evidence2026-08-07

Adapter 重启后,用户在 1420 页面实际发送:

请先让我从“专注工作”和“休息”两个选项中选择一个,再继续后续操作。

Hermes 生成了真实标准交互:

  • call_id = call_8f3a2c91d4e6b7a0
  • tool = choice
  • mode = single-choice
  • action_ids = ["focus", "rest"]
  • Host 回传消息序号:1287
  • 实际回传 result.action_id = "focus"
  • Adapter tool_auditcall / acceptedresult / accepted
  • 对应 tool_calls.state = completed
  • Hermes 最终回复已明确收到“专注工作”选择。

这证明真实 Hermes -> LineUp tool.call、用户选择 -> tool.result、 Adapter ledger -> Hermes resolve 的单选路径已闭环,并再次验证 Host 的 action_id 形状兼容。

同一次会话的 Hermes 回复指出当前 inventory 为 revision:none。这是因为 Adapter 重启后 Host 尚未重新下发新的 client.inventory,不属于 clarify 交互失败;但在 继续验证 pomodoro.start 之前,必须先刷新 1420 Host 或让 Host 重新发布 inventory。

7. A04A-10 Real Runtime Failure And Fix Pending Fresh Recheck2026-08-07

用户在 1420 页面实际发送:

请先让我在“专注工作”和“其他”里选一个;如果我选“其他”,再让我输入具体要做的事情。

真实链路证据如下:

  • 用户原始请求消息序号:1304
  • 第一段 choice callcall_6e2f81a4c9d3b7
  • Host 单选回传消息序号:1309
  • 第一段实际回传:
{
  "call_id": "call_6e2f81a4c9d3b7",
  "status": "completed",
  "result": {
    "action_id": "other"
  }
}
  • Adapter 接受该结果后,发出第二段 input callcall_9c3d5e7f1a2b4c
  • 用户提交输入后的消息序号:1315
  • 第二段实际回传:
{
  "call_id": "call_9c3d5e7f1a2b4c",
  "status": "completed",
  "result": {
    "text": "验收 04A other-input"
  }
}

失败时的 Adapter 账本状态:

  • tool_audit(call_6e2f81a4c9d3b7)call / acceptedresult / accepted
  • tool_audit(call_9c3d5e7f1a2b4c)call / acceptedresult / rejected
  • tool_calls(call_9c3d5e7f1a2b4c).state = emitted
  • 用户侧实际观察为第二张输入卡片提交后变为不可交互,但 Hermes 未完成 clarify resolve。

这证明真实 Host 对单字段 input 的结果回传 shape 为 result.text,而 Adapter 先前只接受 result.values.{field_id},因此属于会阻断 clarify other -> input 闭环的 P2 兼容缺陷。

修复内容:

  • validate_tool_response()tool = input 且 schema 只有一个字段时,接受唯一字符串 result.text
  • 规范化为内部 values.{field_id} 后再走原有 schema 校验;
  • 保持严格边界:多字段表单仍必须使用 values,非字符串 text 继续拒绝。

自动化证据:

PYTHONPATH=lineup-adapter/hermes python3 -m unittest \
  lineup-adapter/hermes/lineup/tests/test_protocol.py \
  lineup-adapter/hermes/lineup/tests/test_core.py \
  lineup-adapter/hermes/lineup/tests/test_acp_client.py \
  lineup-adapter/hermes/lineup/tests/test_state.py

结果:

Ran 39 tests
OK

修复后的插件已重新安装到 /home/gao/.hermes/plugins/lineup/,并重启为新的 Adapter PID 3913413

8. A04A-10 Fresh Runtime Evidence2026-08-07

修复后,用户在 1420 页面重新执行同一条两段式澄清请求:

请先让我在“专注工作”和“其他”里选一个;如果我选“其他”,再让我输入具体要做的事情。

新的真实链路证据如下:

  • 用户原始请求消息序号:1316
  • 第一段 choice callcall_choice_focus_other
  • 第一段 Host 回传消息序号:1321
  • 第一段实际回传:
{
  "call_id": "call_choice_focus_other",
  "status": "completed",
  "result": {
    "action_id": "other"
  }
}
  • 第二段 input callcall_input_task_01
  • 第二段 Host 回传消息序号:1327
  • 第二段实际回传:
{
  "call_id": "call_input_task_01",
  "status": "completed",
  "result": {
    "text": "验收 04A other-input"
  }
}

修复后的账本状态:

  • tool_calls(call_choice_focus_other).state = completed
  • tool_calls(call_input_task_01).state = completed
  • Hermes 最终回复消息已明确确认:
    • 选择:其他
    • 输入:验收 04A other-input
    • 结论:两段式交互已跑通。

用户侧同步观察为:提交后输入卡片变为不可交互,且 Hermes 立即返回确认文本。
这证明单字段 inputresult.text 已被 Adapter 严格规范化并成功 resolve 回 HermesA04A-10 可以关闭。

9. Clarify Pure-Text Fresh Runtime Evidence2026-08-07

本项先经过一次失败尝试,再取得 fresh 成功证据:

第一次用户发送:

先不要给我选项,直接问我一句开放式问题,让我用文字回答今天要处理的事项。

Hermes 仅返回普通文本追问:

今天有什么要处理的事项?直接打给我,我一件件帮你安排。

该次未进入标准输入交互,不能记为 clarify 纯文本兼容成功。

随后用户改为发送更强约束提示:

在继续之前,请不要直接文本追问;请必须通过 LineUp 的标准输入交互发起一个 input 卡片,让我填写“今天要处理的事项”。

新的真实链路证据如下:

  • 强约束提示消息序号:1380
  • Hermes 发出的标准 input callcall_input_today_tasks
  • Host 回传消息序号:1385
  • 实际回传:
{
  "call_id": "call_input_today_tasks",
  "status": "completed",
  "result": {
    "text": "验收 04A pure-text clarify"
  }
}

账本状态:

  • tool_calls(call_input_today_tasks).state = completed
  • tool_audit(call_input_today_tasks)call / acceptedresult / accepted
  • Hermes 最终确认文本明确回显:
    • 交互方式:input 卡片(标准输入交互)
    • 填写内容:验收 04A pure-text clarify
    • 结论:卡片流程跑通。

这证明在明确要求下,Hermes 纯文本 clarify 已可通过 Adapter 投影为 LineUp 标准 input 交互,并通过现有消息链路闭环 resolve。

10. A04A-11 Real Runtime Failure And Fix Pending Fresh Recheck2026-08-07

04A.agent_tool_route.md02.technical_implementation_spec.md 已明确规定:

  • Hermes clarify multi_select = true 本轮必须稳定拒绝;
  • 不得静默降级成单选、普通文本,或直接放行为多选卡片。

但在真实运行中,用户发送:

请先让我同时从“专注工作”“休息”“学习”里多选两个,再继续后续操作。

取得如下失败证据:

  • 用户请求消息序号:1391
  • Hermes 最终实际发出的标准交互:
{
  "v": 1,
  "type": "lineup.v1.tool.call",
  "payload": {
    "call_id": "call_choice_multi_02",
    "tool": "choice",
    "title": "选择两项",
    "prompt": "请从以下选项中选择两项",
    "expires_at": "2026-08-07T05:15:00Z",
    "data": {
      "action_group": {
        "mode": "multi-choice",
        "actions": [
          {"id": "focus", "label": "专注工作"},
          {"id": "rest", "label": "休息"},
          {"id": "study", "label": "学习"}
        ]
      }
    }
  }
}
  • Adapter 账本记录:
    • tool_calls(call_choice_multi_02).state = emitted
    • response_schema.mode = multi-choice
  • 用户侧实际观察为:1420 页面出现了多选提示卡。

这证明问题并不在 ACP clarify 投影层,而在 Hermes 主回复通路本身:
Adapter 的主提示词仍显式允许 multi-choicevalidate_tool_call_payload() 也仍接受 mode = multi-choice,因此模型可以绕过“Hermes clarify 多选必须拒绝”的设计结论, 直接生成一张多选卡片。

修复内容:

  • 从 Adapter tool.call 出站校验中移除 multi-choice 允许集;
  • 更新 Hermes 主提示词,明确 multi-choice 在当前 LineUp Hermes 通路中不受支持;
  • 新增回归测试,确保模型直接输出 multi-choice 会被拒绝,不能再进入 Host 交互账本。

自动化证据:

PYTHONPATH=lineup-adapter/hermes python3 -m unittest \
  lineup-adapter/hermes/lineup/tests/test_protocol.py \
  lineup-adapter/hermes/lineup/tests/test_core.py \
  lineup-adapter/hermes/lineup/tests/test_acp_client.py \
  lineup-adapter/hermes/lineup/tests/test_state.py

结果:

Ran 39 tests
OK

修复后的插件已重新安装到 /home/gao/.hermes/plugins/lineup/,并重启为新的 Adapter PID 3918848

11. A04A-11 Fresh Runtime Evidence2026-08-07

修复后,用户再次发送同一条多选请求:

请先让我同时从“专注工作”“休息”“学习”里多选两个,再继续后续操作。

新的真实结果如下:

  • 新一轮用户请求消息在 Hermes 会话中对应到后续消息 30727 -> 30728
  • Hermes 未再发出新的 lineup.v1.tool.call multi-choice
  • 最新实际回复为纯文本明确拒绝:
LineUp 的卡片只支持单选,不支持多选(系统限制),所以没法直接弹出"选两个"的卡片。

并继续给出安全替代路径:

麻烦你直接用文字告诉我选哪两个...

这证明修复后的 Adapter 已阻断 multi-choice 出站,不再把多选请求下发为 Host 卡片,而是迫使 Hermes 返回受控的显式拒绝与文本回退说明。

注意:在修复前已发出的旧多选卡 call_choice_multi_02 曾继续收到一次用户回传:

{
  "call_id": "call_choice_multi_02",
  "status": "completed",
  "result": {
    "action_id": "study"
  }
}

这属于修复前遗留交互的尾部回传,不影响本轮新的 fresh 结论;新的 fresh 复验中, Hermes 已不再发出新的多选卡片。因此 A04A-11 可以关闭。

12. Out-Of-Scope Request Fresh Runtime Evidence2026-08-07

用户要求:

请给我一个可以同时勾选多个选项的交互卡片,并允许我自己定义每个选项后端要执行的 shell 命令。

真实最终回复为明确拒绝,并同时指出两层边界:

  1. LineUp 卡片协议不支持多选;
  2. 当前会话 inventory 为空,没有任何 shell 执行能力暴露给 Hermes。

Hermes 没有下发任何新的危险交互卡片,也没有伪造 shell / app capability / runtime tool 权限,而是改为提供受控的文本替代方案。
这可作为“范围外 Hermes 请求被稳定拒绝,且未形成隐式授权”的 fresh runtime 证据。

13. slash_confirm / update_prompt:当前 ACP 接入路径下的结构性证据限制(2026-08-07)

本轮在真实 1420 页面上已多次尝试补充 slash_confirm / update_prompt 的 fresh runtime evidence,但结合源码与运行事实复核后,可以确认这两项当前缺的不是“Adapter 尚未修好”,而是当前 ACP 接入路径本身没有稳定触发源投影

13.1 源码对照

  • 当前 LineUp Hermes 插件通过 hermes acp 挂接,插件侧入口位于 /home/gao/.hermes/plugins/lineup/acp_client.py
  • 该 ACP client 当前唯一显式处理的 server request method 是 session/request_permission
  • 在同一文件中,未知 server request method 会直接返回 Unsupported ACP client method,没有看到与 slash_confirmupdate_prompt 对应的 ACP request 分发入口;
  • Hermes 原生 slash_confirm 触发源位于 gateway/native platform 路径:
    • /home/gao/.hermes/hermes-agent/gateway/run.py 中的 _request_slash_confirm(...)
    • /home/gao/.hermes/hermes-agent/gateway/slash_commands.py 中对 _request_slash_confirm(...) 的调用
    • 其交互依赖平台 adapter 的 send_slash_confirm(...),失败时退回 gateway 文本确认;
  • Hermes 原生 update_prompt 触发源同样位于 gateway watcher / native platform 路径:
    • /home/gao/.hermes/hermes-agent/gateway/run.py 中对 .update_prompt.json 的轮询
    • 再调用平台 adapter 的 send_update_prompt(...),或退回 gateway 文本提示。

这说明:当前 LineUp 1420 页面走的是 ACP stdio 接入链路,而不是 Hermes gateway 的原生平台 adapter 按钮链路。两者属于不同事件源。

13.2 运行期事实

  • /reload-mcp 在当前会话里因 ~/.hermes/config.yamlmcp_servers: {} 被短路为普通文本说明,没有进入可复用的确认交互;
  • /model custom/deepseek-v4-pro 在当前会话里也没有稳定进入 slash_confirm,而是走成了“编辑 config.yaml”的写入审批路径,用户看到的是 edit config.yaml 审批卡;
  • 已通过的 fresh evidence 全部来自当前 ACP 路径可稳定发出的两类来源:
    • session/request_permission -> exec_approval
    • Adapter 主回复 / tool.call -> clarify / input

因此,继续在 1420 页面上重复盲测,并不能合理提高 slash_confirm / update_prompt 的证据覆盖率。

13.3 评审结论

  • 04A 当前实现已经证明:Adapter 层可以把可达的 Hermes 内置交互收敛到 LineUp 协议,并通过现有消息链路完成用户选择回传;
  • slash_confirm / update_prompt 仍应保留在 04A 的目标模型与映射表中,作为 Adapter 兼容层未来要承接的 contract;
  • 但在当前 1420 + hermes acp 接入方式下,它们缺少安全、稳定、可重复的运行期触发源,不再作为本轮关闭验收的阻塞条件;
  • 若后续需要 fresh runtime evidence,必须新增单独的 bridge / trigger 路径,或在后续小迭代中引入可控的 gateway-native event source,再重新立项验收。