Skip to content

fix(tests): 修复 LF 检出下 3 处失败与 3 处「假绿」空过,并补 CI 的 Linux 一档 - #15

Merged
3304711297 merged 3 commits into
mainfrom
arena/01a0b2fc-workbuddy2api
Sep 18, 2026
Merged

3304711297 merged 3 commits into
mainfrom
arena/01a0b2fc-workbuddy2api

Conversation

@arena-ai-coding-agent

@arena-ai-coding-agent arena-ai-coding-agent Bot commented Sep 18, 2026

Copy link
Copy Markdown

这个 PR 做了什么

跑仓库自带门禁时发现一件事:Windows CI 全绿,但 LF 检出下 npm test 是 199 pass / 3 fail。差异全部来自换行符与真实 DNS,不是业务逻辑——也就是说 CI 的绿掩盖了 3 类真问题。本 PR 修掉这 3 处失败、3 处「假绿」空过、2 处测试基建缺陷与 1 处静态检查问题,并补了守门的一档 CI。

不改任何业务逻辑converter.py 只有 1 行改动(补 Any 导入),其余全是测试/CI/文档。

修复清单

# 问题 严重度
1 契约测试注释剥离器:LF 下吃掉字符串里的 //(端点断言恒失败);CRLF 下完全空转(写一句解释性注释即误报) P1
2 安全用例可「真回归空过」:proxy.rsep.contains("//") 等行被整段吃掉 P1
3 视觉内联用例依赖真实 DNS:正例必红,反例空过 P1
4 盘根扫描用例写死 Windows 路径形态,非 Windows 检出必红 P2
5 隔离运行器常年红(harness 与用例互相矛盾)→ 故无人接入 CI P1
6 坏路径用例在 POSIX 上往仓库根写垃圾文件,且没验到失败兜底 P2
7 converter.py 12 处用了 Any 却未导入 P2
8 CI 只跑 Windows(CRLF + 有真实 DNS),正是上述缺陷的共同成因 P1

关键证据(变异验证,不是「跑绿了」而已)

① 安全用例的空过——往 proxy.rs 注入 let _probe = format!("http://127.0.0.1:{port}/health"); cmd.arg("--api-key");

剥离实现 结果
旧(HEAD) # pass 4 / # fail 0 —— 漏判真回归
新(本 PR) 用例 A 正确判红

② 视觉用例的空过——把 Content-Type 兜底整段关掉,在禁 DNS 环境下:

用例文件 结果
旧(HEAD) 1 passed —— 空过
新(本 PR) 1 failed —— 抓到

③ 注释剥离器:代码里重新引入 releases/latest → 新旧都抓到;注释里提到它 → 旧实现在 LF 下误报、CRLF 下漏判,新实现正确放行。

④ 盘根扫描用例:把盘根扫描整段去掉 → 仍变红(实际:[]),说明没退化成恒绿。

验证

LF 与 CRLF(全仓转 CRLF 的副本,等价于 Windows 检出)两种检出下均实测全绿

门禁 修复前 修复后
pytest -q 423 passed 423 passed
tests/run_isolated_tests.py 3 failed / exit 1 423 passed / exit 0
npm test(LF) 199 pass / 3 fail 202 passed
npm test(CRLF) 202 passed(含 2 处空过) 202 passed
check_premarked_sync.py exit 0 exit 0

未验证(如实声明)cargo test 没跑——沙箱无 Rust 工具链,Rust 侧本轮只读未改;未打真实上游;未在真实 Windows 上执行(用 CRLF 副本等价验证)。converter.py 约 7.9k 行未逐行审阅。

评审时请留意

  1. 新增的 checks-linux job 可以删。原 ci job 我没动;Linux 档只跑 pytest / 隔离运行器 / 前端测试(不含 cargo——Linux 上 Tauri 需额外系统库)。其余修复不依赖它。
  2. tests/helpers/strip-rust-comments.mjs 是新文件,两处测试共用;它按字符扫描,会跳过字符串/字符/原始串并支持嵌套块注释。
  3. 顺手复核了 docs/audit-2026-09-17.md 的高危项,SSRF / 40 位 SHA / 原子落盘 / 交错工具分块 / 错误帧传播 / 降级误标 均已修复,不必再按旧报告追。

未修,留给后续(详见 docs/audit-2026-09-18.md §3)

  • _url_is_safe_for_fetch 是死代码(零生产调用点),SSRF 校验存在两份且已出现差异。旧报告把它当防线、多个用例在替换它——这给的是虚假信心;真正生效的是 _url_to_data_uri 内部那份。建议抽公共 helper 或删掉死函数。
  • CI 无任何 Python 静态检查(无 ruff/mypy),这正是 Any 能潜伏至今的原因。残留噪声里 responses_projection.py:575saw_output 赋值后从未读取,像是漏了一步判断,建议确认意图而非直接删。
  • 两处测试直接改全局 CONFIG 不还原(test_snapshots_stream_resp.py:23test_snapshots_wire.py:29),属潜在顺序依赖。

注:converter.py:3023/3266cred = _cred()有意的 fail-fast 守卫(无凭据抛 503),不是待清理噪声。


第二轮(新增提交 028e871

一、Issue #14 上游看门:4 项评估完成,均无需吸收代码

上游提交 评估结论
Sliverkiss/workbuddy2api 4ac68b77(global chat 固定走 /v2 绕开 /console WAF) 无需改动——本仓 converter.py 本就原生直连 /v2/chat/completions,天然具备该特性
momo0410/workbuddy-switch-gateway 91b9a292(非 Windows 改用 Child::kill 不适用——本项目是 Windows Tauri 桌面端,带进程树 taskkill 保护链
ardeyouxipianyi/workbuddy2api-intl 95c3e41d(UI 调整;仓库已更名 workbuddy2api-hub 无需吸收——本项目用独立控制中心;已同步 repo 字段更名
orangeboyChen/codebuddy2api 7ccf62f9(prepare release v1.3.8) 常规发版

落地:4 项基线推进 + repo 更名同步;--lint ✅;本地实跑巡检得「0 项待评估 / 0 项查询失败」——满足工作流自动收口条件,合并进 main 后 Issue #14 会被 CI 自动关闭(不手工关闭,以免与实际巡检状态脱节)。

注:本沙箱的 GitHub 凭据无 issue 写权限(Resource not accessible by integration),故评估结论记在此处而非 Issue 评论。

二、报告 §3 三项工程/测试问题闭环

  1. SSRF 校验收敛为单一实现(消除死代码)
    新增 converter._resolve_public_connect_ip(host) -> (ip|None, 原因) 作为「主机/IP 是否可连」的唯一实现:
    _url_is_safe_for_fetch 只保留 URL 级职责(协议白名单 + 取 host);_url_to_data_uri 的逐跳校验改为调用同一函数(拒绝路径 3 条 → 1 条)。
    副带修复:本机/元数据主机名单(_BLOCKED_IMAGE_HOSTS*.localhost)此前只在那份零调用点的死代码里,
    真实下载路径并未执行,现已覆盖。
    防漂移用例 test_url_level_and_fetch_path_share_one_validator 锁定两条路径共用同一函数——变异验证:把任一处改回内联判定即变红。
    连带:test_vision_inlining 不再打桩那个假接缝_url_is_safe_for_fetch,零调用点),只打桩真实接缝(DNS);
    并修掉 test_ssrf_guard_blocks_dangerous_urlsexpect_keyword 只收集不断言的真空断言。

  2. responses_projection.py:575saw_output 关闭
    确认为重构残留而非漏分支:Output: 是 Codex 执行器的分段标题行,本应无条件丢弃。
    删除标志 + 注释保留「将来若要按它分支需连同契约一起改」的提示;用例补
    assert "Output:" not in contentcontent.count("Key output:") == 1,锁定「丢弃标题 ≠ 省略正文标题」。
    responses_projection.py 现已 pyflakes 全清。

  3. 测试全局配置隔离
    test_snapshots_stream_resp.pytest_snapshots_wire.py 以及同子系统的 test_snapshots.py
    _enable() 助手 + 4 个用例)全部改走 monkeypatch.setitem
    tests/conftest.py 新增 autouse 夹具 _isolate_global_config,每例结束把 CONFIG 恢复为快照——
    作为兜底护栏test_wsl_and_tool_repair.py 等仍有直接赋值,现已被兜住)。
    已用探针用例验证:移除护栏即复现泄漏。

三、验证(LF 与 CRLF 两种检出)

门禁 结果
pytest -q 424 passed(+1 新增防漂移用例)
tests/run_isolated_tests.py 424 passed / exit 0
npm test 202 passed
check_premarked_sync.py
tools/check-upstream.py --lint ✓ 19 个源
tools/check-upstream.py(实跑) 0 项待评估 / 0 项查询失败

未跑:cargo test(沙箱无 Rust 工具链,Rust 侧本轮未改动);未打真实 CodeBuddy 上游。

3304711297 and others added 3 commits September 18, 2026 05:39
实测:Linux/LF 检出下 `npm test` 为 199 pass / 3 fail,而 main 的 Windows CI 全绿。
差异全部来自换行符与真实 DNS,不是业务逻辑——即「CI 绿」掩盖了 3 类真问题。

1) 契约测试的注释剥离器两处失真(test_app_update_contract)
   旧实现 `line.replace(/\/\/.*$/, '')`:LF 下吃掉字符串字面量里的 `//`
   (`format!("https://…/commits/{branch}")` 尾部被剪 → 端点断言恒失败);
   CRLF 下 `.` 不匹配 `\r` 而 `$` 锚定其后 → 完全不生效(Windows/CI 即此情形:
   注释原样留下,写一句解释性注释就误报)。统一改用按字符扫描的
   tests/helpers/strip-rust-comments.mjs(跳过字符串/字符/原始串、支持嵌套块注释,LF 与 CRLF 一致)。

2) 安全用例可「真回归空过」(test_secret_injection)
   粗放剥离把 `ep.contains("//")`、URL 字面量这类行从 `//` 起整段吃掉,而本文件断言全是负向。
   实测注入 `let _probe = format!("http://…"); cmd.arg("--api-key");`:
   旧实现 4 passed(漏判),新实现正确判红。

3) 视觉内联用例依赖真实 DNS(test_vision_inlining)
   真实取数路径在 _url_to_data_uri 内部自行解析域名,而桩只替换了无生产调用点的
   _url_is_safe_for_fetch(已核实零生产调用点)。后果:正例离线必红;反例则「因解析失败提前返回」
   而空过——实测把 Content-Type 兜底整个关掉,离线时该用例依然全绿。改为打桩
   converter._resolve_host_ips。

4) 盘根扫描用例写死 Windows 路径形态(test_turing_findsdk_chain)
   `path.join('Z:\','workbuddy')` 在 POSIX 是 `Z:\/workbuddy`,写死的 `^z:/(workbuddy)/` 恒不匹配。
   期望值改为与实现同源推导;变异验证:去掉盘根扫描后本用例仍会变红。

5) 隔离运行器常年红、故无人接入(harness 与用例互相矛盾)
   run_isolated_tests.py 的 autouse 夹具把 usage_log 指向临时目录,而
   test_record_usage_disabled_is_noop 断言该键「默认即 None」→ 该门禁恒失败。
   用例改为显式 monkeypatch 置 None;隔离运行器现 423 passed / exit 0。

6) 坏路径用例在 POSIX 上往仓库根写垃圾文件(test_converter)
   `r"Z:\__no_such_dir__\usage.jsonl"` 在 POSIX 是合法相对文件名 → 生成同名文件(.gitignore 未覆盖),
   且用例实际走成功分支、没验证到失败兜底。改用 tmp_path 下不存在的子目录。

7) converter.py 补 `Any` 导入:12 处注解用到 Any 却只 import 了 Optional,
   仅靠 `from __future__ import annotations` 未炸(mypy / get_type_hints 会失败)。

8) CI 增加 checks-linux(LF + 禁网):上述缺陷的共同成因是「只跑 Windows + 检出为 CRLF + 有真实 DNS」。
   原 job 不动,Linux 档只跑 pytest / 隔离运行器 / 前端测试(不含 cargo:Linux 上 Tauri 需额外系统库)。
   AGENTS.md 补「改测试前必读」四条与隔离运行器命令。

验证(LF 与 CRLF 两种检出下均实测全绿):
  pytest 423 passed | 隔离运行器 423 passed / exit 0 | npm test 202 passed | check_premarked_sync ✓
  未跑:cargo test(本机无 Rust 工具链)、上游真实请求。

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
一、Issue #14 上游看门(4 项评估结论:均无需吸收代码)
  · Sliverkiss 4ac68b77 global chat 走 /v2 绕 WAF —— converter.py 本就原生直连 /v2,无需改动
  · momo0410 91b9a292 非 Windows Child::kill —— 本项目为 Windows Tauri(taskkill 进程树保护),不适用
  · ardeyouxipianyi 95c3e41d UI 调整 —— 本项目为独立控制中心,无需吸收
  · orangeboyChen 7ccf62f9 prepare release v1.3.8 —— 常规发版
  落地:4 项 last_synced_commit/last_synced_sha 推进至最新;ardeyou 仓库更名
  workbuddy2api-intl -> workbuddy2api-hub(name 同步注明);updated_at -> 2026-09-18。
  实跑 tools/check-upstream.py:0 项待评估、0 项查询失败(满足工作流自动收口条件);
  --lint 通过(19 个源)。

二、SSRF 校验两份实现/死代码 -> 收敛为单一实现
  新增 converter._resolve_public_connect_ip(host) -> (ip|None, 原因):「主机/IP 是否可连」的唯一实现。
  · _url_is_safe_for_fetch 仅保留 URL 级职责(协议白名单 + 取 host),判定全部委托;
  · _url_to_data_uri 逐跳校验改为调用同一函数,拒绝路径 3 条 -> 1 条。
  副带修复:本机/元数据主机名单(_BLOCKED_IMAGE_HOSTS、*.localhost)此前只在
  那份零调用点的死代码里生效,现真实下载路径也覆盖。
  防漂移用例 test_url_level_and_fetch_path_share_one_validator 锁定两条路径共用同一函数
  (变异验证:把任一处改回内联判定即变红)。
  连带:test_vision_inlining 不再打桩那个假接缝(_url_is_safe_for_fetch),只打桩真实接缝(DNS);
  并修掉 test_ssrf_guard_blocks_dangerous_urls 中 expect_keyword 只收集不断言的真空断言。

三、responses_projection.saw_output 关闭
  确认为重构残留(`Output:` 是 Codex 执行器分段标题行,本应无条件丢弃),非漏分支。
  删除标志并注释保留未来分支的提示;用例补 assert "Output:" not in content 与
  content.count("Key output:") == 1,锁定「丢弃标题 != 省略正文标题」。

四、测试全局配置隔离
  test_snapshots_stream_resp / test_snapshots_wire / test_snapshots(_enable + 4 用例)
  全部改走 monkeypatch.setitem;conftest 新增 autouse _isolate_global_config,
  每例结束把 CONFIG 恢复为快照作为兜底护栏(探针验证:移除护栏即复现泄漏)。

验证:LF 与 CRLF 两种检出下 pytest 424 passed / 隔离运行器 424 passed exit 0 /
npm test 202 passed / premarked 同步 ✓ / upstream --lint ✓。
未跑:cargo test(本机无 Rust 工具链);未打真实 CodeBuddy 上游。

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
@3304711297
3304711297 merged commit c6522ba into main Sep 18, 2026
2 checks passed
@3304711297
3304711297 deleted the arena/01a0b2fc-workbuddy2api branch September 18, 2026 06:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant