Files
UHD_Media_Tool/docs/plan/09-visual-qa.md
T
rootandClaude Opus 5.5 2b8fe667a5 fix(organize,identity,sites,pi): W10-pre backend fixes from v0.2 visual QA
- slot: new manual_verify event (attention -> verifying, with reason); a
  successful organize of a download whose slot is in attention goes back
  through verifying and lands by verify_passed on the actually imported
  assets; the download's organize_blocked decision is resolved with
  resolution {key: manual_organize | organize_retry, organizationRecordId} (U1)
- acquisition: plan purpose is upgrade only when the slot already has a
  current asset; a movie slot gap is a fill (U7)
- identity: entities created from TMDB details get metadata fields projected
  in the same transaction; TMDB aliases deduped by normalized text, site-title
  aliases skipped when the text already exists (U9)
- pi: auth-mode test of a custom Base URL no longer marks the upstream ok, and
  says to use the minimal completion to probe the endpoint (U2)
- sites: PUT /sites/{id}/credentials replaces same-kind secrets in place and
  names new secrets with site id + random suffix (secret.name is unique; was a
  500 on update); M-Team user data uses config/definition apiBaseUrl instead
  of deriving api.<domain> from the site URL (Invalid URL on IP/local bases)
- copy: setup error says 初始化口令; backup job points at umt backup
- tests: schema expected tables add site_user_data; migration round-trip
  timeout 60s; fake secrets honor label as name; vertical/resolve/pi/slot/
  site-center tests for the above
- docs: 09-visual-qa W10-pre status table (U3 root cause: outbox events are
  never mirrored to SSE)

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 16:29:29 +08:00

19 KiB
Raw Blame History

v0.2 浏览器视觉与交互检查

2026-09-28。Playwright(chromium headless)逐页截图 + 走业务链。截图在 apps/web/test/screenshots/qa-v02/(不进 git),共 310 张。

环境

  • 独立 QA 栈:docker compose -p umtqa,127.0.0.1:4381,独立 .env(随机密钥)与 override;/media、/downloads 挂 /opt/umt-qa/*(属主 10001), 放 18 个假样片(电影 / 剧集 / 整季包目录 / 综艺 / 字幕随行 / 无关文件),视频用 truncate 做成 400 MB 稀疏文件(主视频下限 50 MB)。 用户的 umt 栈(4380)全程未动。
  • mock:testkit 的 qB / NexusPHP(观众,自定 5 条 + 默认 fixture)/ RSS / TMDB / Emby,跑在同一 compose 网络里的 denoland/deno 容器(umtqa-mocks)。 宿主 ufw 的 INPUT 策略是 drop,容器经 host.docker.internal / docker0 访问宿主端口不通,所以没按原计划把 mock 放宿主。
  • 镜像:先用 uhd-media-tool:v0.2.0-rc 检查;修复后以 83498f9 + 本轮改动 构建 uhd-media-tool:qa 替换 app 复测(见"CI 与并行开发")。
  • 视口:桌面 1440×900 明(d)/ 暗(dd),手机 390×844(m)。每页记录 console.error/warn、pageerror、失败请求、横向溢出(scrollWidth + 越界元素扫描)。

走过的流程

流程 结果
首次初始化(空提交 / 口令过短 / 两次密码不一致 / 口令错误)→ 登录 → 改密 → 登出 → 再登录 通过;改密时旧密码错误被踢回登录页(#1,已修)
错误密码限速(另一 X-Real-IP 连续 6 次) 第 5 次起 429「失败次数过多,15 分钟后再试」
设置 9 分区:自动化改检查间隔、库根 /media(哨兵)、路径映射 /downloads(校验)、qB 测试、Emby 测试、观众登记 + 改地址 + Cookie、TMDB key + Base URL、API Key 创建 / 撤销 全部成功
Agent 上游:fake 设默认 + 测试 + 最小补全;自定义兼容端点指向不存在地址;fake 订阅登录 browser(粘回 URL)与 device(自动批准)、退出登录 成功;错误提示问题见 #13、U2
定时任务:立即执行、停用 / 启用、运行记录 成功
Feed 新建 → 立即抓取 → 识别(5 条:4 条识别、1 条待识别)→ 站点工作台库存叠加 → 快照 成功;抓取后列表不自动刷新(U3)
收录策略草案(1080p 模板 + 新作品收录)→ 发布 → 订阅沙丘2 → 下载计划 / qB 任务 → mock 完成 → 自动整理 首次因样片 1 MB 被 too_small 拦下(测试数据问题);改 400 MB 后手动整理成功入库
待处理:待识别事项「手动指定 TMDB ID」(842675) 资源变为已识别
文件管理:浏览、重命名、新建目录、移动(预览 → 执行)、移入回收站、还原、批量整理向导(3 组 5 文件) 成功
Agent 会话:execute、plan_only、spawn 子会话 + await;抽屉 Ctrl+J 开关、Esc 关闭、焦点落输入框、FAB 状态 成功(自定义 fake 脚本后未匹配目标失败,见 U11)
引擎面板 runs / 详情;业务任务失败项重试 成功;引擎里没有失败 run,重跑按钮只看了详情页
审计列表 成功;动作名缺中文(#11,已修)
SSE 断线:页面打开时 docker restart umtqa-app-1 EventSource 3 次内重连,页面无报错;期间 /dashboard 一次 CONNECTION_RESET 属预期

检查矩阵

38 个路由 × 3 视口 = 114 张(文件名 M-<路由>-<d|dd|m>.png),修复后复测截图 V*。无横向溢出、无 pageerror、无非预期 4xx/5xx。 "问题"列指下方清单编号,✓ 为该视口未发现问题。

页面 d dd m 问题
登录 / 初始化 ✓ ✓ ✓ —
首页 问题 问题 ✓ #6 #17
待处理 问题 问题 问题 #5 #12 U15 U16
站点工作台 / 详情(整理视图、快照与 Feed、账号) 问题 ✓ 问题 #3 #15 U8
来源健康 问题 问题 问题 #3 U3
订阅 / 新建订阅 问题 ✓ ✓ #5
收录策略(草案 / 发布) 问题 问题 问题 #4 #5 U4
偏好标签 ✓ ✓ ✓ —
下载队列 / 详情 问题 问题 问题 #2 #6 #9 #14 U7
下载计划 问题 问题 问题 #10
业务任务 / 详情 问题 问题 问题 #5
媒体库 / 详情 问题 问题 问题 #8 U1 U9
整理记录 / 详情 问题 问题 问题 #5 #7
文件管理 / 回收站 / 向导 问题 ✓ 问题 #5 U6 U12 U13
身份与元数据 ✓ ✓ ✓ —
Agent 会话 / 详情 / 抽屉 ✓ ✓ ✓ U10
定时任务 ✓ ✓ ✓ 文案清单
设置·自动化 / 站点与账号 / 下载器 / 媒体库与目录 / 媒体服务器 / 元数据 ✓ ✓ 问题 U5 U6
设置·Agent 问题 问题 问题 #13 U2 U6
设置·API Key ✓ ✓ ✓ 文案清单
设置·账户与安全 问题 ✓ ✓ #1 U14
引擎面板 / 详情 ✓ ✓ ✓ —
审计日志 问题 问题 问题 #11
404 ✓ ✓ ✓ —

问题清单

共 34 项:已修 17、未修 17(另有文案清单 13 条,其中 3 条已随 #9/#5/#13 修掉)。

已修

# 严重度 页面 截图 现象 提交
1 高 设置·账户与安全 02-pwd-wrong-current-d.png → V01-pwd-wrong-current-d.png 改密时旧密码填错,服务端回 401,全局 401 处理当成会话失效直接跳登录页;开启二次验证填错验证码同样 0c0907a
2 中 下载详情·手动整理 45-dl-organize-preview-d.png、45-dl-organize-exec-d.png 预览显示「无法生成计划:source_size_mismatch」时「执行」仍可点,执行后生成一条「未关联作品 0/0」的失败整理记录 d7eb6a4
3 中 来源健康 / 站点详情(手机) M-sources-m.png → V12-sources-m.png Feed 表名称列 320px,健康、启停、立即抓取被挤出屏幕,只能横滑发现 d7eb6a4
4 中 收录策略·新建草案 40-policy-new-d.png、40-rules-err.png 策略键只有占位符 default,看起来像已填;保存只弹「表单有错误」 46d37d8(预填 default)
5 中 策略版本、订阅、待处理、业务任务、整理记录、回收站 40-policy-published-d.png、87-task-retried-d.png、64-trash-d.png 操作者显示 admin_session:<uuid>、user:<uuid>、system 46d37d8
6 中 下载队列、首页缓存水位 42-downloads-d.png → V04-downloads-volume-d.png 没填缓存卷标识时显示 instance:<uuid> 46d37d8(显示下载器名)
7 中 整理记录详情 43-organize_4bedfb53-…-d.png → V03-organize-reason-d.png 失败原因 blocked:no_main_video(blocked) 46d37d8(取冲突说明「没有可入库的主视频」)
8 中 媒体库详情·版本目标 47-library_…-d.png 原因显示 blocked:no_main_video、deferred:slot_busy;inflight:<uuid> 46d37d8
9 低 下载详情 44-downloads_…-d.png 时间线「提交下载:succeeded」「复制:failed」,用途 upgrade,说明 added 46d37d8
10 低 下载计划 M-downloads_plans-m.png → V07-plans-d.png 「优先级 new_work / upgrade」,说明 organize:succeeded 46d37d8
11 低 审计日志 M-audit-m.png → V08-audit-d.png capability.invoke、files.*、site.*、feed_source.created 等无中文 46d37d8
12 低 待处理·待识别 42-inbox-d.png 摘要「没有匹配的作品(no_viable_candidate)」 46d37d8(新开事项生效)
13 低 设置·Agent 上游测试 72-custom-completion-fail-d.png 端点不存在时显示「失败 · Connection error.」,没归到「网络错误」也没说怎么办;凭证来源 stored credential 46d37d8
14 低 手动整理预览 46-dl-organize-preview-ok-d.png 徽章 copy / transfer、文件类型 video d7eb6a4
15 低 站点详情·库存叠加 M-sites_…-m.png 候选标签 1080p:deferred 46d37d8
16 低 全站弹窗 / 抽屉 — 关闭按钮读屏文本 Close、面包屑 More 46d37d8
17 低 首页·最近产出 92-home-after-restart-3s-d.png 无作品的记录显示「未命名」,与整理记录页「未关联作品」不一致 46d37d8

未修

# 严重度 页面 截图 现象 原因
U1 中 媒体库详情 47-library_f020597a-…-d.png、V09-library-slot-d.png 自动整理被拦(版本目标进 attention)后,从下载详情手动整理成功入库、资产已核验,版本目标仍「需处理」、当前资产「无」 设计取舍:transitionWithInflight 对静止态 attention 拒绝 verify_passed("可能已被人工处理")。要么放行 attention→verify_passed,要么手动整理成功时自动解决对应「整理冲突」事项,需要定
U2 中 设置·Agent 上游 V11-pi-test-network-hint-d.png Base URL 不存在,「测试」仍「通过」并把状态改成「可用」;只有「最小补全」会连端点 测试语义设计(只查凭证和模型,不产生费用);建议测试结果不改写可用状态,或给自定义端点做一次 /models 探测
U3 中 来源健康 / 站点详情 90-sse-after-event-d.png 点「立即抓取」后,抓取任务完成不发 SSE 事件,列表只在请求返回那一刻刷新一次;worker 慢时一直显示旧的「最后成功」 需要新事件(如 source.feed_fetched)+ 前端失效,超出本轮
U4 低 收录策略草案 40-policy-saved-d.png 保存失败只弹「表单有错误」,不指明字段、不滚动到错误处(长表单里看不到) 需要表单级错误定位,改动面大
U5 低 设置各分区表单 10-empty-settings_agent-d.png 带说明文字的字段,说明与下一个字段标签只隔 4px,节奏不齐 FormField 间距属设计取舍
U6 低 全站(手机更明显) M-settings_agent-m.png、60-files-d.png 右下 Agent FAB 盖住右对齐开关、文件管理页脚「剩余空间」 FAB 定位设计取舍
U7 低 下载计划 / 详情 44-downloads_…-d.png 新作品首次下载的计划用途是「升级」、时间线写「创建下载计划(升级)」 业务逻辑待查
U8 低 站点详情 32-site-detail-d.png 所有资源都是「H&R 未知」,fixture 里标了 H&R 的也一样 适配器 / mock 选择器待查
U9 低 媒体库详情·元数据 47-library_…-d.png TMDB 已识别,元数据各字段仍「未提供」;别名重复(沙丘2 ×2、Dune: Part Two ×3) 数据层待查
U10 低 Agent 83-agent-run-execute-d.png 配了自定义 fake 脚本后,不匹配的目标直接失败「assistant_error: no fake script matched」,内置演示脚本不再兜底 fake 仅用于演示,行为与 runbook 一致
U11 低 全站说明文字 多处 中文句子里混用半角 ,;: 与全角 。(如「停用后不再访问该站点,也不产生新候选;…」「账号:未验证」) 全站文案规范问题,留给文案轮
U12 低 文件管理 61-files-incoming-d.png 单击目录只选中,双击才进入;手机上不便 交互设计取舍
U13 低 文件管理·移动到… 63-move-preview-d.png 目标树点到源所在目录即自动预览,返回 400 并在控制台报错 预期校验,但应在前端先拦
U14 低 账户弹层 02-account-menu-d.png 浮层透明度高,底下的「实时」「暂停自动化」透出 材质设计取舍
U15 低 待处理(手机) M-inbox-m.png 指标卡说明「待处理 + 调查中 + 等你决定」被截断 文案可缩短
U16 低 身份指定弹窗 50-inbox-assign-dialog-d.png 类型用原生 <select>,输入框只有占位符没有标签 组件统一待做
U17 低 健康检查 — v0.2.0-rc 镜像 /health 报 version: 0.1.0 当前 main 已有 chore(release): v0.2.0,下次构建复核

文案问题清单

位置 现状 建议
下载详情·计划 用途 upgrade、说明 added 已修:升级 / 已添加到下载器
业务任务·触发 user:<uuid> 已修:管理员
上游测试 Connection error. 已修:「连不上上游,检查 Base URL、端口和网络。原始错误:…」
元数据保存 toast 「TMDB已保存」 「TMDB 已保存」(中英文之间空格)
设置·API Key 分区标题「API Key / 签发给外部程序的 Key」下小节又是「API Key / 签发给外部程序(…)的 Key」 删掉一处
定时任务 「每 168 小时」 「每 7 天」
定时任务·备份 「目前由 scripts/backup.sh 在宿主机执行」 与 runbook 的 umt backup 对齐
初始化页 字段叫「初始化口令」,服务端报错「setup token 无效」 统一一个词
待处理指标 「最高 提示」 「最高级别:提示」
版本目标 「延后(单元在途)」 「延后:已有计划在途」
整理记录详情 「整理后 · 库根相对 / 未知或未授权」 失败记录直接写「未生成目标路径」
Agent 上游列表 模型列「provider 默认」 「默认模型」
全站 半角 ,;: 混在中文句子里 见 U11

CI 与并行开发

  • 检查期间 main 上有另一路开发在提交(W9 站点中心、命名模板等),工作区还有大量未提交改动。当前 main 的 deno task ci 在本轮之前就是红的: instances-routes.ts 的 SiteCredentialsPut 类型错误、release-fields.ts 缺 challenge、api-registry 端点未实现等,都不在本轮改动里。
  • 本轮只提交自己的改动,用临时 index 按块提交(organize.ts 里只含本轮 7 行,对方未提交的命名改动未带入),提交后把真实 index 对应路径同步到新 HEAD。
  • 验证:在 83498f9(本轮开始时的 HEAD)+ 本轮改动的独立 worktree 跑 deno task ci:typecheck、lint、check:tokens、build 全过; 测试 server 275 通过,2 个文件因与并行开发共用开发库(55433)的 schema 被对方删掉而失败,单独重跑通过;tasks 的崩溃恢复用例同理重跑通过。 用这份代码构建的 uhd-media-tool:qa 在 QA 栈复测了 #1–#17。

值得一看的 5 张截图

  1. apps/web/test/screenshots/qa-v02/47-library_f020597a-d1f5-4ca0-8d16-81b974ad1960-d.png:手动整理成功后版本目标仍「需处理」(U1)
  2. apps/web/test/screenshots/qa-v02/83-agent-run-spawn-d.png:fake 模型派生子会话 + await,会话树合计与系统核实
  3. apps/web/test/screenshots/qa-v02/66-organize-wizard-1-d.png:批量整理向导识别步骤(整季包 + 电影 + 待选作品)
  4. apps/web/test/screenshots/qa-v02/45-dl-organize-exec-d.png:预览失败仍能执行产生的失败记录(#2,已修)
  5. apps/web/test/screenshots/qa-v02/V11-pi-test-network-hint-d.png:不存在的端点「测试」通过、状态变「可用」(U2)

W10-pre 后端复核(未修项状态)

2026-09-28。只改后端;前端项留给前端波。验证:HEAD + 本轮改动的独立 worktree 跑 deno task ci。

# 归属 状态 说明
U1 后端 已修 协调者拍板:状态机新增 manual_verify(attention → verifying,带原因)。下载任务的整理成功入库时,Slot 若是 attention 先回核验,再由 verify_passed 按实际入库资产落 satisfied / empty(部分覆盖);同一下载任务的「整理冲突 / 做种义务阻止移动」事项(organize_blocked:<下载任务>)自动 resolved,resolution = { key: "manual_organize", organizationRecordId, by },自动重试成功记 organize_retry。纵切测试覆盖
U2 后端 已修 自定义 Base URL(非 OAuth)的「测试」只核对凭证和模型,不再把状态改成「可用」、不记核验时间,返回提示「没有连接 Base URL;用「最小补全」确认端点可达」。前端直接显示 message 即可
U3 后端 + 前端 未修,需定 根因比报告写的大:ctx.outbox.emit 写的事件(feed.fetched、decision.*、download.status_changed、organization.changed 等)只进 outbox 路由成任务,没有任何一条镜像到 SSE 总线;浏览器只收得到直接 ctx.events.publish 的事件(agent、settings、files、schedule、heartbeat)。首页订阅的这些类型实际从未到达。要补一个 outbox → SSE 的桥(提交后可见、顺序与裁剪策略),属于设计改动,超出本轮。桥接好后前端来源健康 / 站点详情订阅 feed.fetched 失效列表
U4 前端 未修 表单级错误定位
U5 前端 未修 FormField 间距
U6 前端 未修 FAB 定位
U7 后端 已修 电影 Slot 缺口的 mode 仍记 upgrade(determineMode 的 slot_gap),但计划用途只在 Slot 已有当前资产时才是「升级」,否则「补缺」;时间线随之显示「创建下载计划(补缺)」
U8 后端 不改 观众站定义(照搬 MP 的 audiences.json)没有 hr 选择器,H&R 三态按设计为 unknown;mock 页面上的 hitandrun 标记不会被读取。要补选择器需先在真实站点核对
U9 后端 已修 按 TMDB 建档(自动识别 / 手动指定 / 按候选建)时同事务写入 TMDB 字段并投影,不再等下一次刷新(不记 last_metadata_refresh_at,剧集季总集数仍由首次刷新补);别名按规范化文本去重(TMDB 译名/别名列表与主标题、原名重复的不再登记,站点标题与已有别名同文本时也不登记)。已有数据里的重复别名不回溯清理
U10 后端 不改 fake 仅用于演示,行为与 runbook 一致
U11 前端 / 文案 未修 全站标点规范
U12 前端 未修 文件管理单击进入
U13 前端 未修 移动目标树先拦「目标 = 源所在目录」
U14 前端 未修 浮层材质
U15 前端 未修 指标卡文案缩短
U16 前端 未修 身份指定弹窗 select / 标签
U17 后端 已核 /health 与 /system/health 都读 apps/server/deno.json,当前为 0.2.0;rc 镜像构建早于版本号提交,下次构建复核

文案清单里的后端项已改:服务端初始化报错改为「初始化口令无效…」(与页面字段同词);定时任务「备份」说明改为「目前用 umt backup(宿主机 cron 调用)」。其余文案(TMDB 空格、API Key 重复小节、「每 7 天」、「最高级别:提示」、「延后:已有计划在途」、失败记录「未生成目标路径」、「默认模型」)在前端。

其他:packages/db/test/schema.test.ts 补 site_user_data(0031),迁移往返用例超时放宽到 60s(35 个迁移 down/up 在共用开发库上超过默认 5s);db-sync 在 HEAD 上已齐。迁移 0031–0035 连续无冲突(0017 历史上空缺,迁移器按文件名排序,不影响);0035 仍是 W9-E 未提交改动,types.ts 已含其列。

前端联调追加的两条站点中心后端 bug(同一提交修):

  • PUT /sites/{id}/credentials 更新已有账号凭证 500:secret 名 site_account:<label> 撞 secret.name 唯一约束(各站点都有 default,换凭证时新 secret 与旧 secret 同名)。改为同账号同类凭证(主凭证 / passkey / TOTP)原地 replace,需要新建时名字带站点 id 与随机后缀;会话 Cookie、POST /site-accounts 同样处理。测试夹具的 fake secret 现在按 label 落 name,能复现唯一约束。
  • 馒头刷新登录 "Invalid URL":用户数据解析器在没有 config.apiBaseUrl 时按站点地址推 https://api.<根域>,站点地址是 IP / 本地 mock 时拼成非法 URL。改为与适配器一致:站点配置 > 定义里的 apiBaseUrl(https://api.m-team.cc)。