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.
11 KiB
验证与取证规范
本文定义修复任务的统一验证口径。任务范围和完成条件见 REPAIR_BACKLOG.md。平台行为契约见 PLATFORM_PLAN.md。
测试前置条件
凭据与运行数据隔离
data/config.json 是不透明秘密。执行测试的 Agent 不得打开、读取、搜索、打印、复制或修改它,也不得用散列或快照方式“验证未变化”。采用以下正向隔离:
- 为每个测试进程创建独立临时目录和最小临时配置。
- 在 import 任意可能间接加载
MainWindow的模块前设置HAOCODE_CONFIG_FILE。 - 在 import
MainWindow前把core.db_manager._DEFAULT_DB指向临时数据库。 - 写入、迁移、附件和截图产物只落到临时目录。
- 用文件打开拦截器或替身断言禁止路径从未被访问,不读取禁止路径本身。
需要真实 API key 的 diag_live_*、smoke_live_* 由用户在受控环境手工决定是否运行;默认测试和工作 Agent 均不运行它们。
GUI 环境
离屏测试只验证结构和一般 Qt 行为,不算真机视觉证据。
Windows PowerShell:
$env:PYTHONIOENCODING = 'utf-8'
$env:QT_QPA_PLATFORM = 'offscreen'
python tests/smoke_offscreen.py
Linux:
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 聚合入口完成前,按影响范围选择下列现有命令。每项任务不要求机械运行所有命令;一个阶段结束时运行完整集合。
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 完成后
运行当前独立回归命令全集,加上:
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 完成后
优先运行新聚合入口:
python tests/run_all.py --group all
再单独运行三个诊断脚本;它们属于人工/半自动取证,不应混入默认聚合:
python tests/diag_render_scale.py 400
python tests/diag_panel_scrollbar.py
python tests/diag_rename_overlay.py
真实桌面矩阵
Windows 10/11 x64
至少覆盖以下路径:
- WebView2 首选路径:启动、发一轮对话、流式输出、附件、分支、切会话。
- QtWebEngine 强制回落:使用临时配置启动同一套基本流程。
- 同时启动两个 QtWebEngine 实例,证明 profile 不争用。
- WebView2 下打开改名遮罩,验证整个客户区覆盖;拖动、缩放、最大化和还原。
- Bash 面板三项以上任务,验证最新任务在顶部、状态保持和滚动条视觉。
- 截图全局热键在应用失焦时仍能捕获并进入附件流程。
证据必须标注实际后端。QtWebEngine 截图不能替代 WebView2 原生遮挡验收。
Ubuntu 22.04/24.04 x64 + X11
至少使用 Python 3.10--3.12 范围内一个受支持版本完成:
python main.py启动 QtWebEngine,渲染 Markdown、KaTeX、代码块和工具时间线。- 发一轮对话并执行 shell 工具,实际命令由
/bin/bash -lc执行。 - 超时和主动中止后检查父/孙进程均不存在。
- 双开应用,两个 QtWebEngine profile 不冲突。
- X11 原生全局截图热键在应用失焦时触发,截图进入附件流程。
- 消息窗口、Bash 排序与滚动条完成一次真机检查。
Ubuntu 22.04/24.04 x64 + Wayland
至少完成:
- QtWebEngine 正常启动并完成基本对话与渲染。
- portal/桌面协议请求有清晰的用户授权流程。
- 全局快捷键和截图通过 portal/桌面协议完成;若当前桌面协议不支持,界面明确报错,应用其余功能继续可用。
- 拒绝授权、portal 服务缺失和协议版本不足各记录一次结果。
- 普通用户启动保持 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 专属命令串。
最终判定
一项修复只有在以下内容齐全时才算完成:定向测试通过、阶段完整回归通过、该平台需要的真实桌面证据齐全、所有跳过项有理由、真实配置和数据库从未被测试访问。任何一项缺失都应标记为“未完成”而不是“基本完成”。