docs: add agent handoff docs, verification guide, and repair evidence

Add docs/agent-handoff (backlog, execution state, verification, platform plan, per-task evidence), repo AGENTS.md, and architecture notes updated for the dual-renderer design.
This commit is contained in:
2026-09-17 16:40:06 +08:00
parent 75b2ec4123
commit bc0b92bcdc
25 changed files with 2347 additions and 0 deletions
+104
View File
@@ -0,0 +1,104 @@
# P2-04 证据:跨平台聚合测试入口
状态:COMPLETE
日期:2026-07-17(本机执行时间)
平台:Windows 11 10.0.26200 x64(主)+ WSL Ubuntu-22.04 / CPython 3.12.3Linux 路径验证)
## 交付物
- `tests/run_all.py`(新增,唯一新文件):跨平台聚合测试入口。
- `python tests/run_all.py --group logic|offscreen|all`(默认 all
- `--list` 只列条目;`--only <id,子串>` 跑子集(调试);`--keep-logs` 保留全部子日志(默认只留失败/超时)。
- 设计:每个子测试 = 独立子进程 + 独立临时目录(`haocode_RUN_<id>`/`haocode_CONF_<id>`POSIX 走 TMPDIR、Windows 走 TEMP+ 显式秒级 timeout`subprocess.run(timeout=...)`);offscreen 组子进程注入 `QT_QPA_PLATFORM=offscreen``HAOCODE_RENDER=software``QTWEBENGINE_CHROMIUM_FLAGS=--disable-gpu`(均 setdefault,不覆盖外层)。
- 退出码语义:任一 FAIL/TIMEOUT → 退出码 1(并打印"失败命令"清单);SKIP 不影响退出码。
- SKIP 双闸门:①依赖探测(`importlib.util.find_spec`node/openai/PyMuPDF/PyQt6,缺失即 SKIP 并给理由);②平台令牌(`platform:win32` 等,平台不适用即 SKIP 并给理由)。
- 聚合鲁棒性:子进程崩溃/超时只记 FAIL/TIMEOUT,不中断后续;输出统一 UTF-8(`errors=replace`Windows cp936/cp1252 宿主安全);WSL 时钟回拨保护(耗时 clamp ≥0)。
- 不要求 pytest / npm / 网络;聚合器自身零第三方依赖。
## 默认聚合范围(25 条)与排除项
- logic 12 条:run_tests.pyagent core 41)、test_tool_params、test_bash_stream、test_copy_session、test_compaction_persist、test_file_attach、test_cross_platform_shell、test_global_hotkey_platforms、test_wv2_guard、test_pdf_reader、test_math_extract.js、test_render_window.js。
- offscreen 13 条:smoke_offscreen、smoke_mode、smoke_copy_session、smoke_bash_panel、smoke_timeline、smoke_midswitch、test_main_window_event_filter、test_config_isolation、test_error_persist、test_think_code_neutral、test_debug_window、test_renderer_matrix、test_screen_capture_platforms。
- 默认排除(有注释理由,不进默认聚合):
- `diag_*`rename_overlay / panel_scrollbar / render_scale):人工/像素诊断,需真机或交互。
- `verify_*`:人工验证脚本。
- `tune_model_popup.py`:调参实验。
- `smoke_offscreen.py` 之外的旧式 real-DB 冒烟(引用真实 `data/haocode.db`,未接临时库)。
- `diag_live_agent.py``probe_agent_loop.py`:需真实 API 凭据。
- `_probe_*``_test_env.py`:探针/工具模块(被其他测试 import,非独立用例)。
- `run_all.py` 自身:聚合器不入聚合。
## 汇总结果(硬约束要求:Windows/Linux 各一份)
### Windows 11 / CPython 3.10.21.venvPyQt6+openai+PyMuPDF 齐全)
| 组 | 结果 | 耗时 |
|---|---|---|
| `--group logic` | **PASS 12 / FAIL 0 / SKIP 0**EXIT=0 | 43.9s |
| `--group offscreen` | **PASS 13 / FAIL 0 / SKIP 0**EXIT=0 | 81.9s |
| `--group all` | 25/25 PASSEXIT=0,两组顺序执行) | ~126s |
- 日志样例:`D:/tmp/runall_win_logic2.log``D:/tmp/runall_win_offscreen.log`
- offscreen 明细:smoke_offscreen 8.3s、smoke_bash_panel 30.3s、smoke_midswitch 8.7s、test_think_code_neutral 9.3s 等 13 条全 PASS。
### WSL Ubuntu-22.04 / CPython 3.12.3(系统 python3,无 PyQt6/openai/PyMuPDF,离线环境)
| 组 | 结果 | 耗时 |
|---|---|---|
| `--group all` | **PASS 4 / FAIL 0 / SKIP 21**EXIT=0 | 0.9s |
- PASS 4 = test_copy_session、test_file_attach、test_math_extract.js、test_render_window.js(纯 stdlib/node)。
- SKIP 21 全部带明确理由:无 openai(5,禁止联网安装)、无 PyQt6(14offscreen 组整体)、无 PyMuPDF1)、平台不适用 win32-only1test_wv2_guardmsvcrt 单实例互斥是 WebView2 守卫的 Windows 专属机制,Linux 无 WebView2 链路)、无 PyQt6 的 GUI 逻辑(1test_global_hotkey_platforms 含 QShortcut 构造)。
- 证明:聚合器在 Linux/3.12 上可运行、隔离约定在 POSIX(TMPDIR)成立、诚实 SKIP 不伪装通过、JS 条目跨平台运行。
- 注:WSL 无 .venv 且离线,依赖型条目按硬约束 SKIP;在按 VERIFICATION 矩阵备齐依赖的 Linux 真机上同命令即可执行全部条目(offscreen 组仍需真实 Linux 桌面环境完成 P1-03/P1-04 的平台验证,状态不变)。
## 故意失败夹具演示(硬约束:崩溃/超时不阻断汇总、退出码反映失败)
- 临时夹具(用后即删,未提交):
- 崩溃夹具(`raise RuntimeError`)→ 聚合器记 **FAIL** 并继续跑后续健康测试。
- 超时夹具(`time.sleep(60)` + budget 5s)→ 聚合器记 **TIMEOUT** 并继续。
- 演示运行:`总计 3: PASS 1 FAIL 1 TIMEOUT 1`,退出码 **1**,完整汇总 + 失败命令清单正常打印。
- 演示日志:`D:/tmp/runall_fixture_demo.log`;夹具文件已删除,仓库无残留(已 rg 复核)。
## 等价性(硬约束:单文件命令仍可直接运行,输出与聚合子进程一致)
- `test_copy_session.py`
- 独立运行:`===== 54/54 PASS ===== / ALL PASS`
- 聚合子进程(保留子日志 tail):`===== 54/54 PASS ===== / ALL PASS` —— 逐字一致。
- 其余条目同理(聚合即 `subprocess.run([sys.executable, ...原命令...])`,命令形态未变)。
## 聚合入口暴露并修复的两个真实缺陷
1. **`tests/test_compaction_persist.py` T9 陈旧断言**(跨平台共同项,Windows 上 FAIL):
- 断言用 `assertIn('msg["role"] not in', src)` 硬编码变量名,而 `ui/views/main_window.py` 现行代码用 `m["role"] not in`P1-01/P2-01 期间变量名演化,测试未跟进)。
- 修复:改为变量名无关的语义断言(同时接受 `msg["role"] not in` / `m["role"] not in` 两种等价写法,检查"摘要标记行被过滤"这一语义本身)。
- 验证:单跑 41/41 PASS;聚合 logic 组 12/12 PASS。
2. **`core/agent/compaction.py` dataclass 不可哈希默认值(Python 3.11+ 崩溃,真跨平台 bug**
- `CompactionPreparation.settings: CompactionSettings = DEFAULT_COMPACTION_SETTINGS`:默认值是 eq-dataclass 实例(`__hash__=None`)。Python ≤3.10 的 dataclass 只拒 list/dict/set 默认值 → 合法;Python 3.11+ 追加"不可哈希默认值"检查 → **import 即 ValueError**
- 影响面:Ubuntu 24.04 自带 CPython 3.12VERIFICATION 矩阵明确支持的 Linux 目标)—— 任何 import `core.agent` 的模块/测试在 3.11+ 全灭。由聚合入口在 WSL/3.12 上首次系统性暴露。
- 修复(1 行,语义完全等价):`settings: CompactionSettings = field(default_factory=lambda: DEFAULT_COMPACTION_SETTINGS)` —— 仍返回同一共享默认实例,3.10 行为不变。
- 验证:3.10 本地 `test_compaction_persist` 41/41 + `run_tests` 41/41 无回归;WSL/3.12 上 `core.agent` 链 import 通过(3 个 openai 依赖条目越过 compaction 后才在 openai 处 SKIP,证明 3.12 兼容)。
## 注册表元数据修正(诚实 SKIP 的前提)
- `test_tool_params.py` / `test_bash_stream.py` / `test_cross_platform_shell.py`:补 `openai` 依赖(均 import `core.agent.tools` → 顶层 `from openai import OpenAI`)。
- `test_global_hotkey_platforms.py`:补 `pyqt6` 依赖(含 QShortcut/overlay 构造)。
- `test_wv2_guard.py`:标 `platform:win32`T4 msvcrt 跨进程互斥为 Windows 专属;非 win32 上 `acquire_instance_lock()` 按设计返回 None)。
## 边界遵守
- 未动任何独立测试命令与既有入口(`run_tests.py` 原样保留)。
- 未要求 pytest/npm/网络;聚合器零第三方依赖。
- 默认聚合未启动任何真实 API / 人工诊断 / 真实桌面 / 凭据脚本(见排除清单)。
- 未读取真实配置(`data/config.json` 零访问);未删除用户运行数据;夹具用后即删。
- 产品代码改动仅 2 处且均为聚合暴露的缺陷修复:`tests/test_compaction_persist.py`(测试断言更新)+ `core/agent/compaction.py`1 行 3.11+ 兼容)。
## 复现命令
```text
python tests/run_all.py --list
python tests/run_all.py --group logic
python tests/run_all.py --group offscreen
python tests/run_all.py --group all
python tests/run_all.py --only test_copy_session --keep-logs
```