Files
UHD_Media_Tool/docs/plan/14-engineering-review.md
T
rootandClaude Opus 5.5 ceb66f8c77 feat: v0.3.8–v0.3.14 工作区汇总(依赖升级、整理来源、手动入库、原地入库等)
生产 v0.3.8~v0.3.13 均由 8013196 加工作区修改构建部署,此前未提交;本提交补齐源码,
并含未部署的 v0.3.14 原地入库。中间各版本源码状态未保存,无法逐版拆分,详见
docs/plan/17-full-upgrade.md 与 docs/plan/18-organize-release.md。

- v0.3.8 全面升级:Deno workspace 依赖、Router 8 / Vite 8、camofox 1.18.0 / Node 24、
  PostgreSQL 18.6、备份客户端 18.6、演示 qB 5.2.4
- v0.3.9 媒体整理:分类规则、整理来源与目录快照(0059)、文件管理整理入口
- v0.3.10 手动下载与入库:独立手动下载、详情页资源下载、TMDB / Local 元数据兜底
  (metadata.resolve_organize)、正常多版本 / 一次性洗版(0060)
- v0.3.11 搜索详情与桌面黑边修复
- v0.3.12 列表分页、搜索历史、首页概况
- v0.3.13 统一整理弹窗与队列
- v0.3.14 原地入库(0061,未部署)

同批审计修复:
- 刮削入队:确认原记录存在后才删重放产生的新记录;写回 run 关联失败时保持 queued,
  由处理器补关联(对齐 MP 先登记、只在入队失败时记失败)
- 识别升级链只在结果更确定时采用,不再用 no_match 顶替原有歧义候选
- bluray_dir 资产以原盘目录本身为刮削根(MP 同做法)
- metadata.resolve_organize 登记到入库排障 Skill 与能力地图
- db/src/types.ts 按迁移重新生成;contracts 整理动作枚举顺序与数据库对齐
- 测试:原地入库用例改为直接查记录表;domain 测试模板补 version
- 前端:通知铃铛弹层与用户菜单统一样式;站点卡片共用卡头、底栏贴底、分页间距

依赖升级证据只提交摘要文件,registry-snapshot.json 移至 .local/(SHA-256 记于文档)。

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-02 15:47:17 +08:00

108 lines
14 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.
# 工程检查与调整建议
本报告回答「继续开发之前是否需要先处理工程问题」。当前版本完整 CI 通过,主流程实现和部署均存在;检查仍发现任务升级、入队与业务记录一致性、故障状态判定以及验收口径需要先厘清。建议先做一轮范围明确的恢复与验收补强,再确定后续功能范围。
日期:2026-10-01。升级前业务代码基线:`main`,`8013196`,`v0.3.7`。开发情况与 R01 至 R32 覆盖见 [当前开发情况基线](13-development-baseline.md)。本轮采用两个中等思考强度的独立代码/验证检查、一个低思考强度的文档检查,由主代理复核和汇总。该检查阶段没有修改业务实现、提交、部署或执行数据修复。后续用户授权的依赖与容器升级执行状态见 [完整升级记录](17-full-upgrade.md)。
后续核查按用户确认先逐项参考 MoviePilot v3 的业务逻辑,再讨论调整。进度见 [MoviePilot v3 逐项业务对照](15-moviepilot-v3-comparison.md):已固定 v3.0.10-1 源码,第一项任务恢复与升级兼容完成源码对照;后续已实施局部恢复修正并做故障注入,见下方当前落实情况。
并行完成的版本检查见 [依赖与程序版本报告](16-dependency-version-review.md):记录 58 个直接依赖、主锁文件和浏览器独立审计、运行程序版本,以及 PG 18/Pi 原生 MCP 的迁移边界;该版本检查阶段没有执行依赖更新或部署。
## 当前落实情况(2026-10-01)
用户讨论后授权的恢复修正已落到源码:引擎接受任务后回填关联失败保留 queued 并记日志;worker 执行时补关联;巡检优先查最新 run 并修复关联,查询失败跳过当前轮次,不误判成不存在补投。刮削去重复用原业务记录,不让回填失败把已接受的任务标成失败。
`enqueue-recovery.test.ts` 在隔离 PostgreSQL schema 中完成 9 个故障测试,包括关联写失败、原 run 修复、已有活跃 run 的查询异常。连同接管、刮削和手动季集覆盖回归,5 个测试文件共 34 个测试通过。发布前旧任务检查补到 [部署手册](../runbook/deploy.md#6-升级)。没有引入新恢复器、任务状态机或永久旧 handler。
后续媒体整理范围经过用户逐项讨论后实现:可编辑 TMDB 分类 YAML、单来源配置、复制/移动、qB 标签接管、首次基线+增量快照、一次性存量向导。运行说明见 [整理手册](../runbook/organize.md)。这轮功能已发布为 v0.3.9,见 [发布记录](18-organize-release.md);下文检查表保留检查阶段的事实和其他仍需讨论的项目。
## 1 结论如何使用
「代码已确认」说明能从当前控制流或配置看到该边界;「影响待复现」说明尚未做故障注入,也未证明用户已经受影响;「验收证据不足」说明已有实现不能用当前证据验收完整要求。下文建议是供讨论的工作范围,不是已执行的修复或已批准的排期。
完整 CI 的 3264 个通过测试能证明现有固定回归通过;不能证明未结束的旧版本任务、线上故障下的双写恢复、真实模型行为或真实媒体挂载已经验收。应为这些具体边界补证据,而不是只扩大通过测试的总数。
### 1.1 用户确认的工程取舍
用户认可任务恢复的调整方向,同时明确本产品面向团队内部,避免过度设计和过度防御。后续优先修复已确认、会影响正常使用的局部问题,复用现有任务引擎、幂等键、巡检和记录页面。MoviePilot 用于参考同一场景的业务处理,不照搬其全部基础设施。
临时查询异常保留日志并等待下一轮,不新增人工审核流程;普通可重试失败使用已有重试,最终失败说明原因并支持现有入口重试。只有删除、覆盖、替换文件等操作出现实际状态不明或冲突时,才停止自动执行并提示处理。没有复现需要之前,不增加通用恢复框架、第二套任务状态机或新的补偿服务。
旧任务兼容先用发布前检查和处置清单解决;没有在途旧任务时,不为假设场景长期维护旧处理器。验证围绕本次改动的失败分支和文件保护展开,T01 至 T06 是场景清单,不作为继续所有开发的统一前置门槛。当前版备份恢复和部署验收已在升级阶段完成,见 [升级记录](17-full-upgrade.md),后续针对实际变更补充验证。
## 2 建议优先核对的恢复边界
### 2.1 刮削任务升级后的旧任务承接
**代码已确认,当前部署未发现未结束的旧刮削任务。** [handlers.ts](../../apps/server/src/modules/acquisition-organize/handlers.ts) 第 193 行起只注册 `scrapeMedia` v2,输入是 `recordId`。旧版本 v1 使用作品 ID 和触发方式等输入。worker 在 [openworkflow-engine.ts](../../packages/tasks/src/openworkflow-engine.ts) 第 221 行起按已注册的任务名和版本过滤认领,当前清单没有 v1。
因此升级前未结束的 v1 run 如果存在,当前 worker 没有对应处理器。0058 迁移还将原 `media_scrape` 表替换为 `scrape_record`,不能简单恢复旧处理器而不核对数据结构。需要明确旧任务应完成、迁移、取消还是以说明终止。
本轮对部署数据库只读聚合:`scrapeMedia|v1|completed|1`,没有其它刮削任务状态;`scrape_record` 没有记录。**这次没有发现受影响的活动旧任务,也没有据此做任何取消或补投。** 这个结论只对应本次检查时点。
最小下一步:把「升级前未结束的任务版本清单及处置」加入发布记录。在隔离环境用上一版本入队、当前版本恢复验证兼容方案,避免只验证同版本崩溃恢复。
### 2.2 入队成功和业务记录关联回填不是一个原子操作
**控制流已确认,故障影响待复现。** [scrape.ts](../../apps/server/src/modules/acquisition-organize/services/scrape.ts) 第 152 行起先插入 `queued` 记录,第 192 行入队,第 207 行回填 `engine_run_id`。入队成功而回填失败,也进入同一个 catch,将记录标为 `failed/task_enqueue_failed`。第 476 行的执行器对 failed 记录直接返回。
可能出现两种不一致:插入后、入队前进程退出,留下没有 run 的 queued 记录;入队已成功、回填失败后记录先被标为 failed,worker 再读取时跳过。实际结果取决于失败时点,本轮没有通过故障注入证明发生概率,也没有把它写成已发生的线上故障。
[common.ts](../../apps/server/src/modules/acquisition-organize/services/common.ts) 第 134 行的 `enqueueTracked` 也依次执行业务行、引擎入队和回填,应一起定义恢复口径。稳定幂等键可以帮助找到已有 run,但本身不等于已完成关联恢复。
最小下一步:在隔离测试中分别注入这三个时点的失败,确认最终状态。再选择恢复回填与补投方案,或复用现有事务 outbox;保持改动集中在这些入口。
### 2.3 引擎查询失败被当成查无任务
**异常处理行为已确认,重复补投的实际影响待复现。** [common.ts](../../apps/server/src/modules/acquisition-organize/services/common.ts) 第 171 行在巡检中使用 `engine.get(...).catch(() => null)`,查询异常和明确不存在共用 null。下一时间槽可能补投新 run,而旧 run 仍在运行,共享同一业务任务行。
下载与文件操作已有底层幂等账本,不能直接推断会重复下载或覆盖文件。但两条 run 竞争业务行、回填关联和状态的风险,需要单独验证。
最小下一步:故障注入中模拟一次引擎查询异常;讨论让查询异常记录并跳过本轮,仅在明确查无 run 或终态时补投。这个边界适合与 2.2 一起检查。
### 2.4 默认空壳可以掩盖正式任务注册遗漏
**维护风险已确认,当前核心任务都有正式处理器。** [context.ts](../../apps/server/src/context.ts) 第 96 行为缺失的核心任务注册 stub;[modules.test.ts](../../apps/server/test/modules.test.ts) 第 86 行主要检查任务名存在。未来如果漏注册真实 handler,名字检查仍可能通过,stub 回显 todo 后可以成功结束。
本轮装配核对确认最初 9 个核心任务均已由业务模块覆盖,不应把当前主流程描述成「还是空壳」。
最小下一步:下一次触及模块或任务注册时,增加完整生产模块装配的处理器来源断言;讨论是否只允许局部测试装配使用 stub。无需因此重写任务系统。
## 3 应先明确的验收口径
| 检查项 | 当前事实 | 需要补的最小证据 |
| --- | --- | --- |
| PG 测试必执行 | 部分 server/tasks harness 在 PG 探测失败时跳过;默认 db 包连接失败会报错,所以不能称默认整条 CI 会在无 PG 时全绿 | 在 CI 汇总中保留跳过清单,讨论严格 PG 模式;区分允许跳过的真实模型和真实 qB |
| 前端冒烟 | 独立于普通 CI;[smoke.mjs](../../apps/web/scripts/smoke.mjs) 第 188 行详情页数据获取失败或为空会 skip,最终主要按失败数退出 | 固定演示数据、必须执行的详情页,以及接口错误和合法空数据的不同判定;本轮没有跑页面冒烟 |
| 模型行为 | E13 有恶意网页清洗、URL 与不可信标注回归,但用固定 FakeScript;AG-5 真实前后评测默认关闭且历史记录明确未跑 | AT18 的真实模型行为单独评测,不用 fake 模型脚本替代;模型调用须在明确范围内进行 |
| 部分入库后的清理 | [downloads.ts](../../apps/server/src/modules/acquisition-organize/services/downloads.ts) 第 1043 行检查最近整理成功并拒绝失败/排队/运行/取消文件,已有保护 | AT29 构造部分成功仍有源文件的反例,核对不会整种清理;不能写成「没有删除保护」 |
| 未纳管占用 | 域层有 `managed:false` 和增长风险断言;服务层现有阈值测试主要使用假磁盘 | AT42 用固定同卷场景核对汇总占用和暂停范围 |
| 多实例同 hash | 多下载器选择有测试,未找到两个实例同 hash 后分别同步、暂停、删除的完整专项断言 | AT73 在 mock qB 的两个实例中核对任务与清理隔离 |
| 备份一致性和恢复 | [backup.sh](../../scripts/backup.sh) 依次 pg_dump、导出映射、归档在线会话,产物不是同一时点;早期临时恢复演练曾通过 | 当前版隔离恢复演练,明确在线变更如何影响映射和会话比对,再决定是否需要一致性改造 |
| 镜像运行与来源 | 编译自检在空环境验证模块图可加载,不能替代最终镜像的进程、工具、静态文件、权限和挂载检查 | 下一次发布记录源码提交和镜像摘要,并做隔离镜像启动验收 |
本轮完整 CI 中 PG 集成实际运行;上述 PG 问题属于后续执行环境变化时的验收可靠性,不是本轮大量跳过集成测试。没有新增或改写测试来掩盖缺口。
## 4 已解决的工程问题与文档调整
已有 cleanup/reconcile 入队、后台任务编排、IO 与 Agent worker 隔离、文件/网络/维护分道、请求限制器、整理 walk 上限、sha256 子进程和操作账本。`GET /inventory/media-servers` 已多实例并行、限制实例内并发并设总超时,旧串行遗留不能继续作为待开发项。
本轮文档调整集中在影响当前判断和操作的内容:建立需求基线与工程检查报告;将早期覆盖表和解耦审计标为历史;校正 README 的能力数、刮削、验证和部署形态;统一当前部署示例的 `.env.deploy`;修正默认桌面镜像构建前提、浏览器内存配置、MCP 工具数、站点详情补请求和识别异步说明。
基线中的所有本地文件链接均另行检查。历史演练表和对应日期、测试数继续保留,避免把新结论改写进旧验收记录。源码中的旧注释与较早手册可能仍有残留,遇到冲突以当前代码和这两份基线报告为准。
## 5 供讨论的下一阶段范围
建议下一阶段先以「任务升级和异常恢复可核验」为范围,交付 2.1 至 2.3 的故障与升级证据、当前恢复演练、明确的测试跳过清单和发布来源记录。2.4 可在同一轮触及装配时补强。这里是建议,尚未修改对应实现或开始功能开发。
然后再确定功能阶段:综艺完整性、独立双版本、旧库接管、智能体选片与规则优化都仍有需求缺口,但应按具体场景分别验收。每阶段要明确触发入口、最终结果、失败和等待处理、固定样本与真实环境需求。
讨论时需要决定的是下一阶段的目标和边界,以及哪些验收证据必须先补。已有授权、稳定路径和清理保护不需要重新设计;尚未复现的问题应先做有针对性的核查,再确定最小实现调整。
## 6 升级核验新增的待讨论证据
2026-10-01 的 1.18 浏览器升级核验已覆盖正常重启、空闲回收、旧元素引用拒绝、登录保持与 SIGKILL 后未落盘登录丢失识别。现有核验脚本原先会捕获错误后返回成功,且仍期待自动重连之前的行为,本次已修正并收紧下载关联和脱敏断言。
精确恢复页面地址仍有证据缺口:核验 a 阶段末尾曾导航回列表,b/idle 恢复观测地址为详情页,缺少 a 末尾的数据库 URL 与最终快照对照,目前不能判定为已复现业务故障。后续应在重启前记录 `BrowserService.view(sid).currentUrl`、`snapshot.url`、`browser_session.current_url` 与当前 `browser_tab.url`,重启后逐一比较;恢复入口见 `apps/server/src/modules/browser/service.ts` 的 `restoreUrl(row.current_url)` 及适配器 `reopenSession`。十项能力核验不等同于精确 URL 恢复已经验收,下一轮业务对照应补这个场景。