feat(core): make todo_write opt-in - #10645
Conversation
E2E Test ReportBaselineOn Branch resultThe bundled CLI was tested with isolated settings against a deterministic local fake OpenAI-compatible server:
Result: 2 passed in 3.80 seconds. Additional verification
Not runThe existing live-provider, model-driven Todo integration scenario was updated to opt in but was not rerun as part of this deterministic check. Windows and Linux runtime checks were not performed locally. |
|
Re-run — the direction question I stopped on last time is settled, so this pass does the full review. @wenshao and @qqqys both approved this exact head ( Template ✓ — all sections present, bilingual, concrete reviewer test plan, and the Risk section is honest about what wasn't validated. Problem. Same split as last time, and it still holds. The mechanism cost is observed and checkable against the code: headless runs declare Direction. Settled by the approvals above. Worth recording for the changelog that this flips a default rather than adding an option: Size. Core paths are touched ( Approach. This is the part I'd want a reviewer to look at, and it holds up. The flag follows the existing Two scope notes, neither blocking. The Risk. Elevated-risk signal now matches, and did not last pass: Moving on to code review. 🔍 中文说明重新运行——上次停下的方向问题已经有结论,所以这一轮做完整审查。@wenshao 和 @qqqys 都在这个 head( 模板 ✓——各部分齐全,中英双语,有具体的验证计划,风险部分也如实说明了未验证的内容。 问题。 与上次相同的分野,而且依然成立。机制成本是可观测、可对照代码核实的:headless 运行默认声明 方向。 已由上述批准确定。值得为 changelog 记录的一点是:这改变的是默认值,而不是新增一个选项——工具关闭后,交互式 TUI 中的 规模。 触及核心路径( 方案。 这是我希望 reviewer 重点看的部分,而它站得住。开关沿用了既有的 两点范围说明,都不构成阻塞。 风险。 本轮命中升级风险信号,上一轮没有: 进入代码审查 🔍 — Qwen Code · qwen3.8-max-2026-09-02 Reviewed at |
E2E test report (tmux, built at head
|
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Not explored to full depth (tool budget reached): "agent 4": none** — all planned checks completed within budget..
[Critical] R1-10: [fails-closed] [regression] This PR breaks 5 existing unit tests in packages/core/src/core/client.test.ts — the CI job 'Test (ubuntu-latest, Node 22.x)' is red on this PR because of it. getMainSessionBaseSystemPrompt now passes a 6th positional argument (config.isTodoWriteEnabled?.() ?? false) into getCoreSystemPrompt (packages/core/src/core/client.ts:383), but the five expect(getCoreSystemPrompt).toHaveBeenCalledWith(...) assertions in client.test.ts (around lines 14259, 14291, 14323 and the two following) still expect the old 5-argument call — client.test.ts is not updated in this diff. Failing tests: 'should append config appendSystemPrompt to the core system prompt', 'passes the active output style to the core system prompt', 'should pass interactive mode to the core system prompt', 'should pass acp mode to the core system prompt', 'should pass headless mode to the core system prompt'. Witness (run-produced): CI run 33403794522 job 99526325819 — 'Tests 8 failed | 22716 passed (22734)', every one of the five showing the assertion diff '+ false' as the extra 6th argument; and local reproduction in the PR worktree: npx vitest run src/core/client.test.ts -t "core system prompt" → 'Test Files 1 failed (1); Tests 5 failed | 385 skipped (390)' with the identical '+ false' diff. The base-side call has 5 arguments (merge-base client.ts), so these tests pass on the merge base — netNew by measurement. Fix: update the five assertions to include the new 6th argument (false with the current mocks, or stub isTodoWriteEnabled), ideally together with the R1-3 tightening (move isTodoWriteEnabled into the required Pick) so future callers cannot silently diverge.
中文说明
未探索到全部深度(达到工具调用预算):"agent 4":none** — all planned checks completed within budget.。
[Critical] R1-10: [fails-closed] [regression] This PR breaks 5 existing unit tests in packages/core/src/core/client.test.ts — the CI job 'Test (ubuntu-latest, Node 22.x)' is red on this PR because of it. getMainSessionBaseSystemPrompt now passes a 6th positional argument (config.isTodoWriteEnabled?.() ?? false) into getCoreSystemPrompt (packages/core/src/core/client.ts:383), but the five expect(getCoreSystemPrompt).toHaveBeenCalledWith(...) assertions in client.test.ts (around lines 14259, 14291, 14323 and the two following) still expect the old 5-argument call — client.test.ts is not updated in this diff. Failing tests: 'should append config appendSystemPrompt to the core system prompt', 'passes the active output style to the core system prompt', 'should pass interactive mode to the core system prompt', 'should pass acp mode to the core system prompt', 'should pass headless mode to the core system prompt'. Witness (run-produced): CI run 33403794522 job 99526325819 — 'Tests 8 failed | 22716 passed (22734)', every one of the five showing the assertion diff '+ false' as the extra 6th argument; and local reproduction in the PR worktree: npx vitest run src/core/client.test.ts -t "core system prompt" → 'Test Files 1 failed (1); Tests 5 failed | 385 skipped (390)' with the identical '+ false' diff. The base-side call has 5 arguments (merge-base client.ts), so these tests pass on the merge base — netNew by measurement. Fix: update the five assertions to include the new 6th argument (false with the current mocks, or stub isTodoWriteEnabled), ideally together with the R1-3 tightening (move isTodoWriteEnabled into the required Pick) so future callers cannot silently diverge.
— qwen3.8-max via Qwen Code /review (v0.22.3)
# Conflicts: # docs/users/configuration/settings.md
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Partially reviewed — gaps disclosed.
2 Suggestion-level finding(s) this review confirmed are already reported on this PR and are not repeated:
- R1-6 todo_write not-found branch is a structural copy of the list_directory branch — dropped as location overlap: packages/core/src/core/coreToolScheduler.ts:2160 is occupied by the round-1 R1-8 comment (comment 3896564552)
- R1-8 daemon/ACP unregistered-tool branch returns a bare error without the opt-in hint — dropped as location overlap: packages/core/src/core/coreToolScheduler.ts:2164 is occupied by the round-1 R1-9 comment (comment 3896564544)
Not reviewed: build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally.
Not reviewed: build-and-test — the workspace unit-test phase did not complete under build-test (budget exhausted in the build phase); targeted verifier runs covered the changed suites.
Deferred under the convergence posture (round 2, not a blocker) — recorded, not requested in this round:
packages/core/src/core/client.ts:383 — [probe] D2-1 Todo prompt/schema gates key off the settings flag, not effective availability (flag on + workspace toggle off still advertises todo_write)packages/core/src/config/config.ts:9372 — [review] D2-2 coreTools allowlist non-promotion of todo_write is intentional per design doc but undocumented in the settings entries and pinned by no testdocs/users/qwen-serve.md:331 — [review] D2-3 added prose 'a new ordinary prompt must enable tools.todoWrite.enabled' ascribes a restart-required operator setting to the promptintegration-tests/cli/todo_write.test.ts:19 — [test] D2-4 new integration test is unreachable by any workspace test lane and the CLI integration lane is skipping on this fork PRintegration-tests/cli/qwen-serve-streaming.test.ts:321 — [test] D2-5 updated serve/streaming integration test is likewise unreachable by workspace lanes
中文说明
仅完成部分审查,审查缺口已披露。
本轮确认的 2 条建议级发现已在 PR 上报告过,不再重复发布(列表见上方英文部分)。
未审查:build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally。
未审查:build-and-test — the workspace unit-test phase did not complete under build-test (budget exhausted in the build phase); targeted verifier runs covered the changed suites。
收敛姿态下延后(第 2 轮,非阻断)——已记录,本轮不要求修改:共 5 条(原文未翻译,列表见上方英文部分)。
— qwen3.8-max via Qwen Code /review (v0.22.3)
|
Addressed all unresolved R1 review comments in Highlights:
Validation:
|
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Partially reviewed — gaps disclosed. Suggestions are inline.
3 Suggestion-level finding(s) this review confirmed are already reported on this PR and are not repeated:
- integration tests unreachable from workspace test lanes (integration-tests/cli/todo_write.test.ts) — already recorded in the round-2 deferral list (D2-4, review 5074197635)
- integration tests unreachable from workspace test lanes (integration-tests/cli/list_directory.test.ts) — already recorded in the round-2 deferral list (D2-4/D2-5, review 5074197635)
- integration test helper unverifiable by workspace lanes (integration-tests/test-helper.ts) — already recorded in the round-2 deferral list (D2-4/D2-5, review 5074197635)
Not reviewed: build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally.
Not explored to full depth (tool budget reached): "agent reverse-audit (round 2)": end-to-end execution of the new/changed integration tests (integration-tests/cli/todo_write.test.ts, list_directory.test.ts) — requires a full npm run build &&….
Convergence: round 3 posted 3 inline comment(s), 3 of them reported for the first time; the previous round posted 7 (0 new). Findings keep coming back to the same files: packages/core/src/core/coreToolScheduler.ts (findings in round 1; 2 more now); docs/users/qwen-serve.md (findings in round 1; 1 more now). A cluster that keeps producing siblings usually means the fixes are treating instances of a shared root cause — triaging that cause before the next round, or splitting an independent cluster into its own pull request, tends to end the loop faster than fixing them one at a time. No Critical finding is open on this round, so merging and moving the remaining Suggestion threads to a follow-up issue is available as an ending — a merged pull request cannot diverge further. (Observation only — nothing was withheld from this review because of this observation.)
中文说明
仅完成部分审查,审查缺口已披露。 建议见行内评论。
本轮确认的 3 条建议级发现已在 PR 上报告过,不再重复发布(列表见上方英文部分)。
未审查:build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally。
未探索到全部深度(达到工具调用预算):"agent reverse-audit (round 2)":end-to-end execution of the new/changed integration tests (integration-tests/cli/todo_write.test.ts, list_directory.test.ts) — requires a full npm run build &&…。
收敛情况:第 3 轮发布了 3 条行内评论,其中 3 条是首次提出;上一轮发布了 7 条(其中 0 条首次提出)。发现反复回到同一批文件:packages/core/src/core/coreToolScheduler.ts(第 1 轮已出过发现,本轮又有 2 条);docs/users/qwen-serve.md(第 1 轮已出过发现,本轮又有 1 条)。一个不断再生兄弟发现的簇,通常意味着逐条修复只在处理同一根因的实例——先定位并处理该根因,或把独立的簇拆成单独的 PR,通常比逐条修复更快结束循环。本轮没有未决的 Critical,因此"合入后把剩余 Suggestion 线程转到后续 issue"是一个可选的结束方式——已合入的 PR 不会继续发散。(仅为观察——本轮评审未因此扣留任何内容。)
— qwen3.8-max via Qwen Code /review (v0.22.3)
|
@qwen-code /resolve |
|
Qwen Code attempted to resolve merge conflicts but the run did not complete successfully. Check the workflow run for full logs. |
# Conflicts: # packages/cli/src/acp-integration/session/Session.ts
|
Qwen Code review did not complete successfully. The review pipeline failed before a review could be posted. A transient error is retried automatically; if you are seeing this, retry with |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Reviewed. Suggestions are inline.
1 Suggestion-level finding(s) this review confirmed are already reported on this PR and are not repeated:
- integration-tests/cli/todo_write.test.ts is collected by no pull_request-time CI lane — already recorded in the round-2 deferral list (D2-4, review 5074197635)
Not explored to full depth (tool budget reached): chunk 11: could not execute prompts.test.ts / coreToolScheduler.test.ts to confirm green — the review worktree has no node_modules or packages/core/dist , so test …; "agent reverse-audit (round 1)": did not execute integration-tests/cli/qwen-serve-streaming.test.ts (daemon Todo Stop Guard replay) to confirm the added tools: { todoWrite: { enabled: true }….
Deferred under the convergence posture (round 4, not a blocker) — recorded, not requested in this round:
packages/cli/src/acp-integration/session/Session.ts:11626 — [probe] the daemon builds the new opt-in guidance but no client frame ever carries it (sessionUpdateCount: 0)packages/cli/src/acp-integration/session/Session.ts:11632 — [probe] three unregistered todo_write calls trip the parameter-loop detector and abort the whole daemon turn with -32603packages/core/src/core/coreToolScheduler.ts:323 — [probe] the CLI never reaches the new deny/allowlist arms, and the message that intercepts gives advice this diff made insufficientpackages/core/src/config/config.ts:9569 — [probe] exitPlanMode.ts:283 and :381 still tell the model to update a todo list that is no longer declareddocs/users/configuration/settings.md:621 — [probe] experimental.sessionWorkflow silently goes inert at the new default with no doc precondition and no warningpackages/core/src/core/prompts.test.ts:92 — [probe] six enabled-variant prompt strings are pinned by no test; one added snapshot closes all sixpackages/core/src/core/coreToolScheduler.ts:324 (+2 locations) — [probe] the settingAction ternaries in the workspace and allowlist arms are each pinned in only one directionpackages/core/src/core/coreToolScheduler.ts:293 — [probe] the list_directory branch skips the deny-rule diagnosis todo_write gets, naming a setting already onpackages/core/src/core/prompts.ts:588 — [probe] the QWEN_WRITE_SYSTEM_MD dump is now flag-dependent while the QWEN_SYSTEM_MD consumer is flag-blindpackages/core/src/config/config.ts:7700 — [probe] allowlist non-promotion of todo_write is recorded in neither a JSDoc nor a test, unlike its sibling getterpackages/core/src/config/config.test.ts:9470 — [probe] the deferred-registration exclusion for todo_write is unpinned; only registerFactory is inspecteddocs/developers/tools/todo-write.md:33 — [probe] the 'When the AI uses this tool' section still describes the old default in unconditional present tensepackages/core/src/config/config.ts:9568 — [review] the TodoCreated/TodoCompleted hook docs and recipe carry no tools.todoWrite.enabled preconditionpackages/cli/src/acp-integration/session/Session.test.ts:35156 — [probe] the new daemon guidance test's assertion is satisfied by both todo_write messages, so it pins neither
中文说明
已审查。 建议见行内评论。
本轮确认的 1 条建议级发现已在 PR 上报告过,不再重复发布(列表见上方英文部分)。
未探索到全部深度(达到工具调用预算):chunk 11:could not execute prompts.test.ts / coreToolScheduler.test.ts to confirm green — the review worktree has no node_modules or packages/core/dist , so test …;"agent reverse-audit (round 1)":did not execute integration-tests/cli/qwen-serve-streaming.test.ts (daemon Todo Stop Guard replay) to confirm the added tools: { todoWrite: { enabled: true }…。
收敛姿态下延后(第 4 轮,非阻断)——已记录,本轮不要求修改:共 14 条(原文未翻译,列表见上方英文部分)。
— qwen3.8-max-2026-09-02 via Qwen Code /review (v0.22.3)
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Partially reviewed — gaps disclosed.
4 Suggestion-level finding(s) this review confirmed are already reported on this PR and are not repeated:
- R5-1 todo_write coreTools non-promotion pinned by no test — already reported in the round-2 deferral list (D2-2, review 5074197635)
- R5-2 experimental.sessionWorkflow silently requires tools.todoWrite.enabled without warn/docs parity — already reported in the round-4 deferral list (settings.md:621, review 5091170739)
- R5-3 default-off deferred-registration cell unpinned (only registerFactory inspected) — already reported in the round-4 deferral list (config.test.ts:9470, review 5091170739)
- R5-4 enabled-variant prompt rendering pinned only by placement-blind substrings — already reported in the round-4 deferral list (prompts.test.ts:92, review 5091170739)
Not reviewed: build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally.
Not explored to full depth (tool budget reached): chunk 6: run cd packages/core && npx vitest run src/core/prompts.test.ts to mechanically confirm the regenerated snapshot matches (worktree has no node_modules; instal…; chunk 9: running packages/core prompts.test.ts to confirm snapshots pass — node_modules is absent in this review worktree; verified instead by verbatim text comparison…; chunk 5: run prompts.test.ts to execute the regenerated snapshots — the worktree has no node_modules / dist , and a monorepo install + build was out of budget; substi….
Deferred under the convergence posture (round 5, not a blocker) — recorded, not requested in this round:
packages/core/src/core/coreToolScheduler.ts:335 — [probe] D5-1 the todo_write attribution fallback branch is pinned by no test (probe: reachable in bare mode with the flag on and a null permission manager)packages/core/src/core/coreToolScheduler.ts:293 — [probe] D5-2 the LS branch never attributes the core-tools allowlist on the daemon/ACP path this PR newly wires into Session.ts (advice that can never register the tool)
中文说明
仅完成部分审查,审查缺口已披露。
本轮确认的 4 条建议级发现已在 PR 上报告过,不再重复发布(列表见上方英文部分)。
未审查:build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally。
未探索到全部深度(达到工具调用预算):chunk 6:run cd packages/core && npx vitest run src/core/prompts.test.ts to mechanically confirm the regenerated snapshot matches (worktree has no node_modules; instal…;chunk 9:running packages/core prompts.test.ts to confirm snapshots pass — node_modules is absent in this review worktree; verified instead by verbatim text comparison…;chunk 5:run prompts.test.ts to execute the regenerated snapshots — the worktree has no node_modules / dist , and a monorepo install + build was out of budget; substi…。
收敛姿态下延后(第 5 轮,非阻断)——已记录,本轮不要求修改:共 2 条(原文未翻译,列表见上方英文部分)。
— qwen3.8-max via Qwen Code /review (v0.22.3)
|
@qwen-code /resolve |
|
Qwen Code resolved the merge conflicts and pushed the branch update. Root causemain's PR #10761 (commit Textual or semanticBoth sides edited the same constructs, but the changes are orthogonal — the union is correct: // client.ts: PR's Pick member + #10761's intersection
type MainSessionPromptConfig = Pick<Config, … | 'isTodoWriteEnabled'> &
Partial<Pick<Config, 'isTrustedFolder'>>;
// ArenaManager.ts: #10761 replaced the style arg; PR appended a new arg
getCoreSystemPrompt(undefined, model.modelId, undefined, 'headless',
this.resolvePeerOutputStyle(), // #10761: replaces getOutputStyle()
this.config.isTodoWriteEnabled(), // PR: new last argument
)The test mock keeps the PR's What is load-bearing
What I could not verify
中文说明根因:main 的 PR #10761(commit 文本还是语义:双方改了同一处结构,但改动正交,取并集即正确(见上方代码块)。 关键点: 未能验证:未运行构建/类型检查/测试。 |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Partially reviewed — gaps disclosed.
1 Suggestion-level finding(s) this review confirmed are already reported on this PR and are not repeated:
- integration tests unreachable by workspace test lanes (integration-tests/cli/todo_write.test.ts, list_directory.test.ts, qwen-serve-streaming.test.ts, test-helper.ts) — already recorded in the round-2 deferral list (D2-4, review 5074197635)
Not reviewed: build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally.
Deferred under the convergence posture (round 6, not a blocker) — recorded, not requested in this round:
packages/core/src/core/prompts.ts:590 — [probe] D6-1 QWEN_WRITE_SYSTEM_MD dump forwards todoWriteEnabled but no test pins the dumped content (mutant survives; re-feeding the dump as QWEN_SYSTEM_MD silently drops Todo guidance)
中文说明
仅完成部分审查,审查缺口已披露。
本轮确认的 1 条建议级发现已在 PR 上报告过,不再重复发布(列表见上方英文部分)。
未审查(原文为英文):build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally.
收敛姿态下延后(第 6 轮,非阻断)——已记录,本轮不要求修改:共 1 条(原文未翻译,列表见上方英文部分)。
— qwen3.8-max via Qwen Code /review (v0.23.0)
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Deferred under the convergence posture (round 7, not a blocker) — recorded, not requested in this round:
packages/core/src/core/prompts.test.ts:942 — [probe] the new wiring test pins only the enabled direction at getMainSessionBaseSystemPrompt; the disabled direction is unguarded at the client.ts:392 read site
中文说明
收敛姿态下延后(第 7 轮,非阻断)——已记录,本轮不要求修改:共 1 条(原文未翻译,列表见上方英文部分)。
— qwen3.8-max via Qwen Code /review (v0.23.0)
|
@qwen-code /triage |
qqqys
left a comment
There was a problem hiding this comment.
APPROVE (verified at head b6f33ce)
Historical blocking items — re-verified against the exact head
- R6-1 (Critical, round-6 CHANGES_REQUESTED at fd73049) — fixed at head. The prescribed member is present in the trust-gate
makeConfig(prompts.test.ts:973, inside themain-session style: project trust gatedescribe starting at :952), mirroring the sibling helper at :845 — and the compile symptom that made it Critical (packages/coreTS2345 halting every dependent build) is disproven at this head by the greenLint & Statictypecheck lane, which is the job that would halt before any test could emit. The three named trust-gate tests were not re-run in this pass (theTest (ubuntu-latest)leg shows a cancellation, not a failure); the code-level member presence plus the green typecheck is what retires the blocker. - R1-10 (Critical, round-2) — long closed. The broken
client.test.tsmocks now carry the member, no later round re-raised it, and rounds 3–7 carry no unresolved Critical list. - The
reviewDecisionflag still reads CHANGES_REQUESTED only because the requesting bot's later rounds were COMMENT-class and never procedurally flipped it; the head round posted zero findings, and the maintainer approved this exact commit.
My Critical-only scan of the opt-in surface
- Default-off is fail-safe in the right direction:
todoWriteEnableddefaults tofalseat every prompt entry point, so guidance can never advertisetodo_writewhen registration is gated off by the same flag (registerLazy(TODO_WRITE)sits behindisTodoWriteEnabled(); the AgentTooltodo_idschema field and description drop with it; the 192-line snapshot shift tracks the prompt change). experimental.todoStopGuardnow ANDs with the tool flag and emits a debug warning naming the dependency when configured-but-inert — no silently-live stop guard over an unregistered tool.getOptInToolNotFoundMessageis bounded diagnostics only (exact-map +Object.hasOwnon canonicalized names, registered-tool short-circuit, precedence workspace-toggle → deny-rule → core-tools-allowlist → setting, otherwise the original not-found error); it cannot gate execution or expose anything beyond setting names already documented.- The
new-appSKILL step and docs were de-referenced fromtodo_writeconsistently with the opt-in posture.
CI at head
25 green including Lint & Static; Test (ubuntu-latest) shows the recurring shared-pool cancellation (not a failure) with one run still queued — non-attributable, non-gating per policy. The thread also carries headless and tmux E2E reports from earlier heads; the human maintainer approved this exact head.
|
Sandboxed verification: The verification job did not complete (checkout, runner, or setup error) and produced no report. See the workflow run for details. 中文 — 判定:
|
Code reviewNo Critical findings. I read the whole production diff (267 lines across 9 files) and traced every consumer of the new flag rather than taking the description's word for it. What I verified, because these are the places a change like this usually goes wrong:
Two Suggestions, neither blocking:
sequenceDiagram
participant P1 as settings tools.todoWrite.enabled
participant P2 as CLI config loader
participant P3 as core Config
participant P4 as ToolRegistry
participant P5 as system prompt
participant P6 as Agent tool schema
participant P7 as ACP Session stop guard
participant P8 as CoreToolScheduler
P1->>P2: read setting, absent means false
P2->>P3: todoWriteEnabled, default false
P3->>P4: register todo_write only when enabled
P3->>P5: Task Management guidance only when enabled
P3->>P6: todo_id field only when enabled
P3->>P7: stop guard ANDs with enabled, warns when inert
P4-->>P8: legacy call arrives, tool not registered
P8-->>P8: actionable error naming the setting
Files changed (16 of 30 shown)
TestingEvidence carried here: the PR's own CI, read through the API. Per the review rules I did not build, run, or execute anything from this PR's tree — no The headline: the unit-test lane is
All four failures are outside this PR's diff, and I classified each from the code rather than from the log's own prose:
Items 2–4 are all filesystem-watcher timing assertions with 2–5 second budgets, on a self-hosted runner whose own telemetry shows a sustained load average of 220–240 for the entire two hours ( Meanwhile every test file this PR touches passed in that same run:
Typecheck evidence, and a correction to the record:
The green Not verified, and why:
Sandboxed verification would settle both open ends, and the author has write access so neither needs sponsoring: 中文说明代码审查未发现 Critical 问题。我读完了全部生产代码 diff(9 个文件、267 行),并亲自追踪了新开关的每一个使用方,而不是照搬 PR 描述。 以下是我核实过的、这类改动最容易出问题的地方:
两条 Suggestion,均不阻塞:
(流程图见上,此处不重复。) 测试本节携带的证据:PR 自身的 CI,通过 API 读取。 按审查规则,我没有构建、运行或执行本 PR 代码树中的任何东西——没有 核心结论:单元测试 lane 是
四个失败全部在本 PR diff 之外,且我依据代码而非日志自述来分类:
第 2–4 项都是预算 2–5 秒的文件系统 watcher 时序断言,而运行它们的 self-hosted runner 自身遥测显示整整两小时负载均值维持在 220–240( 同时,本 PR 触及的每一个测试文件在同一次运行中都通过(见上表)。 关于类型检查证据,以及对既有记录的一处更正: (CI 结论表见上,位于机器可读标记区内,不在此重复。) green 的 未验证项及原因:
沙箱验证可以了结这两个悬而未决的点,且作者具备 write 权限,因此两者都无需 sponsored: — Qwen Code · qwen3.8-max-2026-09-02 Reviewed at |
|
Confidence: 3/5 — the code review is clean and I'd defend every line of it; what I can't give you is a green end-to-end run of the behaviour this PR exists to change. Going back to the proposal I wrote before opening the diff: I said I'd add a If I had to maintain this in six months I'd thank the author. The flag defaults false at every layer, so the failure mode of forgetting to wire something up is "Todo guidance missing" rather than "prompt advertises a tool that isn't registered" — that asymmetry is the whole ballgame for a change like this and they got it right. Generalizing the existing list_directory not-found explanation into one shared helper instead of copy-pasting it for a second tool was the correct instinct, and the precedence order in that helper is more thoughtful than it needed to be. There's a design doc, the schema was regenerated rather than hand-edited, and the existing model-driven integration scenario was opted in instead of being left to rot. Nothing here is trying too hard. So why not approve. Two things, and neither is hygiene. First, the lane that would prove the end-to-end behaviour never ran. Second, this pass grew into I want to be precise about what I am not saying. I found no Critical. I don't think this PR is wrong, over-scoped, or solving a fake problem — the direction question I stopped on at The gap is cheap to close and doesn't need a new push: ⏸️ Deferring to @jifeng — no code-level blocker, but the unit-test lane on this head ended 中文说明Confidence: 3/5 —— 代码审查是干净的,其中每一行我都愿意为其辩护;我给不出的,是这个 PR 存在的目的所要改变的行为的一次 green 端到端运行。 回到我在打开 diff 之前写下的方案:我会新增一个 如果六个月后由我来维护这份代码,我会感谢作者。开关在每一层都默认 false,所以"漏接某处"的失败模式是"缺少 Todo 指导",而不是"提示词宣传了一个未注册的工具"——对这类改动而言,这个不对称性就是全部关键,而他们做对了。把既有的 list_directory not-found 说明泛化为一个共享 helper、而不是为第二个工具复制粘贴,是正确的直觉;该 helper 中的优先级顺序也比必需的更为周全。这里有设计文档,schema 是重新生成而非手改的,既有的模型驱动集成场景被显式开启而不是任其腐坏。这份改动没有任何用力过猛之处。 那么为什么不批准。两件事,都不是卫生问题。 第一,能够证明端到端行为的 lane 从未运行。 第二,本轮改动扩展到了 我想精确说明我没有在说什么。我没有发现 Critical。我不认为这个 PR 是错的、范围过大的,或在解决一个假问题——我在 这个缺口关闭成本很低,且不需要新的 push: ⏸️ 转交 @jifeng —— 没有代码级阻塞项,但该 head 上的单元测试 lane 以 — Qwen Code · qwen3.8-max-2026-09-02 Reviewed at |
|
Released in v0.23.1. |
Qwen Code v0.23.1 made the built-in todo_write tool opt-in through tools.todoWrite.enabled (QwenLM/qwen-code#10645). Generate already spread a hand-written value, but the curated import allow-list dropped it, so an import -> generate round trip lost the key. Add it to QWEN_OVERRIDE_TOOLS_KEYS with a global-machine-wide scope note (upstream lists it in no workspace-scope restriction at v0.23.4), the round-trip and note tests, and the two prose key lists. Refs dyoshikawa#2668 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019yLN6CVqeZ8HCrjRb9o7mK
What this PR does
This change removes the built-in
todo_writetool from the default tool surface in every interaction mode. Users who still rely on Todo can opt in withtools.todoWrite.enabled: trueand restart Qwen Code.When Todo is disabled, the default system prompt and Agent tool schema no longer advertise Todo-specific behavior, and an attempted legacy call returns an actionable error naming the setting. Enabling the setting restores registration, prompt guidance, Todo-to-Agent association, persistence, hooks, ACP rendering, and daemon Stop Guard compatibility.
The built-in new-application workflow now tracks implementation steps without requiring Todo. Existing Todo history and sidecars remain readable; no data is deleted.
Why it's needed
In headless mode, Todo bookkeeping adds an entire model round while text output hides the call and JSON formats expose it only as a generic tool event. Stronger models can maintain and revise their approach without a mandatory checklist, while agent-team workflows already have incremental shared task objects. Making Todo opt-in reduces the default prompt and tool surface and avoids invisible latency without removing the capability.
Reviewer Test Plan
How to verify
todo_write, the stable base prompt does not mention it, and a forced legacy call explains how to enable it."tools": { "todoWrite": { "enabled": true } }, restart, and repeat. Verifytodo_writeis declared, the Task Management guidance is present, and a Todo call succeeds and reaches the follow-up model turn.todo_idappears only when Todo is enabled.Evidence (Before & After)
Before: Latest
maindeclaredtodo_writein headless mode by default. A forced call required two model turns; text mode showed only the final answer, while JSON modes emitted generic tool events.After: The deterministic bundled-CLI integration test omits the declaration and Todo guidance by default and returns an actionable opt-in error for a forced call. With the switch enabled, declaration, prompt guidance, execution, and follow-up delivery are restored.
Tested on
Environment (optional)
Local macOS worktree on Node.js v24.18.0 and npm 11.16.0. Verification included the repository build, typecheck, lint, bundle, targeted unit tests, generated settings-schema consistency, and deterministic headless integration tests against a local fake OpenAI-compatible server.
Risk & Scope
tools.todoWrite.enabledtotrueand restart Qwen Code to preserve the previous behavior. Existing Todo data and historical records are retained.Linked Issues
None.
中文说明
本 PR 做了什么
这个改动从所有交互模式的默认工具集合中移除了内置
todo_write工具。仍然依赖 Todo 的用户可以设置tools.todoWrite.enabled: true,并重启 Qwen Code 来显式开启它。Todo 关闭时,默认系统提示词和 Agent 工具 schema 不再引导模型使用 Todo 专属行为;旧模型或历史上下文仍尝试调用时,会收到包含开关名称的可操作错误提示。开启设置后,工具注册、提示词指导、Todo 与 Agent 的关联、持久化、hooks、ACP 渲染以及 daemon Stop Guard 兼容行为都会恢复。
内置的新应用工作流现在会直接按实施步骤推进,不再强制依赖 Todo。已有的 Todo 历史和 sidecar 仍可读取,不会删除任何数据。
为什么需要这个改动
在 headless mode 下,Todo 记账会额外消耗一整个模型轮次,而文本输出会隐藏工具调用,JSON 格式也只会把它展示成通用工具事件。能力更强的模型可以在没有强制清单的情况下维护并调整实施思路,而 agent-team 工作流已经提供了可增量更新的共享任务对象。把 Todo 改成显式开启,可以缩小默认提示词和工具集合,消除用户看不到的额外延迟,同时保留原有能力。
Reviewer 测试计划
如何验证
todo_write,稳定基础提示词不包含它,并且强制发出的旧式调用会说明如何开启该工具。"tools": { "todoWrite": { "enabled": true } },重启后重复验证。确认请求声明了todo_write,提示词包含 Task Management 指导,Todo 调用成功,并进入携带工具结果的下一模型轮次。todo_id。证据(改动前后)
改动前:最新
main会在 headless mode 中默认声明todo_write。一次强制调用需要两个模型轮次;文本模式只显示最终答案,JSON 模式则输出通用工具事件。改动后:基于 bundle 的确定性 CLI 集成测试证明,默认配置不再声明工具或包含 Todo 指导,强制调用会返回可操作的开启提示;打开开关后,工具声明、提示词指导、成功执行和后续轮次传递都会恢复。
测试平台
环境(可选)
本地 macOS worktree,Node.js v24.18.0,npm 11.16.0。验证范围包括仓库 build、typecheck、lint、bundle、定向单元测试、生成设置 schema 一致性检查,以及针对本地假 OpenAI 兼容服务的确定性 headless 集成测试。
风险与范围
tools.todoWrite.enabled设为true并重启 Qwen Code。已有 Todo 数据和历史记录会保留。关联 Issue
无。