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:
@@ -0,0 +1,262 @@
|
||||
# 验证与取证规范
|
||||
|
||||
本文定义修复任务的统一验证口径。任务范围和完成条件见 [REPAIR_BACKLOG.md](REPAIR_BACKLOG.md)。平台行为契约见 [PLATFORM_PLAN.md](PLATFORM_PLAN.md)。
|
||||
|
||||
## 测试前置条件
|
||||
|
||||
### 凭据与运行数据隔离
|
||||
|
||||
`data/config.json` 是不透明秘密。执行测试的 Agent 不得打开、读取、搜索、打印、复制或修改它,也不得用散列或快照方式“验证未变化”。采用以下正向隔离:
|
||||
|
||||
1. 为每个测试进程创建独立临时目录和最小临时配置。
|
||||
2. 在 import 任意可能间接加载 `MainWindow` 的模块前设置 `HAOCODE_CONFIG_FILE`。
|
||||
3. 在 import `MainWindow` 前把 `core.db_manager._DEFAULT_DB` 指向临时数据库。
|
||||
4. 写入、迁移、附件和截图产物只落到临时目录。
|
||||
5. 用文件打开拦截器或替身断言禁止路径从未被访问,不读取禁止路径本身。
|
||||
|
||||
需要真实 API key 的 `diag_live_*`、`smoke_live_*` 由用户在受控环境手工决定是否运行;默认测试和工作 Agent 均不运行它们。
|
||||
|
||||
### GUI 环境
|
||||
|
||||
离屏测试只验证结构和一般 Qt 行为,不算真机视觉证据。
|
||||
|
||||
Windows PowerShell:
|
||||
|
||||
```powershell
|
||||
$env:PYTHONIOENCODING = 'utf-8'
|
||||
$env:QT_QPA_PLATFORM = 'offscreen'
|
||||
python tests/smoke_offscreen.py
|
||||
```
|
||||
|
||||
Linux:
|
||||
|
||||
```bash
|
||||
PYTHONIOENCODING=utf-8 QT_QPA_PLATFORM=offscreen python tests/smoke_offscreen.py
|
||||
```
|
||||
|
||||
真实桌面检查前移除 `QT_QPA_PLATFORM=offscreen`。不得用离屏截图替代 WebView2、X11、Wayland、portal、DPI 或滚动条真机检查。
|
||||
|
||||
### 结果记录
|
||||
|
||||
每个任务至少记录:
|
||||
|
||||
- 操作系统、桌面会话类型、Python、PyQt6/Qt 版本;
|
||||
- 精确命令、退出码和测试摘要;
|
||||
- 失败或跳过项及理由;
|
||||
- 真机项的截图/录屏路径和复现步骤;
|
||||
- 是否使用临时配置、临时数据库和离屏模式。
|
||||
|
||||
不要写固定“应通过 N 项”的文案;用退出码和当前测试自己报告的数量为准,避免测试增删后文档失真。
|
||||
|
||||
## 定向测试矩阵
|
||||
|
||||
每个任务先跑自己的定向测试。定向通过后才跑所在阶段的完整回归。
|
||||
|
||||
| 任务 | 必跑命令 | 额外人工证据 |
|
||||
|---|---|---|
|
||||
| P0-01 配置隔离 | `python tests/test_config_isolation.py`;`python tests/test_error_persist.py`;`python tests/smoke_bash_panel.py`;test_agent_core(经 `python tests/run_tests.py` 运行) | 打开路径拦截记录只含临时目录 |
|
||||
| P0-02 `eventFilter` | `python tests/test_main_window_event_filter.py`;`python tests/smoke_offscreen.py`;`python tests/smoke_mode.py` | Enter/Shift+Enter 行为记录 |
|
||||
| P0-03 文档 | 文档链接检查与 `rg` 检查 | 从 `AGENTS.md` 演练一次读取路径 |
|
||||
| P1-01 渲染窗口 | `node tests/test_render_window.js`;`python tests/diag_render_scale.py 400`;相关 Qt smoke | 400 条固定夹具、锚点误差、帧时间报告 |
|
||||
| P1-02 shell | `python tests/test_cross_platform_shell.py`;`python tests/test_bash_stream.py`;`python tests/test_tool_params.py` | 两平台进程树消失证明 |
|
||||
| P1-03 渲染器 | `python tests/test_wv2_guard.py`;`python tests/smoke_offscreen.py`;`node tests/test_math_extract.js` | Windows 两后端、Linux X11/Wayland 启动 |
|
||||
| P1-04 热键/截图 | 平台适配单元测试、`python tests/test_file_attach.py` | Windows、X11、Wayland 各自真机行为 |
|
||||
| P2-01 Bash 排序 | `python tests/smoke_bash_panel.py`;`python tests/test_bash_stream.py` | 重排前后状态与滚动位置 |
|
||||
| P2-02 滚动条 | `python tests/diag_panel_scrollbar.py`;`python tests/smoke_bash_panel.py` | Windows/Linux 局部截图和尺寸 |
|
||||
| P2-03 遮罩 | `python tests/diag_rename_overlay.py`;`python tests/smoke_offscreen.py` | Windows WebView2 遮罩截图/移动缩放录屏 |
|
||||
| P2-04 聚合入口 | `python tests/run_all.py --group logic`;`--group offscreen`;`--group all` | Windows/Linux 汇总各一份 |
|
||||
|
||||
表中尚不存在的脚本属于对应任务的交付物,不得在创建前声称已经通过。
|
||||
|
||||
## P1-01 渲染窗口专项
|
||||
|
||||
### DOM 无关状态机
|
||||
|
||||
`tests/test_render_window.js` 直接加载纯状态机,不依赖浏览器、JSDOM 或 npm。至少覆盖:
|
||||
|
||||
- `auto`、`manual` 两种模式;
|
||||
- `size` 为 10、40、200;
|
||||
- 缺失、`true`/`false`、字符串、0、负数、9、201 等值都回落 40;
|
||||
- 初始最新页、连续向上、连续向下、首尾边界;
|
||||
- 加一端时裁另一端,窗口始终不超过上限;
|
||||
- 活动流计入上限,且不会被裁;
|
||||
- 新 token 到来回到底部;
|
||||
- `clearChat` 清游标/缓存/未决请求但保留配置;
|
||||
- 会话/代次变化后丢弃旧响应;
|
||||
- 分支目标保留和目标缺失回底。
|
||||
|
||||
### Qt/DOM 集成
|
||||
|
||||
Qt smoke 使用临时会话生成完整描述,至少包含普通消息、附件、reasoning、工具时间线、工具结果和多分支消息。用 QWebChannel 完成多轮双向换页后,逐项比较重建结果。
|
||||
|
||||
通用硬指标:任意时刻 `.message-wrapper <= render_window_size`。这条对所有夹具、所有窗口大小和流式状态都成立。
|
||||
|
||||
固定 400 条夹具的附加指标:
|
||||
|
||||
| 指标 | 门槛 |
|
||||
|---|---|
|
||||
| `.message-wrapper` | `<= render_window_size`,默认 `<= 40` |
|
||||
| DOM 总节点 | `<= 4000` |
|
||||
| 页面总高度 | `<= 30000 px` |
|
||||
| 向上换页锚点误差 | `<= 2 px` |
|
||||
|
||||
总节点数和页面高度只对版本化的固定 400 条夹具验收。修改夹具必须在结果中说明,不得把这些数字套到任意内容长度。
|
||||
|
||||
### 帧时间
|
||||
|
||||
帧时间属于人工基准报告,不是自动化通过门槛。相同机器、相同窗口尺寸、相同 400 条夹具分别记录修复前/后:
|
||||
|
||||
- 流式追加一段固定文本期间的采样次数;
|
||||
- frame duration 的 median、p95 和最大值;
|
||||
- 是否发生肉眼可见停顿;
|
||||
- 浏览器后端和 Qt 版本。
|
||||
|
||||
报告原始数值和测量方法,不把环境波动包装成确定性断言。
|
||||
|
||||
## 当前独立回归命令
|
||||
|
||||
在 P2-04 聚合入口完成前,按影响范围选择下列现有命令。每项任务不要求机械运行所有命令;一个阶段结束时运行完整集合。
|
||||
|
||||
```text
|
||||
python tests/run_tests.py
|
||||
python tests/test_config_isolation.py
|
||||
python tests/test_main_window_event_filter.py
|
||||
python tests/test_tool_params.py
|
||||
python tests/test_compaction_persist.py
|
||||
python tests/test_copy_session.py
|
||||
python tests/test_bash_stream.py
|
||||
python tests/test_error_persist.py
|
||||
python tests/test_wv2_guard.py
|
||||
python tests/test_debug_window.py
|
||||
python tests/test_think_code_neutral.py
|
||||
python tests/test_file_attach.py
|
||||
python tests/test_pdf_reader.py
|
||||
python tests/smoke_offscreen.py
|
||||
python tests/smoke_mode.py
|
||||
python tests/smoke_copy_session.py
|
||||
python tests/smoke_bash_panel.py
|
||||
node tests/test_math_extract.js
|
||||
```
|
||||
|
||||
平台专属测试在不适用的平台明确 `SKIP`。任何共同逻辑测试失败都不能以平台差异豁免。
|
||||
|
||||
`tests/run_tests.py` 当前只覆盖其显式加载内容;在 P2-04 完成前,不能把它单独称为“全套测试”。
|
||||
|
||||
## 分阶段完整回归
|
||||
|
||||
### P0 完成后
|
||||
|
||||
运行全部纯逻辑测试和所有受影响的离屏 GUI 测试。重点证明测试不会访问真实配置/数据库,并且 `MainWindow` 输入行为没有回归。
|
||||
|
||||
### P1 完成后
|
||||
|
||||
运行当前独立回归命令全集,加上:
|
||||
|
||||
```text
|
||||
node tests/test_render_window.js
|
||||
python tests/test_cross_platform_shell.py
|
||||
python tests/test_global_hotkey_platforms.py
|
||||
python tests/test_screen_capture_platforms.py
|
||||
```
|
||||
|
||||
随后完成 Windows/Linux 真实桌面矩阵。平台适配任务没有真实桌面证据时不能标记完成。
|
||||
|
||||
### P2 完成后
|
||||
|
||||
优先运行新聚合入口:
|
||||
|
||||
```text
|
||||
python tests/run_all.py --group all
|
||||
```
|
||||
|
||||
再单独运行三个诊断脚本;它们属于人工/半自动取证,不应混入默认聚合:
|
||||
|
||||
```text
|
||||
python tests/diag_render_scale.py 400
|
||||
python tests/diag_panel_scrollbar.py
|
||||
python tests/diag_rename_overlay.py
|
||||
```
|
||||
|
||||
## 真实桌面矩阵
|
||||
|
||||
### Windows 10/11 x64
|
||||
|
||||
至少覆盖以下路径:
|
||||
|
||||
1. WebView2 首选路径:启动、发一轮对话、流式输出、附件、分支、切会话。
|
||||
2. QtWebEngine 强制回落:使用临时配置启动同一套基本流程。
|
||||
3. 同时启动两个 QtWebEngine 实例,证明 profile 不争用。
|
||||
4. WebView2 下打开改名遮罩,验证整个客户区覆盖;拖动、缩放、最大化和还原。
|
||||
5. Bash 面板三项以上任务,验证最新任务在顶部、状态保持和滚动条视觉。
|
||||
6. 截图全局热键在应用失焦时仍能捕获并进入附件流程。
|
||||
|
||||
证据必须标注实际后端。QtWebEngine 截图不能替代 WebView2 原生遮挡验收。
|
||||
|
||||
### Ubuntu 22.04/24.04 x64 + X11
|
||||
|
||||
至少使用 Python 3.10--3.12 范围内一个受支持版本完成:
|
||||
|
||||
1. `python main.py` 启动 QtWebEngine,渲染 Markdown、KaTeX、代码块和工具时间线。
|
||||
2. 发一轮对话并执行 shell 工具,实际命令由 `/bin/bash -lc` 执行。
|
||||
3. 超时和主动中止后检查父/孙进程均不存在。
|
||||
4. 双开应用,两个 QtWebEngine profile 不冲突。
|
||||
5. X11 原生全局截图热键在应用失焦时触发,截图进入附件流程。
|
||||
6. 消息窗口、Bash 排序与滚动条完成一次真机检查。
|
||||
|
||||
### Ubuntu 22.04/24.04 x64 + Wayland
|
||||
|
||||
至少完成:
|
||||
|
||||
1. QtWebEngine 正常启动并完成基本对话与渲染。
|
||||
2. portal/桌面协议请求有清晰的用户授权流程。
|
||||
3. 全局快捷键和截图通过 portal/桌面协议完成;若当前桌面协议不支持,界面明确报错,应用其余功能继续可用。
|
||||
4. 拒绝授权、portal 服务缺失和协议版本不足各记录一次结果。
|
||||
5. 普通用户启动保持 Chromium sandbox。
|
||||
|
||||
Wayland 下不得用 X11 私有 API 或静默降级成“仅窗口内快捷键”并声称全局热键通过。
|
||||
|
||||
### 其他发行版
|
||||
|
||||
可以记录探索结果,但统一标记“未验证”,不能扩大官方支持矩阵。
|
||||
|
||||
## 人工 UI 检查
|
||||
|
||||
### Bash 排序与状态
|
||||
|
||||
按 A、B、C 顺序启动,按 B、A、C 或其他不同顺序结束。运行中栏和已完成栏始终按 C、B、A 的启动顺序显示。操作前先:
|
||||
|
||||
- 展开其中一个 layer;
|
||||
- 在输出框分别设置水平和垂直滚动位置;
|
||||
- 滚动运行中栏和已完成栏。
|
||||
|
||||
任务状态迁移后,上述展开状态、输出、代码框滚动和两个 section 滚动均保持。
|
||||
|
||||
### Bash 滚动条
|
||||
|
||||
同时制造横向与纵向溢出,记录:
|
||||
|
||||
- 横纵滚动条实际厚度;
|
||||
- 箭头区域是否消失;
|
||||
- handle 是否可拖动并有 hover;
|
||||
- 横纵交汇处是否与代码框背景一致;
|
||||
- 模型弹窗、会话列表、附件预览和调试窗口是否未受影响。
|
||||
|
||||
### 改名遮罩
|
||||
|
||||
Windows WebView2 下记录打开、移动、缩放、最大化、还原、提交和取消。截图必须包含整个主窗口,能比较聊天区与 Qt 控件区的遮罩亮度。结构性离屏断言只是补充。
|
||||
|
||||
## 聚合入口契约
|
||||
|
||||
P2-04 完成后的聚合入口必须:
|
||||
|
||||
- 使用 Python 子进程执行现有独立测试,不把所有测试 import 到同一进程;
|
||||
- 为每个子进程建立独立临时环境;
|
||||
- 支持至少 `logic`、`offscreen`、`all` 三组;
|
||||
- 汇总命令、退出码、耗时和 PASS/FAIL/SKIP;
|
||||
- 默认排除 live、diag、verify、tune、网络和凭据测试;
|
||||
- 一个子进程失败后继续收集其余结果,最终返回非零;
|
||||
- 在 Windows 和 Linux 使用同一 Python 接口,不嵌入 `.bat` 或 Bash 专属命令串。
|
||||
|
||||
## 最终判定
|
||||
|
||||
一项修复只有在以下内容齐全时才算完成:定向测试通过、阶段完整回归通过、该平台需要的真实桌面证据齐全、所有跳过项有理由、真实配置和数据库从未被测试访问。任何一项缺失都应标记为“未完成”而不是“基本完成”。
|
||||
Reference in New Issue
Block a user