fix(hooks): remove the dead updatedMCPToolOutput field (#5422) - #5423
Conversation
|
@qwen-code /triage |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Hey @ken-jo — thanks for the PR! The change itself looks reasonable (removing a dead field), but the PR body doesn't follow the PR template.
The template requires a few sections that help reviewers understand and verify the change:
- What this PR does — describe the change in prose
- Why it's needed — motivation / problem being solved
- Reviewer Test Plan — how to verify, with evidence (Before/After or N/A for type-only changes) and a "Tested on" table
- Risk & Scope — main risk, what's out of scope, breaking changes
- Linked Issues —
Fixes #5422(you already have this in the body, just needs to be under the heading) - 中文说明 — Chinese translation in a
<details>block
Could you update the PR body to follow the template? It should be quick since the change is small — most sections can be brief.
中文说明
嗨 @ken-jo ——感谢你的 PR!改动本身是合理的(移除一个未使用的字段),但 PR 正文没有按照 PR 模板 来填写。
模板要求几个部分来帮助审查者理解和验证改动:
- What this PR does — 用文字描述改动
- Why it's needed — 动机 / 要解决的问题
- Reviewer Test Plan — 如何验证,附上证据(Before/After,或者纯类型改动写 N/A)和"Tested on"表格
- Risk & Scope — 主要风险、不在范围内的内容、破坏性变更
- Linked Issues —
Fixes #5422(你正文里已经有了,只需要放到对应标题下) - 中文说明 — 用
<details>块提供中文翻译
能否按照模板更新一下 PR 正文?改动很小,大部分部分可以简单写几句就好。
— Qwen Code · qwen3.7-max
wenshao
left a comment
There was a problem hiding this comment.
No review findings. Downgraded from Approve to Comment: CI still running.
The removed updatedMCPToolOutput field is confirmed dead — zero references anywhere in the codebase. Clean removal.
— qwen3.7-max via Qwen Code /review
|
Updated the PR body to follow the template (added the What / Why / Reviewer Test Plan sections). Thanks for the review @wenshao. |
|
@qwen-code /triage |
|
Thanks for the PR! Template looks good ✓ On direction: dead-code cleanup in the hooks type system — squarely within scope and well-aligned with On approach: this is as minimal as it gets — one line removed, no consumers affected. The contrast with Moving on to code review. 🔍 中文说明感谢贡献! 模板完整 ✓ 方向:hook 类型系统中的死代码清理——完全在 方案:已经是最小化改动——删除一行,没有消费者受影响。与 进入代码审查 🔍 — Qwen Code · qwen3.7-max |
Code ReviewIndependent proposal: Read the PR title ("remove the dead updatedMCPToolOutput field") and the "Why" section. My approach: grep for Diff comparison: The PR matches my independent proposal exactly — a single-line deletion in No blockers. No nitpicks. TestingType-only change, no user-visible behavior to compare before/after. Verified build and hook tests on the PR branch: Build ( 中文说明代码审查独立方案: 根据 PR 标题和"Why"部分,我的做法是:在仓库中搜索 Diff 对比: PR 与我的独立方案完全匹配——在 无阻塞项。无细节意见。 测试纯类型变更,无用户可见行为可对比。在 PR 分支上验证了构建和 hook 测试:174 个测试全部通过,构建 0 错误。 — Qwen Code · qwen3.7-max |
|
This is a textbook dead-code removal. The field was declared, never consumed, and the contrast with its sibling Build passes, all 174 hook tests pass, diff is one line. Nothing more to ask for. Approving. ✅ 中文说明这是一个教科书级的死代码移除。该字段被声明但从未被消费,与其兄弟字段 构建通过,174 个 hook 测试全部通过,diff 只有一行。没有更多可要求的了。 批准 ✅ — Qwen Code · qwen3.7-max |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
LGTM, looks ready to ship. ✅
✅ Verification report — real build + live-binary testVerdict: confirmed dead field, safe to merge. The removal is type-only with provably zero runtime footprint: it deletes one optional interface member that nothing reads, that is stripped before any hook output is consumed, and that is fully erased by the TypeScript compiler (the emitted I built the real 1. Static dataflow — zero consumers
Tracing the PostToolUse execution path confirms why: a raw hook result is wrapped by Contrast — the sibling field 2. Origin — incidental cruft, dead ~5 weeks
It rode in on a session-deletion feature and has been dead from day one. 3. Type-only → zero runtime footprint (dist byte-identity)TypeScript interfaces compile to nothing. I built the compiled module with and without the field and hashed it:
Identical. Removing the field cannot change runtime behavior, because the runtime never contained it. 4. Build + tests (this PR branch)
5. Live real-binary test (the decisive behavioral proof)In a tmux session I ran the actual built
The model called the MCP tool; the hook fired ( { "output": "MCP_ORIGINAL_OUTPUT_Z5423\nPOSTHOOK_ADDLCTX_Z5423" }
Because both fields come from the same hook output, this is a clean within-run A/B: it rules out "the hook simply didn't run." The honored sibling worked; the field this PR removes did nothing. One consideration (non-blocking)
Scope / honestyVerified: static dataflow, dist byte-identity, full typecheck, hooks/toolHookTriggers suites (698 tests), and a live MCP + PostToolUse run on the real binary. I did not run the entire repo test matrix (unnecessary for a type-only change the typecheck already covers). Recommendation: merge. 🇨🇳 中文版(完整对应)✅ 验证报告 —— 真实构建 + 真机测试结论:确认是死字段,可以安全合并。 该删除是纯类型改动、运行时零足迹:删掉的是一个无人读取的可选接口成员,它在任何 hook 输出被消费之前就已被丢弃,并且会被 TypeScript 编译器完全擦除(编译出的 我在隔离的 worktree 里用本 PR 构建了真实的 1. 静态数据流 —— 零消费者
追踪 PostToolUse 执行路径可知原因:原始 hook 结果会被 对照 —— 兄弟字段 2. 来源 —— 顺带混入的死代码,已死约 5 周
它搭着一个"会话删除"功能混进来,从第一天起就是死的。 3. 纯类型 → 运行时零足迹(dist 字节级一致)TypeScript 接口编译后什么都不剩。我分别在保留和删除该字段的情况下构建编译模块并取哈希:
完全相同。 删除它不可能改变运行时行为,因为运行时从来就没有它。 4. 构建 + 测试(本 PR 分支)
5. 真机行为测试(决定性证据)我在 tmux 会话里用真实构建的
模型调用了该 MCP 工具;hook 触发( { "output": "MCP_ORIGINAL_OUTPUT_Z5423\nPOSTHOOK_ADDLCTX_Z5423" }
由于两个字段来自同一个 hook 输出,这构成了一次干净的同跑 A/B:排除了"hook 根本没跑"的可能。被尊重的兄弟字段生效了,而本 PR 删除的这个字段什么都没做。 一点考量(不阻塞合并)
范围 / 诚实说明已验证:静态数据流、dist 字节级一致、完整类型检查、hooks/toolHookTriggers 套件(698 个测试),以及真机上的 MCP + PostToolUse 实跑。我没有跑整个仓库的测试矩阵(对一个类型检查已经覆盖的纯类型改动来说没必要)。建议:合并。 |
|
Thanks for the thorough check @wenshao — a real-build + live-binary verification is more than I expected for a dead-field removal, much appreciated. Ready to merge whenever suits you. |
What this PR does
Removes the
updatedMCPToolOutputfield from thePostToolUseOutputhook type. The field is declared but never read — a repo-wide search finds it only as the declaration inpackages/core/src/hooks/types.ts, with no consumer in the executor, aggregator, scheduler, or SDK (the analogousupdatedInputis fully wired by contrast).Why it's needed
The hook-output contract should reflect what the runtime actually honors. A declared-but-unimplemented field misleads integrators into emitting
updatedMCPToolOutputexpecting it to rewrite MCP tool output, when nothing reads it. If that capability is wanted later it would need real wiring plus tests; this just drops the dead declaration. Reported in #5422; confirmed dead by the triage and by @wenshao's review.Reviewer Test Plan
How to verify
Search the repo for
updatedMCPToolOutput: before this PR it appears only as the type field inpackages/core/src/hooks/types.ts; after, there are zero occurrences. Because nothing consumes it, removing it changes no runtime behavior.npm run build(typecheck) still passes.Evidence (Before & After)
N/A — non-user-visible, type-only change.
Tested on
Environment (optional)
N/A — type-only change, no runtime.