Skip to content

fix(review): make agent launches and cleanup resilient - #7259

Merged
wenshao merged 11 commits into
QwenLM:mainfrom
wenshao:fix/review-agent-launch-cleanup
Jul 21, 2026
Merged

fix(review): make agent launches and cleanup resilient#7259
wenshao merged 11 commits into
QwenLM:mainfrom
wenshao:fix/review-agent-launch-cleanup

Conversation

@wenshao

@wenshao wenshao commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator

What this PR does

This PR makes /review resilient when a provider supplies both a caller-owned working_dir and the redundant isolation: "worktree" field. The Agent tool now reuses the validated caller-owned worktree, identical validation failures in one model response count as one retry, and review worktrees are protected by prompt-scoped leases that are released on normal completion, TUI failures, loop termination, and headless fatal cancellation. It also tightens Issue Fidelity guidance so references to motivating incidents are not misclassified as target issues.

Why it's needed

A real /review session successfully prepared its PR context and roster but every review agent failed because the model sent both workspace fields. Three identical validation failures in the same response exhausted the retry budget, skipped the remaining agents, and left the review worktree and branch behind. Prompt-only prohibitions are not sufficient for strict providers, and the cancellation path exits through the global cleanup chain before a function-level finally can reliably protect these resources.

Reviewer Test Plan

How to verify

Run the focused Agent and scheduler tests and confirm that a real caller-owned worktree is reused when both fields are supplied, no additional isolation worktree is created, and repeated validation errors are counted once per model response. Run the focused CLI review and cleanup tests and confirm that leases are prompt-scoped, child prompts cannot release parent resources, explicit cleanup disarms the finalizer, and a lease registered before worktree creation still protects the completed worktree. For end-to-end verification, run /review with the repository's executable CLI entry, interrupt the active prompt with one SIGINT after the review worktree is created, and confirm that the lease, worktree, and temporary branch are all removed before exit.

Evidence (Before & After)

Before: a strict-provider Agent launch with working_dir plus isolation: "worktree" failed validation; same-response failures exhausted the retry budget; abnormal review termination could leave .qwen/tmp/review-pr-* and qwen-review/pr-* behind.

After: the caller-owned worktree is reused without creating another worktree, one correction turn remains available, and a real SIGINT E2E ended with process=no lease=no worktree=no branch=no.

Tested on

OS Status
🍏 macOS
🪟 Windows ⚠️
🐧 Linux ⚠️

Environment (optional)

Node.js 22+, local production bundle built with npm run build && npm run bundle; real-model headless E2E used scripts/cli-entry.js so nested review commands executed the same build.

Risk & Scope

  • Main risk or tradeoff: cleanup now participates in the process-wide fatal-exit registry while a headless prompt is active; normal prompt completion unregisters it, and ownership matching limits cleanup to the exact session, prompt, and repository.
  • Not validated / out of scope: ACP/daemon abnormal cleanup has a different multi-session lifecycle and is intentionally deferred; Windows and Linux were not tested locally; roster prompt-body compression was rejected because it would weaken delivery-receipt verification.
  • Breaking changes / migration notes: none.

Linked Issues

Related to #7235; this adds runtime resilience beyond the prompt-level prohibition.

中文说明

此 PR 做了什么

此 PR 提升 /review 在 provider 同时提供 caller-owned working_dir 与冗余 isolation: "worktree" 时的韧性。Agent 工具现在会复用已校验的 caller-owned worktree;同一个模型响应中的相同参数校验错误只计作一次重试;review worktree 由 prompt-scoped lease 保护,并会在正常完成、TUI 失败、loop 终止和 headless 致命取消时释放。同时收紧 Issue Fidelity 指引,避免将用于说明动机的历史事件引用误判为目标 issue。

为什么需要

一次真实 /review 会话成功准备了 PR 上下文和 roster,但模型同时发送两个 workspace 字段,导致所有 review agent 失败。同一响应中的三个相同校验错误耗尽了重试预算,后续 agent 被跳过,并遗留 review worktree 与分支。仅依靠 prompt 禁止不足以约束 strict provider,而且取消路径会通过全局 cleanup 链退出,不能只依赖函数级 finally 保护这些资源。

Reviewer Test Plan

如何验证

运行 Agent 与 scheduler 定向测试,确认两个字段同时提供时会复用真实 caller-owned worktree,不创建额外 isolation worktree,并且重复校验错误按每个模型响应只计一次。运行 CLI review 与 cleanup 定向测试,确认 lease 按 prompt 隔离、child prompt 无法释放 parent 资源、显式 cleanup 会解除 finalizer,并且在 worktree 创建前登记的 lease 仍能保护随后创建完成的 worktree。端到端验证时,使用仓库的可执行 CLI 入口运行 /review,在 review worktree 创建后向活跃 prompt 发送一次 SIGINT,确认退出前 lease、worktree 和临时分支均已删除。

证据(之前与之后)

之前:strict provider 发送 working_dirisolation: "worktree" 时 Agent 启动校验失败;同一响应中的失败会耗尽重试预算;review 异常终止可能遗留 .qwen/tmp/review-pr-*qwen-review/pr-*

之后:caller-owned worktree 被直接复用且不会创建额外 worktree,模型仍有一次纠错机会,真实 SIGINT E2E 最终状态为 process=no lease=no worktree=no branch=no

测试平台

OS 状态
🍏 macOS
🪟 Windows ⚠️
🐧 Linux ⚠️

环境(可选)

Node.js 22+,通过 npm run build && npm run bundle 构建本地生产 bundle;真实模型 headless E2E 使用 scripts/cli-entry.js,确保嵌套 review 命令执行同一份构建。

风险与范围

  • 主要风险或取舍:headless prompt 活跃期间,cleanup 会注册到进程级致命退出清理链;正常 prompt 完成时会注销,ownership 匹配将清理范围限制在精确的 session、prompt 与 repository。
  • 未验证 / 范围外:ACP/daemon 异常清理具有不同的多 session 生命周期,本次有意延后;Windows 与 Linux 未在本地测试;roster prompt body 压缩因会削弱 delivery receipt 验证而未实施。
  • 破坏性变更 / 迁移说明:无。

关联 Issue

#7235 相关;本 PR 在 prompt 级禁止之外增加 runtime 韧性。

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@qwen-code-ci-bot

qwen-code-ci-bot commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the PR!

Template looks good ✓

Problem: observed bug with evidence — a real /review session failed when a strict provider sent both working_dir and isolation: "worktree", exhausting the retry budget and leaking the worktree. Related to #7235 (the prompt-level prohibition, already merged); this adds runtime resilience on top.

Direction: aligned. Making /review robust against strict-provider schema behavior is squarely within core mission. The CHANGELOG doesn't reference this directly, but the area is clearly relevant — #7235 was merged for exactly this failure mode.

Size: core paths touched (coreToolScheduler.ts 24 prod lines, agent.ts 26 prod lines, SKILL.md 2 lines). Total production: ~348 lines, test: ~721 lines. Under the 500-line awareness threshold.

Approach: scope feels right. Three focused fixes that each address a distinct failure mode: (1) accept redundant isolation when working_dir is set, (2) count identical validation errors once per model response batch, (3) lease-based worktree cleanup on abnormal termination. The ca.js formatting change is a harmless drive-by. No unrelated refactors or scope creep.

Moving on to code review. 🔍

中文说明

感谢贡献!

模板完整 ✓

问题:已观测到的 bug,有证据——一次真实 /review 会话因 strict provider 同时发送 working_dirisolation: "worktree" 而失败,耗尽重试预算并遗留 worktree。与 #7235(已合并的 prompt 级禁止)相关;本 PR 在此基础上增加 runtime 韧性。

方向:对齐。让 /review 对 strict provider 的 schema 行为具备鲁棒性属于核心使命。CHANGELOG 未直接提及,但该领域明显相关——#7235 正是为此失败模式而合并。

规模:触及核心路径(coreToolScheduler.ts 24 行生产代码,agent.ts 26 行,SKILL.md 2 行)。总生产代码约 348 行,测试约 721 行。低于 500 行关注阈值。

方案:范围合理。三个聚焦修复分别对应不同失败模式:(1) 当 working_dir 已设置时接受冗余 isolation,(2) 同一模型响应中相同校验错误只计一次,(3) 基于 lease 的 worktree 异常终止清理。ca.js 格式修改是无害的顺手修复。无无关重构或范围蔓延。

进入代码审查 🔍

Qwen Code · qwen3.7-max

Reviewed at 7a74214c0a5bdd81333af3dcdd0933694a913f9e · re-run with @qwen-code /triage

@qwen-code-ci-bot

qwen-code-ci-bot commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator

Code Review

Independent proposal: given the problem (strict providers send both working_dir and isolation), I would (1) relax the agent validation to ignore isolation when working_dir is present, (2) deduplicate identical validation errors within a single model response so the retry budget isn't exhausted by one mistake repeated N times, and (3) add a file-based lease so abnormal termination can still clean up the review worktree. The PR matches this approach closely.

Findings: no critical blockers.

The recordBatchRetryableToolError closure in coreToolScheduler.ts is correct — it records the first occurrence via the existing recordRetryableToolError, then returns the cached count for duplicates within the same batch. Cross-batch accumulation still works because the underlying validationRetryCounts map persists across schedule() calls.

The lease service (review-worktree-lease.ts) has proper safety rails: validTarget restricts to pr-\d+ (no path traversal), removeLeaseWorktree validates the worktree is inside REVIEW_TMP_DIR via relative(), the branch name is checked against reviewBranch(), and ownership matching (sessionId + promptId) prevents cross-session cleanup. The fallback path (rmSync + prune) when git worktree remove fails is a reasonable degradation.

The useGeminiStream.ts change correctly pairs the new early return StreamProcessingStatus.UserCancelled with moving dualOutput?.finalizeAssistantMessage() inside the cancel block, so finalization still happens on the early-exit path. The cleanupReviewLease flag in the finally block covers cancel, loop-detection, and error paths uniformly.

The registerCleanup returning an unregister function is a minimal, backward-compatible API extension (existing callers ignore the return value).

Real-Scenario Testing

Built the PR (npm run build && npm run bundle) and drove review fetch-pr + review cleanup in tmux with session/prompt env vars set:

$ QWEN_CODE_SESSION_ID=test-session QWEN_CODE_PROMPT_ID=test-prompt \
    node scripts/cli-entry.js review fetch-pr 7259 QwenLM/qwen-code \
    --out /tmp/review-7259-state.json

From https://github.com/QwenLM/qwen-code
 * [new ref]             refs/pull/7259/head -> qwen-review/pr-7259
Preparing worktree (checking out 'qwen-review/pr-7259')
Wrote fetch-pr report to /tmp/review-7259-state.json
PR #7259 (QwenLM/qwen-code): 20 files, +1041/-28, base=main, head=fix/review-agent-launch-cleanup

$ cat .qwen/tmp/qwen-review-lease-pr-7259.json
{
  "sessionId": "test-session",
  "promptId": "test-prompt",
  "target": "pr-7259",
  "repositoryRoot": ".../test-pr-7259",
  "worktreePath": ".../test-pr-7259/.qwen/tmp/review-pr-7259",
  "branch": "qwen-review/pr-7259"
}

$ node scripts/cli-entry.js review cleanup pr-7259
Removed worktree: .qwen/tmp/review-pr-7259
Deleted ref: qwen-review/pr-7259

$ ls .qwen/tmp/qwen-review-lease-pr-7259.json  # GONE
$ ls .qwen/tmp/review-pr-7259                   # GONE
$ git branch --list 'qwen-review/pr-7259'       # empty

Lease created on fetch, cleared on cleanup; worktree and branch removed. ✓

Unit tests: all 646 tests pass across the 4 changed test files (agent 170, scheduler 299, lease+cleanup 20, useGeminiStream 157).

中文说明

代码审查

独立方案: 给定问题(strict provider 同时发送 working_dirisolation),我会 (1) 放宽 agent 校验,当 working_dir 存在时忽略 isolation,(2) 同一模型响应中相同校验错误去重以免耗尽重试预算,(3) 添加基于文件的 lease 以便异常终止时仍能清理 review worktree。PR 与此方案高度一致。

发现: 无关键阻塞。

coreToolScheduler.ts 中的 recordBatchRetryableToolError 闭包正确——首次出现通过现有 recordRetryableToolError 记录,后续重复返回缓存计数。跨批次累积仍正常工作。

lease 服务具有完善的安全防护:validTarget 限制为 pr-\d+(防路径穿越),removeLeaseWorktree 通过 relative() 验证 worktree 在 REVIEW_TMP_DIR 内,分支名与 reviewBranch() 校验,所有权匹配防止跨 session 清理。

useGeminiStream.ts 正确地将 dualOutput?.finalizeAssistantMessage() 移入 cancel 块内,配合新的 early return。

真实场景测试

构建 PR 后在 tmux 中驱动 review fetch-pr + review cleanup:lease 在 fetch 时创建,cleanup 时清除;worktree 和分支均被删除。✓

单元测试: 4 个变更测试文件共 646 个测试全部通过。

Qwen Code · qwen3.7-max

Reviewed at 7a74214c0a5bdd81333af3dcdd0933694a913f9e · re-run with @qwen-code /triage

@qwen-code-ci-bot

qwen-code-ci-bot commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator

Confidence: 4/5 — solid fix for a real observed failure; clean implementation with comprehensive tests and proper safety rails on the lease service.

This PR does three things well: it makes the Agent tool tolerant of strict providers that send redundant schema fields (the immediate cause of the /review failure), it prevents a single model mistake from exhausting the retry budget by counting identical errors once per batch, and it adds prompt-scoped lease protection so review worktrees don't leak on abnormal termination. Each fix is independently motivated and the tests cover the important edge cases (path traversal, cross-session ownership, child-prompt isolation, fallback pruning).

The implementation matches what I'd propose independently — no simpler path was missed. The lease service is the largest new addition but it earns its complexity: file-based leases survive process crashes that would skip finally blocks, and the ownership matching prevents one session from cleaning up another's resources. The registerCleanup unregister return is backward-compatible and the useGeminiStream integration covers all three abnormal-exit paths (cancel, loop, error) uniformly.

Only nit: the ca.js locale reformatting is unrelated drive-by, but it's a single line-wrap fix and not worth splitting.

中文说明

置信度:4/5 — 对真实观测失败的扎实修复;实现干净,测试全面,lease 服务有完善的安全防护。

此 PR 做好了三件事:让 Agent 工具容忍 strict provider 发送冗余 schema 字段(/review 失败的直接原因),防止单个模型错误通过批量去重耗尽重试预算,以及添加 prompt 级 lease 保护以防 review worktree 在异常终止时泄漏。每个修复都有独立动机,测试覆盖了重要边界情况。

实现与我的独立方案一致——没有遗漏更简路径。lease 服务是最大的新增,但其复杂度物有所值:基于文件的 lease 能在进程崩溃(跳过 finally)后存活,所有权匹配防止跨 session 清理。

唯一小问题:ca.js 的格式重排是无关的顺手修改,但只是一行换行,不值得拆分。

Qwen Code · qwen3.7-max

Reviewed at 7a74214c0a5bdd81333af3dcdd0933694a913f9e · re-run with @qwen-code /triage

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM, looks ready to ship. ✅

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Reviewed. Suggestions are inline.

— qwen3.8-max-preview via Qwen Code /review

Comment thread packages/core/src/tools/agent/agent.ts
Comment thread packages/cli/src/services/review-worktree-lease.ts Outdated
Comment thread packages/cli/src/services/review-worktree-lease.ts
Comment thread packages/cli/src/services/review-worktree-lease.ts
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Reviewed diff-only — the PR’s existing discussion could not be fetched, so this is not an approval and not a no-blockers claim. Suggestions are inline. 1 Suggestion-level finding(s) could not be anchored to a changed line and were dropped; nothing further to act on here. Not reviewed: issue-fidelity — pr-context failed (HTTP 503), Agent 0 skipped. Not reviewed: build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally. Not reviewed: Agent 0: Issue fidelity & root-cause ownership — its prompt was built, but no agent on record was launched with it.

— qwen3.8-max-preview via Qwen Code /review

Comment thread packages/cli/src/services/review-worktree-lease.ts Outdated
Comment thread packages/cli/src/services/review-worktree-lease.ts Outdated
Comment thread packages/core/src/core/coreToolScheduler.ts

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed. Suggestions are inline. Not reviewed: build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally.

— qwen3.8-max-preview via Qwen Code /review

Comment thread packages/cli/src/services/review-worktree-lease.ts
Comment thread packages/cli/src/ui/hooks/useGeminiStream.ts
Comment thread packages/cli/src/nonInteractiveCli.ts Outdated
Comment thread packages/cli/src/commands/review/cleanup.ts
Comment thread packages/cli/src/services/review-worktree-lease.test.ts
Comment thread packages/cli/src/services/review-worktree-lease.test.ts
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@wenshao

wenshao commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /takeover

@qwen-code-dev-bot qwen-code-dev-bot added the autofix/takeover Summon the autofix loop to manage this PR (remove to release; needs triage+) label Jul 20, 2026
@QwenLM QwenLM deleted a comment from qwen-code-ci-bot Jul 20, 2026
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤝 Takeover engaged: the autofix loop now manages this PR — it will address new review feedback and resolve base conflicts until the label is removed or the round cap is reached. Remove the autofix/takeover label (or comment @qwen-code /takeover stop) to release.

中文说明

🤝 已接管:autofix 循环现在管理此 PR —— 将持续处理新的评审反馈与 base 冲突,直到移除标签或达到轮次上限。移除 autofix/takeover 标签(或评论 @qwen-code /takeover stop)即可释放。

@yiliang114

Copy link
Copy Markdown
Collaborator

@qwen-code /resolve

Resolve conflict in coreToolScheduler.ts by combining PR's
recordBatchRetryableToolError deduplication helper with main's
plan-mode entry boundary skip logic and indexed loop iteration.
@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

Qwen Code resolved the merge conflicts and pushed the branch update.

Merge Conflict Resolution Summary — PR #7259

Conflict

File: packages/core/src/core/coreToolScheduler.ts

A single conflict region around the tool-processing loop in processNextBatch().

PR branch (HEAD) added:

  • retryErrorsRecordedInBatch map and recordBatchRetryableToolError helper — deduplicates retry-error recording within a batch so duplicate error messages don't inflate counters and trigger false RETRY LOOP DETECTED warnings.
  • Loop form: for (const reqInfo of requestsToProcess)

main added:

  • Changed the loop to for (const [requestIndex, reqInfo] of requestsToProcess.entries()) to track the iteration index.
  • Added planModeEntryBoundaryIndex computation and a guard inside the loop that rejects sibling tool calls when a plan-mode entry tool is present in the batch (only the boundary-indexed call proceeds; others get PLAN_MODE_ENTRY_SIBLING_SKIP_MESSAGE).

Resolution

Combined both sides:

  1. Kept the PR's retryErrorsRecordedInBatch / recordBatchRetryableToolError helper (referenced at two call sites later in the function).
  2. Adopted main's .entries() loop form with requestIndex.
  3. Kept main's plan-mode entry boundary skip guard inside the loop body.

No other files were modified — all other files auto-merged cleanly.

Commit

fix(review): merge main into agent-launch-cleanup branch

Resolve conflict in coreToolScheduler.ts by combining PR's
recordBatchRetryableToolError deduplication helper with main's
plan-mode entry boundary skip logic and indexed loop iteration.

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed. Suggestions are inline. 1 Suggestion-level finding(s) could not be anchored to a changed line and were dropped; nothing further to act on here. Not reviewed: chunk 3, chunk 2, chunk 1, chunk 4 — launched with a prompt that is not the one the CLI built. Not reviewed: Agent 0: Issue fidelity & root-cause ownership, Test coverage matrix (whole-diff), Agent 1b: Removed-behavior audit, Agent 1c: Cross-file tracer, Agent 7: Build & test verification — its prompt was built, but no agent on record was launched with it. Not reviewed: reverse audit — an auditor ran and opened its brief, but no agent was launched with the prompt the CLI built — the launch was written by hand, and what the agent was actually asked is not what this skill certifies. Not reviewed: verification — the review posts findings, but no verifier was launched with a prompt this skill builds — they were ruled on, if at all, without the verdict bar its brief carries.

— qwen3.7-max via Qwen Code /review

Comment thread packages/cli/src/ui/hooks/useGeminiStream.ts
Comment thread packages/cli/src/commands/review/cleanup.ts
Comment thread packages/core/src/core/coreToolScheduler.ts
wenshao and others added 2 commits July 20, 2026 17:26
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed — no blockers. Suggestions are inline.

— qwen3.7-max via Qwen Code /review

Comment thread packages/cli/src/commands/review/cleanup.test.ts
Comment thread scripts/tests/qwen-autofix-workflow.test.js
Comment thread packages/cli/src/ui/hooks/useGeminiStream.ts
@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 Addressed the latest review feedback (round 1/100). What changed, and what I pushed back on:

Review feedback addressed

Commit: 7a74214c0 — test-only changes, no production code modified.

Feedback points

# File Reviewer Finding Decision
1 cleanup.test.ts:100 @qwen-code-ci-bot [Suggestion] Success path for clearReviewWorktreeLease is untested ✅ Implemented — added a test that verifies the lease is cleared with (process.cwd(), 'pr-123') when cleanup succeeds
2 qwen-autofix-workflow.test.js:2367 @qwen-code-ci-bot [Suggestion] Old not.toContain('if git diff --quiet') assertion was dropped instead of kept alongside the new one ✅ Implemented — restored the old assertion so both the simple and compound conditional forms are covered
3 useGeminiStream.ts:2946 @qwen-code-ci-bot [Suggestion] Only the UserCancelled path has a cleanup assertion; error and loop-detected paths are untested ✅ Implemented — added a cleanup assertion to the existing loop-detected test and a new "stream throws" test covering the catch-path cleanup
4 coreToolScheduler.ts:2125 @qwen-code-ci-bot [Suggestion] Duplicate branch deletes ALL validationRetryCounts entries for the tool ⏭️ No change — @wenshao already explained the current behavior is intentional: validationRetryCounts tracks consecutive occurrences of one error per tool, and the A/B/A restoration is the fix from 9c964d1. The focused validation-retry suite passes.

Verification

  • cleanup.test.ts: 2/2 passed
  • useGeminiStream.test.tsx: 157/157 passed
  • qwen-autofix-workflow.test.js: 63/63 passed
  • npm run typecheck: passed
  • eslint on changed files: passed

Conflict

No conflict (--conflict false).

中文说明

已处理的审查反馈

提交:7a74214c0 — 仅测试文件变更,未修改生产代码。

反馈要点

# 文件 审查者 发现 决定
1 cleanup.test.ts:100 @qwen-code-ci-bot [建议] clearReviewWorktreeLease 的成功路径未被测试覆盖 ✅ 已实现 — 添加了测试,验证清理成功时 lease 以 (process.cwd(), 'pr-123') 被清除
2 qwen-autofix-workflow.test.js:2367 @qwen-code-ci-bot [建议] 旧的 not.toContain('if git diff --quiet') 断言被移除而非保留 ✅ 已实现 — 恢复了旧断言,使简单条件形式和复合条件形式均被覆盖
3 useGeminiStream.ts:2946 @qwen-code-ci-bot [建议] 仅 UserCancelled 路径有清理断言;error 和 loop-detected 路径未被测试 ✅ 已实现 — 在现有的 loop-detected 测试中添加了清理断言,并新增了 "stream throws" 测试覆盖 catch 路径的清理
4 coreToolScheduler.ts:2125 @qwen-code-ci-bot [建议] 重复分支删除了该工具的所有 validationRetryCounts 条目 ⏭️ 未修改 — @wenshao 已解释当前行为是有意为之:validationRetryCounts 跟踪每个工具单一错误的连续出现次数,A/B/A 恢复是 9c964d1 中的修复。相关验证重试测试套件通过。

验证结果

  • cleanup.test.ts:2/2 通过
  • useGeminiStream.test.tsx:157/157 通过
  • qwen-autofix-workflow.test.js:63/63 通过
  • npm run typecheck:通过
  • eslint(变更文件):通过

冲突

无冲突(--conflict false)。

Base-conflict check: no conflict with main.

Re-review when you have a moment. After round 100 this bot stops and leaves the PR for a human.


🧠 Handled by Qwen Code · model/模型 qwen3.8-max-preview

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Reviewed. Suggestions are inline. Not reviewed: build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally.

— qwen3.8-max-preview via Qwen Code /review

Comment thread packages/cli/src/commands/review/cleanup.test.ts
Comment thread packages/cli/src/ui/hooks/useGeminiStream.ts
Comment thread scripts/tests/qwen-autofix-workflow.test.js
@wenshao

wenshao commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /review

@github-actions

Copy link
Copy Markdown
Contributor
_Qwen Code review request accepted. Review is queued in [workflow run](https://github.com/QwenLM/qwen-code/actions/runs/29743342886)._

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 Reviewed the latest feedback — no changes needed. Why, point by point:

No action needed — all suggestions already addressed

All three suggestions from this review round are already covered by the current HEAD (7a74214c0 test(review): cover remaining review-cleanup feedback suggestions (#7259)), which landed after the feedback was generated.

1. Success-path test for clearReviewWorktreeLease in cleanup.test.ts

Status: Already present. The test 'clears the lease when cleanup succeeds' asserts clearReviewWorktreeLease is called with (process.cwd(), 'pr-123') after a fully successful cleanup. Verified passing.

2. Lease-cleanup tests for stream-error and loop-detection paths in useGeminiStream.test.tsx

Status: Already present.

  • 'should clean up review lease when the stream throws' — triggers a stream error and asserts cleanupReviewWorktreeLeases is called with { sessionId, promptId, repositoryRoot }. Verified passing.
  • The existing loop-detection test ('should detect loop...') now includes a waitFor assertion that cleanupReviewWorktreeLeases is called with the same shape. Verified passing (12 loop-related tests pass).
  • The UserCancelled test also asserts lease cleanup. Verified passing.

3. scripts/tests/qwen-autofix-workflow.test.js not collected by workspace test commands

Status: Already exercised by CI. The root package.json defines "test:scripts": "vitest run --config ./scripts/tests/vitest.config.ts", and test:ci chains it after workspace tests (npm run test:ci --workspaces ... && npm run test:scripts). CI runs npm run test:ci in the build-and-test job. Verified: all 63 tests in this file pass locally.

中文说明

无需操作——所有建议已在当前代码中实现

本轮审查的三条建议均已在当前 HEAD(7a74214c0 test(review): cover remaining review-cleanup feedback suggestions (#7259))中实现,该提交在反馈生成之后合入。

1. cleanup.test.tsclearReviewWorktreeLease 成功路径测试

状态: 已存在。测试 'clears the lease when cleanup succeeds' 断言在完全成功的清理后以 (process.cwd(), 'pr-123') 调用 clearReviewWorktreeLease。已验证通过。

2. useGeminiStream.test.tsx 中流错误和循环检测路径的租约清理测试

状态: 已存在。

  • 'should clean up review lease when the stream throws'——触发流错误并断言 cleanupReviewWorktreeLeases{ sessionId, promptId, repositoryRoot } 被调用。已验证通过。
  • 现有的循环检测测试('should detect loop...')现在包含一个 waitFor 断言,验证 cleanupReviewWorktreeLeases 以相同形状被调用。已验证通过(12 个循环相关测试通过)。
  • UserCancelled 测试同样断言了租约清理。已验证通过。

3. scripts/tests/qwen-autofix-workflow.test.js 未被工作区测试命令收集

状态: 已由 CI 执行。根 package.json 定义了 "test:scripts": "vitest run --config ./scripts/tests/vitest.config.ts",且 test:ci 在工作区测试之后链式调用它(npm run test:ci --workspaces ... && npm run test:scripts)。CI 在 build-and-test 作业中运行 npm run test:ci。已验证:该文件全部 63 个测试在本地通过。

Base-conflict check: no conflict with main.


🧠 Handled by Qwen Code · model/模型 qwen3.8-max-preview

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed. Not reviewed: every dimension — none of the 10 required agents is on record as launched with a prompt this skill built, so this diff was reviewed, if at all, from prompts the run wrote for itself: no record shows the severity bar, the finding format or this project's own rules reaching an agent.

— qwen3.7-max via Qwen Code /review

@wenshao

wenshao commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /triage

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM, looks ready to ship. ✅

@ytahdn ytahdn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM. 增量 review 无 Critical 缺陷。

核心确认:

  • Agent worktree 兼容createInvocationisolation: undefined 覆盖复用 caller-owned worktree,不修改原始 params
  • Lease 机制:多层验证(validTarget 防路径穿越、branch 匹配 reviewBranch、worktree 必须在 REVIEW_TMP_DIR 下、sessionId+promptId 匹配防子 prompt 释放父资源)。Fallback 路径 rmSync + git worktree prune 处理 git worktree remove 失败
  • Lease 生命周期fetch-pr 在 worktree 创建前注册 lease;TUI UserCancelled/loopDetected/catch 设 cleanup flag + finally 释放;headless registerCleanup fatal exit + finally 显式调用 + unregister 防重复
  • 验证错误去重recordBatchRetryableToolError 使用 batch-scoped Map,同一 response 中相同错误只计 1 次,batch map 不跨 turn 泄漏
  • 小修复finalizeAssistMessage 移入 try 块、UserCancelled breakreturn 干净退出

实现质量高,防御性编程到位。

— qwen3.7-plus via Qwen Code /review

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 Reviewed the latest feedback — no changes needed. Why, point by point:

No action needed — all feedback already addressed

Every feedback point on PR #7259 was verified against the current HEAD (7a74214c0) and confirmed as already resolved:

# File Feedback Status
1 cleanup.test.ts:111 Test for lease clearing on successful cleanup ✅ Already fixed in 7a74214c0 — test "clears the lease when cleanup succeeds" asserts clearReviewWorktreeLease(process.cwd(), 'pr-123')
2 cleanup.test.ts:100 Success-path test with branch deletion ✅ Already fixed in 7a74214c0 — same test invokes runCleanup('pr-123') with refExists true and asserts lease clearing
3 useGeminiStream.ts:2946 Coverage for all three cleanup trigger paths ✅ Already fixed in 7a74214c0 — tests at lines 8376, 8402, 9485 assert cleanupReviewWorktreeLeases for UserCancelled, stream error, and loop detection
4 useGeminiStream.ts:2946 (2nd) Stream-error and loop-detection cleanup assertions ✅ Same as above — all three ownership-tuple assertions present
5 qwen-autofix-workflow.test.js:2368 Both diff-guard assertions ✅ Already fixed in 7a74214c0 — test rejects both if git diff --quiet and if ! git diff --quiet || ! git diff --cached --quiet; then
6 qwen-autofix-workflow.test.js:2367 CI coverage for workflow test ✅ Confirmed — test:ci includes test:scripts; no code change needed
7 Automated reviewer (COMMENTED) Meta-feedback about review process ℹ️ Not actionable code feedback — no CHANGES_REQUESTED

No commits were made in this round.

中文说明

无需操作 — 所有反馈已在先前提交中解决

PR #7259 上的每条反馈均已对照当前 HEAD(7a74214c0)逐一验证,确认已解决:

# 文件 反馈内容 状态
1 cleanup.test.ts:111 清理成功时释放租约的测试 ✅ 已在 7a74214c0 中修复 — 测试 "clears the lease when cleanup succeeds" 断言了 clearReviewWorktreeLease(process.cwd(), 'pr-123')
2 cleanup.test.ts:100 分支删除成功路径的测试 ✅ 已在 7a74214c0 中修复 — 同一测试以 refExists 为 true 调用 runCleanup('pr-123') 并断言租约被清除
3 useGeminiStream.ts:2946 覆盖全部三个清理触发路径 ✅ 已在 7a74214c0 中修复 — 第 8376、8402、9485 行的测试分别断言了 UserCancelled、流错误和循环检测路径的 cleanupReviewWorktreeLeases
4 useGeminiStream.ts:2946(第二条) 流错误和循环检测的清理断言 ✅ 同上 — 三个所有权元组断言均已存在
5 qwen-autofix-workflow.test.js:2368 两个 diff 守卫断言 ✅ 已在 7a74214c0 中修复 — 测试同时拒绝 if git diff --quietif ! git diff --quiet || ! git diff --cached --quiet; then
6 qwen-autofix-workflow.test.js:2367 工作流测试的 CI 覆盖 ✅ 已确认 — test:ci 包含 test:scripts;无需代码变更
7 自动审查器(COMMENTED) 关于审查流程的元反馈 ℹ️ 非可操作的代码反馈 — 未提出 CHANGES_REQUESTED

本轮未产生任何提交。

Base-conflict check: no conflict with main.


🧠 Handled by Qwen Code · model/模型 qwen3.8-max-preview

@wenshao
wenshao enabled auto-merge July 20, 2026 14:57
@ytahdn

ytahdn commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator

Review 总结

变更概述

修复 /review 在 strict provider 同时发送 working_dir + isolation: "worktree" 时的 agent 启动失败、同一 response 中重复验证错误耗尽重试预算、以及异常终止遗留 review worktree 三个问题。20 文件,+1041/-28。

代码质量评估

Agent worktree 兼容(agent.ts):

  • 移除 working_dir + isolation 互斥校验,改为 createInvocation()isolation: undefined 覆盖,复用 caller-owned worktree
  • 不修改原始 params,clean 的覆盖方式;run_in_background + working_dir 不兼容保留

Review worktree lease 机制(review-worktree-lease.ts,231 行新文件):

  • 多层验证:validTarget^pr-\d+$)防路径穿越、branch 匹配 reviewBranch 防任意分支删除、worktree 必须在 REVIEW_TMP_DIR 下防任意目录删除、sessionId+promptId+repositoryRoot 匹配防子 prompt 释放父资源
  • Fallback 路径:git worktree remove --force 失败时 rmSync + git worktree prune
  • Lease 在 fetch-pr.ts 中 worktree 创建之前注册,即使创建失败也有保护

Lease 生命周期集成:

  • TUI(useGeminiStream):UserCancelled / loopDetected / catch 设 cleanupReviewLease flag,finally 中 cleanupReviewWorktreeLeases() 释放
  • Headless(nonInteractiveCli):registerCleanup() 注册 fatal exit handler + finally 显式调用 + unregister 防重复
  • cleanup.ts:成功清理后 clearReviewWorktreeLease() 解除 finalizer

验证错误去重(coreToolScheduler.ts):

  • recordBatchRetryableToolError() 使用 batch-scoped retryErrorsRecordedInBatch Map
  • 同一 model response 中相同 ${toolName}:${errorMessage} 只计 1 次重试
  • 新 unique error 出现时清除同 tool 旧 entries,batch map 不跨 turn 泄漏

小修复:

  • useGeminiStreamfinalizeAssistMessage() 移入 try 块,finalization 错误可被 catch
  • UserCancelled 从 break 改为 return StreamProcessingStatus.UserCancelled,干净退出处理函数

结论

无 Critical 缺陷,防御性编程到位,多层验证确保资源安全清理。可以合并。👍

@yiliang114 yiliang114 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nice work — the security model here is solid (path traversal via relative() checks, branch name validation against qwen-review/pr-<N>, execFileSync with argument arrays throughout), and the test coverage is comprehensive.

Three non-blocking observations:

  1. useGeminiStream.ts ~L2966: the cleanup path uses prompt_id! non-null assertion. If prompt_id is undefined, the lease cleanup silently skips — which is a bit ironic for code whose purpose is preventing silent skips. A defensive guard (if (!prompt_id) return) would make the intent explicit.

  2. fetch-pr.ts ~L145: the lease is intentionally created before the worktree exists. The cleanup handles this correctly (traced through removeLeaseWorktree), but a one-line comment documenting the ordering would save future readers the same trace.

  3. coreToolScheduler.ts L2120–2124: the batch dedup's duplicate branch deletes all retry counts for a tool, not just the repeated key. In a mixed batch this can lose counts for non-repeated errors. Consistent with the existing design and covered by tests, but worth a comment for maintainability.

Nothing blocking merge.

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 Reviewed the latest feedback — no changes needed. Why, point by point:

No action needed

The review from @ytahdn is an approval with a detailed summary of the changes. It identifies no Critical defects, no inline comments, and no failed CI checks. The reviewer explicitly concludes the PR can be merged.

No code changes are required.

中文说明

无需操作

@ytahdn 的评审是一条带有详细变更总结的批准意见。该评审未发现 Critical 缺陷,没有行内评论,也没有 CI 检查失败。评审者明确表示可以合并。

无需进行代码更改。

Base-conflict check: no conflict with main.


🧠 Handled by Qwen Code · model/模型 qwen3.8-max-preview

@wenshao

wenshao commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /triage

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM, looks ready to ship. ✅

@tanzhenxin tanzhenxin left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM!

@wenshao
wenshao added this pull request to the merge queue Jul 21, 2026
Merged via the queue into QwenLM:main with commit 2493248 Jul 21, 2026
271 of 278 checks passed
pull Bot pushed a commit to edisplay/qwen-code that referenced this pull request Jul 21, 2026
…wenLM#7355)

* feat(autofix): render the managed fleet into the scan's run summary

Seeing whether the loop was healthy meant reconstructing it by hand: list the
bot's PRs, fetch each one's comments, regex the autofix-eval markers for round
and watermark, then cross-check gh pr checks and the fork/takeover state. That
is how today's triage of QwenLM#7246, QwenLM#7259, QwenLM#7329, QwenLM#7333 and QwenLM#7336 was done, and it
is why a stalled PR stayed invisible until somebody went looking for it.

The scan already computes every one of those facts while deciding what to
process — it just wrote them to a job log nobody reads. Each per-PR terminal
decision now also records a row, and the step renders one markdown table into
the run summary:

  | PR    | State        | Detail                                          |
  | QwenLM#7329 | SELECTED     | 1 review + 5 inline new (round 0/5)             |
  | QwenLM#7333 | idle         | nothing new since 2026-07-20T13:54:18Z          |
  | QwenLM#7262 | waiting      | active checks in flight                         |
  | QwenLM#7208 | round-capped | round 100/100 - needs a human or @qwen-code /retry |

States cover every branch that ends a PR's inspection: busy, skipped, unknown,
waiting, round-capped, idle and SELECTED — so a PR cannot drop out of the table
by returning early, which is exactly the invisibility this fixes.

No new API calls (the data is already in hand), no writes outside the run
summary, and the helper is defined at the top of the step so it stays clear of
the BUSY_PRS/INSPECTED proximity guard that keeps the free busy-skip from
consuming the inspection budget.

Tests: the real helper and render block are replayed over fixtures (table
structure, one row per state, and an empty fleet still rendering a table), plus
each decision branch is pinned to its fleet_row. Mutation-verified: dropping
one branch's row turns it red.

* fix(autofix): use temp file for fleet test replay; cover fork-head skip (QwenLM#7355)

* test(autofix): assert each skipped fleet_row call site individually (QwenLM#7355)

* fix(autofix): record fleet rows for both budget-break paths (QwenLM#7355)

The candidate-inspection budget break incremented INSPECTED but never
called fleet_row, so the PR that tripped the budget was silently absent
from the fleet table. The target-budget break left all remaining
candidates invisible with no truncation signal.

Add a per-PR deferred row before the inspection-budget break and a
summary deferred row before the target-budget break so the fleet table
stays complete in both cases.

* fix(autofix): harden fleet summary render and clean up temp file (QwenLM#7355)

Address review feedback:
- Escape '|' in detail values to prevent broken table columns
- Render budget summary row (PR '-') as em dash instead of '#-'
- Add trap for FLEET_FILE cleanup on early exit paths
- Document deferred summary row semantics in test comment

* fix(autofix): use summary row for candidate-inspection budget break (QwenLM#7355)

---------

Co-authored-by: wenshao <wenshao@example.com>
Co-authored-by: qwen-code-ci-bot <qwen-code-ci-bot@users.noreply.github.com>
Co-authored-by: qwen-code-dev-bot <qwen-code-dev-bot@users.noreply.github.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Released in v0.20.1.

@yiliang114

yiliang114 commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

[API Error: Connection error. (cause: fetch failed)]


❌ failed

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

Labels

autofix/takeover Summon the autofix loop to manage this PR (remove to release; needs triage+)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants