Skip to content

feat(daemon): guard cross-worktree Git mutations - #8684

Closed
wenshao wants to merge 1 commit into
QwenLM:mainfrom
wenshao:feat/daemon-git-worktree-guard
Closed

feat(daemon): guard cross-worktree Git mutations#8684
wenshao wants to merge 1 commit into
QwenLM:mainfrom
wenshao:feat/daemon-git-worktree-guard

Conversation

@wenshao

@wenshao wenshao commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

What this PR does

Adds a built-in host-side guard for model-issued run_shell_command calls in qwen serve. The guard recognizes Git repository relocation through -C, --work-tree, and --git-dir, then blocks mutating or unclassified commands when the resolved target escapes the session's current effective working directory. It uses daemon-owned session state, composes before an optional external guard, handles compound shell forms, dynamic targets, symlink ancestors, chained -C, and Git global options with values.

Worktree sessions use their live effectiveCwd as the boundary, so mutations inside the session's own worktree remain allowed while mutations targeting another checkout or worktree are denied. Read-only relocated Git commands remain allowed.

The managed guard is installed only for daemon ACP children. CLI/TUI shell validation, permission classification, confirmation, YOLO behavior, and shared core tool execution are unchanged.

Why it's needed

A daemon model can start a shell inside its assigned workspace but relocate Git to another checkout with git -C, --work-tree, or --git-dir. That bypasses the existing shell working-directory boundary and can mutate a sibling worktree or unrelated checkout. Enforcing the boundary in the daemon host prevents the ACP child from forging workspace context and avoids changing normal CLI behavior.

Reviewer Test Plan

How to verify

  1. Start a managed daemon session bound to one checkout or worktree.
  2. Confirm a model-issued mutating command such as git -C <other-worktree> reset --hard is denied before execution.
  3. Repeat with --work-tree, --git-dir, a dynamic relocation target, a symlinked path, a compound command, and a value-taking Git global option such as --namespace; each mutating or unclassified external relocation should be denied.
  4. Confirm git -C <other-worktree> status --short remains allowed.
  5. Confirm a mutating Git command targeting a directory inside the session's effectiveCwd remains subject only to the existing permission flow.
  6. Run the normal CLI/TUI and confirm its shell behavior is unchanged because no shared core shell or permission path is modified.

Evidence (Before & After)

N/A — daemon policy change with unit and integration coverage; no UI changes.

Tested on

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

Environment (optional)

macOS, Node.js 22-compatible workspace. Passed: 25 daemon guard tests, 5 managed ACP guard tests, 97 ACP bridge tests, ACP bridge typecheck, targeted ESLint, Prettier, pre-commit hooks, normal CLI Git regression tests (36/36 in independent verification), npm run dev -- --version, and daemon startup. The targeted run-qwen-serve.test.ts could not be collected in this checkout because the workspace is missing @qwen-code/channel-github; the root build/typecheck is blocked by the same missing channel packages and existing unrelated type errors.

Risk & Scope

  • Main risk or tradeoff: This is intentionally a narrow shell-token policy rather than a complete shell interpreter. Dynamic Git relocation is fail-closed for mutating or unknown subcommands, while commands without recognized relocation retain existing behavior.
  • Not validated / out of scope: Windows/Linux runtime verification, direct user-entered daemon shell commands, linked-worktree exceptions, confirmation UX, and general environment-variable evaluation.
  • Breaking changes / migration notes: None for CLI/TUI users. Daemon model calls that attempt cross-worktree Git mutation are now denied.

Linked Issues

N/A

中文说明

本 PR 做了什么

qwen serve 中模型发出的 run_shell_command 调用增加 Daemon host 侧内置 guard。该 guard 识别通过 -C--work-tree--git-dir 进行的 Git 仓库重定位;当解析后的目标逃出 session 当前有效工作目录时,阻止可变更或无法分类的命令。策略使用 Daemon 持有的可信 session 状态,在可选 external guard 之前执行,并覆盖 compound shell、动态目标、symlink ancestor、连续 -C 以及带值的 Git 全局选项。

Worktree session 使用实时 effectiveCwd 作为边界,因此 session 自己 worktree 内的 mutation 仍然允许,而指向其他 checkout 或 worktree 的 mutation 会被拒绝。重定位后的只读 Git 命令仍然允许。

Managed guard 只安装到 Daemon ACP child。CLI/TUI 的 shell 校验、权限分类、确认、YOLO 行为以及共享 core tool 执行均保持不变。

为什么需要

Daemon 模型可以让 shell 从分配的 workspace 内启动,但通过 git -C--work-tree--git-dir 将 Git 重定位到另一个 checkout。这会绕过现有 shell 工作目录边界,并可能修改 sibling worktree 或无关 checkout。把边界放在 Daemon host 强制执行,可以防止 ACP child 伪造 workspace context,同时避免改变普通 CLI 行为。

Reviewer Test Plan

如何验证

  1. 启动一个绑定到某个 checkout 或 worktree 的 managed daemon session。
  2. 确认模型发出的 git -C <other-worktree> reset --hard 等 mutation 命令在执行前被拒绝。
  3. 分别使用 --work-tree--git-dir、动态 relocation target、symlink path、compound command,以及 --namespace 这类带值的 Git 全局选项;所有指向外部的 mutation 或无法分类命令都应被拒绝。
  4. 确认 git -C <other-worktree> status --short 仍然允许。
  5. 确认指向 session effectiveCwd 内目录的 Git mutation 仍只受现有 permission flow 约束。
  6. 运行普通 CLI/TUI,确认其 shell 行为不变,因为没有修改共享 core shell 或 permission 路径。

Evidence(Before & After)

N/A——这是带单元和集成覆盖的 Daemon 策略改动,没有 UI 变化。

Tested on

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

Environment(可选)

macOS,Node.js 22 兼容 workspace。已通过:25 个 Daemon guard 测试、5 个 managed ACP guard 测试、97 个 ACP bridge 测试、ACP bridge typecheck、定向 ESLint、Prettier、pre-commit hooks、普通 CLI Git 回归测试(独立验证 36/36)、npm run dev -- --version 和 Daemon 启动。当前 checkout 缺少 @qwen-code/channel-github,因此定向 run-qwen-serve.test.ts 无法完成测试收集;root build/typecheck 也被相同的 channel package 缺失和已有无关类型错误阻塞。

风险与范围

  • 主要风险或取舍:这是刻意保持最小范围的 shell token 策略,而不是完整 shell interpreter。动态 Git relocation 对 mutation 或 unknown subcommand fail-closed;没有已识别 relocation 的命令保持原行为。
  • 未验证 / 不在范围内:Windows/Linux runtime 验证、用户直接输入的 Daemon shell 命令、linked-worktree exception、confirmation UX 和通用环境变量求值。
  • Breaking changes / migration notes:CLI/TUI 用户无变化。尝试跨 worktree 执行 Git mutation 的 Daemon 模型调用现在会被拒绝。

Linked Issues

N/A

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

qwen-code-ci-bot commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

Qwen Triage finishedview run. See the stage comments in this thread for the result.

Qwen Triage 已完成 —— 查看运行。结果见本线程中的各阶段评论。

@wenshao

wenshao commented Aug 7, 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 Aug 7, 2026
@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. This is a fork PR, so the first round comes from the next scheduled scan (usually within minutes). Remove the autofix/takeover label (or comment @qwen-code /takeover stop) to release.

中文说明

🤝 已接管:autofix 循环现在管理此 PR —— 将持续处理新的评审反馈与 base 冲突,直到移除标签或达到轮次上限。本 PR 来自 fork,首轮处理将由下一次定时扫描执行(通常几分钟内)。移除 autofix/takeover 标签(或评论 @qwen-code /takeover stop)即可释放。

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

🩺 serve daemon A/B

Built the PR base vs this PR head 2480163, drove a fixed endpoint set against each, and diffed the JSON responses. Only fields that changed are shown.

No response changes against the PR base across 4 scenario(s).

Qwen Code · serve A/B

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Thanks for the PR!

Template looks good ✓

Problem: this one checks out as a real boundary hole rather than a theoretical concern. The shell tool validates the explicit directory argument against the session's workspace, but nothing in the current daemon tool path understands git -C / --work-tree / --git-dir — I verified there is no Git-flag awareness anywhere in the serve path today (the git -C handling in the core shell tool is only about commit attribution, not enforcement). With worktree sessions putting sibling checkouts side by side on disk, a relocated mutating Git command reaches a checkout the session doesn't own. No linked incident, but the escape is mechanical and verifiable from the code.

Direction: aligned. The daemon/ACP path is a first-class surface in this repo, and enforcing the boundary host-side — with the boundary values taken from daemon-owned session state (workspaceCwd/effectiveCwd), never from the child's request — is the right place for it. CLI/TUI behavior stays untouched, which is also the right call.

Size: ~322 production lines (281 for the guard itself, ~41 wiring across run-qwen-serve.ts, acpAgent.ts, bridgeClient.ts/bridgeOptions.ts), ~299 test lines, 70 design-doc lines. Cross-package (acp-bridge + cli), author is a maintainer, so no core-gate escalation.

Approach: scope feels right. Allowing relocated read-only commands while failing closed on mutating/unclassifiable ones is the correct tradeoff for worktree workflows, and the chained--C / global-option / symlink handling all correspond to real Git and shell behavior that the tests pin down. The bundled change to forward nested executors (AGENT/WORKFLOW/…) to the host instead of denying them child-side is entailed by moving policy ownership host-side, not a drive-by. One observation for awareness, not a blocker: with the guard env now unconditionally required-v1, every daemon tool call now makes a host round-trip even when no external provider is configured — presumably the accepted price of host-owned policy.

Risk: packages/cli/src/acp-integration/acpAgent.ts matches this repo's high-risk path list, so this gets full review depth and CI evidence is required before approval. Sandboxed lane will be named in the review comment.

Moving on to code review. 🔍

中文说明

感谢贡献!

模板完整 ✓

问题:这是一个真实存在的边界漏洞,而不是理论性的担忧。shell tool 会校验显式的 directory 参数,但当前 daemon tool 路径中没有任何逻辑理解 git -C / --work-tree / --git-dir——我核实过 serve 路径目前完全没有 Git flag 感知(core shell tool 里对 git -C 的处理只用于 commit 归属,不是强制执行)。worktree session 让兄弟 checkout 并排存在于同一文件系统上,重定位后的 Git mutation 命令可以触及 session 并不拥有的 checkout。虽然没有关联的 incident,但这个逃逸路径是机械性的,可以从代码中直接验证。

方向:对齐。daemon/ACP 是本仓库的一等公民,把边界放在 host 侧强制执行(边界值取自 daemon 持有的 session 状态 workspaceCwd/effectiveCwd,绝不接受 child 请求里的值)是正确的位置。CLI/TUI 行为保持不变,这也是正确的取舍。

规模:约 322 行生产代码(guard 本体 281 行,run-qwen-serve.tsacpAgent.tsbridgeClient.ts/bridgeOptions.ts 约 41 行接线),约 299 行测试,70 行设计文档。跨包(acp-bridge + cli),作者是 maintainer,不触发 core gate 升级。

方案:范围合理。对重定位后的只读命令放行、对 mutating/无法分类的命令 fail-closed,是 worktree 工作流下正确的取舍;chained -C、带值全局选项、symlink 处理都对应真实的 Git/shell 行为,且有测试固定。把嵌套 executor(AGENT/WORKFLOW/…)改为转发到 host 而不是在 child 侧拒绝,是策略归属上移的必然结果,不是顺手改动。一个提醒(非 blocker):guard env 现在无条件设为 required-v1,即使没有配置 external provider,daemon 的每次 tool call 都会多一次 host 往返——这应该是 host 持有策略所接受的代价。

风险:packages/cli/src/acp-integration/acpAgent.ts 命中本仓库的高风险路径列表,因此按完整 review 深度处理,approval 前必须有 CI 证据。沙箱验证通道会在 review 评论中点名。

进入代码审查 🔍

Qwen Code · qwen3.8-max

Reviewed at 2480163eb0566fc36e89c7d21297f3bf70492827 · re-run with @qwen-code /triage

@wenshao

wenshao commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator Author

Superseded by #8687, which uses the in-repository feature branch as intended. Closing this duplicate fork-based PR.

@wenshao wenshao closed this Aug 7, 2026
@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Code review

Reviewed independently before reading the diff: given the existing externalToolGuard hook and daemon-owned session state, I'd have built exactly this — a host-side token policy over run_shell_command, fail-closed on anything dynamic, boundary values taken from the session entry rather than the child. The PR matches that shape, goes further where it earns its keep (chained -C, value-taking global options, symlink ancestors), and the trust wiring checks out end to end: createSessionEntry seeds effectiveCwd = workspaceCwd, the controlled /cd flow is the only updater, BridgeClient validates session + active-prompt ownership before consulting the guard, and the guard throws when the trusted context is missing. Nested-executor semantics are preserved in both configurations (with and without an external provider). Two blocking findings and one to verify, all in the new parser and the CI below — the rest is solid.

1. CI is red on the serve fast-path bundle check, and unit tests never ran (blocker). The ubuntu Test job fails at npm run check:serve-fast-path-bundle with Serve fast-path bundle closure includes pre-listen runtime modules — the glob, chokidar, fzf, @iarna/toml vendor packages and the core shell tool runtime now sit in a shared chunk statically imported by the run-qwen-serve chunk. I'm reading this as PR-caused, not infra noise: the new module-scope import { createDaemonToolGuard } in run-qwen-serve.ts is the only new static edge in that closure, run-qwen-serve.ts already carries comments documenting this exact hazard for other imports (the fix pattern there is a dynamic await import()), and main's most recent red is an unrelated checkout refspec error, not this check. Because the job died before vitest, this commit currently has no CI unit-test evidence at all (macOS/Windows test jobs were skipped). The author's locally-passing test numbers are their claim, not evidence here — and they also reported their local root build/typecheck was blocked, which is presumably why this gate wasn't hit before pushing.

2. Qualified Git paths bypass the guard entirely (blocker, in the PR's own scope). findGitInvocationStart matches only the exact token git, so /usr/bin/git -C <outside> reset --hard (any path-qualified invocation) is not recognized as Git at all and is allowed. The guard advertises recognizing git -C relocation; a basename-style match on the program token would close the most trivial form of this.

3. $(...) relocation targets likely slip past the fail-closed rule (needs verification). The dynamic-target check looks for $ inside plain string tokens, but shell-quote emits command substitutions as non-string entries: in readCommandSegments those either split the segment (dropping the -C value, so readGitInvocation sees no relocation) or empty the segment list — either way git -C $(echo <outside>) reset --hard appears to be allowed, contradicting the "dynamic targets fail closed" policy the $VAR handling implements. I could not execute the parser in this environment (triage never runs code), so please confirm and treat any non-plain-string relocation token as unresolved.

Observations, not blockers — these are documented non-goals, and the codebase's existing Git handling (commit attribution in the core shell tool) takes the same posture: sh -c '…' nesting, GIT_DIR/GIT_WORK_TREE env-var relocation, and wrapper prefixes (sudo git, timeout 5 git — only VAR=, command, env are stripped) all go around the guard. Fine as defense-in-depth; just worth naming so nobody later reads this guard as a hard boundary.

sequenceDiagram
    participant P1 as ACP child managed guard
    participant P2 as BridgeClient daemon host
    participant P3 as Daemon git-worktree guard
    participant P4 as External guard provider
    P1->>P2: tool call externalToolGuardPrepare
    P2->>P2: validate session and active prompt
    P2->>P3: request plus daemon-owned workspaceCwd and effectiveCwd
    P3->>P3: parse run shell command for Git relocation
    alt relocation escapes effectiveCwd and is mutating or unknown
        P3-->>P1: denied, provider not consulted
    else allowed and provider configured
        P3->>P4: forward request
        P4-->>P1: provider decision
    else allowed and no provider
        P3-->>P1: allowed
    end
Loading
Files changed (10 of 10 shown)
File What changed
docs/design/daemon-git-worktree-guard.md Design doc - scope, policy, failure semantics, explicit non-goals
packages/cli/src/serve/daemon-git-worktree-guard.ts New host guard - tokenizes the command, resolves Git relocation against the effective cwd, fails closed
packages/cli/src/serve/daemon-git-worktree-guard.test.ts Guard cases - denials, read-only allows, compound shell forms, chained -C, symlinks, provider interplay
packages/cli/src/serve/run-qwen-serve.ts Installs the guard unconditionally on all three bridges and always sets the required-v1 child env
packages/cli/src/serve/run-qwen-serve.test.ts Asserts the env var and that a guard handler is wired into the bridge options
packages/acp-bridge/src/bridgeClient.ts Adds daemon-owned workspaceCwd and effectiveCwd to the guard request from the session entry
packages/acp-bridge/src/bridgeOptions.ts Extends the guard request type with the two trusted fields
packages/acp-bridge/src/bridgeClient.test.ts Updates the managed-guard test entry and expected request
packages/cli/src/acp-integration/acpAgent.ts Removes the child-side nested-executor denial - the host decides now
packages/cli/src/acp-integration/acpAgent.test.ts Nested executors are forwarded to the host guard instead of denied locally

Test evidence — the PR's own CI, read via the API

Per triage rules no PR code was built or executed here; the table quotes the PR's own check-runs on the reviewed commit, fetched once (no polling — Serve A/B was still in flight at review time and the finalize job will update the table when CI settles). The ubuntu failure classification above comes from the check identity and the diff, not from anything the log text claims.

Check Conclusion
Test (ubuntu-latest, Node 22.x) failure — check:serve-fast-path-bundle step, before unit tests ran
Test (macos-latest, Node 22.x) skipped (fail-fast)
Test (windows-latest, Node 22.x) skipped (fail-fast)
Serve A/B (ubuntu-latest, Node 22.x) pending at review time
web-shell E2E Smoke (ubuntu-latest, Node 22.x) success
Desktop Shell (ubuntu-22.04) success
precheck-pr / precheck success

Not verified: the full unit suite (blocked by the bundle failure on this commit), and Windows/Linux runtime behavior (author tested macOS only — their report, not re-run here).

Sandboxed verification would settle the wiring claim: @qwen-code /verify — that the guard is actually installed in the live daemon tool path and fails closed end-to-end. This PR's unit suite exercises the guard function in isolation and would still pass with the run-qwen-serve.ts wiring removed, so a green suite alone does not pin the behavior.

中文说明

代码审查:方案与我独立推演的做法一致——host 侧对 run_shell_command 做 token 级策略、动态目标 fail-closed、边界值取自 daemon 持有的 session 状态。信任链我逐段核实过:createSessionEntry 初始化 effectiveCwd = workspaceCwd,受控 /cd 流程是唯一更新者,BridgeClient 在调用 guard 前校验 session 与 active prompt 归属,缺失 trusted context 时 guard 直接抛错。嵌套 executor 在两种配置下语义都保持不变。两个 blocker、一个待确认,都在新 parser 和 CI 上,其余部分扎实。

  1. CI 在 serve fast-path bundle 检查上失败,且单测根本没跑(blocker)。ubuntu Test job 挂在 npm run check:serve-fast-path-bundleglobchokidarfzf@iarna/toml 和 core shell tool runtime 进入了被 run-qwen-serve chunk 静态引用的共享 chunk。判定为 PR 导致:run-qwen-serve.ts 新增的模块级 import { createDaemonToolGuard } 是该闭包里唯一的新静态边;该文件里本来就有注释记录同类风险和动态 import 的修法;main 最近的失败是无关的 checkout refspec 基础设施错误。由于 job 在 vitest 之前就挂了,本 commit 目前没有任何 CI 单测证据(macOS/Windows 测试 job 被跳过)。作者本地测试通过的数字是其自述,不是这里的证据——而且作者自己也说本地 root build/typecheck 被阻塞,这大概就是推送前没撞上这个 gate 的原因。
  2. 带路径的 git 调用完全绕过 guard(blocker,且在 PR 自己声明的范围内)findGitInvocationStart 只匹配精确的 git token,/usr/bin/git -C <outside> reset --hard 不会被识别为 Git 而直接放行。对程序 token 做 basename 匹配即可堵住这个最简单的形态。
  3. $(...) 形式的重定位目标可能绕过 fail-closed 规则(待确认)。动态目标检查只看普通字符串 token 里的 $,而 shell-quote 把命令替换解析为非字符串条目:在 readCommandSegments 里要么切断 segment(丢掉 -C 的值),要么清空整个 segment 列表——git -C $(echo <outside>) reset --hard 看起来会被放行,与 $VAR 所实现的"动态目标 fail-closed"策略矛盾。triage 环境不执行代码,我无法实际运行该 parser,请作者确认,并把所有非普通字符串的重定位 token 都视为 unresolved。

观察项(非 blocker,均属已声明的非目标,且与 core shell tool 里 commit 归属逻辑的姿态一致):sh -c '…' 嵌套、GIT_DIR/GIT_WORK_TREE 环境变量重定位、包装前缀(sudo gittimeout 5 git——只剥离 VAR=commandenv)都能绕过。作为纵深防御没问题,但要点明,避免日后把这个 guard 当成硬边界。

测试证据:按 triage 规则,这里没有构建或执行任何 PR 代码;表格直接引用该 commit 的 CI check-run(一次性拉取,不轮询——review 时 Serve A/B 仍在运行,finalize job 会在 CI 落定后更新表格)。失败归因来自 check 身份与 diff,不采信日志文本里的任何说法。未验证:完整单测(被 bundle 失败阻塞)、Windows/Linux 运行时行为(作者只在 macOS 上测试,且为自述)。

沙箱验证可以敲定接线声明:@qwen-code /verify —— guard 是否真的安装在 daemon 实际 tool 路径上并端到端 fail-closed。本 PR 的单测只单独测试 guard 函数,即使删掉 run-qwen-serve.ts 的接线单测仍会全绿,所以仅凭绿色套件无法固定这个行为。

Qwen Code · qwen3.8-max

Reviewed at 2480163eb0566fc36e89c7d21297f3bf70492827 · re-run with @qwen-code /triage

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Confidence: 2/5 — the design is the right one and the trust wiring is genuinely careful, but the PR is red on the repo's own bundle gate with zero CI unit-test evidence, and the parser has a confirmed trivial bypass inside its own stated scope.

Stepping back: this is not a solution looking for a problem — I verified the escape exists in the current code, the host-side placement is correct, and the implementation matches what I'd have proposed independently, down to fail-closed dynamics and daemon-owned boundary values. The test suite pins real Git/shell behavior rather than toy cases, and the design doc states its non-goals honestly. If that were the whole picture this would be close to approve.

What stops it is the state it ships in. The fast-path bundle check fails on this commit — mechanically fixable via the dynamic-import pattern the same file already uses for exactly this hazard — and because it fails before vitest, there is currently no CI evidence that even the green-looking parts hold. On top of that, a guard whose stated job is recognizing git -C relocation shouldn't let /usr/bin/git -C walk past, and the $(...) case needs a confirmation against the stated fail-closed policy. All three are small fixes; the direction needs no rethinking.

@wenshao — requesting changes for the three items above (bundle closure, qualified-git bypass, $(...) verification). Once CI is green on a new push, re-run with @qwen-code /triage and this should move quickly.

中文说明

Confidence: 2/5 —— 设计方向正确,信任链接线相当仔细,但 PR 在仓库自己的 bundle gate 上是红的、没有任何 CI 单测证据,且 parser 存在一个在其自身声明范围内的已确认的简单绕过。

退一步看:这不是"为方案找问题"——逃逸路径我在现有代码里核实过,host 侧的放置是对的,实现与我独立给出的方案一致,包括对动态目标 fail-closed 和 daemon 持有边界值。测试固定的是真实的 Git/shell 行为而不是玩具场景,设计文档也诚实地写明了非目标。如果只有这些,它接近 approve。

挡住它的是当前的提交状态:fast-path bundle 检查在本 commit 上失败——用同一文件里针对同类风险已有的动态 import 模式即可机械修复——而且它在 vitest 之前就失败了,所以目前没有任何 CI 证据表明那些看起来没问题的部分真的成立。另外,一个以识别 git -C 重定位为职责的 guard,不应该让 /usr/bin/git -C 直接通过;$(...) 的情形也需要对照其声明的 fail-closed 策略确认。三项都是小修复,方向不需要推翻。

@wenshao —— 就上述三点(bundle 闭包、带路径 git 的绕过、$(...) 确认)request changes。新 push 后 CI 变绿,用 @qwen-code /triage 重跑即可快速推进。

Qwen Code · qwen3.8-max

Reviewed at 2480163eb0566fc36e89c7d21297f3bf70492827 · 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.

Requesting changes — CI is red on the serve fast-path bundle check (unit tests never ran on this commit), the guard has a confirmed bypass via path-qualified git invocations, and the command-substitution relocation case needs verification against the stated fail-closed policy. Details in the review notes above. 🙏

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.

3 participants