Skip to content

docs(tools): align tool descriptions and prompts with behavior - #41

Merged
h3c-hexin merged 9 commits into
Pinvou:pinvou3-cleanfrom
asto18089:docs/tool-description-accuracy
Sep 10, 2026
Merged

h3c-hexin merged 9 commits into
Pinvou:pinvou3-cleanfrom
asto18089:docs/tool-description-accuracy

Conversation

@asto18089

@asto18089 asto18089 commented Sep 4, 2026 •

Copy link
Copy Markdown
Collaborator

背景

对 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 互相引用对方的退役名 → 全部改为现行面(Run action / Bash / Web action),并把 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 完全不生效,未告知模型
  • workflow script 的 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 必填、github close 的脏工作区拒绝(已落到模型可见的 github 描述与 canonical schema 的 allow_dirty 字段)、gitignore 在两个搜索工具间的不对称、image_ocr 不支持的 PDF、terminal 系列的 512KiB 缓冲丢弃/超时只放弃等待/Unix-only、Bash 30KB 流级截断、remember workspace 需带 origin 的 git 仓库、runtime_mcp 运行时白名单、workflow verify 失败把 run 终态翻为 Failed、create_goal 建议"clear"但模型侧无清除工具等 → 均补入描述/schema

重复/矛盾(提示层)

  • scout 输出契约教模型输出 <codewhale:subagent.done> 哨兵(应由运行时独占生成);scout 角色引言谈 CHANGES 节但 scout 契约已裁掉该节 → 删除两处
  • translation 开启时与 LANGUAGE_PROMPT 语言规则互斥 → 补 override 声明
  • 宿主安装 static composer 后 AUTHORITY_RECAP 仍无条件追加,指向不存在的 "### Whose word wins" 章节 → composer 存在时跳过 recap,附单测
  • 补齐 set_locale_preamble/closer_*_override setter(原覆盖单元格只有声明无 setter,宿主的 zh/ja 替换意图落空),并补 set_authority_recap_override

范围披露

prompts.rs 含两处超出"纯字符串"的改动,均经评审确认正确,保留在本 PR 并如实披露:

  1. static composer 安装时跳过 AUTHORITY_RECAP 的装配门控(改变 composer embedder 的 prompt block 序列,附纯函数单测);
  2. 新增 9 个 pub override setter(8 个 locale preamble/closer + 1 个 authority recap),复用既有 set_prompt_override,消费方为 pinvou3-app 的 bundle 桥接(将随后续父仓 PR 接入,fork 侧 API 先行提供)。r3 集成提醒回应:父仓消费 PR 目前尚未开出,将在本 PR 合入后的首个父仓 PR(gitlink 提升 + 指纹登记)内完成接线并刷新 prompt fingerprint,届时在本 PR 正文补链;若接线 PR 未随合入落地,接受以此为准的追问。

评审修订(第二个提交)

首轮评审发现初版若干修复本身不准确或越界,已全部修正:

  • 回退 agent schema 广告面扩容(推翻 agent tool: simplify the 32-field schema so models stop erroring on it codewhale-hq/Codewhale#5324 既定决策且挂 12 字段守卫测试);
  • 恢复 scout 引导中被守卫测试钉住的 "compressed evidence" 措辞(CHANGES 节清理保留);
  • 删除 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,已修正:

  • goal:render_continuation_prompt 仍教模型 "repeated equivalent gap sets pause the loop for inspection"——与第二个提交在 update_goal gaps 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_search provider 枚举补 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 failed
  • 定向测试全绿:退役名守卫(no_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 通过
  • 注:本机 Windows 环境下 tui::gate_receipts::tests::deterministic_block_receipt_names_the_policy 在默认 2MiB 测试线程栈下栈溢出,RUST_MIN_STACK=16777216 即通过;该测试为单句纯函数断言、与本 PR 改动路径无关,属预先存在的环境问题

评审修订(第四个提交)

针对 r3 正式评审(h3c-hexin,基于 08c9902f)的 Major 与集成提醒,已修正(head d428d6ddc):

  • Major(隐藏兼容名)全部成立并修复:apply_patch/file_search/grep_files/registry_search 描述与 engine 的 Registry-first 运行时指令改为目录精确名(bash、独立 edit);bash schema 的 "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_ms schema、task_shell_wait 的 task_id schema。
  • 其中 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 钉住测试同步改为强制目录内发布名。
  • r1 提交引入的预存回归顺带修复:grep_files context_lines schema 新增事实使 File 家族聚合 schema 达 3136 > 3100 预算(基线 3078),此前两轮验证漏跑 schema_stays_within_its_catalog_byte_budget。压缩同句至 3098(事实不变),测试回绿。
  • 同类漂移关联修复:四个 locale preamble(zh-Hans/ja/pt-BR/vi)的"工具名保持原样"示例由 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::tests 102;tools::canonical_action(含扩展守卫)、tools::tasks 11、tools::skill 14、tools::pandoc 7、tools::handle 9、tools::search 22、tools::file_tool 21(预算测试回绿)、tools::apply_patch 41、tools::file_search 10、tools::mcp_registry 24、tools::shell 139、core::engine::tests 346、tools::goal 27、tools::web_search 69 全绿
  • 全量 cargo test -p codewhale-tui --lib --locked:11704 passed / 0 real failed(仅 remote_control 两个用例在全量并行下偶发失败,属本机已知的并行负载抖动:逐名运行与模块内 77/77 全绿,且与本 PR 改动模块无交集;三轮全量运行的失败集合各不相同亦为佐证)

说明

  • 本 PR 为文档精度修复(含上述已披露的两处 prompts.rs 例外),合入后父仓需按 r11/r12 惯例做 gitlink 提升 + docs/fork-modifications.md/scripts/fork-guard.sh 指纹登记
  • 已知但未在本 PR 处理的行为类问题(建议单独 PR):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.

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown

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 CONTRIBUTING.md for the expected contribution shape. A maintainer can grant recurring PR access by commenting /lgtm on a pull request.

@asto18089

Copy link
Copy Markdown
Collaborator Author

交叉引用:本 PR 对 crates/tui/src/tools/web_search.rs description 的修改(DuckDuckGo→Bing 链尾表述、退役名 fetch_url 改为 Web action=fetch)与 #39(r12 review leftovers 的同一处链尾 copy 修复)存在同行冲突。两处语义一致(都以 #35 的 configured→Bing 单跳为准);建议先合其一,另一个 rebase。本 PR 其余 28 个文件的改动与 #39/#40 无交集。

@asto18089 asto18089 mentioned this pull request Sep 8, 2026
11 of 14 tasks
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>
@asto18089
asto18089 force-pushed the docs/tool-description-accuracy branch from f57253d to 86b5382 Compare September 9, 2026 07:13
@asto18089
asto18089 marked this pull request as draft September 9, 2026 07:35
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>
@asto18089

Copy link
Copy Markdown
Collaborator Author

全新视角复审(head 56d0f930,基于 pinvou3-clean@1fafee7e,树与 headRefOid 一致,无陈旧树问题)

对 31 个文件的 diff 做了逐条核验:把修改后的描述逐句与实现比对(35+ 项事实断言),全部与实现一致;本地 cargo fmt --all -- --check、forkguard_(31/31)、退役名守卫 + schema + authority_recap(5/5)、send_later/plan/goal/github/tasks/prompts(170/170)全绿。按四维给出结论。

结论:价值真实、根因定位准确、无夹带硬伤,但有 1 个 Major 需要先修——同一虚构声明的残留实例与本 PR 自己的修复直接矛盾。

Major

M1 · goal continuation prompt 仍教模型"重复 gap 集会自动暂停",与本 PR 的修复正面对撞
crates/tui/src/tools/goal.rs 的 render_continuation_prompt(经 core/engine.rs:4479、turn_loop.rs:5799、runtime_threads.rs:4510 注入,每个 continuation pass 模型可见)仍写着:

"repeated equivalent gap sets pause the loop for inspection instead of spending indefinitely"

第二个提交已认定该声明为虚构(GoalPauseReason::NoProgress 从未被构造;自动暂停只来自 continuation 上限 → Backoff),并因此在 update_goal 的 gaps schema 里新写了 "Repeating an identical gap set … does not by itself pause the goal — automatic pause comes only from the continuation run limit"。结果是模型在同一 goal 流程里收到两条相反的指令,而 continuation prompt 是出现频率更高的那条。这正是本 PR 要根除的缺陷类别,该根因只修了一半。建议本 PR 内一并改写(例如 "repeated equivalent gap sets only increment repeated_gap_count in the snapshot; the loop pauses at the continuation run limit, not because of repetition"),并补一条钉住测试。

Minor

m1 · required CI link 红:PR 正文缺 Closes #… 或 No-Issue: 行(两次 runs 均因此 exit 1)。加一行 No-Issue: … 即可转绿。

m2 · task_shell_start 的 "stop it with action=cancel" 未点名工具:该 schema 没有 action 参数;能停止它的是 Bash 工具的 action=cancel + 返回的 shell task id,而 tasks action=cancel 吃的是 durable task id。精度 PR 里建议写成 "stop it via the Bash tool's action=cancel with the returned shell task id"。

m3 · pr_attempt_record/pr_attempt_preflight 描述臂不一致:_ => 臂本次新加的 "(approval)" 经核与 action_requires_approval = !READ_ACTIONS 一致、标注正确;但专用臂 Some("pr_attempt_record") 无 approval 字样,且既有 preflight 臂的 "approval-gated elsewhere" 与"preflight 本身即 approval-required"相抵。专用臂目前仅测试别名可达(模型只见 _ => 臂),无模型可见影响;既然本次动了同一描述块,建议顺手对齐。

m4 · web_search provider 枚举漏 duckduckgo:[search] provider 接受 duckduckgo(config/search.rs,且它与 searxng 是仅有的两个接受 base_url 的值);同一句还在教用户配 "private DuckDuckGo-compatible route",枚举里却没有这个键。

m5 ·(范围判断)9 个 override setter 目前全仓无消费方:prompts.rs 新增的 9 个 setter 在 fork 与父仓 main(已 git grep 核过)均无调用点,正文的"消费方为 pinvou3-app 的 bundle 桥接"尚不存在。已如实披露、机械复用 set_prompt_override、与既有 per-locale effective_* 对称,认可留在 fork 先行的依赖顺序;但建议在正文链接将消费它们的父仓 PR(或注明"随下一父仓 PR 消费"),避免合入后一段时间内是纯死 API。相比之下 AUTHORITY_RECAP 装配门控认同属本 PR 主题(悬空章节引用正是"描述指向不存在的东西"类缺陷,且有单测)。

核验为无误的抽样(不构成问题)

  • Bash 大小写:目录广告名实为 bash(BashTool 为隐藏兼容别名,model_visible=false),但 ToolRegistry::resolve 第 1 步即 ASCII 大小写不敏感,可正常分发——不属于本 PR 堵的"不可分发名称"类;追求与目录逐字一致可另开清理。
  • workflow_trigger.rs 模块注释改写属实:evaluate_workflow_trigger 无生产调用方,仅 debug_assert 冒烟引用;Act prompt 层确不提及 Workflow。
  • 守卫测试扩充正确:verify + registry MCP 三工具入 no_advertised_tool_teaches_a_retired_name 的 registry,与退役名清单闭合。
  • 行为类断言逐条核验一致:shell 30KB 流级截断(head/tail + 元数据旗标)、background 不受 timeout_ms 约束、terminal 五工具 Unix-only/512KiB 静默丢弃/超时弃等、github allow_dirty 拒关、send_later message 仅 schedule 必填 + fire_at 严格未来、grep 不吃 .gitignore 而 file_search 吃、file_search exclude 整表替换 + limit 上限 200、runtime_mcp 白名单逐词一致、goal root-only/sub-agents get_goal、workflow pipeline(items, ...stages)/Date+Math.random 禁用/.ts 与 ~/.codewhale/workflows/exact fleet 六字段拒绝/gates[] APPROVE-PASS/verify 失败或跳过翻 Failed、web_run ref_id 30min+256 页/screenshot 仅 PDF 返回文本行 0-based/open 接受裸 URL、Web wait 仅 loopback 不走策略。
  • 与 docs(changelog): record keyless Bing search tail #39 的 web_search.rs 同行冲突语义一致(docs(changelog): record keyless Bing search tail #39 改 //! 模块头链尾文案,本 PR 改模型可见 description),先后落地 rebase 即可。

建议处理 M1 + m1 后合并;m2–m4 顺手修最佳,m5 补个链接即可。

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>
@asto18089
asto18089 marked this pull request as ready for review September 9, 2026 10:40

@h3c-hexin h3c-hexin left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

正式评审:Request changes

评审基于精确 head 08c9902f43f5ac9089b27a282c09ff3b590ec6d4,相对 r1 基线 1fafee7e26b60a59457a43bce50c63aa2ad9dbaf。

Major(阻塞):新文案再次向模型教授了隐藏兼容工具,而不是实际发布的工具目录

新会话的工具目录由 ToolRegistry::build_api_tools() 过滤 model_visible() 后生成。当前实现和既有测试明确规定:

  • 新会话发布的是小写 bash;BashTool("Bash") 仅用于旧 transcript 回放,model_visible=false。
  • 新会话发布的是独立的 read / write / edit;File action family 同样是隐藏兼容接口。canonical_runtime_tools_hide_compatibility_aliases 还明确断言 File 必须不出现在新模型目录。

但本 PR 新增/改写的模型可见内容仍使用这些隐藏名字:

  • crates/tui/src/tools/apply_patch.rs:322:patch` in `Bash、File edit``
  • crates/tui/src/tools/file_search.rs:43:fd` in `Bash
  • crates/tui/src/tools/search.rs:59:rg` ... in `Bash
  • crates/tui/src/tools/mcp_registry.rs:886:through Bash
  • crates/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 内:

  1. 把上述新文案改为目录中的精确接口名(例如 bash、独立的 edit);
  2. 扩展守卫,阻止模型可见 description/schema 教授隐藏兼容名;
  3. 为 registry-first 运行时指令增加对应断言,避免目录外提示再次漂移。

非阻塞集成提醒

本 PR 新增的 9 个 locale/authority override setter 当前在 CodeWhale 与父仓均尚无消费方。接受“底座先提供接口、父仓 r2 随后接线”的依赖顺序,但父仓后续必须完成接线并刷新 prompt fingerprint;建议在 PR 正文链接该消费 PR,避免接口长期悬空。

本地验证

  • cargo fmt --all -- --check:通过
  • forkguard_:31 passed
  • prompts::tests:::102 passed
  • tools::goal:::27 passed
  • tools::tasks:::11 passed
  • no_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>
@asto18089

Copy link
Copy Markdown
Collaborator Author

R4 处理报告(head d428d6ddc,基于 r3 评审 08c9902f)

逐条甄别 r3 正式评审意见后全部采纳,其中 Major 经代码逐项核验完全成立;另按评审要求的守卫扩展实际抓到并修复了 6 处评审未点名、但属同一缺陷类的漏网文案。逐项结论如下。

Major:隐藏兼容名(成立,全部修复)

先核验了评审的事实基础,全部与 08c9902f 一致:

  • with_foreground_shell_tools 注册小写 bash + 隐藏 Bash(model_visible=false,"hidden compatibility name for saved v0.9.x transcripts");with_file_tools 发布独立 read/write/edit + 隐藏 File/read_file/write_file/edit_file;canonical_runtime_tools_hide_compatibility_aliases 确断言 File 等不得出现在新目录。
  • 五处点名文案逐一在 head 上确认存在且模型可见(apply_patch.rs:322、file_search.rs:43、search.rs:59、mcp_registry.rs:886、engine.rs:149)。
  • "守卫只枚举完全退役名、运行时指令不在扫描范围"两点亦核实无误。

三项要求全部落地:

  1. 文案改精确目录名:五处点名 + bash schema 的 "Bash command" 散文,全部改为 bash / 独立 edit。
  2. 守卫扩展:HIDDEN_COMPAT_TOOL_NAMES = ["Bash", "File"],整词 token 匹配(避免 "BashHistory"、小写 bash 散文如 grep_files 自身 description 的误报——这是朴素 contains 方案会破的地方);守卫 registry 同时扩至 with_shell_tools 与其余无参 builder 面(task/skill/pandoc/media/harness/handle/remember 等)。
  3. registry-first 指令断言:新增 registry_first_instruction_only_names_published_tools,同时禁 11 个隐藏兼容名与退役名、并正向钉住 ​bash​/​Web​。

守卫扩面后先红后绿的迭代中,实际又抓到 6 处同类违例(评审未点名,同一缺陷类,已一并修复):

位置 原文案 修复
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::tests 102、tools::tasks 11、tools::skill 14、tools::pandoc 7、tools::handle 9、tools::search 22、tools::file_tool 21、tools::apply_patch 41、tools::file_search 10、tools::mcp_registry 24、tools::shell 139、core::engine::tests 346、tools::goal 27、tools::web_search 69 全绿
  • 全量 lib:11704 passed;仅 remote_control 2 例全量并行下偶发失败(逐名与模块内运行均绿、失败集合逐轮不同、与本 PR 改动模块无交集,判定为本机并行负载抖动,请以 CI 为准)

No-Issue: cross-cutting model-facing doc-accuracy sweep; tracked in this PR only.

@asto18089

Copy link
Copy Markdown
Collaborator Author

@h3c-hexin r3 意见已全部处理完毕(Major 三项要求 + 集成提醒),新 head d428d6ddc,逐项结论与核验证据见上方 R4 报告。扩大扫描面后守卫另抓到 6 处同缺陷类漏网一并修复,其中 task_shell_start 的取消指引经核验教的是调不到的接口,已改为如实陈述。方便时请复审;当前账号无 base 仓的 reviewer-request 权限,故以此评论代为请求。

@h3c-hexin h3c-hexin left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 passed
  • tools::tasks:::11 passed
  • forkguard_:31 passed
  • git diff --check:通过

此前关于 9 个 override setter 的提醒仍作为父仓下一 PR 的非阻塞集成事项:提升 gitlink 时完成接线、登记 fork 指纹并刷新 prompt fingerprint。

Signed-off-by: h3c-hexin <13790929+h3c-hexin@users.noreply.github.com>
@h3c-hexin

Copy link
Copy Markdown

已直接补充修复提交 4c522e626,保留本 PR 作者历史。

  • load_skill 使用实际发布的 list_dir;守卫按实际目录检查其工具引用,并从退役清单移除已恢复发布的 list_dir/file_search/grep_files。
  • 公开 apply_patch.execute() 的 hash 冲突及上下文匹配失败提示改为 read / apply_patch,补充现有错误路径测试中的恢复指引断言。
  • 公开 read 不返回 content_hash,因此同时修正 apply_patch 的 expected_hash schema 和恢复指引,说明完整文件字节的 SHA-256 与 sha256: 前缀。

更正前次复审: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>
@h3c-hexin

Copy link
Copy Markdown

最后一处公开 apply_patch 参数错误中的 File patch 文案已在 8ee033cff 清理,更新了兼容 patch 委托路径的断言。验证:file_tool 21 passed / 0 failed;apply_patch 41 passed / 0 failed;fmt、diff --check 通过。

合并前发现仓库门禁配置不匹配: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>
@h3c-hexin

Copy link
Copy Markdown

门禁修复 #49 已通过完整验收并正常合并,落点 a7215d3c4b10f444c42abefcda45ca547acdd19c。

新工作流实际生成受保护分支要求的 check、Gitleaks、gate;保留 DCO 与原有分支保护。CI 基线验收:14,317 tests passed,14 skipped;格式、Clippy、doctest、全树和新增提交敏感信息扫描全部通过。

本 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>
@h3c-hexin

Copy link
Copy Markdown

已修复本轮全量 CI 唯一失败项,提交 edb7fb52b。

根因是 expected_hash_is_advertised_on_every_mutating_action 把隐藏兼容 write/edit 与公开 apply_patch 的文案一律断言为含 content_hash,未同步此前已修正的公开工具契约:公开 read 不返回该字段,apply_patch 指导计算完整文件字节的 sha256:<hex>。现在按各工具的真实契约分别断言,并保留参数存在性检查、补充 string 类型检查;没有改变运行时行为或删除拒写保护用例。

本地验证:cargo test -p codewhale-tui --lib --locked expected_hash -- --test-threads=1,精确重新编译后 12 passed / 0 failed,覆盖哈希匹配、冲突拒写、缺失文件与可选参数行为;fmt、diff --check 通过。

#47 已通过全部门禁并合并到 bf435e5e8。本 PR 随后通过普通 merge 无冲突同步该基线,保留作者历史;最终集成 head 正在运行完整 CI,待通过后正常合并。

@h3c-hexin
h3c-hexin merged commit c3a3521 into Pinvou:pinvou3-clean Sep 10, 2026
5 checks passed
@h3c-hexin

Copy link
Copy Markdown

最终验收 PASS:集成 head 5234175537776648bbe10515be5e4ad5fc14e3a6 的全部必需门禁通过,workspace 测试 14,321 passed / 0 failed / 14 skipped;格式、Clippy、doctest、Gitleaks、DCO 均通过。

已通过正常 squash merge 合并到 pinvou3-clean,合并提交 c3a35216ed7fcf3a08b7e2a86433be03973c0c93。此前唯一失败的过时 hash 文案断言已修复,未绕过分支保护。

父仓 r2 的 gitlink 提升及 override setter 接线仍是独立后续集成事项,不包含在本次底座 PR 合并中。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants