feat(identify-words): 识别词——全局识别词(MP 语法)+ 作品识别词(季集换算),规则页「识别词」页签
- 新表 identify_words(0094):全局一块 + 每部作品一块原文,带版本与审计;episode_mapping_rule 转成文本行后删表
- 全局识别词移植 MP WordsMatcher(屏蔽 / 替换 / 集数偏移 / 替换+偏移 / {[tmdbid=…]}),所有按标题 / 文件名识别的地方解析前套用,命中的行记在解析结果上;保存后后台按改动行重新识别
- 作品识别词:S02 >> S01 EP+24 / S01E13 >> S00E01 / S01 @组 >> 忽略,解析器 + 打印器 + 编译;发布组繁简视为同一个
- 去掉规则自动停用:算出来对不上季表只待确认,要停用就注释掉那一行
- 集数待确认的采用 / 忽略与智能体 apply_rule 改为往作品识别词追加一行(带来历注释)
- 编辑器可视化 / 文本两种模式改同一份原文,保存前试算;作品页「集数映射」用同一个编辑器
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
This commit is contained in:
1 parent
12f8fc59c3
commit
63e94b308e
90 files changed
+6366
-2131
No files matched your search
@@ -100,6 +100,7 @@ ci 逐行核对这张表与任务注册表(`apps/server/test/worker-lanes.test.t
|
||||
| `enrichPoolEntry` | network | 未识别资源的元数据补全 |
|
||||
| `refreshMetadata` | network | TMDB 元数据刷新 |
|
||||
| `prewarmMetadata` | network | 关注作品预热:详情 / 各季 / 剧集组 / 海报背景标志进缓存(docs/runbook/cache.md) |
|
||||
| `reresolveIdentifyWords` | network | 全局识别词保存后分批扫资源,标题命中改动行的重新识别(docs/design/identify-words.md) |
|
||||
| `searchSubscription` | network | 订阅搜索 |
|
||||
| `snapshotSite` | network | 站点快照 |
|
||||
| `refreshSiteAccount` | network | 站点登录 / 用户数据刷新 |
|
||||
|
||||
+14
-14
@@ -151,20 +151,20 @@ select key, value->>'title' title, value->>'year' y, value->>'source' src from k
|
||||
建订阅、用户搜索 / 手动识别命中已有作品、开始下载(`submitDownload`);刷新会按作品重算待确认 / 滞后放行的资源,换算不了的这时才开事项。
|
||||
集数待确认不再是给用户逐条处理的条目:原因在订阅详情「集数映射」与作品页「集数映射」分区按组显示,建议规则 / 智能体建议在作品页一键确认。
|
||||
|
||||
**规则**在作品页「集数映射」分区管理(`GET/POST /media-entities/{id}/episode-mapping-rules`、`PATCH/DELETE /episode-mapping-rules/{id}`):
|
||||
**规则**是作品识别词(2026-10-08 起,语法与在哪生效见 [识别词](../design/identify-words.md)):一部作品一块文本,在规则页「识别词」和作品页「集数映射」里改的是同一份(`GET/PUT /media-entities/{id}/identify-words`,试算 `POST …/identify-words/dry-run`)。
|
||||
|
||||
- 作用域:作品必填,来源季、发布组可空(空 = 任意);越具体越优先。同作品 + 季 + 发布组(发布组忽略大小写)只能有一条启用的规则,冲突返回 409,先停用或修改旧的那条。
|
||||
- 类型:**偏移表达式**(`EP-12`、`EP*2-1`,省略 EP 按 MP 约定补全,可指定目标季)、**对照表**(每行 `26=S02E01`,区间 `27-28=S02E02`,区间不能重叠)、**特别篇 / 花絮 / 忽略**。表达式解析不了、表格区间不合法直接拒绝。
|
||||
- 每次新建 / 修改 / 停用 / 启用 / 删除都在同一事务里按作品重算已绑定资源(人工锁定的不动),返回重算条数、变化条数、待确认转已解决条数;资源解决后对应的事项自动关闭。
|
||||
- 规则算出的集数对不上季表时自动停用(停用原因写当时的来源季集)并重新开事项;手动停用的原因写「手动停用」。
|
||||
- 一行一条:`S02 >> S01 EP+24`(季集换算)、`S01E13 >> S00E01`(单集对照)、`S01 @发布组 >> 忽略`(特别篇 / 花絮 / 忽略);`@发布组` 可写多个,`*` = 任意季;越具体越优先,同一范围只能有一行。
|
||||
- 规则照写的用:算出来对不上季表的资源保持集数待确认,预览里标「对不上」,这一行不会被自动停用;要停用就把这一行注释掉(可视化里关掉开关)。
|
||||
- 保存带读到的版本,别处先改过返回 409;写错的行拒绝保存;保存后在同一事务里按作品重算已绑定资源(人工锁定的不动),返回重算条数、变化条数、待确认转已解决条数,资源解决后对应的事项自动关闭。改动写审计 `identify_words.updated`(增删的行)。
|
||||
- 0094 迁移把旧的结构化规则(episode_mapping_rule)逐作品转成文本行后删表:同季同换算的多个发布组合成一行,单集对照一行一条,停用的规则变成注释行,智能体写的规则上方加一行注释。
|
||||
|
||||
**模拟预览**(`POST /media-entities/{id}/episode-mapping/preview`,纯读):取作品下最近 100 条已绑定资源(按发布时间倒序,可按季 / 发布组过滤;季按来源季或规范季任一匹配),按原标题重解析后逐条给出原始季集 → 库里的当前结果 → 套用草稿规则后的结果、校验状态、是否有变化;另给季表摘要、按发布组的方式统计与待确认数、各组待确认样本推出的建议规则。草稿规则会替换同作用域的已有规则(修改时用 `replaceRuleId` 替换被改的那条)。作品页边改草稿边预览,点「应用」才写入。
|
||||
**模拟预览**(`POST /media-entities/{id}/episode-mapping/preview`,纯读):取作品下最近 100 条已绑定资源(按发布时间倒序,可按季 / 发布组过滤;季按来源季或规范季任一匹配),按原标题(先过全局识别词)重解析后逐条给出原始季集 → 库里的当前结果 → 套用草稿后的结果、命中的识别词行、校验状态、是否有变化;另给季表摘要、按发布组的方式统计与待确认数、各组待确认样本推出的建议规则。`words` 传整块作品识别词草稿原文。编辑器改动后自动试算,点「保存」才写入。
|
||||
|
||||
**作品页「换算不了的资源」**(原待处理「集数待确认」卡片,2026-10-06 起显示在作品页集数映射分区):每组列出来源季集、原因、建议规则(同组待确认资源按发布时间对播出日期推出,全部样本成立且唯一才给)与它套用到同组资源的模拟结果。
|
||||
|
||||
- 确认:选项 `confirm_suggestion`,建议规则写成 expression 规则 → 事项按用户选择关闭 → 按作品重算(同一事务;仍对不上的资源另开新事项)。
|
||||
- 修改:跳到作品页集数映射并预填草稿(`?mapSeason=&mapGroup=&mapExpr=&mapTarget=#episode-mapping`),在那里改完再应用。
|
||||
- 忽略:只关闭提醒,资源仍待确认;勾选「同时建忽略规则」时走选项 `ignore_rule`,建 special=ignore 规则,这一季这个发布组的资源以后不参与集数解析。
|
||||
- 采用:选项 `confirm_suggestion`,建议写成一行(如 `S01 @Lilith-Raws >> S02 EP-30`,选项的 `input.line`)追加到作品识别词末尾,上方一行注释写来历 → 事项按用户选择关闭 → 按作品重算(同一事务;仍对不上的资源另开新事项)。
|
||||
- 修改:在作品页里把这一行放进编辑器草稿;从别处跳来时地址带 `?mapLine=<那一行>#episode-mapping`。
|
||||
- 忽略:只关闭提醒,资源仍待确认;勾选「同时写一行忽略」时走选项 `ignore_rule`,追加 `S01 @发布组 >> 忽略`,这一季这个发布组的资源以后不参与集数换算。
|
||||
|
||||
处理走 `POST /decisions/{id}/resolve` 的选项,由 sources-identity 直接执行(与身份类事项同一做法)。订阅详情有该作品 + 季的方式统计与待确认数;新建 / 编辑订阅时如果近期资源里有发布组用绝对集号,表单里提示一句。
|
||||
|
||||
@@ -172,14 +172,14 @@ select key, value->>'title' title, value->>'year' y, value->>'source' src from k
|
||||
|
||||
**新建作品的季表**:自动识别新建的作品在关注范围内(用户搜索 / 手动识别 / 接管下载,或已被订阅等)才在事务提交后排一次 full 元数据刷新(幂等键 `refreshMetadata:created:<作品>`),其余等进入关注范围时补排;新建档没有季表时资源先按原号放行(unverified),刷新补齐季表后自动重算为换算结果。
|
||||
|
||||
**智能体兜底**(批次 5):确定性流程(规则 → 原号校验 → 换算)都失败、开了「集数待确认」后,智能体在完整上下文里判断一次,产出一条结构化规则;写入后同类资源由规则自动处理,智能体不逐集调用。
|
||||
**智能体兜底**(批次 5):确定性流程(规则 → 原号校验 → 换算)都失败、开了「集数待确认」后,智能体在完整上下文里判断一次,产出一行作品识别词;写进去后同类资源由这一行自动处理,智能体不逐集调用。
|
||||
|
||||
- 何时触发:设置 → 智能体打开「自动调查」时,新开的 `episode_mapping` 事项和下载失败一样进后台调查(`decision.created` → `resolveDecision` → `autoInvestigate`),同一事项只跑一次。对话里也可以直接说「《X》第二季集数对不上」,走同样三个能力(Skill「集数映射」)。
|
||||
- 三个能力:`episode_mapping.inspect`(只读:事项内资源、同组相邻资源各最多 50 条,季表每季最多 100 集含播出日期与集标题,现有规则含停用原因,确定性建议)→ `episode_mapping.simulate`(只读:复用模拟预览,汇总事项内样本是否全部解决、有没有让已对上的资源变成待确认)→ `episode_mapping.apply_rule`(写)。
|
||||
- `apply_rule` 服务端强制再模拟:样本有一条没解决、或会让当前已对上 / 已换算的资源变成待确认,直接拒绝不写库。通过才写规则:`created_by_type = agent`,样本 ≥ 3 且全部对得上记「多证据」(`multi_evidence`),否则「待复核」(`needs_review`);证据存理由、样本数、模拟摘要与会话 ID;随后按作品重算,资源都解决时事项自动关闭,系统据此核实恢复。
|
||||
- 三个能力:`episode_mapping.inspect`(只读:事项内资源、同组相邻资源各最多 50 条,季表每季最多 100 集含播出日期与集标题,作品识别词原文与逐行解析,确定性建议)→ `episode_mapping.simulate`(只读:复用模拟预览,汇总事项内样本是否全部解决、有没有让已对上的资源变成待确认)→ `episode_mapping.apply_rule`(写)。
|
||||
- `apply_rule` 服务端强制再模拟:样本有一条没解决、或会让当前已对上 / 已换算的资源变成待确认,直接拒绝不写库。通过才把这一行追加到作品识别词末尾,上方一行注释 `# <日期> 智能体(会话 <前 8 位>):<理由>`,审计记操作者为智能体会话;返回追加的原文与行号;随后按作品重算,资源都解决时事项自动关闭,系统据此核实恢复。
|
||||
- 需要什么授权:后台自动调查的模式要是「授权内恢复」(`agent.autoInvestigateMode = recover`),且有一条覆盖 `episode_mapping.apply_rule` 的有效持续授权(action 写 `episode_mapping.apply_rule` 或 `*`;可用 `scope.mediaEntityIds / mediaKinds` 限定作品,按事项的作品核对;不随身份识别策略放开)。对话里没有授权时同样被拒,智能体只会说「需要你批准」。
|
||||
- 没有授权(或模式是只读调查)时降级只读:智能体在会话里用 `simulate`(带事项 ID 和理由)试出的通过规则,会作为「智能体建议」写进事项证据(`evidence.agentSuggestion`,事项刷新时保留),作品页集数映射里显示规则、理由、样本套用后的季集与模拟结果,点「确认智能体建议」(选项 `confirm_agent_suggestion`)即建规则 + 重算;建之前按当前资源再模拟一次,不通过返回 409 不写。人工确认的规则记操作者为管理员、证据等级「人工确认」。
|
||||
- 怎么撤销:作品页「集数映射」里智能体写的规则带「智能体 · 多证据 / 待复核」标记和依据,点「停用」:立即按作品重算(资源回到待确认并重新开事项),且同作用域有手动停用的规则时 `apply_rule` 一律拒绝,智能体不会再自动写回(仍可留建议给人确认)。直接删除不留这个记号,新开的事项可能再被自动写一次(受同根因自动恢复次数上限 `agent.investigateMaxAttempts` 约束)。要彻底停掉自动写规则,撤销那条持续授权或把自动调查模式改回只读调查。
|
||||
- 没有授权(或模式是只读调查)时降级只读:智能体在会话里用 `simulate`(带事项 ID 和理由)试出的通过的那一行,会作为「智能体建议」写进事项证据(`evidence.agentSuggestion.line`,事项刷新时保留),作品页集数映射里显示这一行、理由、样本套用后的季集与模拟结果,点「采用智能体建议」(选项 `confirm_agent_suggestion`)即写进作品识别词 + 重算;写之前按当前资源再模拟一次,不通过返回 409 不写。
|
||||
- 怎么撤销:智能体写的行上方有注释写明来历与理由,把那一行注释掉(可视化里关掉开关)并保存:立即按作品重算(资源回到待确认并重新开事项),且识别词里有同范围被注释掉的行时 `apply_rule` 一律拒绝,智能体不会再自动写回(仍可留建议给人确认)。直接删掉这一行不留这个记号,新开的事项可能再被自动写一次(受同根因自动恢复次数上限 `agent.investigateMaxAttempts` 约束)。要彻底停掉自动写规则,撤销那条持续授权或把自动调查模式改回只读调查。
|
||||
|
||||
## 剧集组(季集结构)
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
**临时结构下的集数映射**(`episode-resolution.ts createStructureEpisodeMapper`):
|
||||
|
||||
1. 季表换成所选结构的季与集数;选剧集组时带每集播出日期与原季集对照(发布者按 TMDB 默认季编号的 `S01E14` 换到组内 `S02E02`)。
|
||||
2. 作品的映射规则是按作品当前结构写的:先按作品季表 + 规则跑一遍,命中规则(含特别篇 / 花絮 / 忽略)就用规则结果,季集再经 TMDB 原季集换到所选结构(换不过去的按待确认排除);没命中规则时按所选结构的季表判定。
|
||||
2. 作品识别词(季集换算)是按作品当前结构写的:先按作品季表 + 规则跑一遍,命中规则(含特别篇 / 花絮 / 忽略)就用规则结果,季集再经 TMDB 原季集换到所选结构(换不过去的按待确认排除);没命中规则时按所选结构的季表判定。
|
||||
3. 资源的集数解析是按作品结构做的,临时结构下不沿用,只取发布时间;按所选结构判不出的文件照常排除为集数待确认,但不并进作品的「集数待确认」待处理。
|
||||
4. 向导里人工填的季集按所选结构理解(决定命名)。
|
||||
|
||||
|
||||
Reference in new issue
Block a user