Files
UHD_Media_Tool/CHANGELOG.md
T
rootandClaude Opus 5.5 ed083fd138 feat(subscriptions): 按 MP 收敛订阅默认值与表单
- 定时主动搜索默认关(DEFAULT_SEARCH_INTERVAL_HOURS = 0),新建 / 手动照常各搜一次,之后靠 RSS 与站点快照
- 多版本自动补全系统缺省改为关
- 表单:基础页 = 作品与范围、下载、洗版;收录版本、优先级、自动补全折叠到进阶页「多版本」
- 对照文档 §7.3 记录落实范围

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-02 22:34:48 +08:00

612 lines
67 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.
# Changelog
版本号遵循 [SemVer](https://semver.org/lang/zh-CN/)。所有成员包(`apps/*`、`packages/*`)与根 `deno.json` 使用同一个版本号;`/api/v1/health` 与备份清单里的版本取自 `apps/server/deno.json`。
## [Unreleased]
### 修复
- OurBits 详情页:简介是页面里未渲染的 BBCode(站点靠前端脚本渲染),之前原样显示 `[quote]`、`[img]` 且换行全丢;改为按 BBCode 解析,保留换行、去掉标记,图片进截图,引用块里的 MediaInfo 单独取;文件列表按需取 `viewfilelist.php`。已缓存的详情在过期或手动刷新后生效。
### 调整(订阅,对照 MP)
- 定时主动搜索默认关闭:新建与手动搜索照常各搜一次,之后靠 RSS 与站点最新资源追更;需要时在订阅里填搜索间隔。没填过间隔的旧订阅也随之不再定时搜。
- 多版本自动补全默认关闭(订阅或规则组显式打开仍生效)。
- 订阅表单收敛:基础页只留作品与范围、下载、洗版;收录版本、优先级、自动补全折叠到进阶页的「多版本」。
### 新增
- 下载器可以单独设水位(硬阈值 / 恢复水位 / 清理目标)和保种天数,不填用全局;多个下载器共用一块缓存盘时取最严格的。公网 BT 专用的 qB 可设保种 0 天(站点 H&R 仍遵守)。
- 内置公开 BT 站:Nyaa、蜜柑计划、AniBT、AnimeGarden(聚合动漫花园 / 蜜柑 / ANi 等)、萌番组。添加站点 → 公开 BT 站里一键添加,不需要账号;支持资源搜索、定时抓最新资源、按资源 ID 取种子或磁力(蜜柑取剧集页的种子,AnimeGarden 只有磁力)。默认不进资源搜索的默认站点集合;萌番组部分网络直连不通,打开站点的「代理」即可。原来手填 RSS 的方式保留。
- 豆瓣 / bgm.tv 辅助信息源(照 MP 的做法,身份仍以 TMDB 为准):
- 识别:资源只有豆瓣 ID 时,本地缓存没有该条目会在线查一次豆瓣(移动版接口),按中文名 / 又名 + 年份匹配 TMDB;AniBT 资源带的 bgm 条目 ID、公开 BT 站上认不出的番剧标题,走 bgm.tv 条目(第二季等季条目去掉季名与年份)再匹配 TMDB。条目缓存 30 天,查不到 6 小时内不重查。
- 新增「发现」页(获取 → 发现):bgm.tv 每日放送、豆瓣实时热门电影 / 剧集;点条目自动匹配 TMDB 作品进作品页(可订阅、搜资源),不确定时列候选。
## [0.3.16] - 2026-10-02
### 新增
- 多下载器路由(照 MP):下载器的名称作为别名;可设一个默认下载器;站点可指定下载器。选择顺序:订阅 / 手动明确指定 > 站点指定 > 默认 > 第一个可用;站点指定的停用时回落默认,明确指定的不可用时不悄悄换。迁移 `0063_downloader_routing`。
### 修复(站点适配,2026-10-02 真实账号列表页核对)
- OurBits:标题列嵌套表格让大小、发布时间取错(大小全为 0),改为只匹配行的直接子单元格;副标题原先取成了标签,改为取标签之后的正文;新增标签与列表页 IMDb / 豆瓣 ID。
- 彩虹岛:副标题前混入的标签与末尾徽标去掉,标签单独取。
- 憨憨:新增列表标签。
- 站点给出纯数字 IMDb ID 时补成 `tt` + 7 位。
## [0.3.15] - 2026-10-02
### 修复
- 整理后自动刮削照 MP:按作品目录刮(剧集根目录 tvshow.nfo / 海报 / 季海报、季目录 season.nfo 照常初始化),集只刮本次整理的文件;同一目录还没开始的刮削合成一批。此前原地入库逐文件刮,剧集根目录与季目录没有元数据。迁移 `0062_scrape_record_videos`,刮削记录新增 `videos`。
- 站点卡片、列表、登录结果、站点概况不再单独显示 VIP 标签(等级里已经体现,各站 VIP 判定也不一致)。
### 工程
- `deno task test:all`:逐包跑完再汇总,连不上测试库直接失败(不再让数据库用例静默跳过);`deno task ci` 改用它。
- `deno task dev:up`:起开发库并迁移到最新。开发 API 端口改为 4390(4380 留给本机部署版)。
- `deno task release`(`scripts/release.sh`):要求工作区干净与 CHANGELOG 条目,打 tag、构建、只替换 app、核对健康版本。
## [0.3.14] - 2026-10-02
v0.3.8~v0.3.13 当时由未提交的工作区构建部署,源码在本版统一提交(`ceb66f8`)。各版细节见 `18-organize-release`(已删除,见 git `ceb66f8`)。
### 新增
- 原地入库:已登记媒体库内的文件保留位置与名称登记为资产(视频、字幕、季集覆盖、版本),不复制 / 移动;可选只刮削本次成功的主视频。迁移 `0061_organize_in_place`。
### 修复
- 识别升级链只在结果更确定时采用,不再用无匹配顶替原有歧义候选(歧义事项照常开)。
- 刮削入队:重放去重时不再返回已删除的记录;任务已入队但关联写回失败时保持排队,由处理器补关联。
- `bluray_dir` 资产以原盘目录本身为刮削根。
- 通知铃铛弹层与用户菜单统一样式;站点卡片共用卡头、底栏贴底,分页不贴卡片。
## [0.3.13] - 2026-10-02
### 变更
- 手动、文件管理、下载详情、历史重整共用一个整理弹窗(电影 / 剧集、TMDB 搜索或 ID、来源配置、复制 / 移动、目标路径、本次刮削、预览),只「加入整理队列」。整理页分队列与记录。
- 成功历史跳过对齐 MP;成功移动的记录从媒体库目标重整。
## [0.3.12] - 2026-10-02
### 新增
- 列表统一分页(10 / 20 / 50 / 100 条,默认 50,记住选择;游标接口按需拉取)。
- 搜索历史(按账号保存最近 30 个关键词,搜索页与 Ctrl / ⌘ K 共用)。
- 首页存储与下载器概况卡。
## [0.3.11] - 2026-10-01
### 新增
- 搜索结果标题可点开资源详情抽屉(与站点工作台同一实现),关闭后保留搜索词、筛选与分页。
### 修复
- 原站视图桌面窗口未最大化导致的上下黑边(浏览器镜像 `1.18.0-umt.1`)。
## [0.3.10] - 2026-10-01
### 新增
- 独立手动下载、串流外详情页资源下载;TMDB / Local 元数据兜底(`metadata.resolve_organize`);正常多版本与一次性洗版。迁移 `0060_manual_acquisition`。
## [0.3.9] - 2026-10-01
### 新增
- 分类规则、整理来源与持久目录快照、手动存量整理、文件管理整理入口。迁移 `0059_organize_source_snapshot`。
## [0.3.8] - 2026-10-01
### 变更
- 全面依赖升级:workspace 直接依赖到当时 latest(Router 8、Vite 8、TypeScript 7 等)、camofox 1.18.0 / Node 24、PostgreSQL 16 → 18.6、备份客户端 18.6、演示 qB 5.2.4。见 `17-full-upgrade`(已删除,见 git `ceb66f8`)。
## [0.3.7] - 2026-10-01
### 新增(HIS-1 整理记录对齐 MP 历史记录页)
- 列表加海报、源 → 目标路径、大小、下载器名称;成功不再加徽章,失败 / 部分成功带一句原因。
- 筛选新增类型(电影 / 剧集 / 未识别)与时间(今天 / 7 天 / 30 天);关键字支持 `*` `?` 通配,并能搜文件名与种子 hash;筛选写进地址栏。
- 列表上方按状态计数(只列非零项,点一下筛选);「按作品分组」。
- 删除记录:可选同时删除源文件、媒体库里的文件(移入回收站,可还原;已入库文件同时从媒体库移除;下载器任务不动)。确认框先核对,写清删几个文件、多大、哪些删不了、哪些下载会被重新自动整理。
- 批量:选择 / 全选、批量删除、批量重新整理(选中记录的源文件一起进整理向导)。行菜单:查看详情、重新整理、让智能体排查、只看这个作品、删除。
- 详情加海报、大小、下载任务与删除;种子 hash 在「技术信息」。
- 接口:`GET /organization-records/stats`、`POST /organization-records/delete`;列表查询新增 `kind`、`since`、`organizeOnly`;公开记录新增 `media.posterPath`、`sizeBytes`、`download`(只加字段)。MP 功能对照表见 `docs/runbook/organize.md`。
### 变更(SCR-2 刮削照 MP 简化:在目录里就地刮削)
- 文件管理里任意视频文件或目录都能「刮削…」(右键 / ⋯ 菜单、多选批量栏、详情),不要求先整理入库:服务端按路径识别作品(目录里已入库的直接用;没入库的按文件名与目录名查本地作品和 TMDB),在该目录里就地写 NFO 和图片。剧集目录递归到季目录与每集,季目录只写季与各集,单集文件只写该集,电影目录写每个视频的 NFO 与目录海报,蓝光原盘目录写 `<目录名>.nfo`。
- 认不准作品时对话框列出候选(可搜索),选一个后「继续刮削」;可打开「同时加入媒体库」,不打开也能刮削(直接用 TMDB 字段)。覆盖方式缺省按设置,对话框里可临时选「只补缺失 / 全部覆盖」。多选时逐项识别。
- 作品详情「重新刮削」「覆盖重写」与入库后自动刮削改为对作品目录刮削,和文件管理同一实现。
- 刮削记录简化为每次一条(目录、识别结果、写了哪些文件、跳过原因),作品详情显示该作品最近一条。去掉"只有已入库作品才能刮削"的限制;「刷新元数据」不再要求有已入库文件。
- 与 MP 的文件布局差分:用 MP `ScrapingChain.scrape_metadata` 的真实决策代码跑同一组目录对照 7 个场景,只有 3 处登记偏离(不写 backdrop.jpg 副本、剧照 `-thumb.jpg`、根下电影图片带视频名)。见 `docs/runbook/scrape.md`「与 MP 的差分」。
- 接口:`POST /files/scrape` 改为 `{items[{root,path,mediaEntityId?,external?}], mode?, addToLibrary?}` → `{records, needsChoice, skipped, pending, entities}`;新增 `GET /files/scrape-records?ids=`;`POST /files/scrape-batch` 去掉 `write`(只刷新元数据);`POST /library/{id}/scrape` 返回 `recordIds`;`GET /library/{id}` 的 `scrape` 改为刮削记录(带 `root` / `path` / `match`)。任务 `scrapeMedia` 升到 v2(输入 `{recordId}`)。迁移 `0058_scrape_record`(替代 `media_scrape`)。
### 新增(ID-3 用站点详情页的 ID 识别资源)
- 识别升级链:标题认不准(有歧义 / 没结果)时,资源有站点详情页且还没抓过,就抓一次详情(走详情缓存与站点限流,失败不影响识别)取 IMDb / TMDB / 豆瓣 ID,再按 ID 查 TMDB 确认作品;确认后照常回填资源、登记别名(守卫照旧)、关闭同资源的待识别项。
- 只在搜索结果、订阅相关的资源、池条目补全前、手动重新识别时抓;RSS 批量入库不抓(订阅相关的推迟到复查)。每站每小时上限可在设置 → 元数据 → 资源识别里调(缺省 10,0 = 不抓)。
- 站点给出的 IMDb / TMDB ID 作为强证据参与打分:标题对不上也能自动确认;年份或类型冲突时只作候选(与 MP 的差别登记在差分组 `site-ids-*`)。
- 详情只有豆瓣 ID 时,用缓存的豆瓣条目(来自站点详情页的豆瓣信息块或元数据补全的搜索摘要,不请求豆瓣)按标题 + 年份匹配 TMDB。
- 观众列表页的豆瓣链接抽成 `doubanId`(新增 UMT 扩展字段 `torrents.fields.doubanid`)。
### 变更
- 能从站点拿到 ID 的资源不再开「没识别出作品」事项;升级链还在排队(每站每小时限额已满)时不开事项、15 分钟内复查;已开的事项在资源被识别后自动关闭。
## [0.3.6] - 2026-09-30
### 新增(SEARCH-4 资源筛选对齐 MP)
- 搜索结果与站点资源的快速筛选新增 8 个维度:音频编码、字幕(中文 / 简体 / 繁体 / 英文…)、配音(国语 / 粤语)、特性(10bit / 50 帧以上 / 特别剪辑版)、年份、分类、大小分档、做种分档,都带计数、可多选、可组合。
- 筛选条顺序照 MP(站点、季/集、促销、编码、质量、HDR、分辨率、制作组),其余维度收进「更多筛选」(桌面宽弹层、手机抽屉)。原「版本」改叫「质量」。
- 解析器补「配音语言」字段(`audioLangs`:国语 / 粤语 / 英语)。
- MP 维度对照表见 `docs/runbook/search.md`「与 MP 的对照」。
### 变更
- 全站弹层、下拉选择、下拉菜单、对话框、抽屉改为不透明实底(不再半透明 + 背景模糊),文字压在列表上也看得清。
- 站点资源 Tab 的「做种」「大小」下拉(只筛已加载的结果)换成快速筛选里的分档,按全部本地资源计数和筛选。
## [0.3.5] - 2026-09-30
### 新增(SCR-1 刮削:NFO 与图片写进媒体库目录)
- 整理入库成功后可自动刮削:按作品写 NFO(电影 `<视频名>.nfo`,剧集 `tvshow.nfo` / 季目录 `season.nfo` / 每集 `<视频名>.nfo`,UTF-8、临时文件 + 改名原子写入),下载海报 `poster.jpg`、背景图 `fanart.jpg`、季海报(作品目录 `season01-poster.jpg` + 季目录 `poster.jpg`)和剧照 `<视频名>-thumb.jpg`。Emby、Jellyfin、Kodi 都能识别。元素与 MP `TmdbScraper` 对照(差分见 `apps/server/test/scrape/`),缺值不写。
- 设置 → 媒体库与目录 →「刮削」:入库后自动刮削(缺省关,同 MP)、已有文件「只补缺失 / 全部覆盖」、下载图片、下载剧照。
- 作品详情新增「刮削」:上次刮削时间、写了哪些文件、失败原因,「重新刮削」「覆盖重写」;文件管理菜单与详情新增「刮削」(与「刷新元数据」分开)。三处都排同一个后台任务 `scrapeMedia`(文件道),图片经图片缓存与出口代理下载、并发 4,失败只记该文件,不影响 NFO。
- 接口:`POST /library/{id}/scrape`、`GET /library/{id}` 的 `scrape`;`POST /files/scrape` 的 `writeNfo` / `images` 不再返回 `not_implemented`(排 `scrapeMedia`,返回 `queued`);`POST /files/scrape-batch` 新增 `write`。迁移 `0057_media_scrape`。见 `docs/runbook/scrape.md`。
### 新增(CF-2 Cloudflare 验证处理)
- 站点请求遇 Cloudflare 挑战(`cf-mitigated: challenge`,或 403 / 503 / 429 的挑战页)不再算凭据错误:不置账号失效、不开「登录失效」事项、不排自动重登;503 挑战不再算维护;健康检测记「需要人机验证」。
- 过挑战级联(只处理有登录态账号的站点;同站 30 分钟最多一次、同一时刻只处理一次;不接打码服务):浏览器用该账号的 profile 打开同一地址 → 等它自己过(≤ 15 秒)→ 「我是人类」复选框 / Turnstile 由系统发起视觉子流程点一下(最多 2 次,预算取设置,自动化总开关关闭时跳过)→ 选图 / 输码类转人工,待处理事项「<站点>需要你在原站视图里过一次验证」,接管过完交还即继续。
- 过了之后读回 `cf_clearance` 与浏览器 UA:账号 UA 跟随浏览器且两端出口一致时交给 HTTP(`__cf_bm` 仍不带),重试 1 次,按站点记复用是否有效;仍被挑战时这次页面请求改由浏览器导航取 HTML 交给原解析器,之后 6 小时该站页面请求直接走浏览器,到期再试 HTTP。
- 站点卡片 / 概览显示「Cloudflare:自动通过 / 浏览器代理中,至 hh:mm / 需要你验证」,原始记录进技术信息。
- camofox 插件新端点 `POST /umt/tabs/{tabId}/mouse-click`:`click_at` 发真实鼠标事件,跨域 iframe 里的 Turnstile 也点得到(需要重建 camofox 镜像)。
### 变更(CF-2 出口统一)
- 站点请求(适配器、RSS、登录、用户数据)不再隐式继承容器的 `HTTP(S)_PROXY`:站点没开代理明确直连,开了走站点 / 全局代理,与浏览器会话同一出口。TMDB、Brave、图片缓存等外网请求照旧按环境变量走代理,改为代码里显式指定。出口表见 `docs/runbook/sites.md`「出口」。
## [0.3.4] - 2026-09-30
## [0.3.3] - 2026-09-30
### 变更(MD-2 简介不回退英文)
- 作品、季、集的简介(以及作品标语)只回退到中文变体(缺省链 zh-CN → zh-SG → zh-TW → zh-HK),不再回退到 en-US;都没有就留空。标题、别名仍按完整回退链(可到 en-US)。排在第一个中文之前的语言照常用,链里没有中文时按原链。对照 MP:每集信息只按配置语言取,简介为空就为空。
- 设置 → 元数据 → TMDB 新增「简介回退到非中文」(`metadata.overviewNonChineseFallback`,缺省关),打开后恢复旧行为。
- 媒体详情:作品和每集没有简介时显示一行小字「暂无简介」。已有的英文简介在下次刷新时按新规则清掉。
- 存量重算脚本 `scripts/overview-recompute.ts`:找出语言不在简介链里的作品 / 季 / 集简介,不请求 TMDB,只用 `kv_cache` 里缓存的 TMDB 响应按新规则重算(缓存已淘汰的直接清空);缺省 dry-run,`--apply` 写库。见 `docs/runbook/metadata.md`「存量简介重算(MD-2)」。
### 变更(AG-4 智能体与浏览器零碎问题)
- 子会话系统提示与父会话一样要求思考、步骤说明和汇报都用中文(目标、工具结果是英文也一样)。
- `agent.spawn` 同目标去重:同一父会话里同一目标的子会话还在运行或 10 分钟内已完成时不再新建,返回已有子会话与结果摘要(`reused: true`)。
- 浏览器会话保活:桌面连接、人工接管、智能体会话正在用的会话每 2 分钟做一次只读调用(`BROWSER_KEEPALIVE_MS`,0 = 关闭),不再被 camofox 空闲 5 分钟回收;用完照常回收,保活时标签页已被回收按 BR-3 自愈重连。
- 会话页:概况条上方恒定一行会话统计(工具调用、MCP、已用 token、距上限剩余、费用);本轮进行中显示「思考中 · 已调用 N 次工具」,结束后并入进度行;汇报兜底不再列「换掉的标识」,原始汇报只在技术信息「原文」里。
### 新增(META-2 短剧元数据补全扩大来源)
- 元数据补全按来源分类抽取:百科(百度 / 搜狗 / 快懂百科、维基)、平台作品页(红果短剧、河马剧场、各视频平台)、豆瓣(只用搜索摘要,不读页面)、其它网站的搜索摘要(摘要模式:只看搜索引擎给的摘要,不打开聚合站网页)。每类来源一个抽取器(标题 / 别名、年份、集数、主演、简介、类型、平台、海报),每个字段带来源类别与置信度,多个网站给出同一值时叠加置信度,取最高的。
- 新增「主演」字段,应用时写进作品主演(没有 TMDB 人物 ID,不链接 TMDB)。
- 读网页前查 robots.txt(每个网站缓存 1 天),不允许的不读;遇到登录墙 / 验证码放弃该来源。
- 命中率:每次补全记录各类来源的结果数与是否命中;设置 → 元数据 → 资源识别 下方显示最近 30 天各来源的命中率,接口 `GET /identity/enrich-stats`。
- 设置「也用其它网站的搜索摘要」(`identity.enrichSnippetAllSites`,缺省开);补全白名单缺省加 `baike.com`、`kuaikaw.cn`(已保存过白名单的需手动加)。
- 真机验证:用户库 4 条短剧此前全部无结果,现在 4 条都从搜索摘要补到标题与年份,3 条有集数,4 条有主演(见 `docs/runbook/identity.md`「真机记录(META-2)」)。
### 变更(META-2)
- 补全的第二次搜索改为「标题 短剧 site:百科 / 豆瓣 / 平台」,摘要已够用时不再搜;只读结果标题 / 摘要含完整标题的网页(只有七成字对得上的首页、榜单页不再读)。
- 模型抽取改为候选之一:模型改写的值置信度 0.3,网页原文更可信时取原文(以前模型改写的简介会盖过原文)。
### 变更(AG-5 智能体提示词与 Skill)
- 系统提示分层:角色与边界 / 当前环境 / 能力地图 / Skill / 行为规则 / 汇报格式 / 本次目标,每层一个文件(`packages/agent/src/prompt/`),按会话类型(用户会话 / 巡检 / 后台调查 / 子会话 / 视觉子流程)选层。
- 「当前环境」:会话开始时把已接入的下载器、媒体服务器、站点、媒体库目录、订阅 / 下载任务计数、待处理数写进提示(名称 + 中文状态 + 相对时间,不含地址与凭证),智能体不再把"站点列表里没有"汇报成"没有下载器"。
- 汇报规则收紧:第一句就是结论、不超过 8 行、大小写 GB、时间写相对时间、不写 ID / hash / adapter / 英文状态码;被拒绝的动作只写一句「没做:…,需要你批准」;不说教。子会话思考与汇报用中文。
- 巡检、后台调查的只读白名单加上 `download.list`、`site.list`、`site.user_data`。
### 新增(AG-5)
- 6 个 Skill(`packages/agent/skills/`):巡检、收录一部作品、入库 / 整理问题排查、下载排查、订阅追更检查、数据清理与存储;每个写明适用意图、步骤、用到的能力、何时需要批准、汇报模板、不要做。用 Pi harness 的 Skill 格式加载,服务端按意图触发词载入(首轮进系统提示,追加消息换意图时附在消息前)。
- 只读能力 `download.list`:按状态 / 作品 / 名称列下载任务,附按状态计数,大小、进度、时间给人话;智能体先列再看,不再向用户要下载任务 ID 或种子 hash。
- 汇报核对 `lintReport` 与提示评测:fake 模型 8 条固定提示(e16),真实模型前后对比脚手架(`e16-agent-prompt-eval.real`,手动跑),记录见 `docs/design/agent-prompt-eval.md`。
## [0.3.2] - 2026-09-30
### 新增(BR-4 浏览器 UA 与指纹统一)
- 固定浏览器身份:浏览器镜像的 umt-cookies 插件首次启动时生成一套 Windows 指纹(UA、navigator、屏幕、WebGL、Windows 字体、随机种子)存进持久卷(`/root/.camofox/umt-identity.json`),之后每次启动复用,不再每次随机;Camoufox / Firefox 升级时只改 UA 与版本字段。修正上游字体配置路径,Windows 字体(含微软雅黑)按 Windows 渲染。新增 `GET /umt/identity`(访问凭据保护,只含 UA / OS / 版本 / 时间)。
- 站点请求 UA 跟随浏览器:列表 / 搜索 / 详情 / 下载种子 / 健康检测、RSS、登录、用户数据都带账号 UA,不再发 `Deno/2.9.7`。优先级:账号手动 > 待切换 > 设置里的全局 UA > 跟随浏览器(读不到浏览器身份时用同型 Windows Firefox UA)。站点账号页显示 UA 来源(跟随浏览器 / 手动填写 / 待切换),原始 UA 在技术信息里。
- 出口按站点统一:站点开了"使用代理"时浏览器会话也走同一代理,没开时直连;浏览器不再使用容器环境变量里的代理(`UMT_BROWSER_PROXY_MODE=env` 可退回)。插件新增 `PUT /umt/sessions/{userId}/proxy`。
- Cloudflare 验证 Cookie(`cf_clearance`、`__cf_bm`)只留在浏览器:回写站点账号时剔除,只记名字,站点请求不用。
### 变更(BR-4)
- 设置 → 站点默认 → User-Agent 缺省改为空(跟随浏览器),原缺省 Windows Chrome 140 去掉;挂站点的 RSS 与站点其它请求同一出口(站点开代理时 RSS 也走代理)。
- 迁移 0056:存量 Cookie / 账密账号标"待切换",继续用取得登录态时的旧 UA,下次重新登录或浏览器回写 Cookie 时 Cookie 与 UA 一起切换;设置里仍是旧缺省 UA 的清空。
- 上线需重建 app 与 camofox(`docker compose build app camofox && docker compose up -d app camofox`);camofox 只有插件层变化,不重新下载浏览器包。见 `docs/runbook/browser.md` §11。
## [0.3.1] - 2026-09-30
### 新增
- IO Worker 分道(WK-1):io worker 进程内分文件 / 网络 / 维护三条道,各自并发(缺省 2 / 4 / 1)、各自排队,文件道占满不挡网络任务;维护道在文件道或网络道有排队 / 运行时让路(连续让路 10 分钟放行一个),调度器里内联的清理、回填、保留期裁剪也走维护道。任务在 `defineTask({ lane })` 显式声明,归属表见 `docs/runbook/dev.md`「IO Worker 分道」,ci 逐项核对。
- 设置 → 自动化 → 高级 →「后台任务并发」:三条道的并发,保存后几秒内生效,不用重启;环境变量 `WORKER_FILE_CONCURRENCY` / `WORKER_NETWORK_CONCURRENCY` / `WORKER_MAINTENANCE_CONCURRENCY` 设了以变量为准。
- 运行状态页进程表按道显示「运行中/并发 · 排队」与维护道让路状态;心跳照常记录事件循环延迟(将来拆进程的判据)。
### 变更
- 下载计划并入下载面板(DL-3):去掉「下载计划」页签,旧地址(含 `?plan=` 与 `/downloads/plans/:id`)跳到下载面板并打开对应行;还没提交的下载作为「进行中」的行与下载任务按加入时间一起排并计入计数,状态写「等你批准」「等磁盘空间」「等开启自动化」「准备提交」,可直接批准 / 取消(等批准的同时在待处理里);下载详情新增「为什么下这个」(来源:订阅 / 智能体会话 / 手动;目的:补缺 / 升级(替换哪个版本)/ 换源;选中理由要点,原始评估进技术信息);没提交就结束的下载(失败 / 取消 / 过期)进作品的下载历史并写明原因;审批被拒、撤销或过期时草案随之结束。新增 `GET /acquisition-plans/{id}/why`、`POST /acquisition-plans/{id}/cancel`,面板接口行带 `kind`(task / plan)并支持 `planId`。界面与智能体能力标题不再出现"下载计划"(动作计数写"准备下载 N 个资源")。
- `WORKER_CONCURRENCY` 从 io 组总并发改为映射到网络道;compose 不再给它缺省值(缺省走设置页)。`worker` / `worker:agent` / `all` 角色与镜像入口不变。
### 变更(IA-2 导航与站点类型)
- 侧栏改为 4 组:概览 / 获取 / 整理 / 系统。「任务」移到系统组;站点、订阅、规则合成「获取」组(组名是 `nav.ts` 的 `ACQUIRE_GROUP_TITLE` 常量,改名只改一处);独立的 RSS 导航项取消。
- RSS 属于站点:站点详情新增「RSS」Tab,承载原 RSS 页的新建 / 编辑 / 启停 / 立即抓取 / 抓取状态,详情里加「最近条目」;原「抓取与 RSS」拆成「抓取」和「RSS」。旧 `/console/sources*` 链接跳到对应站点的 RSS Tab(`?feed=` 查所属站点后打开该 RSS)或站点列表;任务 / 业务任务里的 RSS 链接改指站点。
- 站点类型:站点新增 `kind`(PT 站 / 公开 BT 站 / 自定义 RSS 源;Torznab 索引器只定义结构,未实现),每种类型声明获取方式(搜索 / 列表抓取 / RSS / 详情页 / 登录 / 账号数据),实际可用 = 类型 ∩ 站点定义。站点列表可按类型筛选,详情按类型显示 Tab 与字段(自定义 RSS 源没有登录、账号、等级);添加站点第一步选类型,PT 站仍从站点定义库选。
- 服务端按获取方式调度:快照只排能抓列表的站点,RSS 只排能抓 RSS 的站点,账号数据 / 健康检测只扫有登录的站点,搜索站点只含能搜索的;不支持的登录 / 凭证 / 抓取请求返回 400。
- 不带站点新建 RSS(旧 API)时归入同主机的自定义 RSS 源站点;RSS 不能再移出站点。智能体 `site.list` 带站点类型与获取方式,系统提示同步"RSS 属于站点"。
- 迁移 0055:`site.kind`;旧的通用 RSS 站点 → 自定义 RSS 源;不属于任何站点的 RSS 按主机归入新建的自定义 RSS 源站点,下次抓取把条目写成资源。
### 修复(IA-2)
- 同一站点添加第二个 RSS 且都用缺省名称时,secret 名冲突导致 500。
### 变更(设置页,FIX-8)
- token 类数字(上下文窗口、上下文预算、最大输出、会话上限等)以 K 为单位输入,列表按 K / M 显示;存储仍为 token 数。
- 密钥类字段(模型服务、TMDB、Brave、qB、站点、Emby)已保存时显示「已设置 ••••••••」(有末 4 位提示时带上),留空保存不变,「清除」需确认;明文不下发前端。服务端统一"空串不变、null 清除"。
### 修复(v0.3.0 核对问题,FIX-7)
- 智能体汇报展示层兜底:UUID、能力 ID、原因码换成名称 / 人话(旧会话同样生效)。
- 概况条"全部完成"不再把跳过的步骤算进完成数;子会话数量按实际会话树计(不含失败的派发)。
- 巡检目标不再原样显示 `{{now}}` 等模板占位符。
- 智能体新增 `downloader.list`,不再误报"下载器不在系统内"。
- 字幕文件不再标为主文件;版本行悬浮按钮不遮挡大小 / 时间;作品页「收录版本」文案区分;会话标题里的时间与原因码转人话;种子详情去掉原始错误码。
- 文件管理目录树改为与主面板同款的圆角卡片,头部与工具栏对齐。
- 站点更新凭据时不再误删两步验证密钥与 User-Agent。
## [0.3.0] - 2026-09-29
### 新增
- 搜索快速筛选(SEARCH-3 / POLISH-1):搜索结果与站点资源列表共用一行多选筛选——分辨率、编码、版本、站点、促销、HDR、H&R、制作组、季 / 集,选项带计数,同维度"或"、跨维度"且",记住上次选择;`qf` 参数见 `docs/runbook/search.md`。
- 入库版本可见(LIBV-1):作品详情每集显示入库版本规格(分辨率 · 来源 · 编码 · HDR · 制作组 · 大小),一集多个版本并列;季 / 作品汇总;配了收录版本时标出符合 / 缺失 / 可升级;`GET /library/{id}/versions`;旧文件规格回填脚本(缺省只读)。
- 下载面板(DL-2):总速度、每个种子的 ↓/↑ 速度与剩余时间;「进行中 / 已完成」分段,默认进行中;已完成显示分享率与整理结果;`GET /download-tasks/board`。
- 文件管理(FM-2):宽布局,目录树贴左、可拖宽、可收起;预览文本 / NFO(GBK、UTF-16 自动识别)、字幕前 200 行、.torrent 文件列表(隐藏 passkey)、图片;调研见 `file-preview-research`(已删除,见 git `ceb66f8`)。
- 种子详情可读(DETAIL-1):简介拆成信息块与正文,MediaInfo / BDInfo 转规格概要,截图画廊,文件清单目录树;旧缓存现算,不重抓。
- qB 兼容(QB-1):qB 5.0–5.2 登录(200 / 204、Cookie 名取自响应),认证方式可选账号密码 / API Key / 不认证;接管任务按文件名与种子名识别,识别不出建带候选的待处理;冲突可选替换 / 保留两者 / 跳过;下载历史(迁移 0054)。
- 数据整理(DH-1):full 刷新含季 0(`metadata.includeSpecials`,缺省开);对上 TMDB 结构的临时单元转正式(迁移 0053);重复单元合并(`identity-cleanup.ts --merge-duplicates`,缺省只读),懒建加锁。
### 变更(去 AI 味,DEAI-2 / AGUI-3)
- 术语:「版本目标」→「收录版本」,「Agent 上游」→「模型服务」,界面上的 Agent →「智能体」;见 `docs/design/glossary.md`。
- ID、hash、token、耗时、原始字段默认折进「技术信息」(设置 → 界面可默认展开);内部原因码统一转成人话(`packages/contracts/src/reasons.ts`)。
- 首页只回答"在忙什么 / 要我处理什么 / 最近入库了什么";计划页智能体巡检置顶,自动任务按分类分组折叠,维护类收成「数据清理」。
- 待处理"没识别出作品"主按钮为「指定作品」。
- 智能体对话重做:每轮工具步骤合成一行人话进度;被拒调用变成一行「没做…[批准并重试]」;最终回复不再重复显示;去掉右侧栏;方案卡一键选定,绑定同一计划时选定即批准(只认控制台管理员会话,超时自动选不算批准,删除 / 覆盖仍单独确认);「先看方案」改为单次指令 `/先给方案`;抽屉去 Tab,历史弹层「等你处理」置顶;汇报格式写进系统提示。
### 修复(本版)
- 超预算待处理事项先于会话终态写入,消除 E15 偶发失败。
- 下载面板「已完成」里未整理的外部任务不再显示「待整理」。
### 新增(v0.2.4 之后、INT-3)
- 媒体详情页对照 MP:季 / 集列表、每集标题 / 简介 / 播出日 / 剧照,作品库与 TMDB 预览共用;标题 / 简介按设置 `metadata.languages` 回退(缺省 zh-CN → zh-SG → zh-TW → zh-HK → en-US),另存中文名;`POST /media-entities/{id}/refresh?full=1` 拉全部季的每集信息(MD-1)。
- 新建档(订阅建档、搜索 / TMDB 预览页建档、整理向导、手动指定未登记的 TMDB 身份)当场按语言链取标题 / 简介,并自动入队一次 full 刷新(INT-3)。
- 存储预算与保留:`settings.storage`(PG / 图片 / 备份 / 会话证据预算,各类流水保留天数,缓存有效期)、定时清理任务、`GET /system/storage` 与健康页存储等级,图片缓存按容量 LRU;设置页「自动化 → 存储与保留」可改(CACHE-2 / INT-3)。
- 计划页从任务页拆出:自动任务紧凑列表 + Agent 巡检卡片;`GET /schedules` 给每个巡检带最近 100 次会话的费用与模型汇总(FE-6 / INT-3)。
### 变更
- `cache.tmdbMaxSize` 缺省 256 → 5000,迁移 0051 把仍是旧缺省的已存设置一并调整;`cache.tmdbTtlHours`、`cache.emptyResultTtlSec`、`identity.poolArchiveDays` 弃用,设置页不再显示(由 `storage.cacheTtl` / `storage.retentionDays` 取代)(CACHE-2 / INT-3)。
- 设置页布局:分区标题层级、标签左 / 控件右的表单行、每块独立保存条、吸顶导航与锚点定位(FE-7)。
- 部署:postgres 内存参数与容器内存上限(CACHE-2)。
### 修复(BR-3 浏览器服务重启后自愈)
- camofox 重启后会话操作遇到 404 / 410 自动重连:重新注入账号 Cookie、新开标签页回到原地址并重试一次;失败返回 503 `browser_reconnect_failed`。`POST /browser/sessions/{id}/reconnect` 幂等。
- 桌面模式打开时先确认会话;画面 5 秒未出图自动重连一次(INT-3)。
### 修复(HH-2 憨憨 RSS 与详情页)
- RSS 标题「[分类]名称[副标题][大小][上传者]」在站点适配层拆开;旧 RSS 行按需重新规范化;详情页补全豆瓣信息、截图、MediaInfo 里的 IMDb / TMDB、上传时间与文件清单。
- 原站视图空闲时显示「自动化」,最近有自动化操作才显示「Agent」。
### 修复(ID-2 身份匹配对照 MoviePilot)
- 憨憨 RSS 标题的分类前缀「[电视剧]」「[动漫]」「[音乐]」被当成中文名,经别名召回把多部剧的资源并入同一部作品;分类词、单字、停用词不再作为片名或别名参与比对,自动绑定也不再登记它们。存量用 `scripts/identity-reevaluate.ts --rollback-wrong` 撤销(缺省只读)。
- 副标题与 RSS 内嵌描述里的中文名、别名参与匹配;中英名任一精确 + 年份精确即高证据,续作 / 章节序号与季号参与区分,同级多候选按年份精确、命中的名称文字种数取舍;评分权重成表可覆盖。
- `Travis - 12 Memories` 不再被当成第 12 集。
- 站点资源标题更新后按新标题重新解析并重新识别,不能确认时撤销原自动绑定。
- 憨憨真实标题差分集(113 条)对照 MP:修前一致 88.5%,修后 100%(含 1 条 MP 误识别),见 `docs/porting/moviepilot-identity-match.md`。
### 已知限制
需求逐条覆盖见 `11-requirements-coverage`(已删除,见 git `ceb66f8`):当前相当于 REQ 的 M0 大部分 + M1(仅 mock 环境)+ M2 约三分之一。
- 综艺只识别内容类型与上 / 下分段,不计算正片覆盖,也没有节目级附加内容策略。
- `require_distinct_asset` 只保存设置,同一个文件仍可同时满足两个版本目标。
- 旧库只有库根"只登记 / 纳管"两种模式,没有首次扫描登记和启用前的影响预览。
- Agent 不做主观选片,也没有规则学习与样本回放;策略预览只对最近 200 条已识别资源试算。
- Emby 查询结果不参与收录决策,也没有本地资产与 Emby 的对账。
- 站点 HTTP 访问失败不会自动转浏览器。
- 观众、馒头、CHD 只对 mock 与解析样本验证过,没有连真实账号。
- 用户委托换源时,新提交与原任务的处置不在同一个计划里。
- 定时任务里的"备份"是占位,备份靠宿主机 cron 调 `umt backup`,恢复没有自动化演练。
- 没有身份巡检;同一挂载根离线引起的多条待处理不按根因合并。
- 没有调查整个 qB 实例(含未纳管任务)的能力。
- AT18(恶意标题)、AT29(部分入库不清理)、AT42(未纳管占用)、AT73(多下载器同 hash)与流程版本升级没有测试。
## [0.2.4] - 2026-09-29
### 修复(v0.2.3 真机验收)
- 内置 Agent 巡检模板的能力白名单未包含新增只读能力(迁移 0045 更新)。
- 仅授权 `browser.solve_challenge` 时子流程无法执行点击。
- api 与 worker 进程的浏览器会话状态不同步。
- 浏览器桌面镜像:APT 换源脚本在无 debian.sources 的底座上失败。
## [0.2.3] - 2026-09-29
### 浏览器
- 原站视图改为 Webtop 4.0(Wayland/Selkies)真实远程桌面:同会话(桌面里的窗口就是 Agent 驱动的 camofox),中日文字体、输入法上屏、剪贴板双向,只读/接管口令按人工租约注入;非 HTTPS 或旧镜像自动回退截图模式。
- 视觉自动化闭环:`browser.screenshot` 以图片喂视觉模型,`browser.click_at/type_at/scroll/wait` 按视口坐标操作,`browser.solve_challenge` 有界子流程;二次验证立即转人工。
### Agent
- 新增只读能力 `subscription.list`、`decision.list`、`download.inspect`;`download.plan` 审批判定与授权器一致;超预算会话标注与同根因合并;汇报 Markdown 渲染;系统提示与能力描述补充(中文、参数类型、禁止无意义探查)。
- 上游模型列表一键获取/刷新(远程优先、静态回退),Brave 网页搜索能力 `web.search`/`web.fetch`(白名单抓取)。
- 真实上游验证(OpenCode Go / DeepSeek V4.1 Flash)发现并修复:站点缺失时下载提交无限重试;恢复失败误记为未执行;识别按原名比对;从 TMDB 候选建订阅丢 id;上游测试补全带 sessionId。
### 部署
- camofox 随栈默认启动(本地构建 1.17.0);compose 网段固定 `UMT_SUBNET`;可选 `tls` profile(Caddy 自签或 ACME);容器经宿主代理中继访问境外站点(runbook)。
## [0.2.2] - 2026-09-28
### 修复
- 编译产物启动即 `ERR_MODULE_NOT_FOUND`:web 的 `shadcn` 开发依赖带进第二份 `@modelcontextprotocol/[email protected]`(zod@3),`deno compile --exclude-unused-npm` 嵌入的目录与裁剪后快照解析的路径不一致。去掉 `shadcn` 依赖,只把它的 `tailwind.css` 拷成 `apps/web/app/shadcn-tailwind.css`,MCP SDK 只剩一份。
- 编译产物自检:`scripts/check-compiled-binary.sh` 用空环境跑 `--role preflight`,必须加载完整模块图并在配置校验处以退出码 2 结束;已接入 `deno task ci`(`check:binary`)与 Dockerfile 构建阶段。
- 运行状态页把容器重建前留下的旧心跳行当成"N 个进程超过 45 秒没有心跳"报警。`GET /system/health` 现在把进程分成当前实例(最近 10 分钟有心跳的 host 上、同 host 同 kind 最新启动且未退出的进程)与已下线实例,45 秒 stale 判定与告警只看当前实例;已下线实例放在新字段 `retiredProcesses[]`,不计入 `level`,页面折叠显示。横幅按角色报警,如「io worker 45 秒没有心跳」。
- 进程正常退出(SIGTERM / SIGINT)时把自己的心跳行标 `stopped_at`(迁移 0043),退出后立即不再当活进程;重启后 upsert 清回 null。纯 api 进程退出时也会停心跳写入器。
- 心跳清理改为定时任务 `system.heartbeat_cleanup`(维护组,1 小时):删 24 小时没有心跳的进程行和 7 天前的采样;写入器不再自己裁剪。
## [0.2.0] - 2026-09-28
Agent 上游全覆盖与订阅登录、控制台信息架构重排、定时任务看板、全站文案第二轮审校;W9 与前端波补上站点中心、订阅重做、统一规则、命名模板、全局搜索、文件管理 v2 与统一任务页。基线见 `08-v0.2-closeout`(已删除,见 git `ceb66f8`)(W8-A 与"W10 集成记录")、`09-visual-qa`(已删除,见 git `ceb66f8`)、`docs/design/{console-ia,site-center,subscriptions,naming-template,file-manager-v2,pi-providers,agent-ui-reference}.md`、`docs/runbook/{schedules,agent,sites,rules}.md`。
### Agent
- 全局入口:侧栏顶部常驻 Agent 入口(展开与折叠态均带活跃会话数角标);右下角悬浮按钮(带活跃计数、最新状态摘要),在 Agent 会话页与迷你坞展开时隐藏;`Ctrl/Cmd+J` 切换抽屉、`Esc` 关闭,打开即聚焦输入框;抽屉首屏给出随页面变化的快捷目标。
- Agent 上游:新增 `pi_upstream` 表与 CRUD,一个上游 = 一个 pi provider(41 个内置之一,或 `openai-compatible` 自定义兼容端点,或 `fake`)+ 一份凭证;同一 provider 可建多个上游,各自独立凭证存储;`authKind` 分 `api_key` / `oauth` / `none`;默认上游可指定,`runAgent` 只从上游选模型。
- 订阅登录:8 种(Anthropic Claude Pro/Max、OpenAI Codex、GitHub Copilot、xAI、Kimi Code、Meta Muse、OpenRouter、Radius),browser 与 device 两种交互,登录会话 15 分钟;条款提示只陈述事实(借用官方客户端身份、可能违反条款、有限流或封号风险)。
- 设置页 Agent 分区:上游列表、新建向导(选 provider → 凭据与模型 → 登录 / 测试 / 设默认)、编辑抽屉(登录 / 重新登录 / 退出、测试、设默认、删除)。
- 子会话:`agent.spawn` 派生子会话(独立 agent_run,同一 runAgent 任务),`agent.await` 取子会话状态与脱敏汇报;能力白名单继承父会话并取交集;并发上限 `maxConcurrent`、派生层数上限 `maxDepth`、单会话最多 10 个子会话;预算从父会话划拨;中止父会话递归取消未结束子会话。
- `agent.await` 落定时挂起会话而不占 worker 槽:`drive` 返回 `suspended`,由 `waitForFact` 每 2 秒查一次子会话落定 / 超时 / 父会话取消,再以 `resumedAwaits` 重开会话续跑;单会话最多挂起 100 次。
- 没有候选的待识别资源(无法解析,或候选为 0,或查询失败且自动复查已停)开 `identity_unresolved` 待处理事项:可手动指定 TMDB ID、选本地作品或忽略。
- 旧 `settings.pi.provider / baseUrl / model / thinkingLevel / apiKeySecretRef` 弃用:schema 保留兼容旧数据,`PATCH /settings` 丢弃,设置分区不再展示;`runAgent` 没有上游直接失败并提示「未配置 Agent 上游」。
- Agent 汇报里的下载链接改指向 `/console/downloads/:id`,不再经 `/console/tasks/:id` 404 探测再跳转。
### 控制台信息架构
- IA-3 定稿(前端波 FE-1):侧栏 5 组 14 项(概览、资源、订阅、整理、系统);待处理不进侧栏,改为顶栏收件箱(角标 + 按类型分组的下拉)。
- 引擎面板、定时任务、身份与元数据不再单独入口;旧地址全部重定向到任务页、任务页"计划"页签和媒体概览。
- 统一"任务"页:定时、事件、手动、Agent 触发的运行在一条流里,页签为全部 / 进行中 / 失败 / 计划,来源与业务对象可筛选。
- 任务详情抽屉:业务摘要、时间线、相关审计,引擎步骤折叠在最后;未结束可取消,已结束可重跑。
- 首页按正在进行、需要处理、媒体概览、计划、最近完成与失败、缓存与保留、来源健康、运行状态重组。
- 新增运行状态页:进程心跳、事件循环延迟、SSE 连接数、数据库、磁盘与挂载根,带 1 小时到 7 天的趋势。
- 以下为 IA-1 / IA-2 阶段的调整,部分入口已被 IA-3 收编:
- 侧栏改为 7 组 19 项(概览、资源、订阅、下载、整理、Agent、系统),按业务流程排列;新增"定时任务"入口。
- 站点工作台合并快照与账号:详情页 4 个页签(整理视图 / 原站视图 / 快照与 Feed / 账号)。
- 原"下载与任务"拆分为下载队列、下载计划、业务任务三页;订阅页"收录策略"页签独立为收录规则页。
- 身份判定收口到待处理中心:身份页"待识别"改为只读,已进待处理的行标注跳转,判定动作只在待处理执行。
- 设置页改为 9 个左侧分区(自动化、站点与账号、下载器、媒体库与目录、媒体服务器、元数据、Agent、API Key、账户与安全),用 URL hash 定位到分区与节;旧 `?tab=` 全部重定向到新分区 hash,`settingsPath()` 直接生成 `#分区[/节]`。
### 定时任务看板
- `scheduled_job` / `scheduled_job_run` 表驱动全部周期任务,worker(io 组)内唯一调度器按表调度(`pg_try_advisory_lock` 选出执行者);控制台"定时任务"页(`/console/schedules`)查看与调整。
- 已登记 16 个任务,分 5 组(采集、下载、整理、维护、Agent);Agent 组含 3 个默认关闭的巡检(待处理巡检、下载诊断、订阅与站点周报)。
- 模块自建计时器全部并入注册表:`pi.token_refresh`(上游登录刷新,维护组,10 分钟)与 `auth.cleanup`(登录会话清理,维护组,1 小时)改为 `registerScheduledJob`,模块里不再有 `setInterval`。
- 支持立即执行、跳过本次、开关与周期自定义(`customized` 标记,改过之后再登记不覆盖,`PATCH {reset:true}` 恢复默认);自定义巡检可增删,内置任务只能停用。
- 调度器中断恢复:新执行者拿到锁时,把上一个执行者留下的 `running` 状态改为 `failed`。
### 站点中心
- 站点页是站点的唯一入口:添加站点向导、站点卡片与列表、单站详情。
- 凭证管理:账密、Cookie、API Key(馒头)、Passkey、TOTP,同账号同类凭证原地替换。
- 账号数据:上次登录、上传 / 下载、分享率、等级、VIP、账号状态,新表 `site_user_data`(迁移 0031)保存历史并画走势图。
- NexusPHP 账密登录走 takelogin;验证码或二次验证失败时开待处理事项,提示改用 Cookie。
- 手动"检测健康"与"用凭证刷新登录状态";Agent 能力新增 `site.list`、`site.health_check`、`site.refresh_login`、`site.user_data`,执行类需要持续授权。
### 订阅
- 订阅总览按状态分组(追更中、待搜索、已完成、暂停、待定),可按上次更新和缺集数排序。
- 覆盖矩阵:每条订阅对照库内已有和订阅要求,按季 / 集和版本目标逐格显示。
- 多版本目标逐个显示缺失,可开"自动补全其他版本"并设补全预算。
- 订阅表单 v2:基本与高级两页,旧字段读入时归一化。
### 规则
- 收录策略与偏好标签合为一个"规则"页:硬条件、软偏好、优先级阶梯、排除分层显示。
- 规则组 `rule_group` / `rule_atom`(迁移 0033)与 `/rules` 端点;兼容 MoviePilot 规则字符串的解析与序列化,内置关键字。
- 规则字符串与分层卡片双向同步;可对最近已识别的资源或粘贴的标题试算命中层与拒绝原因。
- 偏好标签作为规则的展示形态保留抑制记录;`/console/preferences` 重定向到规则页。
- 升级判断按订阅引用的规则组重算当前资产的优先级。
### 命名模板
- 模板引擎:Jinja 安全子集,支持 MoviePilot 的命名变量与目录布局。
- 全局、库根、作品三级覆盖,模板按版本保存(迁移 0032);整理与文件管理按覆盖链生成目标路径。
- 设置页命名表单:变量清单、示例、实时预览;库根和作品可单独覆盖。
### 全局搜索
- `GET /search` 聚合本地作品、TMDB 候选、已启用站点的资源(限流、15 秒超时、并发合并、短缓存、库存叠加)与页面跳转。
- 顶栏搜索框与 `Ctrl/⌘+K` 命令面板;`/console/search` 结果页可按站点、分辨率、来源、大小、免费、H&R 筛选和排序,资源行可下载或交给 Agent。
### 文件管理 v2
- 后端补齐 G1–G9:按 TMDB 候选就地建作品、最小体积(设置项 `organize.minSizeBytes`)、目标已存在时的处理、命名来源、建议文件名。
- 目录树可折叠,下载目录在前;列表显示作品与季集、解析提示、目录计数;右键菜单按适用性显示或禁用并说明原因。
- 共享整理向导:文件与作品 → 选项 → 预览并执行;文件管理、下载任务、整理记录都从这里整理。
- 目录展开成逐个视频整理时,同目录同主干的字幕和外挂音轨随行进计划。
- 整理向导执行多组后跳到 `/console/organize?ids=`,只列本次的记录。
### 实时与系统
- outbox 事件(Feed、待处理、下载、整理)投递成功后镜像到 SSE,首页、收件箱、任务流、Feed 列表随之刷新。
- 进程心跳表与 `/system/health`、健康历史;引擎 runs 补关联业务对象与触发来源。
- `/dashboard` 补作品、剧集、季、集、资产计数与版本目标满足率。
- `/engine/runs` 支持 `triggeredBy` 筛选与多值 `status`,任务页的来源筛选和"进行中"页签改为服务端分页。
### 文案与术语
- 全站第二轮文案审校:控制台、设置、Agent、服务端消息统一术语表用词(待处理 / 待识别 / 整理记录 / 运行记录 / 凭证 / 子会话 / Agent 上游),精简说明文字、空态、确认按钮与 toast。
- 内置 Agent 巡检的目标模板改短、改具体。
- 实例(下载器 / 媒体服务器)CRUD 报错改用可读名词,不再显示表名。
- 审计日志补 `pi_upstream` / 定时任务 / 持续授权相关动作的显示名。
- 术语表新增:上游、订阅登录、凭证、定时任务、巡检、运行记录、子会话、停止、持续授权。
### 修复
- 设置页深链改用分区 hash 定位,不再依赖 `?tab=` 查询参数(旧链接仍可打开,经重定向落到新分区)。
- Agent 汇报的下载任务链接直接指向下载详情页,不再先探测业务任务详情再判断是否为下载任务。
- 生产容器静态 ffprobe 升级到 9.0.2;`.gitignore` 忽略 compose override 文件。
- 视觉走查 17 项(`09-visual-qa`(已删除,见 git `ceb66f8`)):改密时旧密码错误不再被踢回登录页;预览失败时不能再执行整理;手机上 Feed 表不再把操作列挤出屏幕;操作者、原因、用途等不再显示内部 id 与英文代码。
- 手动整理成功入库后,处于"需处理"的版本目标回到核验,再按实际入库资产落定;同一下载任务的整理冲突事项自动关闭。
- 自定义 Base URL 的 Agent 上游"测试"不再把状态改成可用,提示用"最小补全"确认端点可达。
- 新作品首次下载的计划用途记为"补缺",不再是"升级"。
- 按 TMDB 建档时同事务写入元数据,别名按规范化文本去重。
- 更新站点账号凭证不再因 secret 重名报 500;馒头刷新登录在站点地址是 IP 时不再拼出非法地址。
- 表单保存失败时提示第一处问题并滚动到出错字段;移动 / 复制选到源所在目录时直接提示,不再发出注定失败的预览请求。
- 数据库迁移只内省目标 schema,并行测试在共用库上删 schema 时不再偶发"schema 不存在"。
### 已知限制
完整清单见 `08-v0.2-closeout`(已删除,见 git `ceb66f8`)"仍遗留"节。
- 41 个 provider 里只有 fake 与 OpenAI 兼容本地端点有自动化覆盖;8 种订阅登录只测了 fake 的 OAuth 状态机;Codex `_randomBytes` 在 Deno 下的行为待 spike(`docs/design/pi-providers.md`)。
- `agent.spawn {await:true}` 仍在进程内轮询等待,占 worker 槽到超时;要挂起需要和 `agent.await` 相同的关闭会话 + 重放机制,但 spawn 是 replay=never,重放会得到"结果未知",需另行设计。
- 子会话挂起期间父会话状态保持 `running`(避免被祖先会话的 `agent.await` 当成已落定);运行时长预算按每段 drive 计,不含挂起等待。
- 查询失败但仍在自动复查期内的资源不开待识别事项,避免 TMDB 抖动刷屏,复查耗尽后才开。
- 身份页"待识别"详情抽屉的提示句仍写"选择候选或忽略",未识别类(无候选)读起来不准确,留给下一轮文案。
- 旧 `settings.pi` 字段只是弃用未删除,真正删除需要一次迁移清理里面的旧键。
- 原站视图仍是占位(IA-1 遗留)。
- 观众站定义没有 H&R 选择器,资源的 H&R 一律显示"未知"(视觉走查 U8)。
- 界面文案中文句子里的半角 `,;:` 与全角 `。` 并存,尚未定全站标点规范(视觉走查 U11)。
- Agent 悬浮按钮在滚动途中仍会盖住页面右下角的控件,页面末尾已留出高度(视觉走查 U6)。
- 订阅还没有 `subscription.*` outbox 事件,订阅页不随后台变化实时刷新。
- `/engine/runs` 的 `triggeredBy` 在服务端逐行推断后筛选,单次请求最多检查 2000 行,命中稀少时一页可能少于 `limit`。
- 定时任务运行记录没有对应的引擎 run id,卡片与任务之间按业务对象关联。
- 控制台账户弹层的二次验证(TOTP)开启时只显示密钥与 otpauth 链接,不渲染二维码。
## [0.1.0] - 2026-09-28
第一个可用版本:REQ v0.7 的 M0 + M1 纵切。全链路在没有真实 PT 账号的情况下用 mock(RSS / 站点 / TMDB / qBittorrent / Emby)验证。范围与验收依据见 `00-first-version-plan`(已删除,见 git `ceb66f8`) §3.1 和 `04-v0.1-acceptance`(已删除,见 git `ceb66f8`)。
### W0 底座
- Deno workspace 单仓(`apps/server`、`apps/web`、`packages/{adapters,agent,contracts,db,domain,mapping,tasks,testkit}`),迁入 uhd_web 设计系统。
- OpenWorkflow 与 Pi SDK 兼容性 spike,结论写入 ADR-002 / ADR-003;Deno 2.9.7 + TypeScript 7 spike 写入 ADR-004。
- MoviePilot / MovieClaw 迁移对照账本(识别、刮削、转移入库、站点框架)。
### W1 领域与适配
- `@umt/domain`:发布标题解析、身份判定、Slot 状态机与完成条件、收录模式判定、路径模板与路径绑定、整理计划、下载状态机,全部是纯函数。
- `@umt/adapters`:qBittorrent(多实例、管理标签、带数据删除前的安全检查)、文件系统(Copy/Move、跨卷 Copy→核验→删源、EXDEV 不静默降级、全量 sha256)、TMDB、Emby、RSS、PT 站点(NexusPHP 观众、馒头 API,移植 MoviePilot 开放站点框架)。`@umt/testkit` 提供对应 mock。
- `@umt/db`:36 张表的全量迁移;`@umt/contracts`:共享 zod 契约与 API 注册表;`@umt/mapping`:domain 与 contracts 之间的映射集中在一处。
- `@umt/tasks`:基于 OpenWorkflow 的持久任务引擎、任务注册表、outbox 中继、操作账本 fencing(旧 attempt 的提交会被拒绝)。
- `@umt/agent`:能力注册中心、Pi AgentRuntimePort、fake 模型、输出脱敏。
### W2 服务编排
- 认证与设置:管理员登录门禁(argon2id、会话 cookie、CSRF 双提交、登录限速、可选 TOTP)、API Key scope(read / organize.read / organize.execute / admin)、密钥加密存储、实例与路径映射、审计、PG 通知驱动的 SSE(带序号,可补读)、自动化总开关与只读对账模式、工作流引擎面板 API。
- 来源与身份:站点与 Feed 管理、多 RSS 抓取与多层去重、站点快照与实时补查、TMDB 识别与本地实体优先、待识别池、人工纠错映射。
- 规则、下载与入库:订阅、Slot、策略版本(发布即生成持续授权)、确定性 evaluateAcquisition、每日预算与并发、qB 同步与标签接管、缓存卷硬阈值与恢复水位、verifyAndImport(Copy/Move)、路径绑定固定、整理记录与公开增量 API、媒体库与首页聚合。
- Agent:14 个能力接到服务,服务端授权(持续授权 / 一次性审批),会话 API + SSE 增量,后台事件触发有界调查任务。
### W3 控制台
- 20 个路由:首页、媒体库、订阅与规则、偏好标签、待处理中心、身份与元数据、PT 站点工作台、来源 / Feed / 快照、下载与任务、整理记录、Agent 会话、系统设置、工作流引擎面板、审计。
### W4 集成验收与修复
- 单容器打包(API + worker + 静态前端,compose 只有 app 和 pg),`DATA_DIR`,备份与恢复脚本,runbook。
- 控制台接入真实端点;Playwright 全路由冒烟(`deno task test:web:smoke`)。
- BrowserProvider 接口与 camofox-browser 适配骨架(只落接口)。
- 主循环解耦:后台循环只做编排,清理 / 对账 / 入库一律入队到任务引擎;io / agent worker 分组;外部 IO 能力调用限流;事件循环延迟探针。
- 安全修复:审批只能由管理员会话决定,共享一份脱敏表,TMDB 错误信息不带 api_key,生产构建不能打开 Agent mock。
- 授权内异常调查与恢复:有持续授权时,调查结论可在授权范围内自动重试并继续。
- 手动整理守卫(`POST /organization-records`):`sourcePaths` 必须在已登记的媒体库根或下载器路径映射之下(realpath 后按目录前缀匹配,拒绝 `..` 与符号链接逃逸,dryRun 同样受限);Move 需要管理员会话,或 API Key 同时有覆盖目标作品的持续授权 / 与本次请求一致的一次性审批;来源是纳管下载任务且做种义务未满足时返回 409 并建待处理,不改成 Copy。
- 剧集完成判定:总集数未知(集单元都是临时单元)时 Slot 不判满足,订阅继续追踪;覆盖按实际文件登记,整季包不因包名覆盖整季;已在库的相同文件算作核验到的内容。
- 工作流引擎面板支持重跑:`POST /engine/runs/{id}/retry`(仅 admin,新幂等键 `retry:<id>:<序号>`,写审计),run 详情页有"重跑"按钮。
- 新增 e2e:E7 常规剧集纵切、E8 管理标签移除与 qB 任务消失(AT24)。
### 文件管理(`/console/files`,00 §6 追加范围)
- 后端 `/files` 模块共 18 个端点:根 / 列表 / stat(行内带资产、Slot、下载任务状态)、mkdir、rename、move、copy、organize、delete、回收站(列表 / 还原 / 还原到… / 清理)、identify、probe、scrape、records、download。
- 路径守卫:realpath 必须落在已登记根内,拒绝 `..`、URL 编码、符号链接逃逸与对根本身的写操作;执行前再做一次 realpath(TOCTOU);根离线返回 503,不返回空列表;fs 竞态错误映射为 503/404/403/400。
- 两阶段写操作:move / copy / organize / delete 先 dryRun 产出 `planId` 与源事实指纹,执行时只认 planId,源变化返回 `plan_stale`;全部写操作带幂等键并写审计。
- move / copy 经 `planImport` 的 `transfer` 变体生成整理记录,由 `verifyAndImport` 执行:逐文件账本可续跑、经 fsproxy、跨卷目录 Move 为逐文件 Copy→核验→删源;资产位置逐文件跟随,整目录搬走时修订路径绑定。请求最多等待 `FILES_TRANSFER_WAIT_SEC`,超出返回 `executed.pending`。
- organize 支持逐项覆盖季 / 集 / 内容单元 / 目标目录 / 操作 / Slot;delete / 回收站 / 还原写整理记录(迁移 0026)。
- 回收站:`<root>/.umt-trash/<day>/<uuid>/`,`trash_item` 表(迁移 0024),删除前核对引用,做种中的文件不能改名、删除或 Move;过期清理由 `purgeTrash` 任务执行。永久删除默认关闭(`FILES_ALLOW_PERMANENT_DELETE`)且只接受管理员会话;API Key 删除每次都要一次性审批。
- download:仅管理员会话,nfo / 字幕 / 图片白名单,`FILES_DOWNLOAD_MAX_BYTES` 上限,`nosniff` + `CSP sandbox`,写审计。
- 前端:目录树、虚拟滚动网格、面包屑、排序与 glob 搜索、多选 / 右键菜单 / 拖拽后 dryRun 预览、键盘操作(F2 / Del / Shift 区间 / Ctrl+A)、离线与空态、移动端布局;改名 / 移动 / 复制 / 删除对话框,4 步整理向导(未决项挡住下一步),回收站页;SSE `files.changed` 触发刷新。`?mock=1` 内存后端只在 DEV 构建生效。
- 运行手册 `docs/runbook/files.md`。
### 订阅增强(对照 MoviePilot,`05-subscription-gap`(已删除,见 git `ceb66f8`))
- 总集数账本:季单元记录 `episode_total` 及来源 / 锁定 / 时间(迁移 0025);`resolveEpisodeTotal` 只增不减,TMDB 回退时以已覆盖的最大集号为下限,手动值可锁定。
- 完成判定按账本:总集数未知时不结束并记疑似缺集;`pending`(元数据未就绪)的订阅可搜可评估但不会完成;once 与持续订阅的当季完成都写 `subscription_history`。
- Slot × 单元预留:缺口 = 发布单元 ∩ 集范围 − 已覆盖 − 在途;剧集 Slot 可同时有多个互不重叠的在途计划,重叠或忙时延后(`slot_deferral`),计划结束或周期重评时再评估。
- 硬条件与优先级:排除来源、HDR / 编码集合、每集体积、include/exclude 正则(白名单校验)、站点范围、最少做种、仅免费;MoviePilot 规则组分级映射为 0–100 优先级并带逐级 trace;分集洗版(`slot_unit` 账本)。
- 季包选文件:提交后读取 qB 文件列表,把已覆盖或在途的集设为不下载;无法判定时整包下载并记录原因。
- 主动搜索:建订阅时、每 `searchIntervalHours`(默认 24h)和 `POST /subscriptions/{id}/search` 入队 `searchSubscription`;元数据每 6h 刷新并写季总集数。
- 前端订阅抽屉:立即搜索、追更进度(每季总集数与来源、每集状态、在途 / 延后计数)、设置并锁定季总集数。
- 新增 e2e E9 持续追更剧集。
### 转移语义与文件系统隔离(`docs/porting/moviepilot-rust-transfer.md`)
- FsProxy + fsworker:文件操作在可杀子进程里执行;复制 / 哈希按进度停滞看门狗(`FS_HANG_TIMEOUT_MS`),快操作按总超时;超时后 SIGTERM → SIGKILL → `FsError('TIMEOUT')`,stat / 根探测超时不会被当作"不存在"。
- 生产二进制内置 `--role fsworker`(`/app/umt-server` 自身 spawn,容器演练见 `docs/runbook/deploy.md`)。
- `copyWithVerify` 支持 conflict / skip / replace:replace 先硬链接留底再原子 rename,旧文件进 `.umt-trash` 并登记 `trash_item`;写前清理超过 24h 的 `.uhd-partial`。
- 核验读失败抛错,不再当作"不匹配";对账错误不再误报 EEXIST;TIMEOUT / IO 有限重试(`FS_TRANSFER_MAX_ATTEMPTS`)后建待处理,不删记录。
- 复制流 1 MiB 块;强制全量 sha256 走 `sha256sum` 子进程;手动整理遍历有上限(`ORGANIZE_WALK_MAX_FILES`)。
- 字幕 `.default` 标记、同集其他版本作为洗版处置候选。
### Agent 会话页
- 移植 agentui(MIT,`LICENSE-agentui.md`)组件并换成本项目语义 token:流式光标、可展开的思考块、带类别 / scope / 风险 / 幂等徽章的工具卡、服务端拒绝的醒目态、压缩标记、预算条、审批卡(仅管理员会话可操作)、"模型声明 vs 系统核实"双栏最终汇报、跟随滚动与回到底部。
- 输入框(Enter 发送、中止需确认、追加、执行 / 只要方案切换、从方案一键执行)、会话列表与状态筛选、断线重连横幅;侧栏抽屉按路由带入上下文,可最小化为迷你坞。
- 设置页新增 `autoInvestigateMode`(调查 / 授权内恢复)与最大恢复次数、`agent.sessionDir`。
### 识别与站点解析补迁(MoviePilot 差分)
- 标题识别:动漫前缀标签、多种集号写法、首括号作标题或组名、原盘判定、`{[tmdbid=…]}` 显式块与 bangumi/anilist id、流媒体平台表等;繁简表补字。标题识别剔除登记项后 100% 对齐,missing / our_bug 清零。
- 站点:18 个站点定义的行选择器收紧、字幕搜索分支(只到解析层)、体积解析的银行家舍入。差分快照与样本来源登记在迁移账本。
### 稳定性与部署
- 容器内三个受监管进程(api + worker(io)+ worker:agent),静态 ffprobe。
- qB 同步在事务内 `for update` 重读下载任务后再合并,修复与入库并发时把 `imported` 写回 `importing` 的丢失更新。
- 授权内恢复的核实结论与 run 终态同一次写入,观察者不会读到中间态。
- 完成判定只保留 `applySlotEvent(verify_passed)` 一条路径,整理流程不再自行把订阅置为完成。
- server 测试分为并行的 unit 组和文件级串行的 pg 组,`packages/tasks` 同样串行;`deno task ci` 连续 3 次全绿(约 340–370 秒)。
### 发布前安全修复(W6-B,`07-v0.1-final-review`(已删除,见 git `ceb66f8`) §1.2)
- 多源 Move 授权:`/files/move` 与 `/files/organize`(action=move)按**每个源**所属作品(声明作品 ∪ 源下已登记资产的作品)逐一核对持续授权,任一不覆盖整体 403 并列出未授权项;无法归属作品的源只接受一次性审批;organize 先整体预检,不会只执行一部分组。
- `GET /files/download`、`POST /files/trash/purge` 在注册表标 `auth:"session"`,由中间件统一只放行管理员会话(DEV key 与 admin scope 的 API Key 一律 403);永久删除同口径;`api-registry.test` 新增反向断言,未标 session 的端点不得对 admin scope 返回 403。
- 脱敏键表只剩一份:rss 与 browser 的参数判定改用 `@umt/contracts` 的 `SENSITIVE_QUERY_PARAMS` / `isSensitiveQueryParam`,补齐 `pass_key`、`c_secure_pass`、`refresh_token`、`password`、`uid_key`、`auth` 等写法,加三处一致性测试。
- 回收站"还原到…"只允许可写的 managed 库根;原位还原逐级重建父目录且不跟随符号链接;跨卷还原受 `FILES_TRASH_CROSS_MAX_BYTES` 上限,回收站进出的跨卷复制经 fsproxy。
- `/files/identify` 的远端查询经进程共享的 TMDB 限流器,单次请求最多 20 个远端查询;`POST /files/probe` 改为需要 `organize.execute`(会写 `media_info`)。
- fsworker 阶段完成的进度一律立即上报,不再被节流吞掉最后一跳(全量 ci 下偶发的 fsproxy 用例失败)。
- fsproxy 挂死验收开关 `UMT_FS_TEST_HANG_AFTER_BYTES` 必须同时设置 `UMT_FS_TEST_HOOKS=1` 才生效,preflight 发现已设置会告警。
- 控制台账户弹层新增"二次验证"入口(生成密钥 → 验证码确认开启;凭密码 + 验证码关闭),不显示二维码,手动输入密钥或 otpauth 链接。
### 已知限制
完整清单与出处见 `07-v0.1-final-review`(已删除,见 git `ceb66f8`) §8;范围外内容以 `00-first-version-plan`(已删除,见 git `ceb66f8`) §3.2 与 §6 为准。
**范围外(00 §3.2 / 02 后置)**
1. 国产综艺分段、`require_distinct_asset` 组合校验、浏览器 / camofox 与原站视图、HHClub / CHD、旧库分范围接管、Agent 主观选片与规则学习、多用户。
2. Passkey、主密钥轮换、子代理、Transmission、TTG 自定义适配、馒头 adult 模式。
**订阅(05 §4 遗留)**
3. 完成判定前不会强制刷新元数据;titleQuery 订阅不会自动建档回填;季范围语义(`current_season` 在没有季单元时固定)未做;偏好标签不参与评估。
4. 同作品同季重复订阅没有查重;`prefer_pack`、回退等待期、Agent 选片理由与独立预算、队列按优先级出队、实体级识别词都未做;没有"清账重置"(只能把状态改回 active 重新订阅)。
5. (已解决)完成判定的双路径已在 W6-A 合并为一条,编号保留以便与 07 §8 对照。
**文件管理**
6. NFO / 图片投影(scrape 的 `writeNfo/images` 返回 `not_implemented`)、硬链接、蓝光原盘整目录操作未做;路径守卫没有下沉到 adapters。
7. 从回收站还原不会恢复资产状态,需要重新整理登记;永久删除开关是环境变量,不是设置项。
8. 跨卷进回收站与跨卷还原(都受 `FILES_TRASH_CROSS_MAX_BYTES` 上限、复制经 fsproxy)、永久删除、identify(已经走 TMDB 限流器,单次最多 20 个远端查询)、probe(串行,每次 30 秒超时)仍在 HTTP 请求内执行;浏览、根探测、readdir 与永久删除的 `rm` 不经 fsproxy。计划 v0.1.1 改为入队(07 S-7)。多项永久删除没有服务端的逐项确认(单项要求 `confirmName`)。
9. 前端没有整理向导 e2e 和移动端快照,页面行为靠 model 单测和冒烟覆盖。
**转移与文件系统**
10. `planImport` 规划期的 stat / 哈希、资产对账和文件管理不经 fsproxy;没有根级熔断;失效软链一律按冲突处理;hardlink、organize 源侧空目录上溯清理、蓝光原盘未做。
11. 二进制必须位于 `/app/umt-server`,否则 fsproxy 回退为进程内看门狗(能按时报 TIMEOUT,但卡住的线程无法回收)。基准 B1(50 GB)、B2(并发)、B3(真实 FUSE 冻结)没有跑。
**Agent 与安全**
12. (已解决,W6-B)控制台 TOTP 入口已补;开启时只显示密钥与 otpauth 链接,不渲染二维码。
13. (已解决,W6-B)rss 和 browser 已改用 contracts 的共享键表;全仓凭证泄漏的故障注入测试留到 M2。
14. `GET /inventory/media-servers` 在请求内串行查 Emby;能力调用超时后,底层调用仍会跑完。
15. Agent 页的幂等键来自审计(最多 3 页),审批卡片的 planId 靠解析工具摘要得到,较早的运行可能取不到。
16. 自动恢复只核实到下载恢复,入库由后续流程负责;恢复白名单只有 `task.retry`、`download.recheck`、`identity.resolve`。
**识别与站点**
17. 字幕搜索只到解析层;RSS 不带时区的时间与 HTML 命名实体未处理;过滤器的 tmdb 放行、SPECSUB 等属于 Slot 能力扩展。
**质量与运维**
18. 恢复流程只有人工演练;流程版本升级没有产品侧测试;下载状态机 `ALLOWED` 未收紧;`scanIncremental` 出错时仍返回 complete;AT18 恶意标题 e2e、AT42 未纳管占用没有测试;`vertical.test` 的用例依赖执行顺序;web 单测少(账户弹层的 TOTP 对话框只有类型检查,没有组件测试);E6 自动恢复只核实到 recheck 后回到下载中,engine-retry 用的是 mock enqueue。
19. `deno task ci` 约 6 分钟(W6-B 两次全绿 357 s / 341 s),server 测试(pg 组文件级串行)是主要耗时。