Skip to content

fix(cli): extend the #8663 loader denylist and harden its scrub lifecycle - #8763

Merged
wenshao merged 12 commits into
mainfrom
fix/8663-loader-denylist-followup
Aug 10, 2026
Merged

wenshao merged 12 commits into
mainfrom
fix/8663-loader-denylist-followup

Conversation

@wenshao

@wenshao wenshao commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

What this PR does

Follow-up to #8663. The /review pass that ran right after #8663 merged surfaced 14 findings that were never addressed (all still unresolved on that PR). This PR handles the substantive ones.

#8663's inherited-env denylist closed the NODE_OPTIONS/NODE_PATH class but left sibling variables that reach the same #8653 cross-workspace outcome: an untrusted workspace .env is frozen into daemonRuntimeBaseEnv and distributed to every workspace's session subprocesses. This PR extends the denylist along #8663's own two tiers, hardens the scrub lifecycle against concurrent embedded daemons, and closes the test/diagnostic gaps the review named.

Denylist additions

Scrubbed loader tier (INHERITED_LOADER_ENV_KEYS — scrubbed from the inherited launch env and rejected from every .env/settings.env scope). Pure-injection vars with no legitimate operator-shell use:

  • OPENSSL_CONF — Node's startup crypto init dlopens an attacker-configured OpenSSL engine/provider .so before any user code runs.
  • NODE_REPL_EXTERNAL_MODULE — a spawned node REPL require()s an attacker file at startup.
  • npm_config_node_gyp — npm's shim runs "$npm_config_node_gyp" "$@" verbatim.
  • npm_config_init_module — require()d by npm init (even npm init -y).

Reject-from-project-.env tier (PROJECT_ENV_HARDCODED_EXCLUSIONS — rejected from project files, but a value the operator sets in their own shell or home .env is preserved). Vars with legitimate operator-shell use whose only exposed vector is an untrusted project file:

  • TLS trust anchors SSL_CERT_FILE, SSL_CERT_DIR, CURL_CA_BUNDLE, REQUESTS_CA_BUNDLE, GIT_SSL_CAINFO — siblings of the already-blocked NODE_EXTRA_CA_CERTS; an attacker CA MITMs the token-bearing traffic a session's git/npm/pip/curl calls make.
  • git command-execution family GIT_SSH_COMMAND, GIT_EXTERNAL_DIFF, GIT_CONFIG_GLOBAL/SYSTEM/COUNT and the numbered GIT_CONFIG_KEY_<n>/GIT_CONFIG_VALUE_<n> pairs (matched by prefix). core/utils/git-branches.ts already scrubs exactly these from the repo's own git invocations, so a project .env setting them contradicts our own model.
  • node-gyp interpreter selection NODE_GYP_FORCE_PYTHON, npm_config_python, PYTHON — run as the build Python during native-addon npm install.

Concurrency hardening

The daemon's process.env scrub/restore and the loader-key rejection reporter were process-global with no guard for concurrent embedded daemons in one process — a documented supported config (acp-bridge/src/bridgeOptions.ts childEnvOverrides). The first daemon's close() restored loader vars into the shared process.env, re-poisoning a still-live sibling's sessions, and dropped its reporter. The scrub is now reference-counted (acquireInheritedLoaderEnvScrub — snapshot on first acquire, restore only on last release) and the reporter is cleared only when still the active one.

Test / diagnostic hardening

  • Pin the daemon-worker channel-boundary scrub breadcrumb (not just key removal), so a refactor onto the silent scrub variant fails.
  • Pin the fast-path settings.env case-folded hardcoded-exclusion gate (previously only the .env loop's case-fold was pinned).
  • Drain the module-global fast-path rejection stash so the accumulates assertion is order-independent (no longer depends on a sibling test consuming first).
  • Docs (settings.md) updated for all new keys.

Deliberately not changed

Verification

npm run build clean; tsc --noEmit, eslint, and prettier --check clean on all changed files. Affected suites: shared-env-keys.test.ts, environment.test.ts, fast-path.test.ts, daemon-worker.test.ts, run-qwen-serve.test.ts — 458 tests pass. New tests cover every added key at the predicate and .env/settings.env application layers, the refcounted scrub (restore does not re-poison while a second holder is live), and the reporter clear-if-current guard.


这个 PR 做了什么

#8663 的后续。#8663 合入后紧接着跑的 /review 给出了 14 条一直未处理的评审意见(在该 PR 上至今全部 unresolved)。本 PR 处理其中实质性的部分。

#8663 的继承环境拒绝列表关闭了 NODE_OPTIONS/NODE_PATH 这一类,但遗漏了通向同一 #8653 跨 workspace 结果的同族变量:不受信 workspace 的 .env 会被冻结进 daemonRuntimeBaseEnv 并分发到每个 workspace 的会话子进程。本 PR 沿 #8663 自身的两层结构扩展拒绝列表,加固剥离生命周期以应对同进程并发内嵌 daemon,并补齐评审指出的测试/诊断缺口。

拒绝列表新增

剥离 loader 层(从继承的启动环境剥离,且在所有 .env/settings.env 作用域被拒绝)——无正当登录 shell 用途的纯注入变量:OPENSSL_CONF(启动时 dlopen 攻击者 OpenSSL engine)、NODE_REPL_EXTERNAL_MODULE、npm_config_node_gyp、npm_config_init_module。

仅拒绝项目 .env 层(从项目文件拒绝,但运维在自己 shell 或 home .env 设置的值保留)——有正当 shell 用途、仅经不受信项目文件暴露的变量:TLS 信任锚 SSL_CERT_FILE/SSL_CERT_DIR/CURL_CA_BUNDLE/REQUESTS_CA_BUNDLE/GIT_SSL_CAINFO(NODE_EXTRA_CA_CERTS 的同族,MITM 会话的 git/npm/pip/curl 携带 token 的流量);git 命令执行家族 GIT_SSH_COMMAND/GIT_EXTERNAL_DIFF/GIT_CONFIG_GLOBAL/SYSTEM/COUNT 及编号 GIT_CONFIG_KEY_<n>/GIT_CONFIG_VALUE_<n> 对(按前缀匹配;core/utils/git-branches.ts 已剥离这些);node-gyp 解释器选择 NODE_GYP_FORCE_PYTHON/npm_config_python/PYTHON。

并发加固

daemon 对 process.env 的剥离/恢复与 loader 键拒绝 reporter 是进程全局的,对同进程并发内嵌 daemon(文档化的受支持配置)无保护。第一个 daemon 的 close() 会把 loader 变量恢复进共享 process.env,重新污染仍存活的同伴会话,并丢掉其 reporter。现改为引用计数(acquireInheritedLoaderEnvScrub——首次 acquire 快照、仅最后一次 release 恢复),reporter 仅在仍是当前活跃者时才清除。

测试/诊断加固

钉住 daemon-worker channel 边界剥离的 breadcrumb(不仅是键删除);钉住快速路径 settings.env 的大小写折叠硬编码排除门控;在 accumulates 断言前排空模块全局 stash 使其与测试顺序无关;settings.md 更新所有新键。

有意未改动

warn-once 去重按进程生效(移除后再加不再复警)是 R3-4 既定设计;库搜索路径(LD_LIBRARY_PATH、PYTHONPATH 等)与残留的 PATH 前缀泄漏仍为 #8663 已跟踪的 deferred 项——拒绝它们会破坏主流工具链。

…ycle

Follow-up to #8663. Its inherited-env denylist closed the NODE_OPTIONS/
NODE_PATH class but left sibling code-execution and TLS-trust-anchor vars
that reach the same #8653 cross-workspace outcome — an untrusted workspace
`.env` is frozen into daemonRuntimeBaseEnv and distributed to every
workspace's session subprocesses.

Denylist additions, split by the PR's own tiering:

- Scrubbed loader tier (INHERITED_LOADER_ENV_KEYS — scrubbed from the
  inherited launch env and rejected from every `.env`/settings.env scope),
  for pure-injection vars with no legitimate operator-shell use:
  OPENSSL_CONF (startup dlopen of an attacker OpenSSL engine),
  NODE_REPL_EXTERNAL_MODULE, npm_config_node_gyp, npm_config_init_module.

- Reject-from-project-`.env` tier (PROJECT_ENV_HARDCODED_EXCLUSIONS —
  rejected from project files, preserved from the shell / home `.env`), for
  vars with a legitimate operator-shell use whose only exposed vector is an
  untrusted project file:
  * TLS trust anchors SSL_CERT_FILE, SSL_CERT_DIR, CURL_CA_BUNDLE,
    REQUESTS_CA_BUNDLE, GIT_SSL_CAINFO (siblings of NODE_EXTRA_CA_CERTS;
    an attacker CA MITMs a session's git/npm/pip/curl traffic).
  * git command-execution family GIT_SSH_COMMAND, GIT_EXTERNAL_DIFF,
    GIT_CONFIG_GLOBAL/SYSTEM/COUNT and the numbered GIT_CONFIG_KEY_<n>/
    GIT_CONFIG_VALUE_<n> pairs (matched by prefix). core/utils/git-branches.ts
    already scrubs these from the repo's own git invocations.
  * node-gyp interpreter selection NODE_GYP_FORCE_PYTHON, npm_config_python,
    PYTHON (run as the build Python during native-addon installs).

Concurrency: the daemon's process.env scrub/restore and the loader-key
rejection reporter were process-global with no guard for concurrent embedded
daemons in one process (a documented supported config). The first daemon's
close() restored loader vars into the shared env, re-poisoning a still-live
sibling's sessions, and dropped its reporter. The scrub is now reference
counted (acquireInheritedLoaderEnvScrub — snapshot on first acquire, restore
only on last release) and the reporter is cleared only when still active.

Test hardening from the same review: pin the daemon-worker scrub breadcrumb
(not just key removal); pin the fast-path settings.env case-folded
hardcoded-exclusion gate; drain the module-global fast-path stash so the
accumulate assertion is order-independent. Docs updated for the new keys.
@wenshao
wenshao force-pushed the fix/8663-loader-denylist-followup branch from e925043 to 92c525f Compare August 8, 2026 22:23
@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Please do not rebase or force-push to an active PR as it invalidates existing review comments. Note for future reference, the bots always squash all changes into a single commit automatically as part of the integration.

中文

请勿对活跃的 PR 执行 rebase 或 force-push,因为这会使已有的评审评论失效。另外,供日后参考:作为集成流程的一部分,机器人始终会自动将所有改动压缩(squash)为单个提交。

@wenshao

wenshao commented Aug 8, 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 8, 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. Remove the autofix/takeover label (or comment @qwen-code /takeover stop) to release.

中文说明

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

@github-actions

github-actions Bot commented Aug 8, 2026 •

Copy link
Copy Markdown
Contributor

Code Coverage Summary

Package Lines Statements Functions Branches
CLI N/A% N/A% N/A% N/A%
Core 87.86% 87.86% 89.39% 86.36%
CLI Package - Full Text Report
CLI full-text-summary.txt not found at: coverage_artifact/cli/coverage/full-text-summary.txt
Core Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   87.86 |    86.36 |   89.39 |   87.86 |                   
 src               |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/__mocks__/fs  |       0 |        0 |       0 |       0 |                   
  promises.ts      |       0 |        0 |       0 |       0 | 1-48              
 src/agents        |   90.38 |    84.54 |   94.85 |   90.38 |                   
  ...transcript.ts |   87.63 |    83.52 |     100 |   87.63 | ...80,588,594-598 
  ...ent-resume.ts |   85.59 |    77.55 |   83.33 |   85.59 | ...1793-1797,1800 
  ...ound-tasks.ts |   94.63 |    90.13 |   96.38 |   94.63 | ...1773,1793-1796 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...ent-result.ts |    96.8 |    92.68 |     100 |    96.8 | 106,129-131       
  ...n-registry.ts |   94.79 |     87.7 |     100 |   94.79 | ...1067,1081-1083 
  ...w-snapshot.ts |   92.12 |    77.14 |     100 |   92.12 | ...65,189,196-198 
 src/agents/arena  |   76.32 |    67.71 |   78.94 |   76.32 |                   
  ...gentClient.ts |   79.47 |    88.88 |   81.81 |   79.47 | ...68-183,189-204 
  ArenaManager.ts  |   75.11 |    64.51 |   78.57 |   75.11 | ...1887,1893-1894 
  arena-events.ts  |   64.44 |      100 |      50 |   64.44 | ...71-175,178-183 
  diff-summary.ts  |    87.5 |    72.34 |     100 |    87.5 | ...32-133,137-138 
  index.ts         |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...gents/backends |   78.09 |    85.23 |   76.28 |   78.09 |                   
  ITermBackend.ts  |   97.97 |    93.93 |     100 |   97.97 | ...78-180,255,307 
  ...essBackend.ts |    90.9 |    85.36 |   93.33 |    90.9 | ...70,672,674-675 
  TmuxBackend.ts   |    90.7 |    76.55 |   97.36 |    90.7 | ...87,697,743-747 
  detect.ts        |   31.25 |      100 |       0 |   31.25 | 34-88             
  index.ts         |     100 |      100 |     100 |     100 |                   
  iterm-it2.ts     |     100 |     92.1 |     100 |     100 | 37-38,106         
  tmux-commands.ts |    6.64 |      100 |    3.03 |    6.64 | ...93-363,386-503 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...agents/runtime |    91.1 |    86.68 |   89.23 |    91.1 |                   
  agent-context.ts |     100 |      100 |     100 |     100 |                   
  agent-core.ts    |   85.07 |     76.8 |   77.77 |   85.07 | ...2291,2337-2339 
  agent-events.ts  |     100 |      100 |     100 |     100 |                   
  ...t-headless.ts |   93.49 |    89.41 |   83.33 |   93.49 | ...96-497,500-501 
  ...nteractive.ts |   81.01 |    82.35 |   76.66 |   81.01 | ...33,535-538,541 
  ...statistics.ts |   98.29 |    82.55 |     100 |   98.29 | 141,165,206,239   
  agent-types.ts   |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...ool-policy.ts |   98.34 |      100 |    92.3 |   98.34 | 81-82             
  ...low-budget.ts |     100 |      100 |     100 |     100 |                   
  ...-scheduler.ts |   97.43 |    96.36 |     100 |   97.43 | 128-130           
  ...ow-journal.ts |   91.76 |    75.86 |     100 |   91.76 | ...38-139,179-181 
  ...chestrator.ts |    92.4 |       90 |   83.78 |    92.4 | ...1862,1911-1914 
  ...ow-prompts.ts |     100 |      100 |     100 |     100 |                   
  ...low-runner.ts |   94.85 |     87.5 |   92.85 |   94.85 | ...93,260,280-283 
  ...ow-sandbox.ts |   96.85 |    91.28 |     100 |   96.85 | ...1705,1711-1712 
  ...flow-saved.ts |   96.51 |    94.36 |     100 |   96.51 | 134-135,234-237   
  ...flow-stall.ts |    97.9 |    83.33 |     100 |    97.9 | 138-139,236       
 src/agents/tasks  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/agents/team   |   82.04 |    84.17 |   88.97 |   82.04 |                   
  TeamManager.ts   |   72.02 |    79.41 |   79.24 |   72.02 | ...1632,1655-1656 
  identity.ts      |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...sionBridge.ts |     100 |      100 |     100 |     100 |                   
  mailbox.ts       |   96.02 |    87.23 |     100 |   96.02 | 352-358           
  ...ptAddendum.ts |     100 |      100 |     100 |     100 |                   
  tasks.ts         |   89.24 |    82.82 |     100 |   89.24 | ...-994,1038-1039 
  team-events.ts   |   60.52 |      100 |      50 |   60.52 | ...40-144,151-155 
  teamHelpers.ts   |   92.02 |    94.91 |   95.23 |   92.02 | ...31-332,368-378 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...eam/test-utils |   94.39 |    94.26 |   98.21 |   94.39 |                   
  ...on-harness.ts |   96.49 |    84.21 |     100 |   96.49 | 128-129,141-142   
  fake-agent.ts    |   98.49 |    95.08 |     100 |   98.49 | 201-203           
  fake-backend.ts  |   86.46 |    97.61 |   95.83 |   86.46 | 124-146           
 src/config        |   84.98 |    87.13 |   75.37 |   84.98 |                   
  approval-mode.ts |     100 |      100 |     100 |     100 |                   
  ...xtDefaults.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |   84.29 |    86.85 |   73.79 |   84.29 | ...8350,8354-8355 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  models.ts        |     100 |      100 |     100 |     100 |                   
  storage.ts       |   94.39 |    91.57 |   88.23 |   94.39 | ...45-446,449-450 
 ...nfirmation-bus |   98.27 |    97.14 |     100 |   98.27 |                   
  message-bus.ts   |   98.14 |    97.05 |     100 |   98.14 | 42-43             
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/core          |   92.34 |    88.04 |   93.26 |   92.34 |                   
  baseLlmClient.ts |    88.4 |     83.8 |   81.81 |    88.4 | ...59,672,678-680 
  client.ts        |   91.95 |    87.18 |   91.56 |   91.95 | ...3928,4026-4027 
  ...tGenerator.ts |   86.34 |    87.34 |   84.61 |   86.34 | ...96-497,542-548 
  ...lScheduler.ts |   90.04 |    84.67 |   96.15 |   90.04 | ...6215,6243-6259 
  geminiChat.ts    |    94.7 |    90.12 |   95.53 |    94.7 | ...5052,5100-5101 
  geminiRequest.ts |     100 |      100 |     100 |     100 |                   
  genai-compat.ts  |     100 |      100 |     100 |     100 |                   
  ...MediaLimit.ts |     100 |       96 |     100 |     100 | 96                
  ...htProtocol.ts |    9.09 |      100 |       0 |    9.09 | ...9,62-66,69-110 
  ...ream-error.ts |     100 |      100 |     100 |     100 |                   
  logger.ts        |   87.41 |    87.02 |     100 |   87.41 | ...64-568,614-628 
  ...lay-buffer.ts |     100 |      100 |     100 |     100 |                   
  ...dispatcher.ts |     100 |      100 |     100 |     100 |                   
  ...tyDefaults.ts |     100 |      100 |     100 |     100 |                   
  ...olExecutor.ts |   93.54 |    83.33 |      50 |   93.54 | 49-50             
  ...on-helpers.ts |   93.49 |    78.57 |     100 |   93.49 | ...10-211,228-229 
  ...issionFlow.ts |   98.97 |    96.96 |     100 |   98.97 | 107               
  ...try-policy.ts |     100 |      100 |     100 |     100 |                   
  ...ell-policy.ts |   94.89 |    88.54 |     100 |   94.89 | ...51-252,297-298 
  prompts.ts       |   93.64 |    91.42 |   83.33 |   93.64 | ...1209,1412-1413 
  ...ing-effort.ts |     100 |      100 |     100 |     100 |                   
  ...n-recovery.ts |   95.13 |       80 |     100 |   95.13 | ...06-107,142-144 
  ...t-profiler.ts |    97.9 |    81.15 |   88.23 |    97.9 | 117,124-125,130   
  ...port-retry.ts |     100 |      100 |     100 |     100 |                   
  tokenLimits.ts   |     100 |     92.1 |     100 |     100 | 87,122-139        
  ...reparation.ts |     100 |      100 |     100 |     100 |                   
  ...tion-guard.ts |   90.38 |    94.73 |     100 |   90.38 | 68-72             
  ...allIdUtils.ts |   98.41 |    93.47 |     100 |   98.41 | 36,45             
  ...okTriggers.ts |   99.45 |    92.43 |     100 |   99.45 | 182,193           
  ...terruption.ts |     100 |     92.3 |     100 |     100 | 86,104            
  turn.ts          |   98.67 |    93.12 |     100 |   98.67 | ...79,707-708,755 
  ...l-fallback.ts |     100 |      100 |     100 |     100 |                   
 ...ntentGenerator |   96.33 |    88.12 |   96.15 |   96.33 |                   
  ...tGenerator.ts |   97.24 |    86.72 |   94.87 |   97.24 | ...1429,1458,1469 
  converter.ts     |   96.19 |    89.25 |     100 |   96.19 | ...1329,1550-1552 
  index.ts         |       0 |        0 |       0 |       0 | 1-21              
  usage.ts         |     100 |      100 |     100 |     100 |                   
 ...ntentGenerator |   88.78 |    72.36 |   89.47 |   88.78 |                   
  ...tGenerator.ts |   87.18 |    71.83 |   88.88 |   87.18 | ...58-364,382-383 
  index.ts         |     100 |       80 |     100 |     100 | 50                
 ...ntentGenerator |    95.6 |    88.74 |    92.3 |    95.6 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...tGenerator.ts |   95.52 |    87.88 |   91.89 |   95.52 | ...1195-1196,1224 
  ...tDetection.ts |     100 |      100 |     100 |     100 |                   
 ...ntentGenerator |   91.63 |    90.43 |   95.61 |   91.63 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  converter.ts     |   91.15 |    89.32 |   96.87 |   91.15 | ...1914,2083-2098 
  errorHandler.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |   60.31 |       75 |      50 |   60.31 | ...71,74-78,90-94 
  ...tGenerator.ts |    66.4 |    70.58 |   88.88 |    66.4 | ...51-157,168-169 
  pipeline.ts      |   95.45 |    91.18 |     100 |   95.45 | ...1301,1309,1408 
  ...ix-caching.ts |   95.23 |    92.85 |     100 |   95.23 | 45-46,69-70       
  ...ureContext.ts |     100 |      100 |     100 |     100 |                   
  ...ingOptions.ts |       0 |        0 |       0 |       0 | 1                 
  ...CallParser.ts |   92.24 |     92.4 |     100 |   92.24 | ...28-529,549-552 
  ...kingParser.ts |     100 |    96.87 |     100 |     100 | 42                
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...rator/provider |   97.19 |    90.44 |   98.36 |   97.19 |                   
  dashscope.ts     |   98.36 |    92.99 |   95.65 |   98.36 | ...93-494,636-637 
  deepseek.ts      |   94.91 |    89.36 |     100 |   94.91 | ...31-132,145-146 
  default.ts       |   99.16 |    96.96 |     100 |   99.16 | 198               
  index.ts         |     100 |      100 |     100 |     100 |                   
  mimo.ts          |   94.11 |    66.66 |     100 |   94.11 | 29,52-53          
  minimax.ts       |     100 |      100 |     100 |     100 |                   
  mistral.ts       |   96.07 |    73.33 |     100 |   96.07 | 32-33             
  modelscope.ts    |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 |                   
  utils.ts         |     100 |      100 |     100 |     100 |                   
  zai.ts           |   92.13 |    82.14 |     100 |   92.13 | ...,39-40,135-137 
 src/extension     |   87.27 |    84.01 |   92.52 |   87.27 |                   
  ...ive-safety.ts |     100 |      100 |     100 |     100 |                   
  ...-converter.ts |   80.55 |    73.66 |     100 |   80.55 | ...1133,1179-1180 
  corruptFile.ts   |     100 |       50 |     100 |     100 | 40-45             
  ...-converter.ts |     100 |      100 |     100 |     100 |                   
  ...me-refresh.ts |     100 |      100 |     100 |     100 |                   
  ...sion-store.ts |   90.85 |    86.38 |   97.87 |   90.85 | ...1218-1224,1268 
  ...ionManager.ts |   82.24 |    80.14 |   81.52 |   82.24 | ...2730,2752-2753 
  ...references.ts |     100 |     90.9 |     100 |     100 | ...05,129,197,200 
  ...onSettings.ts |    92.3 |     94.4 |     100 |    92.3 | ...98-501,570-571 
  ...-converter.ts |    75.9 |    85.36 |   85.71 |    75.9 | ...98,202,214-248 
  github.ts        |   90.42 |    82.66 |     100 |   90.42 | ...0,990-991,1001 
  http-client.ts   |   84.61 |       80 |     100 |   84.61 | 20-21             
  i18n.ts          |   78.26 |       96 |      50 |   78.26 | 104-110,116-123   
  index.ts         |     100 |      100 |     100 |     100 |                   
  marketplace.ts   |   88.39 |    83.11 |     100 |   88.39 | ...08,494,507-508 
  ...ork-policy.ts |   89.72 |       90 |     100 |   89.72 | ...36,148-154,156 
  npm.ts           |   89.02 |    81.81 |     100 |   89.02 | ...86-688,695-700 
  override.ts      |   94.11 |    93.33 |     100 |   94.11 | 63-64,81-82       
  ...-converter.ts |   94.89 |    90.41 |     100 |   94.89 | ...50-151,222-224 
  redaction.ts     |     100 |      100 |     100 |     100 |                   
  settings.ts      |   66.26 |      100 |      50 |   66.26 | 81-107,141-146    
  ...ceRegistry.ts |   94.01 |    83.14 |     100 |   94.01 | ...38-344,365-366 
  storage.ts       |     100 |      100 |     100 |     100 |                   
  ...ableSchema.ts |     100 |      100 |     100 |     100 |                   
  variables.ts     |   88.95 |    84.21 |     100 |   88.95 | ...32-235,238-241 
  ...extraction.ts |   85.77 |       81 |   89.47 |   85.77 | ...02-205,260-261 
 src/followup      |    79.9 |    78.92 |    90.9 |    79.9 |                   
  followupState.ts |   98.44 |    95.74 |     100 |   98.44 | 236-237           
  index.ts         |     100 |      100 |     100 |     100 |                   
  overlayFs.ts     |   96.29 |    88.88 |     100 |   96.29 | 78,108,122        
  speculation.ts   |   71.76 |    64.76 |   71.42 |   71.76 | ...53-654,661-662 
  ...onToolGate.ts |   97.97 |     87.5 |     100 |   97.97 | 105,110           
  ...nGenerator.ts |   72.03 |    81.15 |   83.33 |   72.03 | ...68-219,331-333 
 src/generated     |       0 |        0 |       0 |       0 |                   
  git-commit.ts    |       0 |        0 |       0 |       0 | 1-10              
 src/goals         |    93.3 |    89.05 |    94.6 |    93.3 |                   
  ...eGoalStore.ts |   87.61 |    88.88 |   86.66 |   87.61 | ...85-188,196-204 
  ...t-verifier.ts |   96.27 |     90.9 |     100 |   96.27 | ...20,143-146,163 
  ...checkpoint.ts |   81.48 |    76.19 |     100 |   81.48 | ...02-105,115-118 
  goal-evidence.ts |   88.79 |     88.5 |   96.42 |   88.79 | ...04-805,828-831 
  ...projection.ts |   66.66 |    72.97 |   33.33 |   66.66 | ...83,186,190-192 
  ...ersistence.ts |   87.73 |    84.84 |      80 |   87.73 | ...-94,97,101-106 
  goal-protocol.ts |   95.74 |    93.33 |     100 |   95.74 | 154-155           
  goal-reducer.ts  |    93.4 |    90.65 |   96.96 |    93.4 | ...27,501,519-520 
  goal-runtime.ts  |   97.62 |     89.9 |     100 |   97.62 | ...1049,1169-1170 
  goal-tools.ts    |   98.22 |    93.02 |      95 |   98.22 | ...46-147,248-249 
  ...rn-context.ts |     100 |      100 |     100 |     100 |                   
  goal-verifier.ts |   92.46 |    92.85 |     100 |   92.46 | ...69-172,185-187 
  goal-wire.ts     |       0 |        0 |       0 |       0 | 1-28              
  goalHook.ts      |   96.91 |    92.42 |     100 |   96.91 | 115-120,221-222   
  goalJudge.ts     |   95.84 |    87.09 |     100 |   95.84 | ...55-356,448-449 
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/hooks         |   88.07 |    86.32 |   88.54 |   88.07 |                   
  ...okRegistry.ts |   86.48 |    77.08 |     100 |   86.48 | ...41-344,362-369 
  ...bortSignal.ts |     100 |      100 |     100 |     100 |                   
  context-usage.ts |     100 |      100 |     100 |     100 |                   
  ...terpolator.ts |   96.66 |    93.33 |     100 |   96.66 | 66-67             
  ...HookRunner.ts |   96.68 |    87.23 |     100 |   96.68 | 110-112,231-233   
  ...Aggregator.ts |   96.57 |    91.48 |     100 |   96.57 | ...20-321,402,404 
  ...entHandler.ts |   95.57 |    84.76 |   94.73 |   95.57 | ...1040-1041,1051 
  hookPlanner.ts   |   87.55 |    85.54 |   86.66 |   87.55 | ...22-226,233-244 
  hookRegistry.ts  |   92.53 |    85.43 |     100 |   92.53 | ...39,458,462,466 
  hookRunner.ts    |   62.65 |    72.34 |   66.66 |   62.65 | ...70-771,780-781 
  hookSystem.ts    |   87.64 |     98.5 |   70.83 |   87.64 | ...58-759,765-766 
  ...HookRunner.ts |   79.06 |    66.66 |      80 |   79.06 | ...33-434,452-456 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...edCallback.ts |     100 |      100 |     100 |     100 |                   
  ...HookRunner.ts |   94.19 |    84.37 |   81.81 |   94.19 | ...76-384,458-459 
  ...SkillHooks.ts |   78.75 |       75 |   66.66 |   78.75 | 62-66,137-152     
  ...oksManager.ts |   94.87 |    88.88 |     100 |   94.87 | ...84,325,327-329 
  ssrfGuard.ts     |   86.45 |    89.13 |     100 |   86.45 | ...85,289-295,301 
  stopHookCap.ts   |     100 |      100 |     100 |     100 |                   
  trustedHooks.ts  |      90 |    52.63 |     100 |      90 | ...53,66-67,97-98 
  types.ts         |   94.25 |    96.09 |   88.88 |   94.25 | ...46-547,632-636 
  urlValidator.ts  |     100 |      100 |     100 |     100 |                   
  ...it-context.ts |     100 |      100 |     100 |     100 |                   
 src/ide           |   76.98 |    85.03 |   79.03 |   76.98 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  detect-ide.ts    |     100 |      100 |     100 |     100 |                   
  ide-client.ts    |   69.16 |    84.65 |   68.29 |   69.16 | ...1068,1097-1105 
  ide-installer.ts |   89.06 |    79.31 |     100 |   89.06 | ...36,143-147,160 
  ideContext.ts    |     100 |      100 |     100 |     100 |                   
  process-utils.ts |   84.84 |    71.79 |     100 |   84.84 | ...37,151,193-194 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/lsp           |   58.96 |    70.57 |   66.14 |   58.96 |                   
  ...nfigLoader.ts |   80.55 |       72 |   95.45 |   80.55 | ...02-504,508-514 
  ...ionFactory.ts |   42.81 |    73.07 |      50 |   42.81 | ...76-427,433-450 
  ...Normalizer.ts |   23.09 |    13.72 |   30.43 |   23.09 | ...04-905,909-924 
  ...verManager.ts |   75.73 |     80.1 |   79.66 |   75.73 | ...1346,1352-1382 
  ...eLspClient.ts |   32.78 |       80 |   16.66 |   32.78 | ...89-293,299-300 
  ...LspService.ts |      60 |    73.36 |   78.26 |      60 | ...1575,1635-1645 
  configHash.ts    |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/mcp           |    82.3 |    77.81 |   78.33 |    82.3 |                   
  configHash.ts    |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...h-provider.ts |   86.95 |      100 |   33.33 |   86.95 | ...,93,97,101-102 
  ...h-provider.ts |   79.31 |    58.06 |     100 |   79.31 | ...26-933,940-942 
  ...en-storage.ts |   98.78 |    97.95 |     100 |   98.78 | 106-107           
  oauth-utils.ts   |   73.61 |    85.48 |    92.3 |   73.61 | ...46-366,392-421 
  ...n-provider.ts |   89.83 |       96 |   45.45 |   89.83 | ...43,147,151-152 
 .../token-storage |   82.12 |    88.19 |   89.28 |   82.12 |                   
  ...en-storage.ts |     100 |      100 |     100 |     100 |                   
  ...en-storage.ts |   87.08 |    87.03 |   95.23 |   87.08 | ...00-201,214-215 
  ...en-storage.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...en-storage.ts |   68.14 |    82.35 |   64.28 |   68.14 | ...81-295,298-314 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/memory        |   87.83 |    83.93 |   90.47 |   87.83 |                   
  ...y-document.ts |   89.52 |    84.61 |     100 |   89.52 | ...24-325,329-330 
  ...nel-memory.ts |   97.36 |    96.63 |   96.42 |   97.36 | ...91-293,367-368 
  const.ts         |   94.28 |     92.3 |     100 |   94.28 | 66-67             
  dream.ts         |    64.6 |    72.22 |      50 |    64.6 | ...04-109,124-165 
  ...entPlanner.ts |     100 |    83.33 |     100 |     100 | 136,146           
  entries.ts       |   75.59 |    84.84 |   83.33 |   75.59 | ...56-157,172-180 
  extract.ts       |   92.41 |    79.41 |     100 |   92.41 | 56-61,100,119-122 
  ...entPlanner.ts |   91.59 |    76.74 |     100 |   91.59 | ...05,114-117,293 
  ...ionPlanner.ts |       0 |        0 |       0 |       0 | 1                 
  forget.ts        |   81.83 |       75 |   83.33 |   81.83 | ...51,474,478-507 
  indexer.ts       |   94.14 |       84 |     100 |   94.14 | ...32-233,334,337 
  ...kill-agent.ts |   97.94 |    89.36 |     100 |   97.94 | 82-83,179-180     
  manager.ts       |    78.4 |    82.29 |   77.77 |    78.4 | ...1482,1495-1497 
  ...ent-config.ts |   86.99 |    82.69 |   86.36 |   86.99 | ...69,389,396-402 
  memoryAge.ts     |   90.47 |       80 |     100 |   90.47 | 50-51             
  paths.ts         |     100 |      100 |     100 |     100 |                   
  ...ing-skills.ts |     100 |       72 |     100 |     100 | 31-35,73-78,97    
  prompt.ts        |   97.26 |    87.03 |     100 |   97.26 | ...10-218,222,225 
  recall.ts        |   82.06 |       75 |    90.9 |   82.06 | ...59-364,395-406 
  refresh.ts       |   93.58 |    89.58 |     100 |   93.58 | ...75-176,183-184 
  ...ceSelector.ts |    93.1 |    81.81 |     100 |    93.1 | ...25,127-128,136 
  remember.ts      |   98.89 |    90.19 |     100 |   98.89 | 50,70             
  scan.ts          |   93.12 |    77.41 |     100 |   93.12 | ...08-109,154,157 
  scopes.ts        |     100 |      100 |     100 |     100 |                   
  ...et-scanner.ts |     100 |      100 |     100 |     100 |                   
  ...entPlanner.ts |   77.24 |    74.07 |   72.22 |   77.24 | ...52-456,459,465 
  status.ts        |   10.52 |      100 |       0 |   10.52 | 41-98             
  store.ts         |   92.92 |    81.81 |     100 |   92.92 | ...16-117,147-148 
  ...git-status.ts |     100 |     87.5 |     100 |     100 | 30                
  ...cret-guard.ts |     100 |      100 |     100 |     100 |                   
  ...emory-sync.ts |   94.24 |    82.85 |     100 |   94.24 | ...34-236,246-247 
  types.ts         |     100 |      100 |     100 |     100 |                   
  ...ontextFile.ts |   81.21 |    81.53 |   81.81 |   81.21 | ...63-277,291-296 
 src/mocks         |       0 |        0 |       0 |       0 |                   
  msw.ts           |       0 |        0 |       0 |       0 | 1-9               
 src/models        |   92.55 |    88.97 |   91.13 |   92.55 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...tor-config.ts |   97.77 |    91.83 |     100 |   97.77 | 155,161,171       
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...nfigErrors.ts |   74.22 |    47.82 |   84.61 |   74.22 | ...,67-74,106-117 
  ...igResolver.ts |   98.71 |    93.33 |     100 |   98.71 | 166,328,334       
  modelRegistry.ts |     100 |    98.11 |     100 |     100 | 177,261           
  modelsConfig.ts  |   89.36 |    86.93 |   88.09 |   89.36 | ...1404,1433-1434 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/output        |     100 |      100 |     100 |     100 |                   
  ...-formatter.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/permissions   |   83.79 |    91.16 |   71.07 |   83.79 |                   
  autoMode.ts      |   97.66 |    93.13 |     100 |   97.66 | ...82-589,635,712 
  ...transcript.ts |      98 |       84 |     100 |      98 | 200-201           
  classifier.ts    |      94 |    94.54 |     100 |      94 | 158-165,389-393   
  ...erousRules.ts |     100 |    89.36 |     100 |     100 | 110,133,147,175   
  ...alTracking.ts |     100 |      100 |     100 |     100 |                   
  ...e-commands.ts |   86.77 |     73.8 |     100 |   86.77 | 131-141,210-214   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...on-manager.ts |   86.63 |    89.01 |      80 |   86.63 | ...1111,1217-1221 
  rule-parser.ts   |   94.49 |     92.7 |     100 |   94.49 | ...1447,1481-1483 
  ...-semantics.ts |   70.44 |    91.07 |   46.66 |   70.44 | ...2237,2311-2314 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...sifier-prompts |   99.04 |    95.23 |     100 |   99.04 |                   
  system-prompt.ts |   99.04 |    95.23 |     100 |   99.04 | 220               
 src/prompts       |   83.63 |      100 |    87.5 |   83.63 |                   
  mcp-prompts.ts   |   18.18 |      100 |       0 |   18.18 | 11-19             
  ...t-registry.ts |     100 |      100 |     100 |     100 |                   
 src/providers     |   83.71 |     78.5 |   81.25 |   83.71 |                   
  all-providers.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  install.ts       |   93.11 |     84.5 |     100 |   93.11 | ...56-257,330-331 
  ...der-config.ts |   75.85 |    73.84 |   78.26 |   75.85 | ...73-474,502-503 
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...viders/presets |   97.82 |    91.66 |   63.63 |   97.82 |                   
  ...oding-plan.ts |   87.34 |      100 |       0 |   87.34 | 82-84,87-89,91-94 
  ...a-standard.ts |     100 |      100 |     100 |     100 |                   
  ...token-plan.ts |     100 |      100 |     100 |     100 |                   
  ...m-provider.ts |   97.05 |    81.25 |      75 |   97.05 | 118-119           
  deepseek.ts      |     100 |      100 |     100 |     100 |                   
  grok.ts          |     100 |      100 |     100 |     100 |                   
  idealab.ts       |     100 |      100 |     100 |     100 |                   
  minimax.ts       |     100 |      100 |     100 |     100 |                   
  modelscope.ts    |     100 |      100 |     100 |     100 |                   
  openrouter.ts    |     100 |      100 |     100 |     100 |                   
  requesty.ts      |     100 |      100 |     100 |     100 |                   
  zai.ts           |     100 |      100 |     100 |     100 |                   
 src/qwen          |   85.41 |    78.52 |   95.89 |   85.41 |                   
  ...tGenerator.ts |   98.64 |    98.18 |     100 |   98.64 | 105-106           
  qwenOAuth2.ts    |   82.79 |    73.29 |   90.62 |   82.79 | ...1205-1221,1251 
  ...kenManager.ts |   85.36 |    76.61 |     100 |   85.36 | ...52-757,778-783 
 src/resources     |     100 |      100 |     100 |     100 |                   
  ...e-registry.ts |     100 |      100 |     100 |     100 |                   
 src/services      |   89.74 |    84.59 |   96.91 |   89.74 |                   
  ...ionTrailer.ts |     100 |      100 |     100 |     100 |                   
  ...llRegistry.ts |    98.5 |     87.5 |     100 |    98.5 | 81-82,105,476-477 
  ...ionService.ts |   97.51 |    96.15 |     100 |   97.51 | ...,929,1072-1080 
  ...ingService.ts |   91.41 |    85.15 |   95.65 |   91.41 | ...2116,2143-2144 
  ...ttribution.ts |   91.73 |    87.71 |      90 |   91.73 | ...80-685,826-827 
  ...utSlimming.ts |    97.2 |    93.93 |     100 |    97.2 | ...39-340,378-381 
  cronScheduler.ts |   94.17 |    90.45 |      98 |   94.17 | ...1333,1736-1737 
  cronTasksFile.ts |   95.49 |    90.82 |     100 |   95.49 | ...37,346-347,483 
  cronTasksLock.ts |   94.44 |    89.47 |     100 |   94.44 | ...02-103,132-133 
  ...eryService.ts |   96.22 |    93.54 |      90 |   96.22 | 121,155-156,161   
  ...oryService.ts |   88.17 |    79.02 |    92.3 |   88.17 | ...1303,1344-1347 
  fileReadCache.ts |    97.5 |    96.07 |     100 |    97.5 | 349-350,363-364   
  ...temService.ts |    92.8 |    84.68 |   94.11 |    92.8 | ...41,467-474,519 
  ...ratedFiles.ts |      96 |    88.23 |     100 |      96 | 119-120,146-147   
  gitInit.ts       |     100 |      100 |     100 |     100 |                   
  ...reeService.ts |    73.7 |    68.49 |   95.83 |    73.7 | ...2196,2225-2226 
  ...on-service.ts |   87.38 |       72 |     100 |   87.38 | ...01-305,343-344 
  ...references.ts |   98.39 |    88.76 |     100 |   98.39 | 154-155,215-216   
  ...ionService.ts |   98.26 |    97.35 |     100 |   98.26 | ...13-714,761-762 
  ...ticsDumper.ts |   98.37 |    95.23 |     100 |   98.37 | 185-186           
  ...ureMonitor.ts |   95.82 |    90.52 |   97.05 |   95.82 | ...60,861,875-877 
  ...orRegistry.ts |    97.3 |    91.22 |     100 |    97.3 | ...53-454,611-612 
  ...ttachments.ts |   97.74 |    90.85 |     100 |   97.74 | 298-308,646       
  ...ersistence.ts |   90.95 |    78.75 |     100 |   90.95 | ...78,963-964,992 
  ...on-service.ts |   94.49 |    92.26 |   97.14 |   94.49 | ...98-600,656-664 
  ...ce-service.ts |    98.5 |    94.11 |    90.9 |    98.5 | 64-65             
  ...ipt-reader.ts |   94.55 |    89.78 |   96.66 |   94.55 | ...1353-1354,1422 
  ...est-helper.ts |       0 |        0 |       0 |       0 | 1-65              
  ...iter-lease.ts |   83.14 |    74.47 |   97.61 |   83.14 | ...2433,2445-2448 
  sessionRecap.ts  |   67.56 |    43.47 |     100 |   67.56 | ...60,178,180-183 
  ...ionService.ts |   88.79 |    83.72 |   97.18 |   88.79 | ...2477,2553-2573 
  sessionTitle.ts  |   94.19 |    73.21 |     100 |   94.19 | ...43-246,277-278 
  ...ionService.ts |    84.4 |    78.45 |   97.18 |    84.4 | ...2493,2499-2504 
  ...pInhibitor.ts |   97.42 |    92.77 |     100 |   97.42 | ...30,169,369-370 
  ...Estimation.ts |     100 |    88.23 |     100 |     100 | 118-119           
  ...ageService.ts |   97.76 |    91.59 |   93.75 |   97.76 | ...61-262,366,567 
  ...UseSummary.ts |   94.63 |    88.46 |     100 |   94.63 | ...62-164,214-215 
  ...rd-service.ts |     100 |    88.37 |     100 |     100 | ...29,145-146,241 
  ...oryService.ts |   90.72 |    84.07 |     100 |   90.72 | ...06-509,561-562 
  ...reeCleanup.ts |   14.42 |      100 |   33.33 |   14.42 | 58-186            
  ...ionService.ts |   87.98 |    86.84 |     100 |   87.98 | ...38-439,455-456 
 ...icrocompaction |    98.9 |    95.08 |     100 |    98.9 |                   
  microcompact.ts  |    98.9 |    95.08 |     100 |    98.9 | ...40,749,758-759 
 ...s/visionBridge |   98.81 |    92.12 |     100 |   98.81 |                   
  ...capability.ts |     100 |      100 |     100 |     100 |                   
  ...part-utils.ts |     100 |      100 |     100 |     100 |                   
  ...ion-bridge.ts |   98.72 |    82.35 |     100 |   98.72 | 65,71             
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  ...ge-service.ts |   98.61 |     94.7 |     100 |   98.61 | ...06,666,679-680 
 src/skills        |   89.29 |    85.89 |   93.61 |   89.29 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...activation.ts |     100 |    93.33 |     100 |     100 | 93,112            
  skill-curator.ts |   89.71 |    81.54 |     100 |   89.71 | ...01-902,904-907 
  skill-load.ts    |   94.84 |     87.5 |     100 |   94.84 | ...03,223,235-237 
  skill-manager.ts |   84.82 |    85.29 |   83.33 |   84.82 | ...1243,1250-1254 
  skill-paths.ts   |   90.42 |     87.5 |     100 |   90.42 | ...19-120,125-126 
  symlinkScope.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |   97.91 |    98.03 |     100 |   97.91 | 277-278           
 ...ataviz/scripts |   80.06 |    95.23 |   88.23 |   80.06 |                   
  ...te_palette.js |   80.06 |    95.23 |   88.23 |   80.06 | 261-296,306-328   
 ...s/bundled/loop |   97.48 |    95.77 |     100 |   97.48 |                   
  ...omous-loop.ts |     100 |      100 |     100 |     100 |                   
  ...-task-file.ts |   94.85 |     92.4 |     100 |   94.85 | ...56,367,375-376 
  ...k-resolver.ts |     100 |      100 |     100 |     100 |                   
 src/subagents     |   87.72 |    89.01 |   96.55 |   87.72 |                   
  ...ter-schema.ts |     100 |    98.07 |     100 |     100 | 99                
  ...tin-agents.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...nt-manager.ts |   84.48 |    85.91 |   94.87 |   84.48 | ...1582,1659-1660 
  types.ts         |     100 |      100 |     100 |     100 |                   
  validation.ts    |   92.46 |    95.18 |     100 |   92.46 | 47-52,63-68,71-76 
 src/telemetry     |   81.73 |    83.97 |   84.83 |   81.73 |                   
  ...ty-tracker.ts |     100 |      100 |     100 |     100 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...on-metrics.ts |   99.08 |    80.95 |     100 |   99.08 | 185,199           
  ...on-tracing.ts |   76.31 |    74.62 |   73.68 |   76.31 | ...80,387-389,405 
  ...attributes.ts |   95.15 |    87.27 |     100 |   95.15 | ...97-198,216-217 
  ...ag-metrics.ts |     100 |    77.77 |     100 |     100 | 21,40             
  ...t-loop-lag.ts |   96.85 |    85.71 |     100 |   96.85 | 170-173           
  ...-exporters.ts |   65.78 |    83.33 |   55.55 |   65.78 | ...04-105,108-109 
  ...ai-content.ts |    74.5 |    66.41 |   91.66 |    74.5 | ...1480,1493-1502 
  ...i-provider.ts |     100 |       99 |     100 |     100 | 99                
  ...ai-request.ts |   87.52 |    92.79 |   83.78 |   87.52 | ...55-561,564-570 
  gen-ai-usage.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-111             
  ...-processor.ts |    99.1 |    95.72 |      95 |    99.1 | 145,369-370       
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-128             
  loggers.ts       |   60.03 |    76.51 |   66.07 |   60.03 | ...1484,1501-1521 
  metrics.ts       |   80.37 |    82.35 |   80.95 |   80.37 | ...1150,1153-1164 
  otlp-urls.ts     |     100 |      100 |     100 |     100 |                   
  ...attributes.ts |     100 |      100 |     100 |     100 |                   
  ...ime-config.ts |       0 |        0 |       0 |       0 | 1                 
  sanitize.ts      |      80 |    83.33 |     100 |      80 | 35-36,41-42       
  ...rters-grpc.ts |     100 |      100 |     100 |     100 |                   
  ...rters-http.ts |     100 |      100 |     100 |     100 |                   
  sdk-impl.ts      |   91.06 |    87.15 |   68.75 |   91.06 | ...32,482-483,499 
  sdk.ts           |   82.12 |    90.47 |   66.66 |   82.12 | ...90-194,232-254 
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  ...on-tracing.ts |    91.1 |    88.68 |   96.77 |    91.1 | ...1737,1768-1771 
  ...etry-utils.ts |     100 |      100 |     100 |     100 |                   
  ...l-decision.ts |     100 |      100 |     100 |     100 |                   
  trace-context.ts |     100 |      100 |     100 |     100 |                   
  ...e-id-utils.ts |     100 |      100 |     100 |     100 |                   
  tracer.ts        |   98.56 |    88.63 |     100 |   98.56 | 52,101            
  types.ts         |      83 |    94.32 |   86.36 |      83 | ...1467,1471-1478 
  uiTelemetry.ts   |   97.18 |    93.93 |      88 |   97.18 | ...70,314,461-462 
 ...ry/qwen-logger |   74.23 |     80.7 |      70 |   74.23 |                   
  event-types.ts   |       0 |        0 |       0 |       0 |                   
  qwen-logger.ts   |   74.23 |    80.53 |   69.49 |   74.23 | ...1122,1160-1161 
 src/test-utils    |   96.02 |    98.41 |   82.92 |   96.02 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  ...st-helpers.ts |   94.11 |       90 |     100 |   94.11 | 69-70             
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...mised-lock.ts |     100 |      100 |     100 |     100 |                   
  mock-tool.ts     |   94.85 |      100 |   78.78 |   94.85 | ...53,227-228,241 
  ...aceContext.ts |     100 |      100 |     100 |     100 |                   
 src/tools         |   86.24 |    84.99 |   88.72 |   86.24 |                   
  ...erQuestion.ts |   89.71 |    80.76 |   91.66 |   89.71 | ...66-367,374-375 
  ...-registrar.ts |    77.7 |    66.66 |   66.66 |    77.7 | ...72-277,292-294 
  ...ub-session.ts |   89.67 |     91.3 |   81.81 |   89.67 | ...03-304,315-322 
  cron-create.ts   |   90.64 |    92.85 |   72.72 |   90.64 | ...,73-74,223-231 
  cron-delete.ts   |   97.56 |      100 |   83.33 |   97.56 | 31-32             
  cron-list.ts     |   98.23 |    95.34 |    87.5 |   98.23 | 57-58             
  diffOptions.ts   |     100 |      100 |     100 |     100 |                   
  display-image.ts |   87.42 |    84.84 |   88.88 |   87.42 | ...29-134,194-195 
  edit.ts          |    82.7 |    86.77 |   81.25 |    82.7 | ...43-744,863-913 
  ...r-worktree.ts |   83.14 |    67.56 |    87.5 |   83.14 | ...84-187,278-279 
  enterPlanMode.ts |      85 |     82.6 |    87.5 |      85 | ...28-133,161-175 
  exit-worktree.ts |   83.29 |    83.65 |   94.44 |   83.29 | ...14-515,537-538 
  exitPlanMode.ts  |      95 |    85.29 |     100 |      95 | ...21-325,344,378 
  ...permission.ts |     100 |      100 |     100 |     100 |                   
  glob.ts          |   96.33 |     88.5 |     100 |   96.33 | ...24-225,373,376 
  grep.ts          |   90.73 |    86.61 |   85.71 |   90.73 | ...76-677,727-728 
  ...adTracking.ts |     100 |      100 |     100 |     100 |                   
  image-gen.ts     |   91.66 |    77.41 |    90.9 |   91.66 | ...13-214,221-222 
  list-agents.ts   |   94.02 |    82.35 |   83.33 |   94.02 | 31-32,47-48       
  loop-wakeup.ts   |   99.27 |    92.85 |     100 |   99.27 | 45                
  ls.ts            |   96.74 |    90.27 |     100 |   96.74 | 176-181,212,216   
  lsp.ts           |   72.71 |     59.5 |   90.32 |   72.71 | ...1212,1214-1215 
  ...nt-manager.ts |   82.13 |    80.47 |   85.71 |   82.13 | ...3234,3236-3237 
  mcp-client.ts    |   79.87 |    85.58 |   89.47 |   79.87 | ...2259,2263-2266 
  ...ry-timeout.ts |     100 |      100 |     100 |     100 |                   
  mcp-errors.ts    |     100 |      100 |     100 |     100 |                   
  ...pool-entry.ts |   79.21 |    85.71 |   81.57 |   79.21 | ...1341,1349-1350 
  ...ool-events.ts |       8 |        0 |       0 |       8 | 132-158           
  mcp-pool-key.ts  |   97.46 |    93.93 |     100 |   97.46 | 176-177           
  ...ce-content.ts |   96.55 |    91.17 |     100 |   96.55 | 80-82             
  mcp-retry.ts     |   97.67 |    95.65 |     100 |   97.67 | 131-132           
  ...ion-config.ts |     100 |      100 |     100 |     100 |                   
  mcp-status.ts    |     100 |      100 |     100 |     100 |                   
  mcp-tool.ts      |   98.35 |    93.71 |     100 |   98.35 | ...-990,1045-1046 
  ...sport-pool.ts |   83.98 |     80.3 |   88.46 |   83.98 | ...1409,1416-1420 
  ...ace-budget.ts |   87.27 |     82.6 |     100 |   87.27 | ...00-305,340-345 
  memory-config.ts |     100 |      100 |     100 |     100 |                   
  ...iable-tool.ts |     100 |    84.61 |     100 |     100 | 101,108           
  monitor.ts       |   91.82 |    83.09 |   88.46 |   91.82 | ...99,612,810-815 
  notebook-edit.ts |   85.69 |    77.08 |   81.25 |   85.69 | ...95-911,957-958 
  ...escendants.ts |   36.17 |    64.51 |   55.55 |   36.17 | ...46-310,385-390 
  ...nforcement.ts |   83.21 |    90.69 |     100 |   83.21 | 147-158,207-220   
  read-file.ts     |   95.49 |    88.52 |   86.66 |   95.49 | ...49,464,536-537 
  ...p-resource.ts |   96.85 |      100 |   91.66 |   96.85 | 92-96             
  ...d-artifact.ts |   91.18 |    86.71 |    87.5 |   91.18 | ...26-427,441-453 
  ripGrep.ts       |    94.6 |    87.26 |   95.23 |    94.6 | ...33-734,740-741 
  ...-transport.ts |   71.42 |    55.55 |   71.42 |   71.42 | ...36-137,143-144 
  send-message.ts  |   81.13 |    89.74 |    62.5 |   81.13 | ...80-286,363-371 
  ...n-mcp-view.ts |   94.07 |    91.89 |    90.9 |   94.07 | 131-139           
  shell.ts         |   78.81 |    84.22 |   91.91 |   78.81 | ...5035,5098-5099 
  skill-utils.ts   |     100 |      100 |     100 |     100 |                   
  skill.ts         |   91.39 |    92.55 |      90 |   91.39 | ...84,488,534-556 
  ...eticOutput.ts |   95.12 |      100 |      80 |   95.12 | 87-88             
  task-create.ts   |    94.4 |    93.33 |   81.81 |    94.4 | 45-49,63-64,95    
  task-list.ts     |   73.38 |    77.77 |   83.33 |   73.38 | ...02,105,109-116 
  task-stop.ts     |   93.14 |    96.15 |   85.71 |   93.14 | 39-40,54-64       
  task-update.ts   |   82.89 |    83.92 |    92.3 |   82.89 | ...14-422,454-465 
  team-create.ts   |   97.22 |    85.71 |   83.33 |   97.22 | 48-49,129-130     
  team-delete.ts   |   86.74 |    83.33 |   83.33 |   86.74 | 37-38,42-48,72-73 
  ...n-approval.ts |   92.14 |    96.77 |   77.77 |   92.14 | 38-39,42-43,93-99 
  todoWrite.ts     |   95.13 |    87.85 |   93.33 |   95.13 | ...23-527,540-545 
  tool-error.ts    |     100 |      100 |     100 |     100 |                   
  tool-names.ts    |     100 |      100 |     100 |     100 |                   
  tool-registry.ts |   78.57 |    79.59 |    82.6 |   78.57 | ...89-990,998-999 
  tool-search.ts   |   96.19 |    89.72 |   93.33 |   96.19 | ...09,259-264,426 
  tools.ts         |   93.11 |    92.53 |   91.66 |   93.11 | ...69-570,586-592 
  ...reapproved.ts |   99.27 |    94.11 |     100 |   99.27 | 170               
  web-fetch.ts     |   96.05 |    90.54 |   96.77 |   96.05 | ...85-786,800-801 
  web-search.ts    |   90.58 |    83.57 |      80 |   90.58 | ...1025,1083-1086 
  write-file.ts    |    86.7 |    84.92 |   88.88 |    86.7 | ...24-827,864-899 
  zoom-image.ts    |   95.76 |    93.75 |      90 |   95.76 | 54-59,203-204     
 src/tools/agent   |   87.22 |    87.68 |   88.69 |   87.22 |                   
  agent.ts         |   85.84 |    86.59 |   86.31 |   85.84 | ...4315,4337-4347 
  fork-profile.ts  |   93.65 |       90 |     100 |   93.65 | ...33-134,171-174 
  fork-subagent.ts |   98.73 |       95 |     100 |   98.73 | 101-102,173       
 ...tools/artifact |   95.78 |    92.51 |   88.63 |   95.78 |                   
  artifact-tool.ts |   91.46 |    88.46 |   71.42 |   91.46 | ...13-314,322-325 
  ...-publisher.ts |     100 |    85.71 |     100 |     100 | 32                
  ...-publisher.ts |   96.74 |    97.72 |    87.5 |   96.74 | 29-30,156-157     
  html.ts          |     100 |    96.77 |     100 |     100 | 122               
  ...-publisher.ts |     100 |       80 |     100 |     100 | 30                
  oss-publisher.ts |    98.1 |    91.48 |     100 |    98.1 | 43-45             
  publisher.ts     |     100 |      100 |     100 |     100 |                   
 ...s/computer-use |   90.21 |    82.17 |   78.08 |   90.21 |                   
  bootstrap.ts     |   59.42 |    80.95 |   41.66 |   59.42 | ...35-339,341-345 
  client.ts        |   80.11 |       90 |   77.77 |   80.11 | ...97,242-243,274 
  constants.ts     |     100 |    94.73 |     100 |     100 | 129,256           
  downloader.ts    |   65.29 |    52.77 |   58.33 |   65.29 | ...99-300,316-355 
  index.ts         |     100 |      100 |     100 |     100 |                   
  install-state.ts |   94.44 |    72.72 |     100 |   94.44 | 44-45             
  ...n-detector.ts |     100 |     87.5 |     100 |     100 | 50                
  schemas.ts       |     100 |      100 |     100 |     100 |                   
  tool.ts          |    96.3 |    85.71 |     100 |    96.3 | 75-76,184,252-258 
 ...tools/workflow |   86.51 |    84.81 |      75 |   86.51 |                   
  workflow.ts      |   86.51 |    84.81 |      75 |   86.51 | ...67,512,514-515 
 src/utils         |   92.89 |     89.6 |   96.88 |   92.89 |                   
  LruCache.ts      |     100 |      100 |     100 |     100 |                   
  ...Controller.ts |     100 |      100 |     100 |     100 |                   
  ...ssageQueue.ts |     100 |      100 |     100 |     100 |                   
  ...cFileWrite.ts |   94.94 |    92.47 |     100 |   94.94 | ...43-544,651-655 
  bareMode.ts      |   81.81 |      100 |      50 |   81.81 | 18-19             
  ...ry-content.ts |   98.45 |    95.45 |     100 |   98.45 | 132-133,159-160   
  browser.ts       |   86.84 |    78.94 |     100 |   86.84 | 34,36-37,65-66    
  btwUtils.ts      |   13.95 |      100 |       0 |   13.95 | 17-31,34-55       
  bundlePaths.ts   |     100 |      100 |     100 |     100 |                   
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  ...igResolver.ts |     100 |      100 |     100 |     100 |                   
  ...engthError.ts |   91.06 |    89.47 |     100 |   91.06 | ...46-147,154-155 
  ...n-branches.ts |   95.88 |    94.11 |      95 |   95.88 | ...98-499,511-524 
  ...tion-chain.ts |     100 |      100 |     100 |     100 |                   
  cronDisplay.ts   |     100 |    97.61 |     100 |     100 | 46                
  cronParser.ts    |   95.34 |    93.33 |     100 |   95.34 | 41-42,47-48,70-71 
  debugLogger.ts   |   96.66 |    96.61 |   88.88 |   96.66 | 192-196           
  editHelper.ts    |   93.63 |     83.9 |     100 |   93.63 | ...27-428,462-463 
  editor.ts        |   97.65 |    95.45 |     100 |   97.65 | ...35-336,338-339 
  encoding.ts      |     100 |      100 |     100 |     100 |                   
  env.ts           |     100 |      100 |     100 |     100 |                   
  ...arResolver.ts |   94.28 |    88.88 |     100 |   94.28 | 28-29,125-126     
  ...entContext.ts |   96.63 |    90.13 |   96.66 |   96.63 | ...42,444-445,512 
  errorParsing.ts  |     100 |      100 |     100 |     100 |                   
  ...rReporting.ts |   95.65 |    93.33 |     100 |   95.65 | 37-38             
  errors.ts        |   83.01 |    95.03 |    61.9 |   83.01 | ...62-378,382-388 
  fetch.ts         |   90.68 |    82.51 |     100 |   90.68 | ...72,483-484,503 
  file-identity.ts |     100 |      100 |     100 |     100 |                   
  fileUtils.ts     |   94.87 |    92.95 |   96.15 |   94.87 | ...1907,1915-1916 
  forkedAgent.ts   |   92.45 |    82.35 |   93.75 |   92.45 | ...34,642,647-654 
  formatters.ts    |     100 |      100 |     100 |     100 |                   
  ...eUtilities.ts |    92.4 |    86.95 |     100 |    92.4 | ...52-158,168-169 
  ...rStructure.ts |   94.39 |    94.28 |     100 |   94.39 | ...29-132,343-348 
  getPty.ts        |   31.57 |       50 |     100 |   31.57 | 26-38             
  git-branches.ts  |    91.6 |    84.21 |    92.3 |    91.6 | ...90,405-410,570 
  ...fig-safety.ts |   97.01 |       80 |     100 |   97.01 | 53-54             
  gitDiff.ts       |   95.19 |    81.36 |     100 |   95.19 | ...1073,1419-1420 
  gitDirect.ts     |   98.84 |    94.28 |     100 |   98.84 | 234,318           
  ...noreParser.ts |   94.48 |    93.22 |     100 |   94.48 | ...23-124,158-159 
  gitUtils.ts      |   78.02 |    81.25 |   85.71 |   78.02 | ...22-123,147-198 
  github-prs.ts    |   95.74 |    82.27 |     100 |   95.74 | 216,314-322       
  iconvHelper.ts   |     100 |      100 |     100 |     100 |                   
  ...rePatterns.ts |     100 |      100 |     100 |     100 |                   
  image-view.ts    |   95.12 |    93.33 |     100 |   95.12 | ...68-172,240-244 
  ...ionManager.ts |     100 |     90.9 |     100 |     100 | 27                
  ...lPromptIds.ts |     100 |      100 |     100 |     100 |                   
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  jsonl-utils.ts   |   95.27 |     93.1 |     100 |   95.27 | ...16-317,359-362 
  ...-detection.ts |     100 |      100 |     100 |     100 |                   
  ...iconv-lite.ts |     100 |      100 |     100 |     100 |                   
  ...simple-git.ts |   96.77 |    91.66 |     100 |   96.77 | 38                
  ...m-headless.ts |      96 |    88.88 |     100 |      96 | 34                
  ...iagnostics.ts |    96.4 |     94.2 |     100 |    96.4 | ...66,293-294,376 
  ...yDiscovery.ts |    92.4 |    89.13 |     100 |    92.4 | ...28,331,522-525 
  ...tProcessor.ts |   94.01 |       90 |     100 |   94.01 | ...47-353,445-446 
  ...Inspectors.ts |     100 |      100 |     100 |     100 |                   
  modelId.ts       |   98.96 |    98.21 |     100 |   98.96 | 153               
  ...kerChecker.ts |    90.9 |    91.66 |     100 |    90.9 | 73-79             
  notebook.ts      |   94.57 |    89.91 |   95.83 |   94.57 | ...21,333,385-387 
  openaiLogger.ts  |   91.66 |    89.74 |     100 |   91.66 | ...26-228,251-256 
  osc8.ts          |   54.26 |    64.86 |   83.33 |   54.26 | ...72-195,197-257 
  partUtils.ts     |     100 |    98.64 |     100 |     100 | 211               
  pathReader.ts    |     100 |      100 |     100 |     100 |                   
  paths.ts         |   93.61 |    92.42 |     100 |   93.61 | ...62-563,565-567 
  pdf.ts           |   92.17 |    85.81 |     100 |   92.17 | ...64-565,606-611 
  projectPath.ts   |     100 |      100 |     100 |     100 |                   
  projectRoot.ts   |   71.73 |    78.57 |     100 |   71.73 | 54-66             
  ...ectSummary.ts |   89.62 |    72.41 |     100 |   89.62 | ...40-145,196-199 
  ...tIdContext.ts |     100 |      100 |     100 |     100 |                   
  proxyUtils.ts    |     100 |      100 |     100 |     100 |                   
  ...rDetection.ts |   71.15 |       86 |     100 |   71.15 | ...-90,96-101,147 
  ...noreParser.ts |   92.63 |    91.66 |     100 |   92.63 | ...77-178,197-198 
  rateLimit.ts     |   93.75 |    89.62 |     100 |   93.75 | ...13,218-219,262 
  ...text-range.ts |   96.98 |    87.15 |     100 |   96.98 | ...87-688,763-764 
  readManyFiles.ts |   95.75 |    80.86 |     100 |   95.75 | ...05,558,568-572 
  retry.ts         |   96.09 |    92.52 |     100 |   96.09 | ...67,558-559,577 
  retryContext.ts  |     100 |      100 |     100 |     100 |                   
  ...sification.ts |   97.63 |    97.08 |     100 |   97.63 | ...17,251-252,278 
  retryPolicy.ts   |   97.72 |    90.56 |     100 |   97.72 | 130-131           
  ripgrepUtils.ts  |   90.04 |    93.43 |   95.45 |   90.04 | ...55-565,598-599 
  ...sDiscovery.ts |   97.46 |    93.05 |     100 |   97.46 | ...04,182-183,202 
  ...iagnostics.ts |   83.08 |     67.5 |   92.59 |   83.08 | ...23,543-544,550 
  ...tchOptions.ts |   84.87 |    86.71 |   96.29 |   84.87 | ...71,696,725-734 
  ...odelPrefix.ts |     100 |      100 |     100 |     100 |                   
  runtimeStatus.ts |    97.5 |    89.74 |     100 |    97.5 | 162-163           
  safe-mode.ts     |     100 |      100 |     100 |     100 |                   
  safeJsonParse.ts |     100 |      100 |     100 |     100 |                   
  ...nStringify.ts |     100 |      100 |     100 |     100 |                   
  ...-child-env.ts |     100 |      100 |     100 |     100 |                   
  ...aConverter.ts |   98.03 |    97.75 |     100 |   98.03 | 100,102-103       
  ...aValidator.ts |   92.09 |    83.65 |   90.47 |   92.09 | ...60,882-883,896 
  ...r-launcher.ts |   96.35 |    93.97 |   85.71 |   96.35 | ...35-336,347-348 
  sedEditParser.ts |   91.78 |    92.18 |     100 |   91.78 | ...66-569,645-646 
  ...nIdContext.ts |     100 |      100 |     100 |     100 |                   
  ...orageUtils.ts |   95.98 |    83.96 |     100 |   95.98 | ...70,386,466,485 
  ...-pager-env.ts |     100 |      100 |     100 |     100 |                   
  ...fety-rules.ts |     100 |     89.7 |     100 |     100 | ...01,304,309-311 
  shell-utils.ts   |   86.07 |    88.33 |     100 |   86.07 | ...2269,2276-2280 
  ...lAstParser.ts |   98.27 |    91.38 |     100 |   98.27 | ...1321-1323,1333 
  ...ContextEnv.ts |     100 |       92 |     100 |     100 | 50-52             
  ...nlyChecker.ts |   96.33 |    96.57 |     100 |   96.33 | ...83-284,292-293 
  sideQuery.ts     |   86.82 |    86.66 |     100 |   86.82 | ...79-185,187-193 
  ...pEventSink.ts |     100 |       80 |     100 |     100 | 61                
  ...tGenerator.ts |     100 |      100 |     100 |     100 |                   
  ...ameContext.ts |     100 |      100 |     100 |     100 |                   
  symlink.ts       |   77.77 |       50 |     100 |   77.77 | 44,54-59          
  ...e-encoding.ts |   85.96 |    76.47 |     100 |   85.96 | 58-61,64-65,78-79 
  ...emEncoding.ts |   96.36 |    91.17 |     100 |   96.36 | 59-60,124-125     
  terminalSafe.ts  |     100 |      100 |     100 |     100 |                   
  ...Serializer.ts |   98.72 |       90 |     100 |   98.72 | 42-43,134,201-203 
  testUtils.ts     |   53.33 |      100 |   33.33 |   53.33 | ...53,59-64,70-72 
  ...-constants.ts |     100 |      100 |     100 |     100 |                   
  textUtils.ts     |      65 |      100 |      75 |      65 | 56-75             
  thoughtUtils.ts  |     100 |    95.65 |     100 |     100 | 99                
  ...-converter.ts |   95.23 |    85.71 |     100 |   95.23 | 36-37             
  ...name-utils.ts |     100 |      100 |     100 |     100 |                   
  ...-finalizer.ts |   97.66 |     90.9 |     100 |   97.66 | 165-166,168-172   
  tool-utils.ts    |    95.2 |    93.61 |     100 |    95.2 | ...58-159,162-163 
  ...ultCleanup.ts |   54.62 |       25 |      75 |   54.62 | ...03-105,108-134 
  ...Compaction.ts |   96.13 |    96.42 |     100 |   96.13 | ...34-339,341-346 
  ...pt-records.ts |    87.5 |    86.02 |     100 |    87.5 | ...76-480,510-525 
  truncation.ts    |   90.56 |    90.43 |     100 |   90.56 | ...35-443,480-486 
  windowsPath.ts   |   89.47 |    79.31 |     100 |   89.47 | ...57-58,62,90-91 
  ...aceContext.ts |   96.74 |    91.04 |     100 |   96.74 | ...69,196,299-301 
  xml.ts           |    97.8 |    87.69 |     100 |    97.8 | 98-99             
  yaml-parser.ts   |   83.87 |    77.27 |     100 |   83.87 | ...31-234,239-240 
 ...ils/filesearch |   83.94 |    80.72 |   94.73 |   83.94 |                   
  crawlCache.ts    |     100 |      100 |     100 |     100 |                   
  crawler.ts       |    82.9 |    76.81 |   95.08 |    82.9 | ...1563,1597-1598 
  fileSearch.ts    |   93.78 |    87.67 |     100 |   93.78 | ...71-272,274-275 
  fzfWorker.ts     |       0 |        0 |       0 |       0 | 1-109             
  ...rkerHandle.ts |   84.05 |    75.43 |   89.47 |   84.05 | ...30-334,340-341 
  ignore.ts        |     100 |    97.36 |     100 |     100 | 187               
  result-cache.ts  |     100 |    93.75 |     100 |     100 | 49                
 ...uest-tokenizer |   69.76 |    75.47 |   85.29 |   69.76 |                   
  ...eTokenizer.ts |   65.72 |    74.02 |    92.3 |   65.72 | ...65-466,479-533 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...tTokenizer.ts |   68.39 |    69.49 |    90.9 |   68.39 | ...24-325,327-328 
  ...ageFormats.ts |   76.92 |      100 |   33.33 |   76.92 | 46-49,56-57       
  textTokenizer.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 | 1                 
-------------------|---------|----------|---------|---------|-------------------

For detailed HTML reports, please see the 'coverage-reports-22.x-ubuntu-latest' artifact from the main CI run.

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🔀 Base updated: red check(s) [Test (ubuntu-latest, Node 22.x)] pass on current main — merged current main via update-branch; CI will re-run.

中文说明

🔀 已更新 base:红色检查 [Test (ubuntu-latest, Node 22.x)] 在当前 main 上通过 —— 已通过 update-branch 合入当前 main,CI 将重新运行。

@qwen-code-dev-bot

qwen-code-dev-bot commented Aug 8, 2026 •

Copy link
Copy Markdown
Collaborator

⚠️ AutoFix round 11 ended without publishing a report — view run.

中文说明

⚠️ AutoFix 第 11 轮结束但未发布报告 —— 查看运行。

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 AutoFix updated a stale base — the fix did not pass verification, but this PR was behind main, so it merged current main in via update-branch and will retry on the next scan. A stale base (a dependency or symbol main already changed) can fail the build without being the fix's fault; if it still fails once current, it hands off to a human.

What I found before stopping:
Qwen failed during address-review: status 125.

See the Qwen Autofix agent step logs for model/tool output.

Run log: https://github.com/QwenLM/qwen-code/actions/runs/31283575452


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

… surface

The refcounted acquireInheritedLoaderEnvScrub read/wrote process.env from
config/shared-env-keys.ts, which the serve process.env guard does not scan —
moving the access out of run-qwen-serve.ts dropped its allowlisted count and
failed process-env-guard.test.ts. Pass the env into the coordinator instead so
run-qwen-serve.ts still owns the process.env reference (matching the existing
scrub helpers), and update the allowlist to the new count.
@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 Reviewed the latest feedback — no changes needed. Why, point by point: · 已审阅最新反馈——无需改动。逐点说明原因如下:

Autofix review round: no action required

Nothing to address this round on PR #8763 (head e34df6db92).

Feedback triage

  • Reviews: none newer than the last evaluation (2026-08-08T22:22:36Z).
  • Inline comments: none newer than the last evaluation.
  • Issue-level comments: only the automated serve daemon A/B report, which found ✅ no response changes against the PR base across 4 scenarios — informational, no change requested.
  • Failed / still-red checks: none. All completed checks are SUCCESS or SKIPPED; the only check still running is the automated PR review that produces this round's feedback.
  • No merge conflicts with main; no retry context, budget warnings, or rejected attempts in this round's inputs.

No code changes were made and no commit was created; no verification commands were required because the working tree is untouched.

中文说明

Autofix 评审轮次:无需处理

本轮在 PR #8763(head e34df6db92)上没有需要处理的内容。

反馈分类

  • 评审(Reviews):自上次评估(2026-08-08T22:22:36Z)以来没有新的评审。
  • 行内评论(Inline comments):自上次评估以来没有新的行内评论。
  • Issue 级评论:仅有 serve 守护进程 A/B 自动化测试报告,该报告显示与 PR base 相比在 4 个场景中均无响应变化(✅)——属于信息性内容,未要求任何改动。
  • 失败 / 持续失败的检查:无。所有已完成的检查均为 SUCCESS 或 SKIPPED;唯一仍在运行的检查是产生本轮反馈的自动化 PR 评审。
  • 与 main 无合并冲突;本轮输入中也没有重试上下文、预算警告或被拒绝的尝试。

未做任何代码改动,也未创建提交;由于工作区未被修改,无需运行任何验证命令。

Base-conflict check · 基分支冲突检查: no conflict with main. · 与 main 无冲突。


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

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 AutoFix ran out of time before finishing (timeout (7200000ms)) (attempt 2/100) — it will retry on the next scan.

⚠️ This change was NOT pushed — any commit referenced below was made only in the runner workspace and has been discarded. What the agent reported:
Qwen failed during address-review: timeout (7200000ms).

See the Qwen Autofix agent step logs for model/tool output.

Run log: https://github.com/QwenLM/qwen-code/actions/runs/31290546316


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

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 Addressed the latest review feedback (round 3/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 3/100 轮)。改动内容与我反驳保留之处如下:

Address-review summary — PR #8763 (round after budget timeout)

Scope decision

This round carried a budget warning: the previous round exhausted its time budget without finishing anything. Per the workflow rules, this round addressed only the smallest blocking subset — the two Critical findings — committed as soon as complete, and deferred the twelve Suggestions with per-thread replies (comment-replies.json) so no finding is dropped silently.

Feedback dispositions

Addressed (2 Criticals, one commit: 46e2690465)

Finding Disposition Change
[Critical] GIT_CONFIG_PARAMETERS left the git config-injection family reachable (inline 3742328269) Fixed — verified: core/utils/git-branches.ts GIT_ENV_VARS_TO_CLEAR (the list this PR's comment claims to mirror) already strips it, and the test at shared-env-keys.test.ts:166 pinned the omission Added 'GIT_CONFIG_PARAMETERS' to PROJECT_ENV_HARDCODED_EXCLUSIONS; flipped the pinned assertion (the prefix-overmatch negative case now uses GIT_CONFIG_NOSYSTEM, which only skips the system gitconfig read and injects nothing); extended the case-insensitive coverage; extended the end-to-end loadEnvironment rejection test (environment.test.ts); updated the docs enumeration
[Critical] GIT_SSH (legacy counterpart of the blocked GIT_SSH_COMMAND) not excluded (inline 3742328276) Fixed — verified: git still execs GIT_SSH for SSH transports, and the denylist is centralized in isHardcodedProjectEnvExclusion, which all six application gates (4 in environment.ts, 2 in fast-path-settings.ts) route through Added 'GIT_SSH' next to 'GIT_SSH_COMMAND'; same test/doc updates as above

Both keys stay in the reject-from-project-files tier (not the scrubbed loader set), consistent with their siblings: shell-exported and user-level .env values are preserved.

Deferred with replies (12 Suggestions — see comment-replies.json)

  • 3742328281 GIT_SSL_NO_VERIFY TLS-tier addition — valid; first candidate for the follow-up round.
  • 3742328283 docs overstate the settings.env tier scope — needs a maintainer decision between rewording the docs and making the settings.env gates scope-aware (option (b) changes the PR's security semantics); recommendation recorded in the reply.
  • 3742328285 npm_config_git missing from the docs enumeration — valid; lands with the follow-up.
  • 3742328278 reporter slot LIFO-order diagnostic loss — valid; stack/registry redesign deferred to a dedicated change.
  • 3742328286 no diagnostics for hardcoded-tier rejections — valid; warn-once machinery mirror deferred to a dedicated change.
  • 3742328289, 3742328293, 3742328295, 3742328297, 3742328299, 3742328302, 3742328305 test-efficacy probes (surviving mutants / hunk-survived reverts) — all valid; the proposed tests are grouped into the follow-up (one two-cycle scrub test covers three of the mutants).

Review-level notes

  • The CHANGES_REQUESTED state was driven by issue-level comment 5228685910, which reports the autofix agent's own failed run on a stale base (status 125) and names no code defect — there is nothing to trace in this diff; the substantive unresolved findings were the two Criticals above, now fixed.
  • The reviewer's "not reviewed" note (Integration Tests (CLI, No Sandbox) skipped in CI) is acknowledged: the changed behavior is exercised at the loadEnvironment/fast-path unit surface, which the focused suites cover end-to-end, including the exact attack scenario (project .env → rejected).
  • The reviewer's budget-cut exploration (close()-teardown ordering before restoreScrubbedLoaderEnv()) was left open by the reviewer itself and is not a finding; the scrub-lifecycle questions it raises are covered by the deferred test-efficacy replies above.

Conflict notes

--conflict false: no merge of origin/main performed; none needed.

Verification

Commands actually run this round (repo root unless noted):

  • npm run build — passed (also produced the missing packages/channels/base/dist entry that made fast-path.test.ts uncollectable before the build — a stale-checkout artifact, not related to this change)
  • npm run typecheck — passed
  • npm run lint — passed
  • npx vitest run src/config/shared-env-keys.test.ts src/config/environment.test.ts src/serve/fast-path.test.ts (in packages/cli) — 141 passed (3 files)
  • npx vitest run src/commands/channel/daemon-worker.test.ts src/serve/process-env-guard.test.ts (in packages/cli) — 81 passed (2 files)
  • npx prettier --check on the four touched files — passed

Integration tests after npm run bundle were not run: the touched behavior (project .env/settings.env rejection) is fully exercised by the unit surfaces above, not only through the bundled CLI. npm run generate:settings-schema was not needed: no settings source changed.

中文说明

处理评审总结 — PR #8763(预算超时后的本轮)

范围决定

本轮带有预算警告:上一轮耗尽了时间预算且没有完成任何内容。按照工作流规则,本轮只处理最小阻断子集——两条 Critical 发现——完成后立即提交,并将十二条 Suggestion 以逐线程回复(comment-replies.json)的方式延迟处理,确保没有任何发现被悄悄丢弃。

反馈处置

已处理(2 条 Critical,单次提交:46e2690465)

发现 处置 变更
[Critical] GIT_CONFIG_PARAMETERS 使 git 配置注入家族仍然可达(inline 3742328269) 已修复——已核实:core/utils/git-branches.ts 的 GIT_ENV_VARS_TO_CLEAR(本 PR 注释声称要对齐的列表)本来就清除了它,而 shared-env-keys.test.ts:166 的测试把这一遗漏钉死了 在 PROJECT_ENV_HARDCODED_EXCLUSIONS 中新增 'GIT_CONFIG_PARAMETERS';翻转被钉死的断言(前缀过度匹配的负例改用 GIT_CONFIG_NOSYSTEM——它只跳过系统 gitconfig 读取,不能注入任何配置);补充大小写不敏感覆盖;扩展端到端 loadEnvironment 拒绝测试(environment.test.ts);更新文档枚举
[Critical] GIT_SSH(已被阻断的 GIT_SSH_COMMAND 的旧版对应变量)未被排除(inline 3742328276) 已修复——已核实:git 在 SSH 传输时仍会执行 GIT_SSH,且拒绝名单集中在 isHardcodedProjectEnvExclusion,全部六个应用门控(environment.ts 中 4 处、fast-path-settings.ts 中 2 处)都经由它 在 'GIT_SSH_COMMAND' 旁新增 'GIT_SSH';测试/文档更新同上

两个键都保留在"仅从项目文件拒绝"层(不进入被剥离的 loader 集合),与其同族键一致:shell 导出值与用户级 .env 值仍然保留。

以回复延迟处理(12 条 Suggestion——见 comment-replies.json)

  • 3742328281 TLS 层补充 GIT_SSL_NO_VERIFY——有效;下一轮的第一候选。
  • 3742328283 文档夸大了 settings.env 层的作用域——需要维护者在"改写文档"与"让 settings.env 门控区分作用域"之间做决定(选项 (b) 会改变本 PR 的安全语义);回复中已记录建议。
  • 3742328285 文档枚举缺少 npm_config_git——有效;随下一轮一起合入。
  • 3742328278 reporter 槽在 LIFO 顺序下的诊断丢失——有效;栈/注册表改造延迟到专门的变更。
  • 3742328286 硬编码层拒绝没有任何诊断——有效;复刻 warn-once 机制延迟到专门的变更。
  • 3742328289、3742328293、3742328295、3742328297、3742328299、3742328302、3742328305 测试有效性探针(存活变异体 / hunk 存活回退)——全部有效;所提议的测试归入下一轮(其中一个双周期剥离测试可覆盖其中三个变异体)。

评审层面的说明

  • CHANGES_REQUESTED 状态源自 issue 级评论 5228685910,该评论报告的是 autofix 代理自身在陈旧 base 上的失败运行(status 125),没有指出任何代码缺陷——本 diff 中无可追溯的内容;实质性的未决发现就是上面两条 Critical,现已修复。
  • 评审者的"未审查"说明(CI 中跳过了 Integration Tests (CLI, No Sandbox))已知悉:本次变更的行为在 loadEnvironment/fast-path 单元层面被完整覆盖,聚焦套件已端到端覆盖,包括确切的攻击场景(项目 .env → 被拒绝)。
  • 评审者因预算用尽而未完成的探索(restoreScrubbedLoaderEnv() 之前的 close() 拆除顺序)由评审者自己留作未决,不构成发现;其引发的剥离生命周期问题已由上面延迟的测试有效性回复覆盖。

冲突说明

--conflict false:未合并 origin/main,也无需合并。

验证

本轮实际执行的命令(未注明者均在仓库根目录):

  • npm run build —— 通过(同时生成了此前缺失的 packages/channels/base/dist 入口文件——该缺失曾导致 fast-path.test.ts 无法收集,属于检出环境的陈旧产物,与本变更无关)
  • npm run typecheck —— 通过
  • npm run lint —— 通过
  • npx vitest run src/config/shared-env-keys.test.ts src/config/environment.test.ts src/serve/fast-path.test.ts(在 packages/cli 内)—— 141 通过(3 个文件)
  • npx vitest run src/commands/channel/daemon-worker.test.ts src/serve/process-env-guard.test.ts(在 packages/cli 内)—— 81 通过(2 个文件)
  • 对四个被改动文件执行 npx prettier --check —— 通过

未运行 npm run bundle 之后的集成测试:本次变更的行为(项目 .env/settings.env 拒绝)已由上述单元层面完整覆盖,并非只能经由打包后的 CLI 验证。未运行 npm run generate:settings-schema:未改动任何 settings 源。

Base-conflict check · 基分支冲突检查: no conflict with main. · 与 main 无冲突。

Re-review when you have a moment. After round 100 this bot stops and leaves the PR for a human. · 有空请复审;第 100 轮后本 bot 停止并将 PR 交给人工。


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

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 AutoFix ran out of time before finishing (timeout (7200000ms)) (attempt 4/100) — it will retry on the next scan.

What I found before stopping:
Qwen failed during address-review: timeout (7200000ms).

See the Qwen Autofix agent step logs for model/tool output.

Run log: https://github.com/QwenLM/qwen-code/actions/runs/31307298125


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

…c-file tiers

Close the round-2 review findings: block the remaining git
command-execution siblings (GIT_EXEC_PATH, GIT_TEMPLATE_DIR, GIT_ASKPASS,
GIT_PROXY_COMMAND, GIT_EDITOR), the npm/pip TLS trust knobs
(npm_config_cafile, npm_config_ca, npm_config_strict_ssl, PIP_CERT,
GIT_SSL_CAPATH), and the curl/wget rc-file redirects (CURL_HOME, WGETRC)
from project .env files. Freeze the numbered GIT_CONFIG_KEY_/VALUE_ pairs
on reload together with GIT_CONFIG_COUNT, and sync the qwen-serve.md
loader-key enumeration with settings.md.
@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 Addressed the latest review feedback (round 5/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 5/100 轮)。改动内容与我反驳保留之处如下:

Round response to round-2 review feedback (PR #8763)

Commit: ade3833a27 on top of 46e2690465. No conflicts (--conflict false; origin/main was not merged).

Note: this round ran under a budget warning from the previous round, so the work focused on the blocking subset plus the cheap in-scope fixes; the one decline below is recorded with its reason and its thread stays open.

Feedback dispositions

Finding Severity Disposition
rc:3743394920 — git exec-family siblings missing from both tiers Critical Fixed
rc:3743394923 — npm/pip TLS trust knobs pass every gate Suggestion Fixed (PIP_INDEX_URL declined, see below)
rc:3743394925 — qwen-serve.md enumeration out of sync Suggestion Fixed
rc:3743394926 — reload gate lacks the prefix handling Suggestion Fixed
rc:3743394927 — home .env removals don't propagate on reload Suggestion Fixed via the documentation option the finding offered
rc:3743394928 — multi-daemon scrub/restore audit gap Suggestion Declined this round (reply posted on the thread, left open)
Review CHANGES_REQUESTED — integration suite skipped in CI, not run locally Review event Addressed with a local run (see Verification)

What changed

rc:3743394920 (Critical). Added the remaining git command-execution siblings to the reject-from-project-.env tier: GIT_EXEC_PATH, GIT_TEMPLATE_DIR, GIT_ASKPASS, GIT_PROXY_COMMAND. GIT_EDITOR was evaluated on the same terms as requested and added too: git executes it whenever an editor opens (git commit without -m, interactive rebase) — the same exec class as the already-blocked GIT_EXTERNAL_DIFF; the reject-only tier still preserves an operator's own shell/home value. Pinned by membership, case-folded predicate, and project-.env rejection tests. While editing the family comment I also corrected its overclaim that core/utils/git-branches.ts "scrubs exactly these" (it scrubs the config-injection subset).

rc:3743394923. Added the npm/pip/git trust knobs to the TLS tier: GIT_SSL_CAPATH, npm_config_cafile, npm_config_ca, npm_config_strict_ssl, PIP_CERT. npm_config_strict-ssl (hyphen form) is listed as well: npm treats underscore/hyphen spellings of a config key as the same key — the same model this PR's loader comment already relies on — so the hyphen twin is blocked too. PIP_INDEX_URL was deliberately not added: it is the registry-redirection class, and npm_config_registry is likewise not blocked (declared-deferred class); blocking only pip's index knob would be inconsistent and incomplete. If that class is closed later, it should be closed for npm and pip together.

rc:3743394925. The docs/users/qwen-serve.md loader enumeration now lists OPENSSL_CONF, NODE_REPL_EXTERNAL_MODULE, npm_config_node_gyp, npm_config_init_module, matching settings.md.

rc:3743394926. isReloadExcludedKey now ORs in isHardcodedProjectEnvExclusion, giving the reload gate the same prefix handling as the hardcoded tier (the literal hardcoded exclusions were already spread into RELOAD_EXCLUDED_KEYS, so this adds exactly the prefix coverage). The numbered GIT_CONFIG_KEY_<n>/GIT_CONFIG_VALUE_<n> pairs now freeze on reload together with GIT_CONFIG_COUNT — one mechanism, one gate. A new test pins the freeze for both edits and removals, and that an ordinary neighboring key still rotates.

rc:3743394927. Took the finding's documentation option rather than the provenance-based deletion change: settings.md now states the reject-only keys are frozen at boot from a user-level .env (edits and removals do not apply on settings reload until process restart). Implementing provenance-tracked deletion propagation is a larger reload-path behavior change that belongs in its own change.

rc:3743394928. Declined this round, with a reply on the thread: the finding is diagnostics-only (reject/restore behavior is correct and test-pinned, as the finding itself notes), and the durable-log coordination plus pre-close callback rework is disproportionate diff growth for a budget-constrained round. The thread stays open so the suggestion is not silently dropped.

Review-level CHANGES_REQUESTED (integration suite). The "Integration Tests (CLI, No Sandbox)" job is merge-queue-gated by design (if: github.event_name == 'merge_group' in ci.yml), so it is skipped on every PR push and runs before landing. As local evidence for this surface, the serve-related integration files were run against the freshly built bundle (npm run build + npm run bundle): cli/qwen-serve-routes.test.ts, cli/qwen-serve-streaming.test.ts, cli/daemon-invocation-context.test.ts — 41 tests passed. The full merge-queue suite remains the authoritative gate for the rest of that surface.

Verification

  • npm run build — passed
  • npm run typecheck — passed
  • npm run lint — passed
  • npx eslint on the 4 touched source/test files — passed; npx prettier --check on the 6 touched files — passed
  • vitest run src/config/shared-env-keys.test.ts src/config/environment.test.ts (packages/cli) — 59 passed
  • vitest run src/serve/fast-path.test.ts src/serve/process-env-guard.test.ts src/commands/channel/daemon-worker.test.ts (packages/cli) — 166 passed
  • npm run bundle — passed
  • QWEN_SANDBOX=false vitest run --root ./integration-tests cli/qwen-serve-routes.test.ts cli/qwen-serve-streaming.test.ts cli/daemon-invocation-context.test.ts — 41 passed (3 files)
中文说明

对第 2 轮审查反馈的回应(PR #8763)

提交:ade3833a27,基于 46e2690465。无冲突(--conflict false;未合并 origin/main)。

说明:由于上一轮耗尽时间预算,本轮带有预算警告,因此工作聚焦于阻塞子集加上低成本的范围内修复;下方唯一一条拒绝已记录理由,其讨论串保持打开。

反馈处置

发现 严重度 处置
rc:3743394920 — git 命令执行家族的同族变量在两层名单中均缺失 Critical 已修复
rc:3743394923 — npm/pip 的 TLS 信任锚旋钮可通过所有门控 Suggestion 已修复(PIP_INDEX_URL 被拒绝,见下文)
rc:3743394925 — qwen-serve.md 枚举未同步 Suggestion 已修复
rc:3743394926 — 重载门控缺少前缀处理 Suggestion 已修复
rc:3743394927 — home .env 中的删除不随重载传播 Suggestion 按该发现提供的文档选项修复
rc:3743394928 — 多 daemon 剥离/恢复的审计缺口 Suggestion 本轮拒绝(已在讨论串回复并保持打开)
审查级 CHANGES_REQUESTED — 集成套件在 CI 被跳过且本地未运行 审查事件 以本地运行结果回应(见"验证"一节)

变更内容

rc:3743394920(Critical)。 将剩余的 git 命令执行家族变量加入"拒绝来自项目 .env"层:GIT_EXEC_PATH、GIT_TEMPLATE_DIR、GIT_ASKPASS、GIT_PROXY_COMMAND。按要求以同样标准评估了 GIT_EDITOR 并一并加入:git 在需要编辑器时会执行它(不带 -m 的 git commit、交互式 rebase)——与已被阻断的 GIT_EXTERNAL_DIFF 同属命令执行类;仅拒绝层仍会保留操作者自己 shell/home 中的值。以成员断言、大小写折叠谓词断言和项目 .env 拒绝测试钉住。编辑该家族注释时,同时修正了其中"core/utils/git-branches.ts 已精确剥离这些键"的过度表述(它实际剥离的是配置注入子集)。

rc:3743394923。 将 npm/pip/git 的信任旋钮加入 TLS 层:GIT_SSL_CAPATH、npm_config_cafile、npm_config_ca、npm_config_strict_ssl、PIP_CERT。同时列出了 npm_config_strict-ssl(连字符形式):npm 将配置键的下划线/连字符拼写视为同一键——与本 PR loader 注释已采用的模型一致——因此连字符孪生形式也被阻断。PIP_INDEX_URL 有意未加入:它属于注册表重定向类,而 npm_config_registry 同样未被阻断(已声明延期的类别);只阻断 pip 的索引旋钮既不一致也不完整。若将来关闭该类,应同时为 npm 与 pip 关闭。

rc:3743394925。 docs/users/qwen-serve.md 的 loader 枚举现已列出 OPENSSL_CONF、NODE_REPL_EXTERNAL_MODULE、npm_config_node_gyp、npm_config_init_module,与 settings.md 保持一致。

rc:3743394926。 isReloadExcludedKey 现在并入 isHardcodedProjectEnvExclusion,使重载门控具备与硬编码层相同的前缀处理(硬编码的字面量排除项本已展开进 RELOAD_EXCLUDED_KEYS,因此这里恰好只补上前缀覆盖)。编号 GIT_CONFIG_KEY_<n>/GIT_CONFIG_VALUE_<n> 对现在与 GIT_CONFIG_COUNT 一起在重载时冻结——同一机制、同一门控。新增测试钉住编辑与删除两种情形下的冻结,以及相邻普通键仍可轮换。

rc:3743394927。 采用该发现提供的文档选项,而非基于来源跟踪的删除传播:settings.md 现已说明这些"仅拒绝项目文件"的键在来自用户级 .env 时于启动时冻结(settings 重载不会应用对它们的修改或删除,直到进程重启)。实现基于来源的删除传播是对重载路径较大的行为变更,应作为独立变更处理。

rc:3743394928。 本轮拒绝,并已在讨论串回复:该发现仅影响诊断(拒绝/恢复行为正确且有测试钉住,发现本身也如此说明),而持久日志协调加上关闭前回调通道的改造,对于预算受限轮次而言属于不成比例的 diff 增长。讨论串保持打开,该建议不会被静默丢弃。

审查级 CHANGES_REQUESTED(集成套件)。 "Integration Tests (CLI, No Sandbox)" 任务在设计上仅由合并队列触发(ci.yml 中 if: github.event_name == 'merge_group'),因此每次 PR 推送都会被跳过,并在落地前运行。作为该应用面的本地证据,已对新构建的 bundle(npm run build + npm run bundle)运行 serve 相关集成文件:cli/qwen-serve-routes.test.ts、cli/qwen-serve-streaming.test.ts、cli/daemon-invocation-context.test.ts —— 41 个测试全部通过。该应用面其余部分的权威门控仍是合并队列的完整套件。

验证

  • npm run build — 通过
  • npm run typecheck — 通过
  • npm run lint — 通过
  • 对 4 个改动的源码/测试文件运行 npx eslint — 通过;对 6 个改动文件运行 npx prettier --check — 通过
  • vitest run src/config/shared-env-keys.test.ts src/config/environment.test.ts(packages/cli)— 59 通过
  • vitest run src/serve/fast-path.test.ts src/serve/process-env-guard.test.ts src/commands/channel/daemon-worker.test.ts(packages/cli)— 166 通过
  • npm run bundle — 通过
  • QWEN_SANDBOX=false vitest run --root ./integration-tests cli/qwen-serve-routes.test.ts cli/qwen-serve-streaming.test.ts cli/daemon-invocation-context.test.ts — 41 通过(3 个文件)

Base-conflict check · 基分支冲突检查: no conflict with main. · 与 main 无冲突。

Re-review when you have a moment. After round 100 this bot stops and leaves the PR for a human. · 有空请复审;第 100 轮后本 bot 停止并将 PR 交给人工。


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

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 Could not produce a passing fix for this feedback (round 6/100). This item now needs a human; the loop stays engaged and still picks up new feedback and base conflicts, but will not retry this item on its own.

What I found before stopping:
Qwen failed during address-review: status 137.

See the Qwen Autofix agent step logs for model/tool output.

Run log: https://github.com/QwenLM/qwen-code/actions/runs/31322652532


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

…ist-followup

# Conflicts:
#	packages/cli/src/config/shared-env-keys.test.ts

@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.

⚠️ Downgraded from Request changes to Comment: self-PR; CI still running. 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.

中文说明

⚠️ 已从请求修改降级为评论:self-PR; CI still running。 已审查。 建议见行内评论。 未审查:build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally。

— gpt-5.6-sol via Qwen Code /review (v0.21.8)

Comment on lines +337 to +339
sharedProcessEnvScrubDepth++;
const removedKeys = scrubAndReportInheritedLoaderEnv(
env,

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.

[Critical] R1-2: A nested scrub acquisition deletes a later host assignment without snapshotting it. — Failure scenario: daemon A acquires, the embedding host assigns NODE_OPTIONS, then daemon B acquires and scrubs it; the final release leaves the value absent or restores an older snapshot, corrupting the embedding process environment. Preserve newly present loader-key assignments before nested scrubs and add the exact A → assign → B → release regression test.

中文说明

R1-2: 嵌套 scrub acquire 会删除后续 host 赋值,却没有把它记入快照。失败场景:daemon A acquire 后,嵌入宿主设置 NODE_OPTIONS,随后 daemon B acquire 并将其剥离;最终 release 后该值保持缺失或恢复成更旧的快照,破坏嵌入进程环境。请在嵌套剥离前保存新出现的 loader 键赋值,并增加精确的 A → 赋值 → B → release 回归测试。

— gpt-5.6-sol via Qwen Code /review (v0.21.8)

Comment on lines +68 to +70
'npm_config_strict_ssl',
'npm_config_strict-ssl',
'PIP_CERT',

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.

[Critical] R1-3: PIP_CONFIG_FILE remains accepted and can redirect all pip configuration. — Failure scenario: an untrusted project points it at a repository file that sets index-url, trusted-host, proxy, cert, or client-cert; a session pip invocation sends traffic or credentials to attacker-controlled infrastructure. Add it to the project-only exclusions and cover every application/reload boundary.

中文说明

R1-3: PIP_CONFIG_FILE 仍可被接受,并能重定向 pip 的全部配置。失败场景:不受信项目将其指向仓库内配置文件,设置 index-url、trusted-host、代理、证书或客户端证书;会话中的 pip 调用会把流量或凭据发送到攻击者控制的基础设施。请将其加入仅项目级排除名单,并覆盖所有应用/重载边界。

— gpt-5.6-sol via Qwen Code /review (v0.21.8)

Comment on lines +97 to +99
'GIT_TEMPLATE_DIR',
'GIT_ASKPASS',
'GIT_PROXY_COMMAND',

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.

[Critical] R1-4: SSH_ASKPASS remains accepted although Git uses it as a fallback executable. — Failure scenario: a project sets SSH_ASKPASS to an attacker script and forces askpass; a Git authentication challenge executes the script as the daemon user. Add SSH_ASKPASS (and evaluate SSH_ASKPASS_REQUIRE) to the project exclusion tier with application and reload tests.

中文说明

R1-4: SSH_ASKPASS 仍可被接受,而 Git 会把它作为后备可执行程序。失败场景:项目将 SSH_ASKPASS 设置为攻击者脚本并强制 askpass;Git 认证挑战会以 daemon 用户身份执行该脚本。请将 SSH_ASKPASS(并评估 SSH_ASKPASS_REQUIRE)加入项目排除层,补齐应用和重载测试。

— gpt-5.6-sol via Qwen Code /review (v0.21.8)

Comment on lines 210 to 212
'npm_config_script_shell',
'npm_config_prefix',
'NODE_PATH',

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.

[Critical] R1-6: LESSOPEN remains accepted although less executes it as an input preprocessor. — Failure scenario: a project sets LESSOPEN to an attacker command; a session running less on a file executes that command as the daemon user. Add it to the appropriate exclusion tier and cover every environment-loading boundary.

中文说明

R1-6: LESSOPEN 仍可被接受,而 less 会将其作为输入预处理器执行。失败场景:项目将 LESSOPEN 设置为攻击者命令;会话对文件运行 less 时会以 daemon 用户身份执行该命令。请将其加入合适的排除层,并覆盖所有环境加载边界。

— gpt-5.6-sol via Qwen Code /review (v0.21.8)

Comment on lines +154 to +156
return HARDCODED_PROJECT_ENV_EXCLUSION_PREFIXES.some((prefix) =>
lowerKey.startsWith(prefix),
);

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.

[Suggestion] R1-7: The prefix matcher rejects nonnumeric GIT_CONFIG_KEY_/GIT_CONFIG_VALUE_ suffixes that Git does not consume. — Concrete cost: a project-defined variable such as GIT_CONFIG_KEY_CACHE is silently rejected and frozen although Git only interprets decimal-numbered pairs. Match a numeric suffix and add negative tests for empty/nonnumeric suffixes.

中文说明

R1-7: 前缀匹配会拒绝 Git 并不消费的非数字 GIT_CONFIG_KEY_/GIT_CONFIG_VALUE_ 后缀。具体代价:如 GIT_CONFIG_KEY_CACHE 这样的项目自定义变量会被静默拒绝并冻结,尽管 Git 只解释数字编号对。请只匹配数字后缀,并增加空后缀/非数字后缀负例。

— gpt-5.6-sol via Qwen Code /review (v0.21.8)

Comment on lines +882 to +883
// An ordinary key next to them still rotates — the freeze is key-scoped.
expect(process.env['RUNTIME_DOTENV']).toBe('allowed');

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.

[Suggestion] R1-8: The ordinary-key reload assertion is vacuous because the fixture value never changes. — Concrete cost: if reload accidentally freezes every environment key, RUNTIME_DOTENV remains allowed and this test still passes. Rewrite the second fixture with a distinct value such as rotated and assert it after reload.

中文说明

R1-8: 普通键重载断言是空洞的,因为 fixture 的值从未变化。具体代价:若重载错误地冻结所有环境键,RUNTIME_DOTENV 仍为 allowed,测试依然通过。请将第二个 fixture 改为不同值(如 rotated),并在重载后断言该值。

— gpt-5.6-sol via Qwen Code /review (v0.21.8)

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 Addressed the latest review feedback (round 7/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 7/100 轮)。改动内容与我反驳保留之处如下:

Autofix address-review round — PR #8763

Feedback triage

Critical-only mode is active after five change-producing rounds. This round's actionable sections contained no feedback: no reviews, no inline comments, no issue-level comments, no failed checks, and no still-red checks. The Deferred non-Critical feedback section is an audit record and was not worked, per the round rules. No threads were resolved or replied to, so resolved-comments.txt and comment-replies.json are omitted.

Base-conflict resolution (requested via --conflict true)

Merged origin/main (0a3d7bb5c1, tip of main) into fix/8663-loader-denylist-followup and resolved both sides by understanding, not by taking one side:

  • The single conflict was in packages/cli/src/config/shared-env-keys.test.ts import block: main added ENV_ACP_REPEATED_TOOL_FAILURE_GUARD (from feat(acp): Protect against repeated tool execution failures #8469) while this PR added acquireInheritedLoaderEnvScrub and clearLoaderKeyRejectionReporterIfCurrent. All three imports are used by tests from both sides, so the resolution keeps all of them in the file's case-insensitive alphabetical order.
  • Auto-merged files were verified pairwise against both parents:
    • shared-env-keys.ts — main's QWEN_TLS_INSECURE / NODE_TLS_REJECT_UNAUTHORIZED / rollout-marker exclusions coexist with this PR's TLS-trust-anchor, git command-exec, rc-file, and interpreter-selection tiers; no duplicate or dropped entries.
    • run-qwen-serve.ts — main's session-restore-timeout, caller-supplied session ID, local-control, and skill-batch-toggle additions sit alongside this PR's reference-counted loader scrub and reporter lifecycle changes; neither side touches process.env in the new code.
    • environment.test.ts, fast-path.test.ts, and both docs files — both sides' additions present, no conflict markers anywhere.
  • Process-env guard inventory: main added no new process.env accesses in any scanned file (packages/cli/src/serve/**, packages/acp-bridge/src/**), so this PR's updated allowances (whole: 5, no computed:key) remain exact — confirmed by the guard test itself passing.
  • The post-merge PR diff is byte-identical in scope to the pre-merge one: same 10 files, 712 insertions / 27 deletions. The merge is a pure union; no behavior was re-edited.

Merge commit: b77fc000a1.

Verification

  • npm run build — passed
  • npm run typecheck — passed
  • npm run lint — passed
  • vitest run src/config/shared-env-keys.test.ts src/config/environment.test.ts src/serve/process-env-guard.test.ts (packages/cli, all touched by this PR) — 3 files, 63 passed
  • vitest run src/serve/fast-path.test.ts src/commands/channel/daemon-worker.test.ts (packages/cli, both touched by this PR) — 2 files, 163 passed
  • vitest run src/serve/run-qwen-serve.test.ts (packages/cli, covers the ref-counted scrub and reporter lifecycle changes) — 241 passed
  • npm run generate:settings-schema — ran clean with no output diff (schema already up to date; this PR does not touch a settings source, so no artifact needed)
  • Integration tests — not run: the touched behavior (env denylist tiers, loader scrub, ref-counted restore) is fully exercised by the unit tests above, not only through the bundled CLI or integration harness.
中文说明

Autofix address-review 轮次 — PR #8763

反馈分类

在经历 5 个产生改动的轮次后,当前处于仅处理 Critical 的模式。本轮可执行区域没有任何反馈:无 review、无行内评论、无 issue 级评论、无失败检查、无持续失败的检查。Deferred non-Critical feedback(延后的非 Critical 反馈)部分是审计记录,按本轮规则不做处理。没有解决或回复任何线程,因此省略 resolved-comments.txt 和 comment-replies.json。

基础分支冲突解决(由 --conflict true 请求)

将 origin/main(0a3d7bb5c1,main 的最新提交)合并进 fix/8663-loader-denylist-followup,并在理解双方内容的基础上解决冲突,而不是盲目取某一边:

  • 唯一的冲突位于 packages/cli/src/config/shared-env-keys.test.ts 的 import 块:main 添加了 ENV_ACP_REPEATED_TOOL_FAILURE_GUARD(来自 feat(acp): Protect against repeated tool execution failures #8469),而本 PR 添加了 acquireInheritedLoaderEnvScrub 和 clearLoaderKeyRejectionReporterIfCurrent。三个 import 都被双方的测试使用,因此解决方案是全部保留,并按该文件的不区分大小写字母顺序排列。
  • 自动合并的文件已逐对对照两个父提交验证:
    • shared-env-keys.ts — main 的 QWEN_TLS_INSECURE / NODE_TLS_REJECT_UNAUTHORIZED / 灰度标记排除项与本 PR 的 TLS 信任锚、git 命令执行、rc 文件、解释器选择等层级共存;没有重复或丢失的条目。
    • run-qwen-serve.ts — main 的会话恢复超时、调用方提供会话 ID、local-control、技能批量开关等新增内容,与本 PR 的引用计数 loader 清理及 reporter 生命周期改动并存;双方的新增代码均未直接访问 process.env。
    • environment.test.ts、fast-path.test.ts 以及两个文档文件 — 双方的新增内容均在,任何位置都没有残留冲突标记。
  • process-env guard 清单: main 没有在任何被扫描文件(packages/cli/src/serve/**、packages/acp-bridge/src/**)中新增 process.env 访问,因此本 PR 更新后的许可配置(whole: 5、移除 computed:key)依然精确 — 由 guard 测试本身通过得到确认。
  • 合并后的 PR diff 与合并前完全一致:同样是 10 个文件,712 行新增 / 27 行删除。本次合并是纯粹的并集,没有重新编辑任何行为。

合并提交:b77fc000a1。

验证

  • npm run build — 通过
  • npm run typecheck — 通过
  • npm run lint — 通过
  • vitest run src/config/shared-env-keys.test.ts src/config/environment.test.ts src/serve/process-env-guard.test.ts(packages/cli,均为本 PR 改动文件)— 3 个文件,63 个测试通过
  • vitest run src/serve/fast-path.test.ts src/commands/channel/daemon-worker.test.ts(packages/cli,均为本 PR 改动文件)— 2 个文件,163 个测试通过
  • vitest run src/serve/run-qwen-serve.test.ts(packages/cli,覆盖引用计数清理与 reporter 生命周期改动)— 241 个测试通过
  • npm run generate:settings-schema — 运行后无任何输出差异(schema 已是最新;本 PR 未改动 settings 源,因此无需重新生成产物)
  • 集成测试 — 未运行:本次改动的行为(env 拒绝名单层级、loader 清理、引用计数恢复)已完全由上述单元测试覆盖,并非只能通过打包后的 CLI 或集成测试框架验证。

Deferred non-Critical feedback

Critical-only mode is active after 5 change-producing rounds. The workflow excluded the non-Critical feedback below from this round's actionable sections; the items remain open for human follow-up. Maintainer feedback is deferred only after its author has used 2 regular feedback batches in this window's Critical-only tail; authors at that budget, if any, are named below. (@qwen-code /retry starts a fresh counting window.)

中文说明

完成 5 个产生改动的轮次后进入仅处理 Critical 的模式。本轮可执行区域已排除下方非 Critical 反馈;这些条目保持开放,留待人工跟进。维护者反馈仅在其本人于本窗口 Critical-only 阶段已使用 2 批常规反馈预算后才会延后;达到预算的作者(如有)在下方点名。(评论 @qwen-code /retry 可开启新的计数窗口。)

Base-conflict check · 基分支冲突检查: conflicted with main — resolved in this push. · 与 main 有冲突——已在本次推送中解决。

Re-review when you have a moment. After round 100 this bot stops and leaves the PR for a human. · 有空请复审;第 100 轮后本 bot 停止并将 PR 交给人工。


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

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 Addressed the latest review feedback (round 8/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 8/100 轮)。改动内容与我反驳保留之处如下:

Review round summary — PR #8763

All six findings (4 Critical, 2 Suggestion) were verified against the code and addressed in one commit: eca8ad2f56.

Findings and dispositions

  • [Critical] R1-2 — nested scrub acquisition deletes a later host assignment (rc:3744689988) — Fixed. Verified the race: daemon A acquires, the embedding host assigns NODE_OPTIONS, daemon B's acquire scrubbed it without snapshotting it (snapshots were taken only at depth 0), so the final release left the value absent or restored a stale one. acquireInheritedLoaderEnvScrub now snapshots the loader-key values present at every acquire boundary (newest observation wins), and the final release restores them. Added the exact A → assign → B → release regression test plus a stale-snapshot variant (packages/cli/src/config/shared-env-keys.test.ts).
  • [Critical] R1-3 — PIP_CONFIG_FILE accepted (rc:3744689997) — Fixed. Added to PROJECT_ENV_HARDCODED_EXCLUSIONS. All application/reload boundaries (initial .env load, mid-session reload, settings.env load + reload, buildRuntimeEnvironment, serve fast path) route through the shared isHardcodedProjectEnvExclusion predicate, so the single list addition covers every boundary; tests cover .env load + reload, settings.env load + reload, and the runtime-env build.
  • [Critical] R1-4 — SSH_ASKPASS accepted (rc:3744690010) — Fixed. Added to the project-only exclusion tier with application and reload tests. Evaluated SSH_ASKPASS_REQUIRE: it only selects when the askpass program is consulted and executes nothing itself; with SSH_ASKPASS project-blocked it has no program to run, so it stays settable (pinned by a negative test and a code comment recording the evaluation).
  • [Critical] R1-6 — LESSOPEN accepted (rc:3744690014) — Fixed. Added LESSOPEN and, same mechanism pair, LESSCLOSE (less invokes it on exit whenever the preprocessor ran, so with an operator-set LESSOPEN a project-set LESSCLOSE alone would still execute). Covered at the .env and settings.env boundaries with load + reload tests.
  • [Suggestion] R1-7 — prefix matcher rejects nonnumeric GIT_CONFIG_KEY_/GIT_CONFIG_VALUE_ suffixes (rc:3744690024) — Fixed. Git only reads decimal-numbered pairs (GIT_CONFIG_KEY_%d up to GIT_CONFIG_COUNT), so the denylist now matches an anchored numeric suffix (/^git_config_key_\d+$/u); project-defined vars like GIT_CONFIG_KEY_CACHE stay settable. Added negative tests for empty, nonnumeric, and trailing-garbage suffixes. The core git-branches.ts scrub keeps its broad prefix (over-scrubbing there is harmless; a denylist rejection freezes the key, so only this gate needs precision).
  • [Suggestion] R1-8 — vacuous ordinary-key reload assertion (rc:3744690032) — Fixed. The second fixture now rotates RUNTIME_DOTENV from allowed to rotated and asserts the new value after reload, so a mutant that freezes every key can no longer ship green.

Docs: the settings.md denylist enumeration now lists the new reject-only keys.

No conflict handling was needed (--conflict false).

Verification

  • npm run build — passed (exit 0)
  • npm run typecheck — passed (exit 0)
  • npm run lint — passed (exit 0)
  • npx vitest run src/config/shared-env-keys.test.ts src/config/environment.test.ts (packages/cli, touched) — 66 passed
  • npx vitest run src/serve/fast-path.test.ts src/serve/process-env-guard.test.ts src/commands/channel/daemon-worker.test.ts (packages/cli, touched) — 166 passed
  • Post-commit re-run of the two config suites against the committed tree — 66 passed
  • npx prettier --check on the changed files — passed
中文说明

审查轮次总结 — PR #8763

全部 6 条发现(4 条 Critical、2 条 Suggestion)均已对照代码核实,并在一次提交中处理完毕:eca8ad2f56。

发现与处理

  • [Critical] R1-2 — 嵌套 scrub acquire 会删除后续 host 赋值(rc:3744689988) — 已修复。已核实该竞态:daemon A acquire 后,嵌入宿主给 NODE_OPTIONS 赋值,daemon B 的 acquire 在未将其记入快照的情况下把它剥离(快照只在深度为 0 时拍摄),因此最终 release 后该值要么缺失、要么被恢复成更旧的快照。acquireInheritedLoaderEnvScrub 现在在每一次 acquire 边界都对当前存在的 loader 键取值做快照(以最新观察到的值为准),最终 release 时恢复。已补充精确的 A → 赋值 → B → release 回归测试,以及陈旧快照变体测试(packages/cli/src/config/shared-env-keys.test.ts)。
  • [Critical] R1-3 — PIP_CONFIG_FILE 被接受(rc:3744689997) — 已修复。已加入 PROJECT_ENV_HARDCODED_EXCLUSIONS。所有应用/重载边界(初始 .env 加载、会话中重载、settings.env 加载 + 重载、buildRuntimeEnvironment、serve 快速路径)都经由共享的 isHardcodedProjectEnvExclusion 谓词,因此单处列表新增即可覆盖所有边界;测试覆盖 .env 加载 + 重载、settings.env 加载 + 重载以及运行时环境构建。
  • [Critical] R1-4 — SSH_ASKPASS 被接受(rc:3744690010) — 已修复。已加入仅项目级排除层,并补齐应用与重载测试。对 SSH_ASKPASS_REQUIRE 的评估结论:它只决定何时咨询 askpass 程序,本身不执行任何东西;在 SSH_ASKPASS 已被项目级屏蔽的前提下它没有可执行的程序,因此保持可设置(用负例测试固定,并在代码注释中记录该评估)。
  • [Critical] R1-6 — LESSOPEN 被接受(rc:3744690014) — 已修复。已加入 LESSOPEN,以及同一机制对的 LESSCLOSE(只要预处理器运行过,less 退出时就会调用它;因此在宿主已设置 LESSOPEN 时,项目单独设置 LESSCLOSE 也会被执行)。已在 .env 与 settings.env 边界用加载 + 重载测试覆盖。
  • [Suggestion] R1-7 — 前缀匹配会拒绝 Git 并不消费的非数字 GIT_CONFIG_KEY_/GIT_CONFIG_VALUE_ 后缀(rc:3744690024) — 已修复。Git 只读取十进制编号对(GIT_CONFIG_KEY_%d,上限为 GIT_CONFIG_COUNT),因此 denylist 改为锚定的数字后缀匹配(/^git_config_key_\d+$/u);GIT_CONFIG_KEY_CACHE 这类项目自定义变量保持可设置。已为空后缀、非数字后缀、尾部带杂字符的后缀补充负例测试。core 的 git-branches.ts 剥离逻辑保留宽前缀(在那里过度剥离无害;而 denylist 的拒绝会冻结该键,所以只有这个门需要精确匹配)。
  • [Suggestion] R1-8 — 普通键重载断言空洞(rc:3744690032) — 已修复。第二个 fixture 现在把 RUNTIME_DOTENV 从 allowed 轮换为 rotated,并在重载后断言新值;这样"重载冻结所有键"的变异不再能绿灯通过。

文档:settings.md 中的 denylist 清单已列出新增的仅拒绝键。

无需处理冲突(--conflict false)。

验证

  • npm run build — 通过(exit 0)
  • npm run typecheck — 通过(exit 0)
  • npm run lint — 通过(exit 0)
  • npx vitest run src/config/shared-env-keys.test.ts src/config/environment.test.ts(packages/cli,涉及包)— 66 通过
  • npx vitest run src/serve/fast-path.test.ts src/serve/process-env-guard.test.ts src/commands/channel/daemon-worker.test.ts(packages/cli,涉及包)— 166 通过
  • 提交后对已提交树重跑两个 config 测试套件 — 66 通过
  • npx prettier --check 检查改动文件 — 通过

Deferred non-Critical feedback

Critical-only mode is active after 5 change-producing rounds. The workflow excluded the non-Critical feedback below from this round's actionable sections; the items remain open for human follow-up. Maintainer feedback is deferred only after its author has used 2 regular feedback batches in this window's Critical-only tail; authors at that budget, if any, are named below. (@qwen-code /retry starts a fresh counting window.)

中文说明

完成 5 个产生改动的轮次后进入仅处理 Critical 的模式。本轮可执行区域已排除下方非 Critical 反馈;这些条目保持开放,留待人工跟进。维护者反馈仅在其本人于本窗口 Critical-only 阶段已使用 2 批常规反馈预算后才会延后;达到预算的作者(如有)在下方点名。(评论 @qwen-code /retry 可开启新的计数窗口。)

Base-conflict check · 基分支冲突检查: no conflict with main. · 与 main 无冲突。

Re-review when you have a moment. After round 100 this bot stops and leaves the PR for a human. · 有空请复审;第 100 轮后本 bot 停止并将 PR 交给人工。


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

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🔀 Base updated: red check(s) [Test (ubuntu-latest, Node 22.x)] pass on current main — merged current main via update-branch; CI will re-run.

中文说明

🔀 已更新 base:红色检查 [Test (ubuntu-latest, Node 22.x)] 在当前 main 上通过 —— 已通过 update-branch 合入当前 main,CI 将重新运行。

@wenshao

wenshao commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /triage

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 Reviewed the latest feedback — no changes needed. Why, point by point: · 已审阅最新反馈——无需改动。逐点说明原因如下:

Autofix round summary — PR #8763 (no action)

Feedback triage

Critical-only mode is active (after 5 change-producing rounds). Everything listed under Deferred non-Critical feedback — the five inline suggestion findings (settings.md denylist wording ×2, the "release is idempotent" test note, the GIT_SSL_NO_VERIFY note, the co-resident daemon acquire note) and one PR comment — was left untouched this round, as required: no code changes, no thread resolutions, no replies for them.

No failed checks and no still-red checks were reported for this round.

The single actionable item and its disposition

The [COMMENTED] review surfaces one unresolved item: a **[Critical]** pointer to issue-level comment 5228685910 (@qwen-code-dev-bot autofix status).

Disposition: no code action required (declined with evidence).

  1. That comment is the autofix agent's own operational status report about a failed address-review run on a stale base ("Qwen failed during address-review: status 125"). It names no code defect, and the automated reviewer itself recorded: "names no code defect to trace against this diff — cannot tell."
  2. The failure's precondition no longer holds: the branch already contains the current base — origin/main (55e20db) is an ancestor of HEAD (3b70728, "Merge branch 'main' into fix/8663-loader-denylist-followup") — and this round was invoked with no base conflict.
  3. Nothing in this round's feedback identifies a defect in the diff, and no check is failing.

Verification performed this round

The review recorded a coverage gap from its own run: only filtered runs of the new fast-path tests had executed, and the daemon-worker.test.ts change had been verified by code inspection only ("full unfiltered runs of fast-path.test.ts and daemon-worker.test.ts" were left unexplored when the tool budget was reached). That exact gap was closed locally this round.

The review also noted "Integration Tests (CLI, No Sandbox) was skipped in CI". That is a workflow skip, not a failing check, and no named defect is attached to it — no code action to take.

Verification

Commands actually run this round and their results:

  • git merge-base --is-ancestor origin/main HEAD — confirmed the branch already contains the current base (stale-base precondition gone).
  • npm run build — passed. This also fixed a checkout build-state gap found during testing: packages/channels/base had no dist/, so @qwen-code/channel-base (declared entry dist/index.js) failed to resolve and initially blocked two test files. Environmental, not caused by this PR.
  • Full unfiltered Vitest run of every test file touched by this PR (packages/cli): src/commands/channel/daemon-worker.test.ts, src/config/environment.test.ts, src/config/shared-env-keys.test.ts, src/serve/fast-path.test.ts, src/serve/process-env-guard.test.ts — 5/5 files passed, 232/232 tests passed.

Outcome

No code changes this round; no commit created. Working tree clean; HEAD unchanged at 3b70728.

中文说明

Autofix 本轮总结 — PR #8763(无操作)

反馈分类

当前处于仅处理 Critical 的模式(在 5 个产生改动的轮次之后)。Deferred non-Critical feedback(延后的非 Critical 反馈)中列出的全部内容——5 条行内建议类发现(settings.md 拒绝清单措辞 ×2、"release is idempotent" 测试说明、GIT_SSL_NO_VERIFY 说明、同宿主 daemon acquire 说明)以及 1 条 PR 评论——本轮均按要求保持原样:不改代码、不解决线程、不回复。

本轮没有报告失败的检查,也没有报告持续红色的检查。

唯一的可处理条目及其处置

该 [COMMENTED] 审查提出了 1 条未决条目:一个指向 issue 级评论 5228685910(@qwen-code-dev-bot autofix 状态)的 **[Critical]** 指针。

处置:无需代码操作(附证据予以驳回)。

  1. 该评论是 autofix 代理自身的一次运行状态报告,记录的是在陈旧 base 上一次失败的 address-review 运行("Qwen failed during address-review: status 125")。它没有指出任何代码缺陷,自动审查器自己也记录道:"names no code defect to trace against this diff — cannot tell"(没有指出任何可以对照本 diff 追踪的代码缺陷——无法判断)。
  2. 该失败的前置条件已不复存在:分支已包含当前 base —— origin/main(55e20db)是 HEAD(3b70728,"Merge branch 'main' into fix/8663-loader-denylist-followup")的祖先——且本轮调用时不存在 base 冲突。
  3. 本轮反馈中没有任何内容指出 diff 存在缺陷,也没有任何检查失败。

本轮执行的验证

审查记录了其自身运行时留下的覆盖缺口:当时只对新增的 fast-path 测试做了过滤运行,且 daemon-worker.test.ts 的改动仅通过代码审阅验证(在达到工具调用预算时,"fast-path.test.ts 和 daemon-worker.test.ts 的完整无过滤运行"未能执行)。本轮已在本地补齐了这一确切缺口。

审查还提到 "Integration Tests (CLI, No Sandbox) was skipped in CI"(集成测试在 CI 中被跳过)。这是工作流层面的跳过,并非检查失败,且没有与之关联的已指名缺陷——无需采取代码操作。

验证

本轮实际执行的命令及结果:

  • git merge-base --is-ancestor origin/main HEAD —— 确认分支已包含当前 base(陈旧 base 的前置条件已消除)。
  • npm run build —— 通过。这同时修复了测试过程中发现的检出构建状态缺口:packages/channels/base 缺少 dist/,导致 @qwen-code/channel-base(声明入口为 dist/index.js)无法解析,最初阻塞了 2 个测试文件。这是环境问题,并非本 PR 所致。
  • 对本 PR 触及的每个测试文件执行完整无过滤的 Vitest 运行(packages/cli):src/commands/channel/daemon-worker.test.ts、src/config/environment.test.ts、src/config/shared-env-keys.test.ts、src/serve/fast-path.test.ts、src/serve/process-env-guard.test.ts —— 5/5 个文件通过,232/232 个测试通过。

结果

本轮无代码改动;未创建提交。工作树干净;HEAD 保持在 3b70728 未变。

Deferred non-Critical feedback

Critical-only mode is active after 5 change-producing rounds. The workflow excluded the non-Critical feedback below from this round's actionable sections; the items remain open for human follow-up. Maintainer feedback is deferred only after its author has used 2 regular feedback batches in this window's Critical-only tail; authors at that budget, if any, are named below. (@qwen-code /retry starts a fresh counting window.)

中文说明

完成 5 个产生改动的轮次后进入仅处理 Critical 的模式。本轮可执行区域已排除下方非 Critical 反馈;这些条目保持开放,留待人工跟进。维护者反馈仅在其本人于本窗口 Critical-only 阶段已使用 2 批常规反馈预算后才会延后;达到预算的作者(如有)在下方点名。(评论 @qwen-code /retry 可开启新的计数窗口。)

Base-conflict check · 基分支冲突检查: no conflict with main. · 与 main 无冲突。


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

@wenshao

wenshao commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /triage

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 Reviewed the latest feedback — no changes needed. Why, point by point: · 已审阅最新反馈——无需改动。逐点说明原因如下:

No action required on PR #8763

This review round has no actionable items:

  • Reviews: none newer than the last evaluation (2026-08-10T00:01:58Z).
  • Inline comments: none.
  • Issue-level comments: none.
  • Failed checks: none.
  • Still-red checks: none.
  • Base conflict: none (--conflict false); no merge was performed.

Critical-only mode is active after 5 change-producing rounds. The only item in
the "Deferred non-Critical feedback" section is an automated PR comment by
@qwen-code-ci-bot. Per the round rules, that section is an audit record, not
work: no code was modified, no thread was resolved, and no reply was written
for it. The item remains open for human follow-up.

No code was changed and no commit was made in this round. The branch stays at
3b7072826d.

中文说明

PR #8763 无需处理

本轮评审没有任何可处理的项目:

  • 评审(Reviews): 自上次评估(2026-08-10T00:01:58Z)以来没有新的评审。
  • 行内评论(Inline comments): 无。
  • Issue 级评论(Issue-level comments): 无。
  • 失败的检查(Failed checks): 无。
  • 持续失败的检查(Still-red checks): 无。
  • 与 base 分支的冲突: 无(--conflict false),未执行任何合并。

在 5 个产生改动的轮次之后,已进入仅处理 Critical 的模式。"Deferred non-Critical feedback"(延后的非 Critical 反馈)部分中唯一的条目是 @qwen-code-ci-bot 的一条自动化 PR 评论。按照本轮规则,该部分属于审计记录而非待办工作:未修改任何代码、未解决任何讨论串,也未就该条目撰写任何回复。该条目保持开放,留待人工跟进。

本轮未改动任何代码,也未创建任何提交。分支保持在 3b7072826d。

Deferred non-Critical feedback

Critical-only mode is active after 5 change-producing rounds. The workflow excluded the non-Critical feedback below from this round's actionable sections; the items remain open for human follow-up. Maintainer feedback is deferred only after its author has used 2 regular feedback batches in this window's Critical-only tail; authors at that budget, if any, are named below. (@qwen-code /retry starts a fresh counting window.)

中文说明

完成 5 个产生改动的轮次后进入仅处理 Critical 的模式。本轮可执行区域已排除下方非 Critical 反馈;这些条目保持开放,留待人工跟进。维护者反馈仅在其本人于本窗口 Critical-only 阶段已使用 2 批常规反馈预算后才会延后;达到预算的作者(如有)在下方点名。(评论 @qwen-code /retry 可开启新的计数窗口。)

Base-conflict check · 基分支冲突检查: no conflict with main. · 与 main 无冲突。


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

@wenshao
wenshao enabled auto-merge August 10, 2026 03:44

@doudouOUC doudouOUC 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.

Unresolved, please confirm: [Critical] issue-level comment 5228685910: autofix status — reports the autofix agent's own failed run on a stale base; names no code defect to trace against this diff — cannot tell. Re-checked against the code at 3b70728: the comment is an autofix infrastructure status report, not a code defect.

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

[Critical] issue-level comment 5228685910 (@qwen-code-dev-bot autofix status) — reports the autofix agent's own failed run on a stale base; names no code defect to trace against this diff — cannot tell

中文说明

未决,请确认:[Critical] issue-level comment 5228685910: autofix status — reports the autofix agent's own failed run on a stale base; names no code defect to trace against this diff — cannot tell. Re-checked against the code at 3b70728: the comment is an autofix infrastructure status report, not a code defect.

未审查:build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally。

[Critical] issue-level comment 5228685910 (@qwen-code-dev-bot autofix status) — reports the autofix agent's own failed run on a stale base; names no code defect to trace against this diff — cannot tell

— deepseek-v4-flash via Qwen Code /review (v0.21.8)

Comment on lines +371 to +377
for (const key of Object.keys(env)) {
if (!isLoaderEnvKey(key)) continue;
const value = env[key];
if (value !== undefined) sharedProcessEnvScrubOriginals.set(key, value);
}
sharedProcessEnvScrubDepth++;
const removedKeys = scrubAndReportInheritedLoaderEnv(

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.

[Suggestion] acquireInheritedLoaderEnvScrub double-iterates process.env — the snapshot loop (lines 371-375) and the subsequent scrubAndReportInheritedLoaderEnv call both iterate Object.keys(env) and both call isLoaderEnvKey on every key. — Failure scenario: On every daemon startup (including overlapping embedded daemon acquires), process.env is iterated twice instead of once. For a typical ~150-entry env, this is ~300 isLoaderEnvKey calls per acquire, each doing a canonicalLoaderKey transform (2 regex substitutions + .replace()). Suggested fix: Merge the snapshot and the scrub into a single Object.keys(env) pass that both records the value and deletes the key.

中文说明

acquireInheritedLoaderEnvScrub 对 process.env 做了两次迭代——快照循环(第 371-375 行)和后续的 scrubAndReportInheritedLoaderEnv 调用都遍历了 Object.keys(env) 并对每个键调用了 isLoaderEnvKey。失败场景:每次 daemon 启动时(包括重迭内嵌 daemon 的 acquire),process.env 被迭代两次而非一次。建议:将快照和剥离合并为一次 Object.keys(env) 遍历,同时记录值并删除键。

— deepseek-v4-flash via Qwen Code /review (v0.21.8)

Comment on lines +362 to +364
if (sharedProcessEnvScrubDepth === 0) {
sharedProcessEnvScrubOriginals.clear();
}

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.

[Suggestion] Mutant-survived: deleting the sharedProcessEnvScrubOriginals.clear() at acquire time (line 364) leaves every affected test green. — Failure scenario: A future change that removes or skips this clear() call would not be caught by any test in this diff, allowing stale originals from a prior scrub cycle to leak into the next scrub's snapshot. Suggested fix: Add a test that verifies sharedProcessEnvScrubOriginals is empty when the scrub depth drops to zero after a full acquire/release cycle.

中文说明

变体存活:删除 acquire 时的 sharedProcessEnvScrubOriginals.clear()(第 364 行)所有测试仍然通过。失败场景:未来删除了该 clear() 调用不会被任何测试捕获。建议:增加测试验证 sharedProcessEnvScrubOriginals 在完整 acquire/release 周期后为空。

— deepseek-v4-flash via Qwen Code /review (v0.21.8)

Comment on lines +389 to +390
if (sharedProcessEnvScrubDepth > 0) return;
for (const [key, value] of sharedProcessEnvScrubOriginals) {

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.

[Suggestion] Mutant-survived: deleting the sharedProcessEnvScrubOriginals.clear() at release time (line 397) leaves every affected test green. — Failure scenario: Same as the acquire-time clear — a future removal would not be caught by any test. Suggested fix: Confirm or add coverage for this reset path.

中文说明

变体存活:删除 release 时的 sharedProcessEnvScrubOriginals.clear()(第 397 行)所有测试仍然通过。建议:确认或补充此重置路径的测试覆盖。

— deepseek-v4-flash via Qwen Code /review (v0.21.8)

Comment on lines +400 to +403
export function resetInheritedLoaderEnvScrubForTesting(): void {
sharedProcessEnvScrubDepth = 0;
sharedProcessEnvScrubOriginals.clear();
}

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.

[Suggestion] Mutant-survived: deleting the sharedProcessEnvScrubOriginals.clear() in the test-only reset helper (line 403) leaves every affected test green. — Failure scenario: A future removal of this clear() call would compromise test isolation between dependent test suites. Suggested fix: Confirm or add coverage for this reset path.

中文说明

变体存活:删除仅测试重置辅助函数中的 sharedProcessEnvScrubOriginals.clear()(第 403 行)所有测试仍然通过。建议:确认或补充此重置路径的测试覆盖。

— deepseek-v4-flash via Qwen Code /review (v0.21.8)

Comment on lines +373 to +375
const value = env[key];
if (value !== undefined) sharedProcessEnvScrubOriginals.set(key, value);
}

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.

[Suggestion] Mutant-survived: the if (value !== undefined) guard (line 374) is never exercised — no test pins when the guard must NOT fire. — Failure scenario: A change that removes the value !== undefined guard would not be caught by any test, allowing undefined values to be stored in sharedProcessEnvScrubOriginals. Suggested fix: Add a test case that exercises the value === undefined branch and verifies the key is not stored.

中文说明

变体存活:if (value !== undefined) 守卫(第 374 行)从未被触发——没有测试验证守卫在什么情况下必须不触发。建议:增加测试用例,验证当 value === undefined 时该键不会被存储。

— deepseek-v4-flash via Qwen Code /review (v0.21.8)

acquireInheritedLoaderEnvScrub iterated process.env twice (a snapshot
pass, then the scrub); record the originals inside the scrub's single
pass instead. Drop the acquire-time snapshot clear, which the
release-time clear made unreachable defense, and add tests that kill
the previously surviving mutants on the release-time clear, the
test-only reset, and the undefined-value guard.
@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 Addressed the latest review feedback (round 9/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 9/100 轮)。改动内容与我反驳保留之处如下:

Autofix review round summary — PR #8763

Feedback points and dispositions

Review-level Critical: issue-level comment 5228685910 (autofix status) — Declined (no code defect)

Confirmed, as the reviewer's own re-check concluded: comment 5228685910 is the
autofix bot's infrastructure status report about its own failed run on a stale
base. It names no code defect traceable against this diff, and re-reading the
full diff at HEAD surfaces nothing it could refer to. No code action. The
review's side note that the "Integration Tests (CLI, No Sandbox)" suite was
skipped in CI is a statement of the reviewer's coverage, not a request: this
round's change is unit-level and fully exercised by the focused Vitest runs
below.

[rc:3746607294] Double iteration of process.env in acquire — Resolved

Merged the snapshot and the scrub into one pass: scrubInheritedLoaderEnv now
accepts an optional snapshotInto map (record the value, then delete the key,
in the same loop), scrubAndReportInheritedLoaderEnv passes it through, and
acquireInheritedLoaderEnvScrub hands it the shared-originals map and drops
its own iteration. One Object.keys(env) pass and one isLoaderEnvKey call
per key per acquire, and the stderr breadcrumb wording stays in its single
shared home. The one-shot call sites (daemon base env, ACP child, channel
worker) keep the old one-argument form.

[rc:3746607299] Mutant survived: acquire-time clear() — Resolved (by removal, not by a new test)

The acquire-time clear and the release-time clear are mutually redundant — at
depth 0 the snapshot map is always empty (the last release clears it; the
test-only reset clears it), so the acquire-time clear defended a state the
refcount cannot reach, and its presence is exactly what masked the other two
clears' mutants. Per Simplicity First the redundant clear was removed
rather than pinned by a test; with it gone, the surviving clear's behavior
becomes observable and is pinned by the new cycle-isolation test below.

[rc:3746607303] Mutant survived: release-time clear() — Resolved

New test does not restore a prior cycle snapshot for a key the host removed:
a full acquire/release cycle, then the host removes the key, and a second
cycle's final release must not resurrect it from the prior snapshot. Mutant
verified killed: deleting the release-time clear() makes this test fail.

[rc:3746607305] Mutant survived: test-only reset clear() — Resolved

New test reset drops a leaked snapshot before the next acquire: an acquire
whose handle is never released (leaked), a reset, then a fresh cycle must not
re-inject the leaked value on its final release. Mutant verified killed:
deleting the reset's clear() makes this test fail.

[rc:3746607308] Undefined-value guard never exercised — Resolved

New test does not snapshot loader keys whose value is undefined: an env with
NODE_OPTIONS: undefined is scrubbed (key removed) but the final release must
not write undefined back into the env. Mutant verified killed: dropping the
value !== undefined guard makes this test fail.

Changes

  • packages/cli/src/config/shared-env-keys.ts: snapshot recorded inside the
    scrub's single pass (snapshotInto parameter); acquire no longer iterates
    separately; redundant acquire-time snapshot clear removed; stale doc
    sentence updated.
  • packages/cli/src/config/shared-env-keys.test.ts: three tests added, each
    proven to kill its mutant (mutant applied → test fails → restored → 41
    pass).

Commit: 146c448caf fix(cli): merge the loader-env scrub snapshot into one pass (#8763)

Conflict notes

--conflict false: no merge of origin/main performed; branch stays on its
existing merge base.

Verification

  • cd packages/cli && npx vitest run src/config/shared-env-keys.test.ts (baseline) — 38 passed
  • Mutant runs: release-clear mutant — 1 failed | 40 passed (target test fails); reset-clear mutant — 1 failed | 40 passed (target test fails); undefined-guard mutant — 1 failed | 40 passed (target test fails); restored source — 41 passed
  • cd packages/cli && npx vitest run src/config/shared-env-keys.test.ts src/config/environment.test.ts src/serve/fast-path.test.ts src/serve/process-env-guard.test.ts src/commands/channel/daemon-worker.test.ts — 5 files, 235 passed
  • npx prettier --check on both edited files — passed
  • npm run build — passed
  • npm run typecheck — passed
  • npm run lint — passed
  • Post-commit re-run src/config/shared-env-keys.test.ts — 41 passed
  • Integration tests (after npm run bundle) — not run: the touched behavior (refcounted shared-env scrub internals) is exercised directly by the unit tests above, not only through the bundled CLI or integration harness
  • npm run generate:settings-schema — not needed: no settings source changed
中文说明

Autofix 审查轮次总结 — PR #8763

反馈点与处理结论

Review 级 Critical:issue-level comment 5228685910(autofix 状态)— 拒绝(无代码缺陷)

确认无误,与审查者自己的复核结论一致:评论 5228685910 是 autofix 机器人关于其在陈旧 base 上运行失败的基础设施状态报告。它没有指出任何可追溯到本 diff 的代码缺陷,重新通读 HEAD 的完整 diff 也未发现其可能指向的问题。无需代码改动。Review 中附带提到 "Integration Tests (CLI, No Sandbox)" 在 CI 被跳过,这只是对审查者自身覆盖面的说明,不是诉求:本轮改动属于单元级别,已由下方的定向 Vitest 运行完整覆盖。

[rc:3746607294] acquire 中对 process.env 的双重迭代 — 已解决

将快照与剥离合并为一次遍历:scrubInheritedLoaderEnv 现在接受一个可选的 snapshotInto map(在同一个循环中先记录值再删除键),scrubAndReportInheritedLoaderEnv 将其透传,acquireInheritedLoaderEnvScrub 把共享原始值 map 交给它并移除了自己的迭代。每次 acquire 只对 Object.keys(env) 遍历一次、每个键只调用一次 isLoaderEnvKey,且 stderr 提示文案仍保留在唯一的共享位置。一次性调用的站点(daemon base env、ACP 子进程、channel worker)保持原有的单参数形式。

[rc:3746607299] 变体存活:acquire 时的 clear() — 已解决(通过删除而非新增测试)

acquire 时的 clear 与 release 时的 clear 互相冗余——深度为 0 时快照 map 必然为空(最后一次 release 会清空它;仅测试用的 reset 也会清空它),所以 acquire 时的 clear 防御的是引用计数根本无法到达的状态,而它的存在恰恰掩盖了另外两处 clear 的变体。按照 Simplicity First 原则,冗余的 clear 被删除而不是用测试钉住;删除之后,保留的 clear 的行为变为可观测,并由下方新增的周期间隔离测试钉住。

[rc:3746607303] 变体存活:release 时的 clear() — 已解决

新增测试 does not restore a prior cycle snapshot for a key the host removed:完整执行一次 acquire/release 周期,然后宿主删除该键,第二个周期的最后一次 release 不得从上一周期的快照中复活该键。变体已验证被杀死:删除 release 时的 clear() 会使该测试失败。

[rc:3746607305] 变体存活:仅测试用 reset 中的 clear() — 已解决

新增测试 reset drops a leaked snapshot before the next acquire:一次 handle 从未 release 的 acquire(泄漏)、一次 reset,之后的新周期在其最后一次 release 时不得重新注入泄漏的值。变体已验证被杀死:删除 reset 中的 clear() 会使该测试失败。

[rc:3746607308] undefined 值守卫从未被触发 — 已解决

新增测试 does not snapshot loader keys whose value is undefined:一个含 NODE_OPTIONS: undefined 的 env 会被剥除(键被删除),但最后一次 release 不得把 undefined 写回 env。变体已验证被杀死:去掉 value !== undefined 守卫会使该测试失败。

改动内容

  • packages/cli/src/config/shared-env-keys.ts:快照改在剥境的单次遍历中记录(snapshotInto 参数);acquire 不再单独迭代;冗余的 acquire 时快照 clear 被删除;过时的文档句已更新。
  • packages/cli/src/config/shared-env-keys.test.ts:新增三个测试,每个都已证明能杀死对应变体(应用变体 → 测试失败 → 还原 → 41 通过)。

提交:146c448caf fix(cli): merge the loader-env scrub snapshot into one pass (#8763)

冲突说明

--conflict false:未合并 origin/main;分支保持在现有 merge base 上。

验证

  • cd packages/cli && npx vitest run src/config/shared-env-keys.test.ts(基线)— 38 通过
  • 变体运行:release-clear 变体 — 1 失败 | 40 通过(目标测试失败);reset-clear 变体 — 1 失败 | 40 通过(目标测试失败);undefined-guard 变体 — 1 失败 | 40 通过(目标测试失败);还原源码后 — 41 通过
  • cd packages/cli && npx vitest run src/config/shared-env-keys.test.ts src/config/environment.test.ts src/serve/fast-path.test.ts src/serve/process-env-guard.test.ts src/commands/channel/daemon-worker.test.ts — 5 个文件,235 通过
  • 对两个改动文件执行 npx prettier --check — 通过
  • npm run build — 通过
  • npm run typecheck — 通过
  • npm run lint — 通过
  • 提交后重新运行 src/config/shared-env-keys.test.ts — 41 通过
  • 集成测试(npm run bundle 之后)— 未运行:本次触及的行为(引用计数的共享 env 剥除内部逻辑)由上述单元测试直接覆盖,并非只能通过捆绑 CLI 或集成测试框架验证
  • npm run generate:settings-schema — 不需要:未改动任何 settings 源

Deferred non-Critical feedback

Critical-only mode is active after 5 change-producing rounds. The workflow excluded the non-Critical feedback below from this round's actionable sections; the items remain open for human follow-up. Maintainer feedback is deferred only after its author has used 2 regular feedback batches in this window's Critical-only tail; authors at that budget, if any, are named below. (@qwen-code /retry starts a fresh counting window.)

中文说明

完成 5 个产生改动的轮次后进入仅处理 Critical 的模式。本轮可执行区域已排除下方非 Critical 反馈;这些条目保持开放,留待人工跟进。维护者反馈仅在其本人于本窗口 Critical-only 阶段已使用 2 批常规反馈预算后才会延后;达到预算的作者(如有)在下方点名。(评论 @qwen-code /retry 可开启新的计数窗口。)

Base-conflict check · 基分支冲突检查: no conflict with main. · 与 main 无冲突。

Re-review when you have a moment. After round 100 this bot stops and leaves the PR for a human. · 有空请复审;第 100 轮后本 bot 停止并将 PR 交给人工。


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

@qwen-code-dev-bot
qwen-code-dev-bot dismissed a stale review via 146c448 August 10, 2026 05:29
@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 Addressed the latest review feedback (round 10/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 10/100 轮)。改动内容与我反驳保留之处如下:

Round summary (PR #8763, review round 4)

All seven actionable findings were verified against the exact code at this
commit and addressed in one commit (28352d54ae). Every finding named an env
key that still reached an exec/config-redirect sink from a project .env
despite the denylist this PR builds; all application gates route through
isHardcodedProjectEnvExclusion, so adding the keys to
PROJECT_ENV_HARDCODED_EXCLUSIONS closes the initial load, reload,
buildRuntimeEnvironment, and serve fast-path boundaries at once. The new
keys join the reject-only tier: operator-set launch-env and home-.env
values are preserved.

Findings and dispositions

Finding Severity Disposition Change
R4-1 GIT_SEQUENCE_EDITOR missing Critical Addressed Added beside GIT_EDITOR; git execs it for git rebase -i todo-list edits. Git-family comment updated to name it.
R4-5 VISUAL/EDITOR missing Critical Addressed Added to the reject-only tier. Verified: git's documented editor fallback chain, and useLaunchEditor.ts returns process.env['VISUAL'] || process.env['EDITOR'] || 'vi' straight into spawnSync.
R4-6 XDG_CONFIG_HOME missing Critical Addressed Added after GIT_CONFIG_SYSTEM per the suggestion. git merges $XDG_CONFIG_HOME/git/config with ~/.gitconfig, so an XDG redirect plants the same core.hooksPath injection the GIT_CONFIG_* blocks exist for, around them.
R4-7 PYTHONSTARTUP missing Critical Addressed Added to the reject-only tier next to PYTHON — the Python analogue of NODE_REPL_EXTERNAL_MODULE; stays reject-only because operators legitimately set it in their own shells.
R4-8 BROWSER missing Critical Addressed Added after npm_config_git per the suggestion. Verified: openBrowserSecurely spawns a set $BROWSER before the CI/DISPLAY gates.
R4-9 QWEN_CDP_MCP_COMMAND / QWEN_SERVE_CDP_TUNNEL_OVER_WS missing Critical Addressed Added beside QWEN_CLI_ENTRY. The daemon spawns the former as the browser-automation MCP adapter and the latter switches the tunnel surface on; internal uses (operator launch env, daemon childEnvOverrides) are untouched by the reject-only tier.
R4-2 scrub test passes vacuously for the four new loader keys Suggestion Addressed OPENSSL_CONF, NODE_REPL_EXTERNAL_MODULE, npm_config_node_gyp, npm_config_init_module added to the 'removes every loader-affecting key and keeps the rest' fixture and its expected removedKeys, so a stale literal-list mutant now fails the test.

No finding was declined or escalated.

Also in this commit

  • CHANGES_REQUESTED review body: the review's request-changes event was its
    own verification-coverage note (integration suite merge-queue-gated by
    design; the reviewer could not run unit tests in its worktree). Response:
    the five named suites were actually run this round (see Verification).
  • Tests: class-membership pins for the eight new keys, case-insensitive
    predicate pins, and a reject-only pin asserting none of them is a
    loader-scrub key (so a user's own VISUAL/EDITOR/BROWSER are never
    stripped from the launch env). New environment.test.ts boundary test
    rejects all eight keys on initial load, reload, settings.env, and the
    runtime-env build.
  • Docs: docs/users/configuration/settings.md denylist paragraph updated
    with the new keys.
  • No base-conflict work (--conflict false; no merge performed).

Verification

  • npm run build — passed
  • npm run typecheck — passed
  • npm run lint — passed
  • npx vitest run src/config/shared-env-keys.test.ts src/config/environment.test.ts src/serve/fast-path.test.ts src/serve/process-env-guard.test.ts src/commands/channel/daemon-worker.test.ts (in packages/cli) — 5 files passed, 239/239 tests passed
  • npx prettier --experimental-cli --write on the four changed files — applied (one file reformatted)
  • npm run generate:settings-schema — not required (no settings source changed)
  • Integration tests — not run: the suite is merge-queue-gated by design, and the changed behavior (env rejection) is exercised directly by the unit suites above at all four application boundaries rather than only through the bundled CLI. The workflow's CI remains the final gate.
中文说明

轮次总结(PR #8763,审查第 4 轮)

全部 7 条可执行发现均已在本提交的代码上逐一核实,并在一次提交(28352d54ae)中处理完毕。每条发现都指出了一个仍能经由项目 .env 触达“执行/配置重定向”汇点的键;由于所有应用门控都经过 isHardcodedProjectEnvExclusion,将这些键加入 PROJECT_ENV_HARDCODED_EXCLUSIONS 即同时封堵初始加载、重载、buildRuntimeEnvironment 与 serve 快速路径四处边界。新键均加入“仅拒绝项目文件”层:操作者在启动环境或家目录 .env 中设置的值不受影响。

发现与处置

发现 严重度 处置 改动
R4-1 缺少 GIT_SEQUENCE_EDITOR Critical 已处理 加在 GIT_EDITOR 旁;git 在 git rebase -i 编辑 todo 列表时会执行它。git 家族注释已同步提及。
R4-5 缺少 VISUAL/EDITOR Critical 已处理 加入仅拒绝层。已核实:git 文档化的编辑器回退链会使用它们,且 useLaunchEditor.ts 直接返回 process.env['VISUAL'] || process.env['EDITOR'] || 'vi' 交给 spawnSync。
R4-6 缺少 XDG_CONFIG_HOME Critical 已处理 按 suggestion 加在 GIT_CONFIG_SYSTEM 之后。git 会将 $XDG_CONFIG_HOME/git/config 与 ~/.gitconfig 合并读取,因此 XDG 重定向能绕过 GIT_CONFIG_* 阻断植入同样的 core.hooksPath 注入。
R4-7 缺少 PYTHONSTARTUP Critical 已处理 加入仅拒绝层、置于 PYTHON 旁——它是 NODE_REPL_EXTERNAL_MODULE 的 Python 同型变体;因操作者常在自己的 shell 中合法设置它,保持仅拒绝语义。
R4-8 缺少 BROWSER Critical 已处理 按 suggestion 加在 npm_config_git 之后。已核实:openBrowserSecurely 在 CI/DISPLAY 门控之前就会启动已设置的 $BROWSER。
R4-9 缺少 QWEN_CDP_MCP_COMMAND / QWEN_SERVE_CDP_TUNNEL_OVER_WS Critical 已处理 加在 QWEN_CLI_ENTRY 旁。daemon 会将前者作为浏览器自动化 MCP 适配器启动、后者开启隧道应用面;内部用途(操作者启动环境、daemon 的 childEnvOverrides)不受仅拒绝层影响。
R4-2 剥离测试对四个新 loader 键空洞通过 Suggestion 已处理 将 OPENSSL_CONF、NODE_REPL_EXTERNAL_MODULE、npm_config_node_gyp、npm_config_init_module 加入 'removes every loader-affecting key and keeps the rest' 的 fixture 与期望 removedKeys,使“陈旧字面量列表”变异体现在会被该测试杀死。

无发现被拒绝或升级待决。

本提交的其他内容

  • CHANGES_REQUESTED 审查正文:该请求改动事件是审查方自身的验证覆盖说明(集成测试在 CI 中按设计受 merge-queue 门控;审查 worktree 无法运行单元测试)。应对:本轮实际运行了审查点名的 5 个测试套件(见验证部分)。
  • 测试:为 8 个新键增加类别成员钉住测试、大小写不敏感谓词钉住测试,以及“仅拒绝、不属于 loader 剥离键”的钉住断言(确保用户自己的 VISUAL/EDITOR/BROWSER 不会被从启动环境剥离)。environment.test.ts 新增边界测试,验证 8 个键在初始加载、重载、settings.env 与运行时环境构建上均被拒绝。
  • 文档:docs/users/configuration/settings.md 的拒绝名单段落已更新新键。
  • 无基线冲突处理(--conflict false,未执行合并)。

验证

  • npm run build — 通过
  • npm run typecheck — 通过
  • npm run lint — 通过
  • npx vitest run src/config/shared-env-keys.test.ts src/config/environment.test.ts src/serve/fast-path.test.ts src/serve/process-env-guard.test.ts src/commands/channel/daemon-worker.test.ts(位于 packages/cli)— 5 个文件通过,239/239 个测试通过
  • 对 4 个改动文件执行 npx prettier --experimental-cli --write — 已应用(1 个文件被重排)
  • npm run generate:settings-schema — 无需执行(未改动 settings 源)
  • 集成测试 — 未运行:该套件按设计受 merge-queue 门控,且本次改动的行为(环境变量拒绝)已由上述单元测试在全部四处应用边界直接覆盖,并非只能经打包后的 CLI 验证。工作流的 CI 仍是最终验证门。

Deferred non-Critical feedback

Critical-only mode is active after 5 change-producing rounds. The workflow excluded the non-Critical feedback below from this round's actionable sections; the items remain open for human follow-up. Maintainer feedback is deferred only after its author has used 2 regular feedback batches in this window's Critical-only tail; authors at that budget, if any, are named below. (@qwen-code /retry starts a fresh counting window.)

中文说明

完成 5 个产生改动的轮次后进入仅处理 Critical 的模式。本轮可执行区域已排除下方非 Critical 反馈;这些条目保持开放,留待人工跟进。维护者反馈仅在其本人于本窗口 Critical-only 阶段已使用 2 批常规反馈预算后才会延后;达到预算的作者(如有)在下方点名。(评论 @qwen-code /retry 可开启新的计数窗口。)

Base-conflict check · 基分支冲突检查: no conflict with main. · 与 main 无冲突。

Re-review when you have a moment. After round 100 this bot stops and leaves the PR for a human. · 有空请复审;第 100 轮后本 bot 停止并将 PR 交给人工。


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

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

📊 Takeover milestone — round 10/100, in the current window. Census: 6 pushed fix(es), 3 no-change review(s), 2 timeout(s), 1 rejected attempt(s), 1 other round(s) (crash / model error / gate error / infra), 2 base update(s).

This many rounds deserves a human look. Options: keep going (fine — nothing changes), split or reduce the PR if rounds keep accumulating, or release takeover (remove the autofix/takeover label or comment @qwen-code /takeover stop). Management continues unchanged unless you act.

中文说明

📊 接管里程碑 —— 第 10/100 轮(当前窗口)。统计:推送修复 6 次、审阅无需改动 3 次、超时 2 次、验证拒绝 1 次、其他轮次(崩溃/模型错误/门错误/infra)1 次、base 更新 2 次。

轮次到这个量值得人工看一眼。可选:继续(无需操作);若轮次持续累积,考虑拆分或缩减 PR;或释放接管(移除 autofix/takeover 标签或评论 @qwen-code /takeover stop)。不操作则托管照常继续。

@wenshao

wenshao commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator Author

@qwen-code /triage

@qwen-code-dev-bot

Copy link
Copy Markdown
Collaborator

🤖 AutoFix updated a stale base — the fix did not pass verification, but this PR was behind main, so it merged current main in via update-branch and will retry on the next scan. A stale base (a dependency or symbol main already changed) can fail the build without being the fix's fault; if it still fails once current, it hands off to a human.

What I found before stopping:
Qwen failed during address-review: status 125.

See the Qwen Autofix agent step logs for model/tool output.

Run log: https://github.com/QwenLM/qwen-code/actions/runs/31381560750


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

@doudouOUC doudouOUC 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 the exact current head (02fcc3b). I revalidated the unresolved Critical threads against the tree rather than relying on GitHub thread state: the previously reported git config/SSH, config-discovery, browser-launch, and CDP command surfaces are now present in the hardcoded project-env gate and covered across the initial load, reload, runtime-env build, and serve fast path. The ref-counted inherited-env scrub also has balanced startup/close cleanup.

The remaining open items are non-blocking Suggestions: reporter diagnostics for overlapping embedded daemons, hardcoded-tier warning/docs accuracy, a few adjacent denylist candidates, and mutation-strength test gaps. This PR has already exceeded the repository review-round budget, so those should stay in the stated follow-up rather than widening this round. Approving with suggestions; CI should still finish green.

@wenshao
wenshao added this pull request to the merge queue Aug 10, 2026
Merged via the queue into main with commit 7c89665 Aug 10, 2026
41 of 43 checks passed
pull Bot pushed a commit to bit-cook/qwen-code that referenced this pull request Aug 10, 2026
…eak (QwenLM#8816)

* feat(ci): A/B deterministic gate rejections against the pre-round ref

A deterministic rejection in the autofix verification gate is only
chargeable to the round if the same check passes without the round's
commit. The gate charged every red to the fix unconditionally, and run
31276008548 measured what that costs when the premise is false: PR
8614's branch predated QwenLM#8693's tsconfig guard while node_modules came
from the post-QwenLM#8693 trusted base, so `npm run build` was equally red at
origin/<branch> — 63 minutes of accepted agent work discarded, an
18-minute repair burned on a failure the repair agent is forbidden to
touch (it may only amend the round's own fix), thirteen rounds in a
row, and the same again on the QwenLM#8616 leg.

On rejection the gate now re-runs the failing check at origin/<branch>
(the branch as pushed, before the round) in the same environment:

- baseline green: today's path exactly — outcome=failed,
  retryable=true, the repair pass gets its chance.
- baseline red too: outcome=failed with preexisting=true and NO
  retryable. The repair step keys on retryable and is skipped — it
  cannot reach a failure outside the round's diff by construction —
  and gate-rejection.md says outright that the branch needs a base
  update (merge main), which flows into the failure comment as-is.

Fail-closed toward today's semantics: any A/B infrastructure problem
(missing ref, checkout failure) charges the fix as before, and a
restore failure after the baseline run rejects outright since the tree
can no longer be trusted. The round's work is still not pushed — this
changes the verdict's honesty and cost, not the push policy.

Tested by executing the real script in a real two-remote git repo with
an npm stub whose failures are keyed by commit SHA: round-caused red
(baseline green), pre-existing red (both red), and the untouched green
path. Mutation-tested, 3 of 3 caught: skipping the A/B, claiming
pre-existing without measuring, and dropping the tree restore.

* Address review: bound the A/B to checks it can honestly compare

All seven findings verified before fixing; the three Criticals were
each a way the A/B compared something other than the check that failed.

R1-1 — the contracts check feeds on stdin, which its first run drains;
the baseline leg re-ran against EOF and checked an empty file list.
R1-3 — the schema check's verdict rides on packages/core/dist, which
the core-rebuild guard built from ROUND sources and which, being
gitignored, survives the detach. Both checks are now A/B-exempt
(run_check_no_ab): their baseline verdicts prove nothing, and their
rejections stay where the repair agent can actually act on them.

R1-2 — a workspace the round ADDS does not exist at the baseline, and
npm exits 1 there with "No workspaces found" (measured; --if-present
forgives a missing script, not a missing workspace) — a round-caused
failure misread as pre-existing, skipping the one repair that can fix
the round's own package. The per-package loop now A/Bs only when the
workspace exists at origin/<branch>.

R1-4 — a chatty PASSING baseline used to flood the tail -c 3000
evidence window and push the actual failure text out of
gate-rejection.md, the sole carrier into the repair feedback, the PR
comment, and the next round's LAST_REJECTION. The baseline transcript
now goes to a side log and only a FAILING tail is merged back, where it
is the evidence.

R1-5 — the pre-existing paragraph pushed gate-rejection.md past the
report's head -c 3500 cap, truncating the closing fence for branch
names past 44 characters. Cap raised to 3900, invariant comment
updated with the new arithmetic.

R1-6 — preexisting=true had no read site. It now flows verify →
Finalize verification → the failure report, whose headline swaps the
generic gate clause for "PRE-EXISTING failure … needs a base update
(merge main)".

R1-7 — the no-round-commit guard was unpinned (deleting it kept all
tests green). Now exercised through the core-rebuild path, the one
A/B-eligible check that runs before the commit gate.

Four new behavioral scenarios (chatty baseline, no-commit round,
A/B-exempt checks, round-added workspace) plus workflow pins for the
forwarding, the clause, and the cap. Mutation-tested, 4 of 4 caught:
schema back to A/B (3 tests), guard dropped, side log reverted,
no-commit guard dropped.

* Address review round 2: A/B only what it can prove, prove what it claims

Ten findings across two rounds, each verified before fixing. The three
deepest share one lesson: the A/B is only sound for a check whose
inputs travel entirely with the git ref, and whose failure it can
IDENTIFY, not merely observe.

R2-1 — rc=1 at both legs does not make them the same failure: the
branch can fail for reason A while the round fails for reason B, and a
baseline infrastructure hiccup is a nonzero exit too. Pre-existing now
requires a MATCHING failure identity — tsc diagnostics normalized to
file + error code (positions shift with the round's edits), compared
via comm(1) on a per-check transcript. No diagnostics on either side
means identity cannot be established and the round stays charged.

R2-2 / R2-7 — gitignored dist survives the detach carrying the ROUND's
build, so any dist-consuming check A/Bs reverted sources against
round-built artifacts: package tests (channel-base resolved through
dist exports) and typecheck (sdk-typescript resolves core's d.ts —
probe-verified three-arm flip). Both are now A/B-exempt, as is lint,
leaving `npm run build` — the incident class, and the one check that
rebuilds its own inputs from the checked-out sources — as the sole A/B
candidate. The workspace-existence guard dissolves with it.

R2-3 — the fixture inherited the caller's global git config; a failing
global pre-commit hook broke all seven cases. The harness now isolates
GIT_CONFIG_GLOBAL/SYSTEM for every git child, and the suite is proven
green under a deliberately hostile hooksPath.

R2-4 — Finalize verification now selects preexisting from the same
attempt whose outcome it selects (repair verification included).

R2-5 / R2-8 — the "merge main" advice is now conditional at both
layers: the script paragraph states the measured fact and hedges the
remedy; the report headline uses the compare the step already ran —
behind/diverged gets the base-update clause, an up-to-date branch is
told its own pre-round code needs attention.

R2-6 — the rejection document now sizes its evidence tail against its
preamble (floor 500 bytes, total under the 3900-byte render cap), so
the closing fence can no longer be truncated off by a long branch name.

R2-9 — dissolved by R2-2: package tests no longer A/B, the guard and
its uncovered positive branch are gone.

R2-10 — the baseline-evidence merge is now pinned: the pre-existing
scenario asserts the baseline leg's own failure line (keyed by its SHA)
reaches gate-rejection.md.

Eight behavioral scenarios; mutation-tested 5 of 5: identity dropped,
typecheck re-enrolled, package tests re-enrolled, evidence merge
dropped, fixed tail restored.

* Address review round 4: sharpen identity, stage the git failures, sync prose

Nine findings, all refinements — the design held, the edges did not.

Identity now keeps the diagnostic MESSAGE (file + code collide: two
unrelated TS2339s in one file compared equal, skipping a repair that
could have shipped — probe-reproduced by the review), and the fixture
emits a SHIFTED position on the baseline leg so the position strip is
load-bearing instead of decorative (deleting the sed survived every
test before; it fails one now). vite/esbuild failures still yield an
empty signature by design — documented as the fail-closed limit rather
than half-widened.

The fail_signature assignments take `|| true`: grep exits 1 on the
normal no-match case and survives errexit today only because the caller
sits in an if-condition — a future unconditional call site would crash
the gate verdict-less.

The restore-failure branch is now stageable and staged: the baseline
leg recreates (untracked) a file the branch tracks, the checkout back
refuses, and the test pins retryable-not-preexisting with the
'could not restore' label. Relaxing the branch to `|| true` fails it.

Prose synced to the mechanisms that replaced it: the render-cap
invariant restates against the dynamic tail budget (the old 3000-based
arithmetic would misguide the next retune), the no-round-commit guard
comment names the core rebuild (schema/contracts left the A/B last
round), the describe wording counts both A/B-eligible builds, and the
pre-existing clauses no longer claim "the repair pass was skipped" —
with REPAIR_PREEXISTING forwarded, repair may have RUN; they now state
the invariant that is true either way: repair may only amend the
round's own fix, so it cannot reach this failure.

Mutation-tested, 3 of 3 caught: position strip dropped, message dropped
from the identity, restore rejection relaxed.

* fix(ci): watchdog silent sandbox hangs and reap the containers they leak

Four autofix rounds have died the same way (QwenLM#8663 twice, QwenLM#8761 r3,
QwenLM#8763 r4): the agent's last output is the sandbox wrapper's
"ContainerName (regular): …" line at docker container entry, then
nothing — not one event — until the 2-hour absolute budget kills the
round. Four different runners, two image versions: systemic, not a bad
machine. Where exactly the container wedges is still unknown (that
needs docker state on the runner); what is certain from the logs is the
shape — a wedged sandbox produces NOTHING, and a legitimate run is
never silent for long (the fleet's longest tolerated quiet is the
review pipeline's 10-minute stream-idle window for thinking phases).

Two mitigations, each aimed at a measured half of the damage:

- run-agent.mjs gains an idle watchdog (QWEN_IDLE_TIMEOUT_MS, default
  20 minutes = 2x that longest legitimate silence): zero output for the
  window kills the agent with a distinct "idle-timeout … the sandbox
  likely hung at startup" detail, so the failure comment names the
  right knob and a hung round costs 20 minutes instead of 120. Polled,
  not reset-per-chunk — a busy stream should not spend its time
  re-arming timers.

- Both sandboxed jobs reap stale qwen-code-* containers at job start:
  a budget kill reaps the HOST-side docker client, not the container,
  so every killed sandbox keeps running on the persistent runner —
  observed directly when a later leg's container-name counter found
  qwen-code-0.21.8-0 already occupied and picked -1. One job per runner
  at a time makes any container alive at job start stale by definition.

Tested by executing the real run-agent.mjs end to end with stub agents:
the hang shape (one line, then silence) dies at the idle window naming
the idle limit, and a slow-but-talking agent that outputs every 400ms
across a 1500ms window survives to a clean exit — the test that
distinguishes a watchdog from a disguised absolute timer. Mutation-
tested, 3 of 3 caught: watchdog disabled, last-output tracking dropped
(the disguised-timer regression), cleanup dropped from a job.

* Address review round 5: the gate's verdict defects and the reaper's live kill

Budget-warning round — the five Criticals from both reviewers, no
suggestions (each deferred with a recorded reply).

fail_signature: `[^\n]*` in an ERE bracket expression does not mean
"rest of line" — in POSIX bracket expressions `\` is literal, so it
matched "neither backslash nor the letter n" and truncated every tsc
message at its first n. Nearly every real message has an early n
("Cannot find name", "is not assignable"), so distinct same-file
failures collapsed into identical signatures and a round-caused failure
could be labeled pre-existing, skipping the repair. grep is
line-oriented: `.*` is exactly the rest of the line. New fixture: two
messages differing only after their first n.

Pre-existing verdict: the intersection test mislabeled in both
directions. A round that ADDS a diagnostic sharing one normalized line
with the baseline was called pre-existing (repair skipped for a
round-caused, repairable failure); and `comm -12 | grep -q` under
`set -eo pipefail` SIGPIPEs comm (exit 141) once the shared output
outruns the pipe buffer, charging true pre-existing failures to the
round — the exact 18-minute repair waste the gate exists to kill.
Pre-existing now means the round's failing set is a SUBSET of the
baseline's, and the difference is captured before testing. New fixture:
a round adding a second diagnostic to a failing baseline.

Restore failure after the baseline leg: was retryable=true with HEAD
still detached at the baseline commit — the repair agent works in that
very checkout and does no git recovery, so its commit would land on the
baseline and be orphaned. Now rejected non-retryable (reject_fix grows
a third arg); the next round starts clean from the trusted checkout.
The restoreClash test pins the new semantics.

Stale-container reap: the premise "a runner runs one job at a time, so
any live qwen-code-* container is stale" holds per runner registration,
but the filter queries the docker daemon, which is per host — and this
pool runs several registrations on one OS. With per-issue/PR
serialization only, a concurrent job's sandbox is a substring match
away from `docker rm -f`. The reap now takes only provably-dead
containers (--filter status=exited/dead, both jobs) and the comment
says why a running one is left alone.

Preamble printf: the `\`` escapes sat inside a single-quoted format
where backslash is literal, so every pre-existing rejection rendered
raw backticks instead of code spans (shellcheck SC2016). Backticks
need no escaping there. Also syncs the side-log comment to the dynamic
tail_budget it actually renders.

Verified: scripts suite 140/140 (was 138; the two new fixtures and the
rewritten restoreClash test all fail against the pre-fix script),
npm run build / typecheck / lint pass, bash -n clean.

* Address review round 6: reap the kill's own orphan, tolerate the reaper

* Address review: hang-bound the reaper, unblock the kill path, pin the unpinned arms

- Wrap every docker call in the stale-container reap with timeout 30: an
  alive-but-wedged daemon blocks docker ps indefinitely, and the existing
  || guards only catch nonzero exits, not hangs (R3-1).
- Make the kill-path container removal async in run-agent.mjs: the
  spawnSync blocked the event loop between SIGTERM and the 10s SIGKILL
  backstop for up to its 30s timeout — in exactly the wedged-daemon
  scenario the watchdog exists for. The main flow awaits the removal so
  the leak warning stays deterministic (R3-6).
- Split the pre-existing gate clause for an empty CMP_R: a transient
  compare-API failure is "never measured", not "measured not-behind", and
  must not assert the branch's own code is at fault (R3-7).
- Swap the timeout breaker's closing remedy to the sandbox investigation
  when every counted timeout was idle, mirroring the round-level split
  (R3-11).
- Tests: pin the budget kill path separately from the idle kill path
  (R3-3), parameterize the idle-window parse guard over -1/0/NaN (R3-5),
  add a stderr-only liveness case (R3-12), pin the strict-subset A/B arm
  via a baseline-superset fixture knob (R3-15), and pin the breaker's
  current-round idle increment (R3-18).

---------

Co-authored-by: verify <verify@local>
Co-authored-by: qwen-code-ci-bot <[email protected]>
Co-authored-by: qwen-code-dev-bot <[email protected]>
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