# Changelog 版本号遵循 [SemVer](https://semver.org/lang/zh-CN/)。所有成员包(`apps/*`、`packages/*`)与根 `deno.json` 使用同一个版本号;`/api/v1/health` 与备份清单里的版本取自 `apps/server/deno.json`。 ## [0.1.0] - 2026-09-28 第一个可用版本:REQ v0.7 的 M0 + M1 纵切。全链路在没有真实 PT 账号的情况下用 mock(RSS / 站点 / TMDB / qBittorrent / Emby)验证。范围与验收依据见 `docs/plan/00-first-version-plan.md` §3.1 和 `docs/plan/04-v0.1-acceptance.md`。 ### 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::<序号>`,写审计),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)。 - 回收站:`/.umt-trash///`,`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,`docs/plan/05-subscription-gap.md`) - 总集数账本:季单元记录 `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 秒)。 ### 已知限制 完整清单与出处见 `docs/plan/07-v0.1-final-review.md` §8;范围外内容以 `docs/plan/00-first-version-plan.md` §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 合并为一条(见"稳定性与部署")。 **文件管理** 6. NFO / 图片投影(scrape 的 `writeNfo/images` 返回 `not_implemented`)、硬链接、蓝光原盘整目录操作未做;路径守卫没有下沉到 adapters。 7. 从回收站还原不会恢复资产状态,需要重新整理登记;永久删除开关是环境变量,不是设置项。 8. 跨卷进回收站(≤2 GiB)、跨卷还原、永久删除、identify(每项超时 15 秒,不经 TMDB 限流器)、probe 都在 HTTP 请求内执行,也都不经 fsproxy。 9. 前端没有整理向导 e2e 和移动端快照,页面行为靠 model 单测和冒烟覆盖。 **转移与文件系统** 10. `planImport` 规划期的 stat / 哈希、资产对账和文件管理不经 fsproxy;没有根级熔断;失效软链一律按冲突处理;hardlink、organize 源侧空目录上溯清理、蓝光原盘未做。 11. 二进制必须位于 `/app/umt-server`,否则 fsproxy 回退为进程内看门狗(能按时报 TIMEOUT,但卡住的线程无法回收)。基准 B1(50 GB)、B2(并发)、B3(真实 FUSE 冻结)没有跑。 **Agent 与安全** 12. 控制台没有 TOTP 开关入口(后端 `GET/POST /auth/totp` 已有)。 13. rss 和 browser 的脱敏键表没有与 contracts 统一。 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 单测少。 19. `deno task ci` 约 6 分钟,server 测试(pg 组文件级串行)是主要耗时。