chore(release): v0.3.26

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-10-03 20:08:42 +08:00
1 parent 7793c7b3bc
commit 6b19cede62
15 files changed
+26 -73

No files matched your search

+1 -2
View File
@@ -17,7 +17,7 @@
## 当前状态
- 版本 v0.3.25,本机测试环境已部署。
- 版本 v0.3.26,本机测试环境已部署。
- 开发与发布约定见仓库根 [CLAUDE.md](../../CLAUDE.md)。
## 待办
@@ -31,7 +31,6 @@
### 进行中
- 集数解析与映射:[episode-resolution.md](episode-resolution.md),5 批,Agent 兜底在最后。
- 补字幕:[subtitles.md](subtitles.md),第 1、2 步已完成;待办:以后接进整理 / 订阅工作流。
- 沙箱第二批:站点网页、RSS、网页抓取的 HTML / XML 解析迁入常驻子进程池(ADR-005)。
-59
View File
@@ -1,59 +0,0 @@
# 集数解析与映射(2026-10-03 定)
解析器只回答「发布者声称这是第几季第几集」;本模块回答「媒体库应当把它当成哪一集」。参考 MP 的偏移表达式、ANI-RSS 的订阅预览,在其上加元数据校验、确定性换算、规则与待处理,Agent 兜底放最后。
ANI-RSS(GPL-2.0,只借思路不抄代码)摸排结论:一条订阅 = 一条 feed + 一个字幕组 + 一个 bgm 条目;集号靠一条正则;偏移只有整数,自动推断 = `-(feed 最小集号 - 1)`,不核对元数据;TMDB 只用于集标题(可选 Episode Group);体验来自「订阅预览」(按偏移算好的集号 + 已下载 + 缺集)与缺集 / 摸鱼提醒。
## 现状与缺口
- 本地 UUID 主身份、外部身份表、集单元的 `kind / content_type / segment / source_issue` 已有。
- `release-parser/offset.ts` 的偏移表达式求值器没有任何调用方。
- `ensureUnits` 拿解析结果直接找或建集单元:TMDB 第 2 季 12 集,解析出 S02E13 会建临时 S02E13,不报错。
- 整理(`organize-plan.ts`)、季包选文件(`downloads.ts`)、接管(`takeover.ts`)会对文件名重新解析,映射必须在这些地方同样生效。
## 判定流程
输入:解析结果 + 作品 + 季表(每季总集数、是否最新季、作品是否完结、已知每集播出日期)+ 资源发布时间 + 发布组 + 该作品的映射规则。只处理剧集类作品的正片(`content_type = main`、季号 ≥ 1);电影、特别篇、花絮原样通过。
1. **有适用规则**(作品 + 季 + 发布组,越具体越优先)→ 按规则换算 → 校验。校验失败:规则停用、开待处理,本条资源按「待确认」处理。
2. **无规则,原号校验**:
- 季存在且集号 ≤ 该季总集数 → 通过。
- 季总集数未知、或该季是最新季且作品未完结、且集号超出不多 → **放行**(元数据滞后),记 `unverified`。
- 否则 → 不通过,进第 3 步。
3. **确定性换算**(结果都要再校验,且只取唯一解):
- 季内绝对集号:`S02 13`、第 1 季 12 集 → `13 - 12 = S02E01`。
- 跨季绝对集号:季号是推定的(`seasonInferred`),集号超出第 1 季 → 按各季总集数累加换算。
- 与「元数据滞后」冲突时(最新在播季)用发布时间判:发布时间与换算后那集的播出日期相差 ≤ 7 天才认换算,否则按滞后放行。
- 综艺:有 `airDate` 时按播出日期对集。
4. **仍不行** → 资源已绑定作品但集数待确认:不建集单元,订阅评估跳过(原因 `episode_unresolved`),开待处理 `episode_mapping`(按作品 + 季 + 发布组去重),附建议规则。
结果写入 `source_release.episode_resolution`(原始季集、规范季集、方式 `raw / rule / absolute_in_season / absolute_cross_season / air_date / unverified / unresolved`、规则 id、证据),`parsed` 里的季集改为规范值,下游不用改口径。
## 映射规则
- 作用域:作品(必填)+ 来源季(可空)+ 发布组(可空)。不做全局 / 站点级(站点标题差异由别名表解决)。
- 类型:`expression`(复用 `offset.ts`,如 `EP-12`、`EP*2-1`,可带目标季)、`table`(`26 → S02E01`、`27-28 → S02E02`)、`special`(映射为特别篇 / 花絮 / 忽略)。
- 证据等级复用 `manual / rule_confirmed / multi_evidence / needs_review`,不用百分比。
- 失效:规则算出的结果校验不通过 → 停用并开待处理,不做置信度衰减。
- 规则建立或修改后,按作品重算已绑定资源的集数解析(不重做身份识别)。
- 建议规则:同作品 + 季 + 发布组下的待确认资源,用发布时间对播出日期配对,试 `EP±n` / `EP*2` / `EP*2-1`,全部样本成立才给建议。
## 分批
| 批次 | 内容 | 验收要点 |
| --- | --- | --- |
| 1 领域纯函数 | `packages/domain/src/episode-resolution/`:类型、校验、确定性换算、规则应用、建议规则推导、总入口 | domain 单测覆盖上面每个分支(含滞后放行、发布时间判定、多解拒绝、表格规则、双集) |
| 2 存储与识别接入 | 迁移(`episode_mapping_rule` 表、`source_release.episode_resolution`);季表加载;识别(`resolve.ts` 及其他 `ensureUnits` 调用方)接入;`parsedOf` 叠加;订阅评估跳过待确认;待处理 `episode_mapping`;规则失效;按作品重算 | server pg 测试:ANi 连续编号进库即为 S02E01 并能被订阅覆盖;规则失效开待处理;滞后放行不卡追更 |
| 3 文件侧接入 | 整理计划、季包选文件、接管、文件管理识别统一套用同一作品的映射 | 下载按 S02E01 计划、文件名 ` - 13` 整理后命名为 S02E01;季包按缺集选对文件 |
| 4 接口与界面 | contracts 端点:规则增删改、模拟预览(给定作品 / 季 / 发布组 / 草稿规则,列近期资源的原始 → 规范与校验结果);待处理 `episode_mapping` 的确认 / 修改 / 忽略;作品页与订阅详情「集数映射」面板 | 契约测试、web 单测、冒烟;文案过 `check:copy` |
| 5 Agent 兜底 | 能力 `episode_mapping.inspect`(只读上下文包)、`episode_mapping.simulate`(试草稿规则)与 `episode_mapping.apply_rule`(经授权写规则,服务端强制先模拟全部样本通过、不误伤已对上的资源);Skill「集数映射」与能力地图;`episode_mapping` 待处理接后台自动调查,没有授权时留「智能体建议」一键确认 | agent 测试;模拟不通过的建议不能写入 |
以后再做:TMDB Episode Group、Bangumi `sort / ep` 对照、综艺会员加更等变体细分。
## 状态
- [x] 批次 1
- [x] 批次 2
- [x] 批次 3
- [x] 批次 4
- [x] 批次 5