Files
UHD_Media_Tool/docs/plan/09-visual-qa.md
T
rootandClaude Opus 5.5 52402864d6 style(copy): punctuation rules and site-wide fix with a CI check (QA U11)
- glossary: 10 punctuation rules (full-width in Chinese, CJK/Latin spacing,
  full-width parens around Chinese, single ellipsis, 「」 quotes, period rules)
- scripts/check-copy-punctuation.mjs: checks string literals, templates and JSX
  text (not comments, types, keys, match/compare strings); --fix, --strict,
  --by-file; wired into deno task ci as check:copy in warn mode
- --fix applied to web, server and contracts; files other lanes were editing
  (subscriptions, sites, browser, agent, auth/account, inventory) left for them
- tests updated for the changed messages

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

207 lines
22 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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`)。
## W10 前端复核(未修项终态)
2026-09-28。前端项与 U3 在 W10 集成里处理,提交见 `docs/plan/08-v0.2-closeout.md`"W10 集成记录"。
| # | 状态 | 说明 |
| --- | --- | --- |
| U3 | 已修 | OutboxRelay 新增 `mirror`:`feed.*`(除 `feed.due`)、`decision.*`、`download.*`、`organization.*`、`subscription.*` 投递成功、认领事务提交后按顺序发到 SSE 总线,payload 原样(带业务 id);只镜像不路由的类型也会被认领并标记已投递(以前 `feed.fetched`、`organization.changed` 等一直停在 pending)。Feed 表收到 `feed.fetched` / `feed.health_changed` 刷新,任务流多听 Feed 与待处理事件。目前没有 `subscription.*` 事件 |
| U4 | 已修 | `lib/form-errors.ts`:保存失败 toast 写出第一处问题,滚到第一个 `aria-invalid` / `role=alert` 并聚焦;用在收录策略草案、设置分节、实例抽屉、订阅表单 |
| U5 | 已修 | `FormField` 加 4px 底距,说明文字与下一个标签至少隔 8px |
| U6 | 部分 | 页面底部原已留 `pb-24`;文件管理状态栏的"剩余空间"改为靠左。滚动途中悬浮按钮仍会暂时盖住右侧控件,属悬浮按钮的定位取舍 |
| U11 | 不改 | 代码与文档自 W1 起统一用半角 `,;:` + 句末全角 `。`,改成全角要先定全站规范并整体替换(数千条),单改几处只会更乱。留给文案规范决定 |
| U12 | 已修(FE-4) | 窄屏单击目录直接进入、长按多选;桌面保持单击选中、双击进入 |
| U13 | 已修 | `transferTargetProblem`:目标是源所在目录或在源目录之内时,移动 / 复制对话框直接提示,不发预览 |
| U14 | 已修 | 账户弹层用近实底材质 `pg-float-solid` |
| U15 | 已修 | 指标卡说明改为「含调查中、等你决定」 |
| U16 | 已修 | 手动指定 TMDB 的弹窗改用共享 Select,类型 / TMDB ID / 备注都有标签 |
文案清单前端项已改:「TMDB 已保存」等 toast 的中英文空格、API Key 小节标题改「已签发的 Key」、整天间隔显示「每 7 天」、「最高级别:提示」、「延后:已有计划在途」、失败记录的整理后路径显示「未生成目标路径」、上游模型列「默认模型」。
## v0.2.1 C1-C(U6 / U11 收尾)
| # | 状态 | 说明 |
| --- | --- | --- |
| U6 | 已修 | 悬浮按钮向下滚动时滑出右侧,向上滚动、滚到页底或回到顶部附近时回来(只看高度 ≥ 半屏的页面级滚动区域);键盘聚焦时照常显示。静止在页中时仍在右下角,底部 `pb-24` 与状态栏靠左保持不变 |
| U11 | 已修 | `docs/design/glossary.md`「标点」定 10 条规范;`scripts/check-copy-punctuation.mjs` 检查字符串字面量 / 模板 / JSX 文本(不看注释、类型、对象键、匹配与比较用的字符串),接入 `deno task ci`(`check:copy`,warn 模式);`--fix` 已对 web、server、contracts 执行。订阅、站点、浏览器、Agent、认证/账户、库存相关文件当时有并行改动,未改,留给各自收尾时 `--fix` |