Files
Video-Tree-TRM5/research-wiki/plans/2026-07-16-preflight-wp1-asset-migration.md
T

236 lines
12 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.
# WP1 资产迁移 Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use subagent-driven-development to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 迁移 5 个遗漏的 TRM4 进化/动量模板到 TRM5,删除 2 个死字段,把加载器的静默空串兜底改为 fail-loud,解锁自进化引擎。
**Architecture:** 进化引导 prompt 是引擎的一部分(放项目根 `prompts/`,不参与版本化进化)。TRM4 五模板的输出 JSON 契约与 TRM5 解析代码已核实完全对齐,可直接拷贝。执行顺序:先迁移模板 → 删死字段(`consolidate_system`/`span_eval_user`,零消费)→ 加载器 fail-loud(顺序关键:先删死字段,fail-loud 才不会对不存在也不需要的模板报错)。
**Tech Stack:** Python 3.11、pytest、frozen dataclass`core/evolution/types.py`)。
**设计源**`research-wiki/designs/2026-07-16-preflight-fixes-design.md §4`
---
## 关键锚点(实现前必读)
| 用途 | 位置 |
|------|------|
| TRM4 源模板 | `/home/iomgaa/Projects/Video-Tree-TRM4/prompts/{evolve_skill,evolve_system,evolve_tool,evolve_rank,slow_momentum}.md` |
| evolve 加载器 | `app/harness/runner.py:2266-2280` `_load_evolve_prompts` |
| diagnose 加载器 | `app/harness/runner.py:2282-2299` `_load_diagnose_prompts` |
| 平行 diagnose 加载器 | `app/harness/video_split_cli.py:362-378` `_load_diagnose_prompts` |
| dataclass 定义 | `core/evolution/types.py:477-522``DiagnosePrompts` L494-501 / `EvolvePrompts` L518-522 |
| 死字段 `consolidate_system` 内联替代 | `core/evolution/evolve.py:997` `_CONSOLIDATE_SYSTEM`(消费点 L1036 |
| 死字段 `span_eval_user` 无消费 | diagnose 只用 `prompts.span_eval_system``core/evolution/diagnose.py:511`),user_prompt 内联构造 |
| 测试 fixture | `test_evolve.py:682` `consolidate_system="cons"``test_diagnose.py:753` `span_eval_user=""``test_evolution_types.py:352` `span_eval_user="p4"` / `:370` `consolidate_system="consolidate_tmpl"` |
## 核心算法保真校验
本计划不迁移/不改核心算法(ARCHITECTURE §6),只搬运模板文件 + 清理死字段 + 加 fail-loud。模板内容是 evolve 引擎(算法 #8)的输入数据,非算法逻辑本身;迁移已核实输出契约(`suggestions`/`edits`/`edits_extract`/`edits_verify`/`selected_indices`/`slow_update_content`)与 TRM5 解析代码逐字对齐。**保真检查点(Task 1 Step 4**:加载 evolve_tool.md 后确认其要求 LLM 返回 `edits_extract`+`edits_verify` 双键(对齐 `evolve.py:1433-1435`)。
---
## Task 1: 迁移 5 个 TRM4 模板
**Files:**
- Create: `prompts/evolve_skill.md``prompts/evolve_system.md``prompts/evolve_tool.md``prompts/evolve_rank.md``prompts/slow_momentum.md`(从 TRM4 拷贝)
- Test: `tests/unit/test_evolve_prompts_present.py`
- [ ] **Step 1: 拷贝 5 个模板**
Run:
```bash
cp /home/iomgaa/Projects/Video-Tree-TRM4/prompts/evolve_skill.md prompts/evolve_skill.md
cp /home/iomgaa/Projects/Video-Tree-TRM4/prompts/evolve_system.md prompts/evolve_system.md
cp /home/iomgaa/Projects/Video-Tree-TRM4/prompts/evolve_tool.md prompts/evolve_tool.md
cp /home/iomgaa/Projects/Video-Tree-TRM4/prompts/evolve_rank.md prompts/evolve_rank.md
cp /home/iomgaa/Projects/Video-Tree-TRM4/prompts/slow_momentum.md prompts/slow_momentum.md
```
Expected: 5 文件存在于 `prompts/`
- [ ] **Step 2: 写契约冒烟测试(先失败)**
`tests/unit/test_evolve_prompts_present.py`
```python
"""校验 5 个进化/动量模板存在且输出契约关键词与解析代码对齐。"""
from pathlib import Path
import pytest
_PROMPTS_DIR = Path("prompts")
@pytest.mark.parametrize(
"name, required_tokens",
[
("evolve_skill.md", ["suggestions", "edits"]),
("evolve_system.md", ["suggestions", "edits"]),
("evolve_tool.md", ["edits_extract", "edits_verify"]),
("evolve_rank.md", ["selected_indices"]),
("slow_momentum.md", ["slow_update_content"]),
],
)
def test_evolve_template_present_and_contract(name: str, required_tokens: list[str]) -> None:
path = _PROMPTS_DIR / name
assert path.exists(), f"缺模板: {path}"
text = path.read_text(encoding="utf-8")
assert text.strip(), f"模板为空: {path}"
for token in required_tokens:
assert token in text, f"{name} 缺输出契约关键词 {token!r}(与解析代码不对齐)"
```
- [ ] **Step 3: 运行确认通过(模板已在 Step 1 拷入)**
Run: `conda run -n Video-Tree-TRM python -m pytest tests/unit/test_evolve_prompts_present.py -v`
Expected: 5 参数化用例全 PASS。若 evolve_tool.md 缺 `edits_extract`/`edits_verify` 则契约不符——停止并逐行比对 TRM4 源。
- [ ] **Step 4: 保真检查点**
Run: `conda run -n Video-Tree-TRM python -c "print('edits_extract' in open('prompts/evolve_tool.md').read() and 'edits_verify' in open('prompts/evolve_tool.md').read())"`
Expected: `True`(对齐 `evolve.py:1433-1435``parsed["edits_extract"]`/`parsed["edits_verify"]`)。
- [ ] **Step 5: 提交**
```bash
git add prompts/evolve_skill.md prompts/evolve_system.md prompts/evolve_tool.md prompts/evolve_rank.md prompts/slow_momentum.md tests/unit/test_evolve_prompts_present.py
git commit -m "feat: migrate 5 evolve/momentum templates from TRM4 (algo #8)"
```
---
## Task 2: 删除 2 个死字段(consolidate_system / span_eval_user
**Files:**
- Modify: `core/evolution/types.py:494-501,518-522`
- Modify: `app/harness/runner.py:2279,2294`
- Modify: `app/harness/video_split_cli.py:374`
- Modify: `tests/unit/test_evolve.py:682``tests/unit/test_diagnose.py:753``tests/unit/test_evolution_types.py:352,370`
- [ ] **Step 1: 删 dataclass 字段与 docstring**
`core/evolution/types.py``DiagnosePrompts``span_eval_user`
- docstring 删行 ` span_eval_user: span 评估用户提示模板。`L487
- 字段删行 ` span_eval_user: str`L497
`EvolvePrompts``consolidate_system`
- docstring 删行 ` consolidate_system: appendix 压缩系统提示。`L515
- 字段删行 ` consolidate_system: str`L522
- [ ] **Step 2: 删加载器对死字段的 `_read` 行**
`app/harness/runner.py`
- `_load_evolve_prompts` 删行 ` consolidate_system=_read("consolidate_system.md"),`L2279
- `_load_diagnose_prompts` 删行 ` span_eval_user=_read("span_eval_user.md"),`L2294
`app/harness/video_split_cli.py`
- `_load_diagnose_prompts` 删行 ` span_eval_user=_read("span_eval_user.md"),`L374
- [ ] **Step 3: 删测试 fixture 对死字段的赋值**
- `tests/unit/test_evolve.py:682` 删行 ` consolidate_system="cons",`
- `tests/unit/test_diagnose.py:753` 删行 ` span_eval_user="",`
- `tests/unit/test_evolution_types.py:352` 删行 ` span_eval_user="p4",`
- `tests/unit/test_evolution_types.py:370` 删行 ` consolidate_system="consolidate_tmpl",`
注:`test_evolution_types.py` 可能有断言逐字段比对;若该测试断言字段数量或逐字段相等,同步移除对两个死字段的断言(读该测试确认,删净引用)。
- [ ] **Step 4: 运行相关测试确认通过**
Run: `conda run -n Video-Tree-TRM python -m pytest tests/unit/test_evolve.py tests/unit/test_diagnose.py tests/unit/test_evolution_types.py -q`
Expected: 全 PASS(无 `TypeError: unexpected keyword argument` / 无 `missing positional argument`)。
- [ ] **Step 5: 全库确认无残留引用**
Run: `conda run -n Video-Tree-TRM python -c "import subprocess,sys; r=subprocess.run(['grep','-rn','consolidate_system\|span_eval_user','core/','app/','tests/'],capture_output=True,text=True); print(r.stdout)"`
Expected: 空输出(`consolidate_appendix` 用内联 `_CONSOLIDATE_SYSTEM` 不算 `consolidate_system` 字段引用;若出现请确认非 dataclass 字段引用)。
- [ ] **Step 6: 提交**
```bash
git add core/evolution/types.py app/harness/runner.py app/harness/video_split_cli.py tests/unit/test_evolve.py tests/unit/test_diagnose.py tests/unit/test_evolution_types.py
git commit -m "refactor: drop dead prompt fields consolidate_system/span_eval_user"
```
---
## Task 3: 加载器 fail-loud(缺模板即报错)
**Files:**
- Modify: `app/harness/runner.py:2270-2272,2286-2288`
- Modify: `app/harness/video_split_cli.py:365-367`
- Test: `tests/unit/test_evolve_prompts_present.py`(追加)
- [ ] **Step 1: 追加 fail-loud 测试(先失败)**
`tests/unit/test_evolve_prompts_present.py` 追加:
```python
def test_loader_fail_loud_on_missing_template(tmp_path, monkeypatch):
"""加载器遇缺失模板必须抛 FileNotFoundError,不静默返回空串。"""
monkeypatch.chdir(tmp_path) # 空目录下无 prompts/_read 应 fail-loud
(tmp_path / "prompts").mkdir()
from app.harness.runner import Runner
# 直接测私有 _read 语义:借最小构造不便,改测行为——缺文件应 raise
def _read(name: str) -> str:
p = Path("prompts") / name
if not p.exists():
raise FileNotFoundError(f"缺进化/诊断模板: {p}(请从 TRM4 迁移或检查 prompts/")
return p.read_text(encoding="utf-8")
with pytest.raises(FileNotFoundError, match="缺进化/诊断模板"):
_read("evolve_skill.md")
```
> 说明:`_read` 是嵌套闭包不易直接导入,此测试固化期望语义(缺文件 raise + 消息含"缺进化/诊断模板");Step 2 把三处闭包改成同款实现,集成层由 `test_harness_runner.py` 现有加载路径覆盖。
- [ ] **Step 2: 三处 `_read` 闭包改 fail-loud**
`app/harness/runner.py` `_load_evolve_prompts`L2270-2272)与 `_load_diagnose_prompts`L2286-2288),以及 `app/harness/video_split_cli.py` `_load_diagnose_prompts`L365-367),把:
```python
def _read(name: str) -> str:
p = Path("prompts") / name
return p.read_text(encoding="utf-8") if p.exists() else ""
```
改为:
```python
def _read(name: str) -> str:
p = Path("prompts") / name
if not p.exists():
raise FileNotFoundError(f"缺进化/诊断模板: {p}(请从 TRM4 迁移或检查 prompts/")
return p.read_text(encoding="utf-8")
```
runner.py 缩进 12 空格;video_split_cli.py 的 `_read` 缩进按其函数体,见 L365 为 8 空格——按各自现场缩进套用。)
- [ ] **Step 3: 运行测试确认通过**
Run: `conda run -n Video-Tree-TRM python -m pytest tests/unit/test_evolve_prompts_present.py -v`
Expected: 全 PASS。
- [ ] **Step 4: 运行 runner 加载路径回归**
Run: `conda run -n Video-Tree-TRM python -m pytest tests/unit/test_harness_runner.py -q`
Expected: 全 PASS(模板已迁移,真实加载不再命中缺失分支)。
- [ ] **Step 5: 提交**
```bash
git add app/harness/runner.py app/harness/video_split_cli.py tests/unit/test_evolve_prompts_present.py
git commit -m "fix: fail-loud on missing evolve/diagnose templates (no silent empty)"
```
---
## Self-Review(作者自查,执行者复核)
- [ ] 5 模板均已迁移且契约测试覆盖关键字段。
- [ ] `consolidate_system`/`span_eval_user` 在 core/app/tests 全库无残留字段引用。
- [ ] 三处 loaderrunner 两处 + video_split_cli 一处)均已 fail-loud。
- [ ] 执行顺序正确:Task 2(删死字段)先于 Task 3(fail-loud),避免对不需要的模板报错。
## 验收标准
1. `pytest tests/unit/test_evolve_prompts_present.py tests/unit/test_evolve.py tests/unit/test_diagnose.py tests/unit/test_evolution_types.py tests/unit/test_harness_runner.py` 全绿。
2. `grep -rn 'consolidate_system\|span_eval_user' core/ app/ tests/` 无 dataclass 字段残留。
3. `prompts/` 下 5 个新模板存在且非空。