| 落地 |
|---|
| apps/api/agent/tools.ts | 每个工具一份 META 常量(名称 / 中文标签 / 描述 / promptSnippet / 入参 schema / 输出形态说明),工具定义由它构造({...META, execute});execute 的实现不动 | ✅ ToolMeta / ToolParametersSchema 类型 + 5 份 META(NOTES_*_META ×3、WEB_SEARCH_META、SESSION_RENAME_META);output 必填;web_search 的 phases 键在 Record<WebSearchPhase, string> 上,websearch.ts 加阶段不补文案编译不过 |
| apps/api/agent/catalog.ts(新) | 只读端点,expose: true 且无需鉴权(与其它访客端点同口径),吐上述元信息 | ✅ GET /agent/tools;toolCatalog() 从三条构造路径派生分组;publicEntry 白名单序列化(只按名取字段,不 spread) |
| apps/api/agent/catalog.test.ts(新) | 元信息与工具定义一致性测试(见验收 #2)+ 响应不含配置值的断言(见验收 #3) | ✅ 12 个用例,对应验收 #2 / #3 / #6 |
| apps/web/components/workbench/ToolsPanel.tsx(新) | Tools 面板组件,逐画板对照 1f / 1g | ✅ 按后端 group 渲染,Record<ToolGroup, …> 让「后端多出第四组」变成前端编译错误;约束徽标(≤64 / 1–128)从 JSON Schema 边界关键字派生 |
| apps/web/components/workbench/Workbench.tsx | tab 数组加第 4 项 ["tools", "Tools"],面板分支接上 | ✅ PANEL_TABS 四项;空会话下 Tools 例外于「前三个 tab 都落到 Lifecycle 待命图」 |
| apps/web/lib/agent-api.ts | 类型与调用 | ✅ listTools() + 从生成物派生的 ToolCatalog / ToolGroup / ToolParamSchema 类型 |
| apps/web/lib/api-client.ts | dev.ps1 gen 重新生成(生成物,不手改) | ✅ 已重生成;仅按 BACKLOG R3 的先例把 app slug 噪音(936eu↔3vpi6)那两行还原 |
| docs/security.md | §1 第 1 层 R-TOOLS 补记(规则 9):公开的是能力说明,不公开的是配置面,两层落点 | ✅ |
| apps/api/agent/README.md | 端点清单 + 「工具元信息 META」一节(新增工具要动的两处) | ✅ |
| .claude/launch.json | 加 api 配置(浏览器验证工具起后端用,powershell -File dev.ps1);非产品代码 | ✅ |
端点不得吐(所有者裁定,ROUNDS.md R-TOOLS):execute 函数本体、ActiveWebSearchConfig 的任何字段 (baseUrl / key / model / provider)、dailySearchLimit 与当日用量、tool_config 的 enabled 状态。
要解决的是「每次发版顺便处理一下 Tools 面板的展示」这件事本身。光把端点写成「遍历注册表」不够 —— 画板 1f/1g 上有两样 pi 的 ToolDefinition 没有的东西(工具分组、输出形态说明), 它们才是会反复要人手工补的地方。三条一起才成立:
META 不许含配置值,这是结构性的而不是靠自觉:META 定义在闭包外面, makeWebSearchTool(cfg) 的 cfg 与 sessionRename(ctx) 的 ctx 在那个作用域里根本不存在。 今天没人往 description 里插「每日 N 次」,不代表明年没人插;放在闭包外面之后,插不进去。
已知的一个洞,要写进实现注释:派生只覆盖它认识的构造路径。今天是三条(两个注册表 + makeWebSearchTool), 将来有人加第四条构造路径且不进 META,派生法看不见它。验收 #2 的双向集合相等把这个洞收到 「加工具必经的两个地方」上 —— 见下。
| # | 检查 | 命令 / 期望 | 结果 |
|---|---|---|---|
| 1 | 右栏出现第 4 个 tab | 本机 dev.ps1 + npm run dev;tab 条四项,样式/间距/字号/选中态与前三个一致(规则 7:不新造 tab 样式) | ✅ 本机实测(空会话态与 Tools 选中态各一张截图,见「本轮实测」)。四个 tab 走同一段渲染代码(PANEL_TABS.map),tab 样式零新增 |
| 2 | 目录与实现双向对齐 | ①逐字段:测试从工具定义对象取 name/label/description/parameters 与端点吐的元信息比对,不一致即失败(不靠眼看);②集合相等:目录的 name 集合 == 两个注册表 + web_search 的并集,多一个少一个都失败;③穿过库的兜底:迁移里 tool_config 种下的每个名字都要有 META(新工具必经这两处,漏一处就红) | ✅ catalog.test.ts「目录与实现双向对齐」段:①对每条目录项按其 group 走真实构造路径取定义(TOOL_REGISTRY[name] / SESSION_TOOL_REGISTRY[name](ctx) / makeWebSearchTool(假 cfg))后 toEqual;②集合相等 + 无重名;③SELECT name FROM tool_config 逐名断言,且先断言表非空(空表不许空转通过) |
| 3 | 响应不泄配置面 | 对端点响应做 grep:不含 key / baseUrl / model / provider / 限额数字 / enabled;web_search 的条目在未配置时也不暴露配置缺失细节 | ✅ catalog.test.ts「响应不泄配置面」段:一份每个值独一无二的假配置(9 个值)逐一 grep 不到、16 个配置面字段名 grep 不到、会话 id grep 不到;每条字段集 ⊆ 8 个白名单键;web_search 在 websearch_config 为空时照样列出、没有 available/configured/enabled 字段,且与带配置构造出的定义逐字段相等 |
| 4 | 空会话下也有内容 | 新开一个未发消息的会话,切到 Tools 仍显示完整清单(它不依赖 events) | ✅ 本机实测:「未选择会话」态点 Tools,五条全在(截图) |
| 5 | 逐画板对照 | 列表态对 1f、展开态对 1g(展开 web_search,含四阶段进度说明);分组色 #6b7280 / #2563eb / #f9c22e | ✅ 列表态:三组分组头(色点 / 组名 / 组注)+ 卡片(等宽名 / 中文标签 / 组徽标 / 折叠箭头 / 单行省略描述)+ 三行脚注;展开态:全文描述 / INPUT(query string 必填 2–300 + 描述)/ OUTPUT 两行 / PROGRESS 发起 → 已受理 → 检索中 → 综述中 + tool_execution_update 注。色值三个都是设计稿的 |
| 6 | 5 个工具齐 | notes_list_series · notes_get_chapter · notes_search · web_search · session_rename,分三组 | ✅ 端点实测响应 5 条、pure ×3 / outbound ×1 / session ×1;测试钉住三组齐全与顺序 |
| 7 | 测试与类型 | dev.ps1 test 全绿;dev.ps1 gen 后 dev.ps1 check 通过,前端引用生成类型无 any 兜底 | ✅ dev.ps1 test:14 文件 291 用例全过(新增 catalog.test.ts 12 个);dev.ps1 gen → dev.ps1 check 通过;额外跑了 tsc --noEmit:apps/api 与 apps/web 都是 0 错误(门禁不跑 tsc,见 BACKLOG);前端类型全部从生成物派生,无 any |
默认继承两条:不改前端页面样式(规则 7);不加设计稿没有的功能(规则 8)。本轮另加:
目录是静态的:5 个工具全列。若 web_search 未配置或被 tool_config 关掉,面板仍会列出它—— 这与「不显示启停状态」是同一枚硬币的两面。若所有者认为「列了但用不了」比「泄配置面」更糟, 再单独裁定改口径。
第 1 轮(1 条 findings:0×P1 · 1×P2)
| # | 级别 | findings | 处置 |
|---|---|---|---|
| 1 | P2 | resultCharLimit 的契约不准确:capText 超限时保留全部 8000 字符正文再追加截断标注,实际返回文本长于端点与脚注宣称的「8000 字符上限」。建议二选一:在 capText 里给标注预留空间,或把这个值描述为正文预算而不是硬上限 | 采纳,按第二条(改描述)整改 |
整改内容与理由:
第 2 轮(零 findings):全量复审(分支对 main)。原文:「No actionable correctness, security, or compatibility defects were identified in the changes. The new catalog endpoint, generated client integration, and Tools panel are consistent with the repository's design and security constraints.」
同一验收项针对性整改后连续 2 次验证仍不过 → 写 rounds/round-tools/BLOCKED.md,停下呼人。禁止放宽验收标准自我通过。