Files
Haocode/docs/agent-handoff/VERIFICATION.md
T
sorrow404null bc0b92bcdc 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.
2026-09-17 16:40:06 +08:00

11 KiB
Raw Blame History

验证与取证规范

本文定义修复任务的统一验证口径。任务范围和完成条件见 REPAIR_BACKLOG.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

$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.pypython tests/test_error_persist.pypython tests/smoke_bash_panel.pytest_agent_core(经 python tests/run_tests.py 运行) 打开路径拦截记录只含临时目录
P0-02 eventFilter python tests/test_main_window_event_filter.pypython tests/smoke_offscreen.pypython tests/smoke_mode.py Enter/Shift+Enter 行为记录
P0-03 文档 文档链接检查与 rg 检查 AGENTS.md 演练一次读取路径
P1-01 渲染窗口 node tests/test_render_window.jspython tests/diag_render_scale.py 400;相关 Qt smoke 400 条固定夹具、锚点误差、帧时间报告
P1-02 shell python tests/test_cross_platform_shell.pypython tests/test_bash_stream.pypython tests/test_tool_params.py 两平台进程树消失证明
P1-03 渲染器 python tests/test_wv2_guard.pypython tests/smoke_offscreen.pynode 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.pypython tests/test_bash_stream.py 重排前后状态与滚动位置
P2-02 滚动条 python tests/diag_panel_scrollbar.pypython tests/smoke_bash_panel.py Windows/Linux 局部截图和尺寸
P2-03 遮罩 python tests/diag_rename_overlay.pypython 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。至少覆盖:

  • automanual 两种模式;
  • 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

至少覆盖以下路径:

  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 到同一进程;
  • 为每个子进程建立独立临时环境;
  • 支持至少 logicoffscreenall 三组;
  • 汇总命令、退出码、耗时和 PASS/FAIL/SKIP
  • 默认排除 live、diag、verify、tune、网络和凭据测试;
  • 一个子进程失败后继续收集其余结果,最终返回非零;
  • 在 Windows 和 Linux 使用同一 Python 接口,不嵌入 .bat 或 Bash 专属命令串。

最终判定

一项修复只有在以下内容齐全时才算完成:定向测试通过、阶段完整回归通过、该平台需要的真实桌面证据齐全、所有跳过项有理由、真实配置和数据库从未被测试访问。任何一项缺失都应标记为“未完成”而不是“基本完成”。