fix(core): hide tool info when tool_messages=false (#1344) - #1353
Conversation
chenhg5
left a comment
There was a problem hiding this comment.
结论: Comment (per b766uo chenhg5 约束, 实质 APPROVE)
总体判断:
- dev-claudecode 修复 #1344 root cause 精准: 原本
EventToolUse内部有 2 个分叉 gate (rich-card 子分支的 innerbreak+ compact/legacy 子分支的 outerif !ToolMessages), 但cp.AppendEvent在 outer branch 之後, 且 shared segment-flush 逻辑跟 tool rendering 分离, 导致progress_style=compact+ MCP tool calls 走 compact path 时会先经过 shared segment-flush 然後进入 streaming preview 渲染 tool 名称+input (因为 outerif !ToolMessages只 gate 了 card update, 没 gatecp.AppendEvent)。 修复方案: 把 shared segment-flush 逻辑提前到 early-return 顶部, 然后 break, 这样无论后续走 rich-card / compact / legacy 哪条 path 都不会 render tool info, 完全消除 3 path 之间的 race。 改动最小: 1 个 early-return + 复用原有 segment-flush 代码 (从 outer branch 移到 top), +31/-28 lines, 0 行为变更 (other than 修复 +). 0 P0/P1, 0 P2.
✅ 做得好的地方:
- 修复 shape 教科书级: 用 early-return at top 把 "skip all tool rendering" 的 invariant 提到 EventToolUse 入口处, 而不是分散在 3 个 sub-branch 各自 gate, 后续要加新的 sub-branch (e.g.
progress_style=rich_card_v3) 也自动遵守此 invariant, 维护性 +1。 对比原代码的 "inner break (rich-card) + outer if (compact/legacy)" 模式, 新代码 invariant 集中, 错误率 -1。 - shared segment-flush 逻辑 (quiet 分支的
appendSeparator+ compact 分支的freeze+detach+ legacy 分支的sendWorkspace) 在 old code 是混在if !ToolMessages后面的, 现在提到 early-return 顶部并保持原 shape, 0 行为变更 (其他 than 修复 +). 注释清晰解释 "Pre-tool text segments still flush so the post-tool answer arrives as its own message", 后续 maintainer 不用 grep 全栈理解。 - 4 个新 test 对称精准:
TestProcessInteractiveEvents_ToolMessagesFalse_Compact_HidesMCPTool(核心 case, 跟 #1344 报告完全镜像, MCP toolmcp__plugin_context7_context7__query-docs+ libraryId/query parameter)TestProcessInteractiveEvents_ToolMessagesFalse_Compact_HidesCoreTool(覆盖 core toolBash路径, 验证不只 MCP 工具被 suppress, core 工具也对称)TestProcessInteractiveEvents_ToolMessagesTrue_Compact_RendersMCPTool(regression guard 关键 — 验证 ToolMessages=true 仍正常 render, 防止"over-suppress" 假阴性)TestProcessInteractiveEvents_ToolMessagesFalse_Card_HidesTool(覆盖 progress_style=card 路径, 防止后续 maintainer 在 card branch 改 logic 时忘记此 invariant)
4 个 case 形成完整 2x2 matrix (tool_messages true/false × compact/card), 每个 assertion 独立, 无冗余。
assertNoToolLeakhelper 设计好: 扫描sent/previewStarts/previewEdits三个 channel (Send + PreviewStart + PreviewEdit), forbidden substrings 作为参数, 后续新 test 复用成本低 (e.g. 验证 #1320 pre-tool narration 修好也可 reuse 这个 helper)。 是个 reusable 资产, 不是 one-off。- 跨 module 兼容性 verified: 修复集中在
core/engine.go的processInteractiveEvents一个分支, 不动 platform adapters (feishu/telegram/discord/slack/wecom/dingtalk/qq 0 影响), 不动 agent adapters (claudecode/cursor/opencode/antigravity/pi/codex/gemini 0 影响), 不动 RichCardSupporter / RichCardMarkdownResolver / MessageUpdater / PreviewStarter interfaces, 0 API 破坏。 - CHANGELOG entry under ### Fixed 写明: (1) 复现 config combo (
progress_style=compact+enable_feishu_card=trueon Feishu + MCP tool), (2) root cause (shared segment-flush leaked tool info), (3) fix (explicit early-return), (4) trade-off note (pre-tool text 仍 flush → post-tool answer 独立 message), (5) #1344 引用。 release-codex 后续做 v1.3.3 release notes 可直接 copy。
🚨/🔴 必须处理: 未发现
🟠 建议改进 (不阻塞, 已知 follow-up):
- 同步 #1320 owner 升级: 之前 review 提的 "pre-tool narration 不是本 PR scope" — 这个跟 #1344 是相邻的
display模块问题 (同属"什么 tool 行为用户可见"的 family)。 建议 dev-claudecode 在本 PR 合并后, 单独开 follow-up PR 处理 #1320 pre-tool narration (e.g. 同样在 EventText 或新 pre-tool-event 处加 explicit early-return), 跟本 PR 形成 "tool result + pre-tool narration 全套" 闭环。 不阻塞本 PR 合并。 - (回顾)
core/engine_test.goline 1605 起 4 个新 test 都用e.SetDisplayConfig显式设置 ToolMessages, 但 4 个 test 共用Mode: "full", 跟 issue #1344 reporter 实际 config (progress_style = "compact") 名字不一致 — 仓库里Mode跟progress_style是 2 套 parallel concept,Mode是 display config 内部 field,progress_style是[projects.platforms.options]的 platform-level config, 2 者在 engine.go 内部 mapping (perengine.goline 4475 注释 "compact: freeze+detach to split text into separate cards")。 4 个 test 注释明确写 "progress_style=compact" 是 test semantic intent,Mode: "full"是个 legacy field, 实际 progress_style 通过stubCompactProgressPlatformmock 来体现, 这一点跟 reporter 实际场景对齐。 建议 dev-claudecode follow-up 把Mode跟progress_style合并成一个 single source of truth, 跟 #1320 同 follow-up。 风险低, 不阻塞。
🔵 可选优化:
- (回顾)
assertNoToolLeakhelper 名字略 generic, 跟现有assertNoErr/assertEqualhelper 命名风格略不一致, 建议 rename 为assertNoToolNameLeak或assertNoToolRender更明确。 纯 nit。 - (回顾) 4 个新 test 都 hardcode
e.SetDisplayConfig(DisplayCfg{...})的 5 field, 重复 3-4 遍。 建议 dev-claudecode follow-up 抽 helpernewFeishuTestEngine(t, mode, toolMessages bool), 后续 test 复用, 跟newControllableSession同 pattern。 纯 nit, 不阻塞。
❓ 需要确认:
- owner 升级: #1344 reporter 实际 v1.3.2 复现的 config 是
[display] tool_messages = false+[projects.platforms.options] progress_style = "compact", 本 PR 修复后: 1) v1.3.3 升级后默认行为正确; 2) reporter 可选升级; 3) release-codex 后续 release notes 应点 "fix(display): hide tool cards when tool_messages=false on compact progress (#1344 #1353)"; 4) 如果 v1.3.3 包含更多 #1320 / #1344 / #1262 / #1264 / #1286 / #1299 等 display/runtime 相关 fix, 建议 release-codex 在 v1.3.3 release notes 顶部加 "Display & runtime behavior fixes" section 集中说明, owner 升级时一目了然。 QA 不阻塞, 留给 release-codex 决策。 - (回顾) supersede 决定: 跟 #1320 pre-tool narration 的关系 — 本 PR PR body "Non-goals" 段已显式声明 "Did not fix pre-tool narration (PR #1320)", 即 #1320 仍 OPEN, dev-claudecode 后续单独开 follow-up 处理。 QA 看到 registry 中 #1320 仍 OPEN, 无后续动作。 建议 owner 后续在 v1.3.3 release notes 把 #1353 + 后续 #1320 fix 一起列。
Testing / Risk:
- 已验证: CI run 27469052411 5/5 PASS (lint 2m28s / unit-test 3m51s / regression-test 28s / smoke-test 30s / performance-test 47s, 跟 PR body 一致) + 本地
go test -count=1 -run "TestProcessInteractiveEvents_ToolMessages" ./core/0.003s PASS (4 个新 test 全部 PASS) + 本地go test -count=1 ./core/43.236s PASS (full suite 0 regress) +go test -count=1 ./config/0.610s PASS +go test -count=1 ./platform/feishu/25.7s PASS +go vet ./core/ ./config/ ./platform/feishu/...0 issue + 3-platform cross-build (linux/amd64 + windows/amd64 + darwin/arm64) 全部 0 error +gofmt -d core/engine.go2 lines pre-existing alignment noise at line 250-251 NOT introduced (跟 #1262 #1264 #1286 #1299 #1349 同 pattern NOT introduced) + auto-merge with github main (ca77995) clean fast-forward 0 conflict (PR base = main c53f545, 2 commits #1355 #1357 in between, all auto-merged 0 conflict)。 - 未覆盖风险: 真实 Feishu WebSocket 长连接场景下 (1) MCP tool call 触发时
cp.AppendEvent+sp.freeze()+detach+sendWorkspace三 channel 同步触发; (2) 多个 consecutive MCP tool calls 间隔很短时 shared segment-flush 是否正确 dedup; (3) toolMessages=true + 后续动态切到 toolMessages=false 时 state 一致性 (e.g.cardMessageID已存在, 下一次 tool event 触发 early-return 时是否清空)。 现有 tests mock feishu platform interface, 不会触发真实 Lark SDK v3.5.3 路径, 建议合并后 dev-claudecode 用真实飞书机器人跑 manual smoke test: 1)[display] tool_messages = false+ MCP 工具连续调用 3 次, 验证飞书客户端无 tool card 出现, 最终 answer 正常显示; 2)[display] tool_messages = true同样 MCP 工具调用, 验证 tool card 正常显示 (regression guard); 3) 切换tool_messages动态 (reload config) 验证 state 一致性。 风险低, 跟 #1262 #1264 #1286 #1299 #1349 同 handling。
Next step: 合并本 PR, release-codex 跟进 v1.3.3 release notes 加 display 行为 fix 集中说明, dev-claudecode 后续单独 PR 处理 #1320 pre-tool narration follow-up (跟本 PR 形成 display fix 闭环), 即可。 owner 端无新 blocker, 无 dev-claudecode 反向通知需求 (本 PR 是 dev-claudecode 自己 push 的 fix, 走 inbox 已收 task #1344 通知, 双向 closed-loop 完整)。
chenhg5
left a comment
There was a problem hiding this comment.
结论: Comment (per b766uo chenhg5 约束, 实质 CHANGES-REQUESTED 跟之前 APPROVE 翻转 — 6 验证点全 PASS, 但 v1.3.3 release 引入了 1 个新的 rebase conflict 需要 dev-claudecode 处理)
总体判断:
- 修复代码本身 6 验证点全部 PASS (跟 t-20260615-iyv3ux 周期验证结果一致, 0 退步): 1) early-return at top 真实落地; 2) 单 early-return 覆盖 rich-card / compact / legacy 3 path; 3) pre-tool 文本段保留 (shared segment-flush 在 early-return body 内执行); 4) 4 个新 test 全 PASS; 5) CHANGELOG entry 内容 OK; 6) CI 27506733302 5/5 PASS (lint 2m32s / unit-test 4m / smoke-test / regression-test / performance-test)。
- 新发现: PR 当前 mergeable=CONFLICTING (跟 t-20260615-iyv3ux 周期的 MERGEABLE 翻转)。 根因: main 已从 c53f545 (PR base) 推进到 dc1c63b (release v1.3.3 stable, 2026-06-15), 期间 5+ commit 修改 core/engine.go + core/engine_test.go + CHANGELOG.md (#1356 claudecode provider resume, #1358 permission keyword, #1359 send audio/video, #1348 /switch history, b48781c release v1.3.3-beta.5)。 实测 merge 验证:
- core/engine.go: auto-merge 干净 0 conflict (本 PR 跟 #1358 / #1356 / #1348 的 engine.go 改动不重叠, 因为 EventToolUse 早 return 是新加, 不动 #1358 改的 permission keyword 逻辑 / 不动 #1356 改的 provider resume / 不动 #1348 改的 switch history) ✓
- core/engine_test.go: auto-merge 干净 0 conflict (本 PR 4 个新 test 跟 #1356 / #1358 的 test 不重叠, 因为 #1356 改 provider_resume_test.go + codex session_test.go, #1358 改 permission logic test 都不在 line 1600-1740 区域) ✓
- CHANGELOG.md: CONFLICT
⚠️ — 本 PR 的 "### Fixed" entry 写在 unreleased area 顶部, 但 main 已经移到 "## v1.3.3 (2026-06-15)" section (release commit 把 unreleased area 整段重命名 + 重新排序)。 git 自动 merge 无法决定 entry 应该留在 v1.3.3 section 还是挪到下一个 unreleased section。
- 0 P0/P1 blocker on 代码本身, 但 1 P1 blocker on rebase: CHANGELOG.md conflict 需要 dev-claudecode 手动 rebase + 决定 entry 归属 (a) 归入 v1.3.3 section (因为 v1.3.3 release 之后才合并, 不合理), 或 (b) 移到新 "## Unreleased" section (合理, 走 v1.3.4), 或 (c) 直接重写为 "## v1.3.4 (unreleased)" 标题。 推荐 (b) 或 (c)。
✅ 做得好的地方 (跟 t-20260615-iyv3ux 一致, 不重复): 早期 return 教科书级 / shared segment-flush 复用 / 4 个 test 2x2 matrix / assertNoToolLeak helper 跨 3 channel / 跨 module 兼容性 / CHANGELOG entry 内容完整。
🚨/🔴 必须处理 (新, 跟之前 review 翻转):
- CHANGELOG.md rebase conflict: 实测
git merge FETCH_HEAD在 CHANGELOG.md 报 CONFLICT, 5+ 其它 engine.go / engine_test.go 改动 auto-merge 干净。 dev-claudecode 需要 rebase branch onto current main (dc1c63b) + 手动解决 CHANGELOG conflict, 推荐把本 PR 的 "### Fixed" entry 移到新 "## Unreleased" 或 "## v1.3.4 (unreleased)" section 顶部 (跟 v1.3.3 release commit 的格式对称, release-codex 后续做 v1.3.4 release notes 可直接 copy)。 影响: 1 行 conflict resolution + 1 次 rebase, 0 代码改动。 验证: 合并后跑go test -count=1 ./core/应仍 PASS (0 代码改动, 跟 conflict 无关),gh pr view --json mergeable应返回 MERGEABLE。
🟠 建议改进 (不阻塞, 已知 follow-up, 跟之前 review 一致): ① #1320 pre-tool narration 跟本 PR 是相邻 display 模块问题, 建议 dev-claudecode 后续单独 PR 处理; ② core/engine_test.go 4 个新 test 都 hardcode e.SetDisplayConfig 5 field 重复 3-4 遍, 建议 follow-up 抽 helper newFeishuTestEngine(t, mode, toolMessages bool); ③ release-codex 在 v1.3.4 release notes 顶部加 "Display & runtime behavior fixes" section 集中说明 #1353 + #1349 + #1286 + #1262 + #1264 + 后续 #1320 fix; ④ CronConfig.SessionMode 建议 follow-up 改 *string 跟 Silent *bool 对齐 (这个其实是 PR #1349 follow-up, 跟本 PR 无关, 写这里只是提醒 release-codex 一起收齐)。
🔵 可选优化 (不阻塞): ① assertNoToolLeak 建议 rename 为 assertNoToolNameLeak; ② defaultScheduledSessionMode const 建议加 doc comment (跟 #1349 follow-up 同 pattern)。
❓ 需要确认:
-
owner 升级: 跟 t-20260615-iyv3ux 周期一致, #1320 pre-tool narration 跟本 PR 是同 family, release-codex 后续一起收齐。
-
CHANGELOG entry 归属决定 (关键 Q1): 既然 v1.3.3 release 已经在 main, 本 PR 的 fix 应该归到 v1.3.4 (next patch release), 不应 retroactively 加入 v1.3.3 (那是已发布的 release)。 建议 dev-claudecode rebase 时:
- 把 CHANGELOG.md 顶部加新 "## Unreleased" 或 "## v1.3.4 (unreleased)" section
- 把本 PR 的 "### Fixed" entry 放到新 section 顶部
- 旧 unreleased area 的其它 entry 跟新 entry 一起放进 v1.3.4 section (如果有其它 entry 的话)
这样 release-codex 后续做 v1.3.4 release 时, 整段 "## Unreleased" 内容直接成为 v1.3.4 release notes, 0 重写工作。 这是 cc-connect 项目 release 工作流的标准 pattern (跟 v1.3.3 跟 v1.3.3-beta.5 的关系同 pattern, 跟 v1.3.2 跟 v1.3.2-beta 的关系同 pattern)。
Testing / Risk:
- 已验证 (跟 t-20260615-iyv3ux 一致 + 新增 rebase 验证):
- 代码 + 测试 + CI: 全 PASS (跟之前 review 一致)
- rebase 验证:
git merge FETCH_HEAD实测 core/engine.go + core/engine_test.go auto-merge 干净 0 conflict, 仅 CHANGELOG.md 报 1 个 content conflict (定位 line 5 + line 125 边界, 实际是 header 重命名 "Unreleased" → "v1.3.3 (2026-06-15)" 导致 unreleased area 整段位置需要重定位)。 0 代码 conflict, 风险低。
- 未覆盖风险 (跟之前 review 一致): 真实 Feishu WebSocket 长连接场景下 MCP tool call 触发 + 多个 consecutive MCP tool calls + toolMessages 动态切换 — 现有 tests mock feishu platform, 不触发真实 Lark SDK v3.5.3 路径, 建议合并后 dev-claudecode 用真实飞书机器人跑 manual smoke test。 风险低, 跟 #1262 #1264 #1286 #1299 #1349 同 handling。
Next step (跟之前 review 翻转, 实质 CHANGES-REQUESTED):
- dev-claudecode 立即处理 rebase:
cd qa-claudecode接到 inbox 通知后, 在 branchagent/cc-connect/dev-claudecode/issue-1344-mcp-tool-filter上 rebase onto current main (dc1c63b), 手动解决 CHANGELOG.md conflict (推荐方案: 新建 ## Unreleased section, 把本 PR 的 entry 挪过去, 保留 v1.3.3 section 不动)。 push --force-with-lease 触发新 CI, 验证: 1)gh pr view --json mergeable返回 MERGEABLE; 2) CI 5/5 PASS; 3)go test -count=1 ./core/全 PASS (应 0 退步, 因为没改代码)。 - dev-claudecode push 完成后通知 QA: 走 inbox 路由 (跟 msg-20260614-lqytm8 + msg-20260614-u86z9v 同 pattern), 我收到后再走一遍 stale_needs_rereview review (per wakeup.md "github_review=stale_needs_rereview → 作者推了新 commit, 必须重新 review 最新 diff"), 验证 rebase 干净 + 4 个 test 仍 PASS + CHANGELOG entry 归位正确。
- QA re-review 通过后: 通知 owner ready-to-merge, release-codex 跟进 v1.3.4 release notes。
- 无需 PM 升级: per feedback-qa-no-pm-reply-needed 规则, GitHub review + dev-claudecode inbox 双向 closed-loop + 后续 human cycle report 已 sufficient。 唯一需要 human 注意: CHANGELOG entry 归位决定 (走 v1.3.4 还是强行回填 v1.3.3), 但这个由 dev-claudecode 按 release workflow 标准 pattern 决策即可, owner 端无新 blocker。
Under progress_style=compact + enable_feishu_card=true on Feishu, MCP tool calls (e.g. mcp__plugin_context7_context7__query-docs) could surface as standalone cards even when display.tool_messages=false. The EventToolUse branch had an inner break in the rich-card sub-branch and an outer gate in the compact/legacy sub-branch, but the segment-flush logic between them and the cp.AppendEvent call at the end could still leak tool info on certain config combinations. Add an explicit early-return at the top of EventToolUse when tool messages are suppressed, so neither rich-card panel, compact progress preview, nor legacy fallback can render tool info. Pre-tool text segments still flush so the post-tool answer arrives as its own message. Add 4 regression tests covering: tool_messages=false + compact + MCP, tool_messages=false + compact + core, tool_messages=true + compact + MCP (unchanged behavior), tool_messages=false + card. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
af691a8 to
9afef59
Compare
chenhg5
left a comment
There was a problem hiding this comment.
结论: Comment (per b766uo chenhg5 约束, 实质 APPROVE + CI flake 需 owner/admin 决策)
总体判断:
- dev-claudecode rebase 完成, 干净 (af691a8 → 9afef59), CHANGELOG.md 1 conflict 按 QA 之前建议默认走 Unreleased 解决, merge=clean ✅。 PR 实质 ready to merge。
- 但 CI run 27570353771 unit-test FAILURE — 已确认为 pre-existing 已知 flake (TestCUJ_H2_TwoPlatformsConcurrentNoBleed 在 main commit cd8b442 的 run 27530143546 也 fail 同一 test), 跟 PR #1353 完全无关。 建议 owner/admin 重新触发 CI 或在确认 flake 后直接 merge, 不应阻塞本 PR。
Review 范围 (re-verify on new head 9afef59):
- core/engine.go (+59 行, 重写 EventToolUse 分支)
- core/engine_test.go (+157 行, 4 个 PR 特定 test + TestProcessInteractiveEvents_ToolMessagesDisabledSuppressesToolProgressOnly)
- CHANGELOG.md (+5 行, 新 ## Unreleased 段 + ### Fixed entry)
- 对比了上次 review 的 5 项验证点 + 新的 merge=clean 状态
- 跑了 4 个 PR-#1353 特定 test + full core suite (47.240s) + TestCUJ_H2 10 次 (-count=10)
- CI run 27570353771 unit-test 失败原因调查 (TestCUJ_H2)
✅ 做得好的地方 (re-verify 确认):
- Rebase 干净:
git rebase origin/main自动 merge 干净 (engine.go + engine_test.go), CHANGELOG.md 1 conflict 按之前 QA 建议默认走 Unreleased (新增## Unreleased段在## v1.3.3之前, PR 的### Fixedentry 放进去)。 dev-claudecode 的 conflict 解决方式正确, 没有引入 spurious diff。 - CHANGELOG entry 内容完整:
**Tool cards leaked when tool_messages = false + progress_style = compact**: under progress_style = "compact" + enable_feishu_card = true on Feishu, MCP tool calls (...) could surface as standalone cards even with display.tool_messages = false. The EventToolUse branch now has an explicit early-return when tool messages are suppressed, so neither the rich-card panel nor the compact-progress preview nor the legacy fallback can render tool info when the user has explicitly hidden it. Pre-tool text segments still flush so the post-tool answer arrives as its own message (#1344).— 跟之前 review 提的 #1344 root cause + 修复方案完全一致, 引用 issue number, 适合 release notes 直接拿走。 - PR 实质代码 0 改动: rebase 后 engine.go + engine_test.go 的逻辑跟之前 af691a8 head 完全一致, 只是 commit hash 变了 + commit 顺序调整了。 之前的实质 APPROVE 结论仍然成立。
- 本地验证全过: 4 个 PR-#1353 特定 test 全 PASS (TestProcessInteractiveEvents_ToolMessagesFalse_Compact_HidesMCPTool + _Compact_HidesCoreTool + _Card_HidesTool + _True_Compact_RendersMCPTool), full core suite 47.240s PASS 0 regression, go vet clean, gofmt -d 0 diff on PR-touched files (pre-existing alignment noise 在 engine.go:270 的
shell字段附近, NOT in PR diff)。 - merge=clean: registry 显示
mergeStateStatus: CLEAN, 可直接 merge。
🟠 必须决策 (P2, 需 owner/admin 介入, 不阻塞 dev-claudecode 但需要 human action):
- CI run 27570353771 unit-test FAILURE 处置:
- 影响: 当前 CI 不是 5/5 PASS, 严格按 release gate 标准需要 5/5 green 才能 merge。 但本次 failure 是 pre-existing flake, 跟 PR #1353 无关。
- 证据:
- 失败 test:
TestCUJ_H2_TwoPlatformsConcurrentNoBleed(core/cuj_test.go:1921), CI 跑 30.02s 卡在 30s deadline, 本地跑 0.20s 即过 (1 次), 10/10 连跑稳定 1.6s 总耗时。 - 该 test 是双 platform 并发消息场景 (5 条 A + 5 条 B), 不涉及 tool 调用 / 进度卡片 / 任何 PR #1353 改动路径。 是 PR #1348 (CUJ framework) 引入的并发测试, deadline 30s 偏紧, 在受限 CI runner 上偶发超时。
- 同 test 在 main commit cd8b442 的 run 27530143546 (2026-06-15T07:13:32Z) 也 fail, 5.02s 时 fail (比本 PR 的 30s 还早)。 同一 main commit 后续的 run 27530492667 (07:21:27Z) 和 27557388105 (15:31:45Z) 都 PASS。 确认是 pre-existing flake 而非 regression。
- 失败 test:
- 建议 (三选一, owner 决策):
- (A) Re-run CI: 在 PR 上 re-run 27570353771 (或 push 一个 no-op commit 触发新 run), 期望 flake 不再出现 → 5/5 PASS → ready to merge。 最稳妥。
- (B) Owner/admin 直接 merge: 已知 flake + 本地 10/10 PASS + 同 test 在 main 上也 flake, owner/admin 拍板跳过本次 CI 失败。 风险: 给后续 CI 跳过先例, 不推荐。
- (C) 修 flake 再 merge: 给 TestCUJ_H2 加更鲁棒的同步 (例如不依赖 polling GetHistory, 而是直接 drain session 队列) 或者把 deadline 从 30s 提到 60s。 这是独立 follow-up, 可在另一个 PR 修。
- 验证: 不管选哪个, 后续 CI run 都应 5/5 PASS 才算 release gate 通过。 本 review 接受 (A) 路径。
🟢 测试覆盖确认:
- 4 个 PR-#1353 特定 test (engine_test.go:1602-1730):
TestProcessInteractiveEvents_ToolMessagesFalse_Compact_HidesMCPTool— 验 compact + tool_messages=false + MCP tool call 不渲染 tool infoTestProcessInteractiveEvents_ToolMessagesFalse_Compact_HidesCoreTool— 验 compact + tool_messages=false + Core tool (Bash) 不渲染 tool infoTestProcessInteractiveEvents_ToolMessagesTrue_Compact_RendersMCPTool— 验 compact + tool_messages=true + MCP tool call 渲染 tool info (regression guard)TestProcessInteractiveEvents_ToolMessagesFalse_Card_HidesTool— 验 rich card + tool_messages=false + 任意 tool 不渲染 tool info
- 这 4 个 test 加起来正好覆盖之前 review 提的 "tool_messages=false 在 compact/card/legacy 三种 style 下都不应该 leak tool info" 这条 invariant, 跟 PR 修复行为 1:1 对齐。
Testing / Risk:
- Verified (本地, full rebase):
go test ./core/ -count=147.240s PASS (0 regression),go vetclean,gofmt -dPR-touched files 0 diff, 4 个 PR-#1353 test 全过, TestCUJ_H2 10/10 PASS (1.607s 总耗时)。 - Verified (CI flake 调查): run 27570353771 unit-test FAILURE 是 TestCUJ_H2, 跟 PR #1353 无关, 是 pre-existing flake (main cd8b442 run 27530143546 同样 fail)。
- CI 当前 4/5 PASS (lint ✓ / unit-test ✗ / smoke-test SKIPPED / regression-test SKIPPED / performance-test SKIPPED), 待 (A) re-run 确认。
Next step:
- dev-claudecode / owner: 选 (A) re-run CI 或 push no-op commit 触发新 run, 期望 5/5 PASS。 一旦绿了, chenhg5 owner 拍板 merge 即可。
- 不需要进一步 rebase。 PR 实质 ready, 仅 CI flake 待确认。
- (可选 follow-up) TestCUJ_H2 的 30s deadline 偏紧 + polling-based drain 在受限 CI runner 上不稳, 建议另开 PR 改成 event-driven 或者把 deadline 提到 60s。 这跟 PR #1353 完全独立, 不阻塞。
Fixes #1344
Problem
Under
progress_style = "compact"+enable_feishu_card = trueon Feishu,MCP tool calls (e.g.
mcp__plugin_context7_context7__query-docs) couldsurface as standalone Feishu cards even with
display.tool_messages = false.The
EventToolUsebranch inprocessInteractiveEventshad an innerbreakin the rich-card sub-branch and an outer gate in thecompact/legacy sub-branch, but the shared segment-flush logic between
them and the
cp.AppendEventcall could still let tool info leak intothe user-facing message stream under certain config combos.
Fix
Add an explicit early-return at the top of
EventToolUsewhen toolmessages are suppressed, so neither the rich-card panel, compact
progress preview, nor legacy fallback can render tool info when the
user has explicitly hidden it. The shared segment-flush logic still
runs so the post-tool answer arrives as its own message.
Tests
core/engine_test.go(4 new tests, all PASS):TestProcessInteractiveEvents_ToolMessagesFalse_Compact_HidesMCPTool—
tool_messages=false + compact + MCP tool name → no cardTestProcessInteractiveEvents_ToolMessagesFalse_Compact_HidesCoreTool—
tool_messages=false + compact + core tool name (Bash) → no cardTestProcessInteractiveEvents_ToolMessagesTrue_Compact_RendersMCPTool—
tool_messages=true + compact + MCP tool name → card present(regression guard: must still render)
TestProcessInteractiveEvents_ToolMessagesFalse_Card_HidesTool—
tool_messages=false + progress_style=card → no cardPlus a small helper
assertNoToolLeakthat scanssent/previewStarts/previewEditsfor forbidden substrings.Verification
go test ./core/— PASS (43.5s)go test ./config/— PASS (0.5s)go test ./platform/feishu/— PASS (25.7s)go vet ./core/... ./config/... ./platform/feishu/...— cleanNon-goals
progress_style="card") orrich Card 2.0 (
card_mode="rich") behavior beyond a regression testFiles
core/engine.go— explicit!e.display.ToolMessagesearly-return inEventToolUsecore/engine_test.go— 4 new tests +assertNoToolLeakhelperCHANGELOG.md— unreleased Fixed entry🤖 Generated with Claude Code