refactor(tree): subtitle 迁入 L3Card/L2Card + 建树管线修正

- L3Card/L2Card 新增 subtitle: str 字段(L1Card 不加)
- L3Node 移除 subtitle 字段(数据迁入 Card)
- assign_subtitles_voronoi 改写 Card.subtitle + L2 聚合
- _collect_card_strings 增加 skip_fields 排除 subtitle
- _node_full_text/_node_anchored_text 保持 字幕:/[sN] 语义
- get_subtitle 读 Card.subtitle(L2/L3)
- verify.py/synthesizer.py: l3.subtitle → l3.card.subtitle
- 迁移脚本 tools/migrate_subtitle_to_card.py(幂等,300 棵树已迁移)
- 9→6 个测试文件适配(3 个无需改动)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-09 11:57:41 -04:00
parent c72b55508a
commit d3be9b1322
13 changed files with 253 additions and 46 deletions
+6 -6
View File
@@ -97,10 +97,10 @@ class TestTreeModuleE2E:
SRTEntry(start=5.0, end=7.0, text="The crowd goes wild!"),
]
assign_subtitles_voronoi(index, srt_entries)
assert l3_0.subtitle is not None
assert "sprints" in l3_0.subtitle
assert l3_1.subtitle is not None
assert "crowd" in l3_1.subtitle
assert l3_0.card.subtitle != ""
assert "sprints" in l3_0.card.subtitle
assert l3_1.card.subtitle != ""
assert "crowd" in l3_1.card.subtitle
# Step 3: TreeEnvironment 查询
env = TreeEnvironment(index)
@@ -139,8 +139,8 @@ class TestTreeModuleE2E:
assert len(loaded.roots) == 1
assert loaded.roots[0].card.scene_summary == "百米短跑决赛"
assert loaded.roots[0].children[0].children[0].subtitle is not None
assert "sprints" in loaded.roots[0].children[0].children[0].subtitle
assert loaded.roots[0].children[0].children[0].card.subtitle != ""
assert "sprints" in loaded.roots[0].children[0].children[0].card.subtitle
# verify 的修改也被保留
assert "幻觉实体XYZ" not in loaded.roots[0].children[0].card.entities