Repository navigation
docs(tools): align tool descriptions and prompts with behavior - #41
Conversation
|
Thanks @asto18089 for taking the time to contribute. This repository is observing a maintainer-managed PR intake gate in dry-run mode, so this pull request is staying open. This note helps maintainers prepare the allowlist before any enforcement is considered. Please read |
f853f8f to
ff299f9
Compare
Model-facing doc audit fixes across tui tools and prompts: stop advertising retired tool names (run_verifiers, exec_shell, fetch_url, web_search) in model-visible descriptions and extend the retired-name guard registry; fix web screenshot semantics (PDF-only, text output) and the search backend chain description; document shell background timeout limits, terminal buffer/timeout semantics, workflow pipeline signature and plan gates; declare required send_later message, github dirty-worktree refusal, gitignore asymmetry, and OCR format limits; add missing agent schema keys (allowed_tools), fix scout output contract and sentinel teaching, note translation rule precedence, skip the authority recap when a static composer owns the prompt, and add locale override setters for embedders. Signed-off-by: Pinvou Agent Review <review@pinvou.local>
f57253d to
86b5382
Compare
Review of the description-accuracy pass found several fixes that were themselves inaccurate or out of scope: - Revert the advertised agent schema expansion (allowed_tools/ disallowed_tools): the 12-field surface is a pinned decision (codewhale-hq#5324, codewhale-hq#5123); the two keys stay parse-accepted but unadvertised, and the schema guard test holds. - Keep the scout CHANGES cleanup but restore the pinned "compressed evidence" wording its test asserts. - goal: drop the fabricated "three identical gap sets auto-pause (no_progress)" claim — NoProgress is never constructed; repeated gap sets only increment repeated_gap_count in the snapshot. Align the create_goal description with the corrected error message: agents cannot clear goals; only the user/host can. - send_later: keep required = ["action"]; message is required only for action=schedule, now stated in prose. - task_shell_start: timeout_ms is accepted but not enforced (the task always starts in the background); drop the fictitious foreground wait. - gate_run: dangerous-command blocking only applies without auto-approve. - github: surface the dirty-worktree refusal on the model-visible github description and the canonical allow_dirty schema field, not only on hidden alias descriptions. - engine: scrub retired exec_shell/fetch_url names from the registry-first instruction. - workflow fleet: name the real rejected override fields (model_strength, subagent_type). - search: drop the unverifiable "faster" claim; file_search keeps the workspace scope wording. - prompts: reference the literal ## Language heading; add the missing set_authority_recap_override; web_run ref_id wording; stale comments in text.rs/plan.rs/image_ocr.rs. Signed-off-by: Pinvou Agent Review <review@pinvou.local>
全新视角复审(head
|
Fresh review of this PR found residual inaccuracies: - goal: render_continuation_prompt still taught the fabricated "repeated equivalent gap sets pause the loop" claim that the second commit removed from the update_goal gaps schema (NoProgress is never constructed; the only automatic pause is the continuation run limit). Reword to the snapshot-counter fact and pin it with a test. - tasks: the task_shell_start timeout_ms description now names the stop path (the Bash tool's action=cancel with the returned task id) instead of a bare "action=cancel". - tasks: the pr_attempt_record arm states its approval requirement, and the pr_attempt_preflight arm no longer claims approval lives "elsewhere" (preflight is approval-required). Alias-reachable arms only; text alignment. - web_search: add duckduckgo to the [search] provider enumeration to match the config enum. Signed-off-by: Pinvou Agent Review <review@pinvou.local>
h3c-hexin
left a comment
There was a problem hiding this comment.
正式评审:Request changes
评审基于精确 head 08c9902f43f5ac9089b27a282c09ff3b590ec6d4,相对 r1 基线 1fafee7e26b60a59457a43bce50c63aa2ad9dbaf。
Major(阻塞):新文案再次向模型教授了隐藏兼容工具,而不是实际发布的工具目录
新会话的工具目录由 ToolRegistry::build_api_tools() 过滤 model_visible() 后生成。当前实现和既有测试明确规定:
- 新会话发布的是小写
bash;BashTool("Bash")仅用于旧 transcript 回放,model_visible=false。 - 新会话发布的是独立的
read/write/edit;Fileaction family 同样是隐藏兼容接口。canonical_runtime_tools_hide_compatibility_aliases还明确断言File必须不出现在新模型目录。
但本 PR 新增/改写的模型可见内容仍使用这些隐藏名字:
crates/tui/src/tools/apply_patch.rs:322:patch` in `Bash、Fileedit``crates/tui/src/tools/file_search.rs:43:fd` in `Bashcrates/tui/src/tools/search.rs:59:rg` ... in `Bashcrates/tui/src/tools/mcp_registry.rs:886:through Bashcrates/tui/src/core/engine.rs:149:运行时注入指令中的Bash
内部 resolver 的 ASCII 大小写兼容,只能保证旧名字在被构造出来后仍可分发;它不会把隐藏工具的 schema 发布给模型。尤其 File { action: "edit" } 的 action-family schema 已不在新目录中。因此这里不是单纯的大小写风格问题,而是“提示文本所教接口”与“模型实际获得的接口”不一致,正好属于本 PR 试图修复的漂移类型。
现有 no_advertised_tool_teaches_a_retired_name 仍会通过,是因为它只枚举了完全退役的名字,没有覆盖“仍可回放但不得向新模型广告”的 Bash / File;运行时注入的 registry-first 指令也不在该目录扫描范围内。
请在本 PR 内:
- 把上述新文案改为目录中的精确接口名(例如
bash、独立的edit); - 扩展守卫,阻止模型可见 description/schema 教授隐藏兼容名;
- 为 registry-first 运行时指令增加对应断言,避免目录外提示再次漂移。
非阻塞集成提醒
本 PR 新增的 9 个 locale/authority override setter 当前在 CodeWhale 与父仓均尚无消费方。接受“底座先提供接口、父仓 r2 随后接线”的依赖顺序,但父仓后续必须完成接线并刷新 prompt fingerprint;建议在 PR 正文链接该消费 PR,避免接口长期悬空。
本地验证
cargo fmt --all -- --check:通过forkguard_:31 passedprompts::tests:::102 passedtools::goal:::27 passedtools::tasks:::11 passedno_advertised_tool_teaches_a_retired_name:1 passed(同时证明当前守卫漏检的是隐藏兼容名,而非完全退役名)git diff --check:通过
Round-3 review blocked on model-visible copy still teaching hidden compatibility tool names instead of the published catalog (new sessions advertise lowercase bash and the independent read/write/edit; the uppercase Bash/File families are model_visible=false replay aliases): - apply_patch, file_search, grep_files, and registry_search descriptions now cite bash / the independent edit tool instead of Bash / File edit. - The engine's Registry-first runtime instruction cites bash; pinned by new registry_first_instruction_only_names_published_tools. - no_advertised_tool_teaches_a_retired_name also scans for the hidden compat names (whole-token match so prose never trips), and its registry grows to the shell, task, skill, pandoc, media, harness, and misc surfaces. The wider scan caught six further offenders: handle_read, load_skill, the loaded-skill companion-file blurb, pandoc, and the task_shell_start/task_shell_wait schemas. - task_shell_start's timeout_ms no longer points at the replay-only Bash action=cancel path (the published bash rejects action); it states that a running shell task cannot be cancelled model-side. - Locale preambles cite bash/Web as the keep-verbatim tool-name examples; the zh pinning test now enforces the published names. - grep_files' context_lines fact reworded to fit the File schema byte budget the longer wording broke (3136 > 3100 since the first commit; now 3098), so schema_stays_within_its_catalog_byte_budget is green again. Signed-off-by: Pinvou Agent Review <review@pinvou.local>
R4 处理报告(head
|
| 位置 | 原文案 | 修复 |
|---|---|---|
handle_read description |
File action="read" for workspace files |
the \read` tool for workspace files` |
load_skill description |
File action="read" plus File action="list" |
separate read and list calls |
| 已加载 skill 的 companion-file 引导(模型可见注入文本) | File action="read" / through Bash |
the \read` tool/through `bash`` |
pandoc description |
via \Bash`` |
via \bash`` |
task_shell_start timeout_ms schema(r3 自己写入的) |
stop it via the Bash tool's action=cancel |
见下 |
task_shell_wait task_id schema |
returned by task_shell_start or \Bash`` |
returned by task_shell_start |
其中 task_shell_start 一处需要特别说明:r3 的取消指引本身是假的。contract_bash_legacy_input 只接受 command/timeout/sandbox_permissions/justification,公开 bash 拒绝 action 参数;tasks action=cancel 只吃 TaskManager 的 durable task id,不吃 shell task id。即新会话模型侧不存在 shell task 取消路径。已改为如实陈述("A running shell task cannot be cancelled from the model surface; it ends when the command finishes."),不再教一个调不到的接口——这正是本 PR 要根除的缺陷类别,r3 修工具名时把能力断言也一起保留了下来。
非阻塞集成提醒(采纳)
9 个 override setter 的父仓消费 PR 尚未开出。已在正文注明:接线在本 PR 合入后的首个父仓 PR(gitlink 提升 + docs/fork-modifications.md/fork-guard.sh 指纹登记)内完成并刷新 prompt fingerprint,届时回本 PR 补链;若未随合入落地,接受追问。
顺带修复:r1 引入的预存测试回归
全量跑测时发现 schema_stays_within_its_catalog_byte_budget 在 08c9902f 上就是红的(此前两轮验证漏跑该用例):r1 给 grep_files context_lines schema 新增的 58 字节事实使 File 家族聚合 schema 达 3136 > 3100(基线 3078)。已在同句内压缩至 3098(事实保留),测试回绿。属本 PR 自身引入,故在本 PR 内修复。
同类关联修复(评审未要求)
四个 locale preamble(zh-Hans/ja/pt-BR/vi,模型可见 system prompt 文本)的"工具名保持原样"示例 File/Bash → bash/Web,与 engine 指令同类;zh 钉住测试原意即"示例必须是现行工具名",已同步钉住发布名。
核验为不修的同类候选(披露)
file.rs错误恢复文案(File action="read"、File \{action}` refused):verify_expected_hash仅被隐藏遗留write_file/edit_file的 legacy execute 调用;reject_unknown/apply_param_aliases` 的 "File …" 标签仅触发于 legacy execute 路径。新会话模型不可见。- 隐藏工具自身 description(如
WriteFileTool的Bash、EditFileTool的File \read``,且有旧 rationale 的钉住测试):不进目录,无模型可见影响。 acp_server.rs的 "foreground Bash runs":ACP 宿主面能力文案,非模型目录。
本机验证
cargo check -p codewhale-tui --locked/cargo fmt --all -- --check/git diff --check通过forkguard_31/31;扩展守卫、prompts::tests102、tools::tasks11、tools::skill14、tools::pandoc7、tools::handle9、tools::search22、tools::file_tool21、tools::apply_patch41、tools::file_search10、tools::mcp_registry24、tools::shell139、core::engine::tests346、tools::goal27、tools::web_search69 全绿- 全量 lib:11704 passed;仅 remote_control 2 例全量并行下偶发失败(逐名与模块内运行均绿、失败集合逐轮不同、与本 PR 改动模块无交集,判定为本机并行负载抖动,请以 CI 为准)
No-Issue: cross-cutting model-facing doc-accuracy sweep; tracked in this PR only.
|
@h3c-hexin r3 意见已全部处理完毕(Major 三项要求 + 集成提醒),新 head |
h3c-hexin
left a comment
There was a problem hiding this comment.
R4 正式复审:Approve
复审基于精确 head d428d6ddc5bfbdc5c2cee6f27a36a47ec3b263a1。
原 Major 已完整解决:五个点名位置均改为新会话实际发布的 bash / 独立 edit,目录守卫已覆盖隐藏兼容名,registry-first 运行时指令也有独立断言。扩大扫描后发现并修复的同类文案与实现一致;task_shell_start 改为明确说明模型侧无法取消,也符合公开 bash schema 不接受 action 的事实。未发现新增阻塞问题。
本地在该 head 上精确重编译并验证:
cargo fmt --all -- --check:通过- 隐藏/退役工具名目录守卫:1 passed
- registry-first 发布名守卫:1 passed
- schema byte budget:1 passed
prompts::tests:::102 passedtools::tasks:::11 passedforkguard_:31 passedgit diff --check:通过
此前关于 9 个 override setter 的提醒仍作为父仓下一 PR 的非阻塞集成事项:提升 gitlink 时完成接线、登记 fork 指纹并刷新 prompt fingerprint。
Signed-off-by: h3c-hexin <13790929+h3c-hexin@users.noreply.github.com>
|
已直接补充修复提交
更正前次复审:apply_patch 的上述错误提示并非仅隐藏 legacy 路径可达,之前批准时漏查了这条调用链,本提交已补齐。 本地验证最终提交:apply_patch 41 passed / 0 failed;canonical_action 7 passed / 0 failed;skill 14 passed / 0 failed;forkguard 31 passed / 0 failed;cargo fmt 与 git diff --check 通过。按 scoped AGENTS.md 选择相关验证,未运行全 workspace 测试或跨平台验证。等待该提交的 GitHub 检查。 |
Signed-off-by: h3c-hexin <13790929+h3c-hexin@users.noreply.github.com>
|
最后一处公开 apply_patch 参数错误中的 File patch 文案已在 合并前发现仓库门禁配置不匹配:pinvou3-clean 分支保护要求 Check Signed-off-by、gate、Gitleaks、check;当前两个 PR 仅产生 DCO/link。CI 的 pull_request 过滤只包含 main/master,当前工作流中也没有 Gitleaks 定义。普通合并 #47 已被 GitHub base branch policy 拒绝;#41 同样受该保护约束。尚未合并,也未绕过或修改分支保护。 |
Signed-off-by: h3c-hexin <13790929+h3c-hexin@users.noreply.github.com>
|
门禁修复 #49 已通过完整验收并正常合并,落点 新工作流实际生成受保护分支要求的 本 PR 已通过普通 merge commit 无冲突同步门禁修复,未改写作者历史。最新 head 的完整 CI 已触发,待真实门禁通过后再正常合并。 |
Signed-off-by: h3c-hexin <13790929+h3c-hexin@users.noreply.github.com>
Signed-off-by: h3c-hexin <13790929+h3c-hexin@users.noreply.github.com>
|
已修复本轮全量 CI 唯一失败项,提交 根因是 本地验证: #47 已通过全部门禁并合并到 |
|
最终验收 PASS:集成 head 已通过正常 squash merge 合并到 父仓 r2 的 gitlink 提升及 override setter 接线仍是独立后续集成事项,不包含在本次底座 PR 合并中。 |
背景
对 Pinvou Agent 及 CodeWhale 的模型向文档(注入 LLM 上下文的工具 description / schema / prompt 文本)做了一次全量审计(30 个分区,约 16 万行),本 PR 修复其中属于引擎层的发现。修改绝大多数仅触及注入模型的字符串与对应测试;范围披露:
prompts.rs含两处超出纯字符串的改动,见下方「范围披露」节。主要修复(按审计四轴)
错误(描述指向不存在的工具名/与实现相反)
verify描述仍教模型调用已退役的run_verifiers;registry_sync/file_search/search引用exec_shell;fetch_url/web_search互相引用对方的退役名 → 全部改为现行面(Runaction /Bash/Webaction),并把 verify、registry MCP 三工具加入no_advertised_tool_teaches_a_retired_name守卫测试的 registry,堵住漏网;engine.rs的 registry-first 指令同步清理exec_shell/fetch_url退役名web_search描述称 API 后端 "DuckDuckGo then Bing" 降级,实现与 forkguard 测试是 configured→Bing 单跳web.run screenshot未说明仅支持 PDF 且返回文本页;Web声称全部 action 网络策略感知但wait只限 loopback 且不走策略shell/task_shell_start的timeout_ms对background=true完全不生效,未告知模型workflowscript 的pipeline(thunks)签名错误(实为pipeline(items, ...stages),照抄会静默零分发);source_path限定 ".workflow.js 且必须在 workspace 内" 与实现(.ts/~/.codewhale/workflows)不符agent的type=custom描述引用了未广告的allowed_tools:按 agent tool: simplify the 32-field schema so models stop erroring on it codewhale-hq/Codewhale#5324/Agent spawn surface has too many knobs — labeled builder runs read-only and self-BLOCKED codewhale-hq/Codewhale#5123 的既定决策,该键保持 parse-accepted 但不广告(评审后回退了初版"补 schema 属性"的做法,12 字段广告面及其守卫测试维持不变)遗漏
send_later未说明message仅action=schedule必填、githubclose 的脏工作区拒绝(已落到模型可见的github描述与 canonical schema 的allow_dirty字段)、gitignore在两个搜索工具间的不对称、image_ocr不支持的 PDF、terminal系列的 512KiB 缓冲丢弃/超时只放弃等待/Unix-only、Bash 30KB 流级截断、rememberworkspace 需带 origin 的 git 仓库、runtime_mcp运行时白名单、workflow verify失败把 run 终态翻为 Failed、create_goal建议"clear"但模型侧无清除工具等 → 均补入描述/schema重复/矛盾(提示层)
<codewhale:subagent.done>哨兵(应由运行时独占生成);scout 角色引言谈 CHANGES 节但 scout 契约已裁掉该节 → 删除两处AUTHORITY_RECAP仍无条件追加,指向不存在的 "### Whose word wins" 章节 → composer 存在时跳过 recap,附单测set_locale_preamble/closer_*_overridesetter(原覆盖单元格只有声明无 setter,宿主的 zh/ja 替换意图落空),并补set_authority_recap_override范围披露
prompts.rs含两处超出"纯字符串"的改动,均经评审确认正确,保留在本 PR 并如实披露:AUTHORITY_RECAP的装配门控(改变 composer embedder 的 prompt block 序列,附纯函数单测);set_prompt_override,消费方为 pinvou3-app 的 bundle 桥接(将随后续父仓 PR 接入,fork 侧 API 先行提供)。r3 集成提醒回应:父仓消费 PR 目前尚未开出,将在本 PR 合入后的首个父仓 PR(gitlink 提升 + 指纹登记)内完成接线并刷新 prompt fingerprint,届时在本 PR 正文补链;若接线 PR 未随合入落地,接受以此为准的追问。评审修订(第二个提交)
首轮评审发现初版若干修复本身不准确或越界,已全部修正:
agentschema 广告面扩容(推翻 agent tool: simplify the 32-field schema so models stop erroring on it codewhale-hq/Codewhale#5324 既定决策且挂 12 字段守卫测试);goal中虚构的 "three identical gap sets auto-pause (no_progress)"(NoProgress是从未构造的死枚举;重复 gap 集只计入快照的repeated_gap_count,自动暂停仅由 continuation 上限触发),并把create_goal描述与错误消息对齐(agent 无法 clear,仅用户/host 可/goal clear);send_later回退全局required(message仅 schedule 必填,read-only 变体会被误伤),改为描述限定;task_shell_start的timeout_ms描述改为"接受但不生效"(该工具恒后台启动,不存在前台等待);gate_run危险命令阻断补充 auto-approve 前提;fleet override 列表改为真实字段名(model_strength/subagent_type);search去掉无法证实的 "faster";若干注释残留清理。评审修订(第三个提交)
复审(2026-09-09)发现一处 Major 残留与三处 Minor,已修正:
render_continuation_prompt仍教模型 "repeated equivalent gap sets pause the loop for inspection"——与第二个提交在update_goalgaps schema 里写上的 "does not by itself pause the goal" 直接矛盾(NoProgress是从未构造的死枚举,自动暂停仅来自 continuation 上限)。改为快照计数事实,并新增钉住测试continuation_prompt_does_not_claim_gap_repetition_pauses_the_loop;task_shell_start的timeout_ms描述点名停止路径:Bash 工具action=cancel+ 返回的 task id(原文 "action=cancel" 未点名工具,易与tasks action=cancel的 durable task id 混淆);pr_attempt_record/pr_attempt_preflight专用描述臂补 approval 标注,并消除 "approval-gated elsewhere" 抵触(两者按action_requires_approval = !READ_ACTIONS均 approval-required;专用臂现仅测试别名可达,属纯文本对齐);web_searchprovider 枚举补duckduckgo(config/search.rs接受该值,且原句正教用户配置 "private DuckDuckGo-compatible route")。验证
cargo check -p codewhale-tui --locked通过;cargo fmt --all -- --check通过cargo test -p codewhale-tui --lib --locked forkguard_:31 passed / 0 failedno_advertised_tool_teaches_a_retired_name)、subagent_tool_schemas_advertise_real_type_and_role_vocabulary(12 字段面)、explore_prompt_orients_before_searching、authority_recap_*(2)、send_later(13)、tools::plan::(8)、tools::goal::/tools::github::/prompts::tests::(136)、tools::tasks::(11)tools::goal/tools::tasks/tools::web_search+ 退役名守卫 + schema/recap 守卫 +forkguard_共 142 passed / 0 failed(含新增钉住测试);cargo fmt --all -- --check通过tui::gate_receipts::tests::deterministic_block_receipt_names_the_policy在默认 2MiB 测试线程栈下栈溢出,RUST_MIN_STACK=16777216即通过;该测试为单句纯函数断言、与本 PR 改动路径无关,属预先存在的环境问题评审修订(第四个提交)
针对 r3 正式评审(h3c-hexin,基于
08c9902f)的 Major 与集成提醒,已修正(headd428d6ddc):apply_patch/file_search/grep_files/registry_search描述与 engine 的 Registry-first 运行时指令改为目录精确名(bash、独立edit);bashschema 的 "Bash command" 散文同步小写化。no_advertised_tool_teaches_a_retired_name新增HIDDEN_COMPAT_TOOL_NAMES(Bash/File,整词匹配避免 "BashHistory"/小写 bash 散文误报),守卫 registry 扩至 shell/task/skill/pandoc/media/harness 等全部无参 builder 面。扩面后守卫实际又抓到 6 处评审未点名的同类违例并已一并修复:handle_read、load_skill、已加载 skill 的 companion-file 引导、pandoc、task_shell_start的timeout_msschema、task_shell_wait的task_idschema。task_shell_start的 r3 文案 "stop it via the Bash tool's action=cancel" 经代码核验本身是假的:公开bash经contract_bash_legacy_input只接受 command/timeout/sandbox_permissions/justification(拒绝action),tasks action=cancel只吃 durable task id——新会话模型侧不存在 shell task 取消路径。改为如实陈述("cannot be cancelled from the model surface; it ends when the command finishes"),不再教一个调不到的接口。registry_first_instruction_only_names_published_tools钉住运行时指令;zh locale preamble 钉住测试同步改为强制目录内发布名。context_linesschema 新增事实使 File 家族聚合 schema 达 3136 > 3100 预算(基线 3078),此前两轮验证漏跑schema_stays_within_its_catalog_byte_budget。压缩同句至 3098(事实不变),测试回绿。File/Bash改为bash/Web(模型可见 system prompt 文本,与 engine 指令同类)。file.rs/apply_patch.rs错误恢复文案中的File action="read"/File \patch`标签——verify_expected_hash仅被隐藏遗留write_file/edit_file路径调用、apply_param_aliases的 "File …" 标签仅触发于 legacy execute 路径,新会话模型不可见;隐藏工具自身 description(如WriteFileTool的`Bash``)同理不进目录。若需一并清理建议随后续行为类 PR。验证(第四提交后)
cargo check -p codewhale-tui --locked、cargo fmt --all -- --check、git diff --check通过forkguard_31/31;prompts::tests102;tools::canonical_action(含扩展守卫)、tools::tasks11、tools::skill14、tools::pandoc7、tools::handle9、tools::search22、tools::file_tool21(预算测试回绿)、tools::apply_patch41、tools::file_search10、tools::mcp_registry24、tools::shell139、core::engine::tests346、tools::goal27、tools::web_search69 全绿cargo test -p codewhale-tui --lib --locked:11704 passed / 0 real failed(仅 remote_control 两个用例在全量并行下偶发失败,属本机已知的并行负载抖动:逐名运行与模块内 77/77 全绿,且与本 PR 改动模块无交集;三轮全量运行的失败集合各不相同亦为佐证)说明
docs/fork-modifications.md/scripts/fork-guard.sh指纹登记image_query绕过网络策略;grep_files的truncated恒 false;Web/WebSearch/web.run 三份 search schema 手抄漂移;fetch_url→Web包装器描述借用重构;allowed_tools/disallowed_tools是否广告(需独立论证并同步注释/测试/docs/SUBAGENTS.md)No-Issue: cross-cutting model-facing doc-accuracy sweep; tracked in this PR only.