# ep-mv-trial01 六轮失败根因定谳报告

**分析对象**: `skills/kais-movie-pipeline/episodes/ep-mv-trial01`（MV 变体管线 MV_PHASE_REGISTRY 13 相首台）
**时间窗**: 2026-10-15 20:21:14 → 2026-10-17 02:50:25（六轮 run.sh 耗尽 rc=1）
**纪律**: 架构分析禁改代码；全部结论带 log 行号 / 文件:行号；未证实处标「待验证」。
**代码基线**: run.sh PYTHONPATH 指向 `/home/kai/workspace/kais-hermes-skills`，已 diff 确认与 `/data/workspace/kais-hermes-skills` 五个关键文件**逐字节一致**（runner.py / p07_scene_generation.py / phases/__init__.py / runner_hooks.py / gate.py）——本报告引用行号对两树同时成立。

---

## 0. 一图流：六轮失败的结构性闭环

每轮 attempt 的实际轨迹（run.log + `.pipeline-assets/phase-execution-log.jsonl` 42 事件重建）：

```
┌─► resume: start_idx=0（mv01 重入）──────────────────────────────────────────┐
│   mv01_song_intake 重跑 → mv01-gate 重提（新 review_id，blocking 3600s）      │
│   ├─ 操作者 3600s 内在 KAP 审核台批了 → mv01 completed → mv02 → p04(REUSE)    │
│   │  → p07 delegate → vision_verify 硬门「抽签」拒图 → ①                     │
│   └─ 无人审 → HumanGateTimeout → exit 1 → 下一 attempt start_idx=1 ──────────┤
│                                                                              │
│  start_idx=1（mv01 跳过）: mv02 重跑 → p04 REUSE-01 缓存 → p07 → 抽签拒 → ①   │
│                                                                              │
│  ① p07 QualityGateRejection 处理链（runner.py:4303-4470）:                    │
│     写 fix-required(p07) → checkpoint=p04（正确）→                            │
│     idx = _phase_id_to_index("p07_scene_generation")【无 registry → drama:7】 │
│     【runner.py:4463】→ MV registry[7] = p11b_final_render →                  │
│     p11b 重入：提 p11b-gate（又一张新 review 卡）→ 返回空 video-clips →        │
│     Layer4 schema 秒败 → fix-required 被 p11b 条目【覆写】(runner.py:4556)    │
│     → _save_retry_rollback【无 registry → drama:17 → 前一相=p11a5】           │
│     【runner.py:4581 + 450-488】→ 写伪 checkpoint p11a5_preview_audio         │
│     （MV 链里根本不存在的相，却标 completed）→ current_phase_id=p11a5          │
│     → re-raise → exit 1 → 下一 attempt 读到孤儿 checkpoint → start_idx=0 ─────┘
```

**8 个完整故障周期**（phase-execution-log.jsonl 事件 4-41，每周期 = p07 `quality_gate_rejected` + p11b `layer4_schema_retry` + 下一轮 mv01 `human_gate_timeout` 或 approve）：

| # | p07 拒绝 | p11b 秒败 | mv01 门提交(review_id) | 结果 |
|---|---------|----------|----------------------|------|
| 1 | 10-15 21:01:53 (L387) | 21:01:53 (L398) | 21:02:28 (#54) | **approve 21:06:28** (L427) |
| 2 | 10-15 21:20:38 (L516) | 21:20:38 (L526) | 21:21:15 (#56) | **approve 22:14:17** (L558) |
| 3 | 10-15 22:38:45 (L692) | 22:38:45 (L701) | 22:39:16 (#58) | 超时 23:39:18 (L716) |
| 4 | 10-15 23:52:20 (L832) | 23:52:20 (L841) | 23:53:23 (#60) | 超时 00:53:25 (L863) |
| 5 | 10-16 01:04:08 (L971) | 01:04:08 (L981) | 01:04:38 (#62) | 超时 02:04:41 (L1017) |
| 6 | 10-16 23:15:10 (L1125) | 23:15:10 (L1135) | 23:15:45 (#64) | 超时 00:15:47 (L1150) |
| 7 | 10-17 00:27:06 (L1246) | 00:27:06 (L1256) | 00:27:41 (#66) | 超时 01:27:43 (L1271) |
| 8 | 10-17 01:49:50 (L1401) | 01:49:51 (L1412) | 01:50:23 (#68) | 超时 02:50:25 (L1427) → RUN_SCRIPT_DONE rc=1 |

另：首轮 approve #52（提交 20:21:27 → 批 20:30:57, L10/13）后 mv02 `[SCHEMA]` 段缺失连炸 5 次（L16/50/84/118/152/186，20:31-20:32 每次仅 2-3 秒）。

---

## 主题 1：p07 死循环根因定谳（初判-1）

### 现象
run.log 每轮 fix feedback 点名「用 `--skip-existing` 重生成 S01/S02/S03 各视图」（L388/517/693/833/972/1126/1247/1402），但 `assets/S07/` mtime：S01 六图 + S02 六图全冻结在 **10-15 22:29:00-02**，S03 直到 **10-17 01:41-01:43** 才变。八轮拒绝间文件零变化。

### 证据链（四层，层层独立致哑）

**第 1 层 — 指令文本自相矛盾（确认）**。fix feedback 由 p07_scene_generation.py:2025-2039 拼装，fix_instructions 硬编码字面量 `"用 scene_multiview_dualwall.py --skip-existing 重生成以下视图"`（:2037）。而 `--skip-existing` 的语义是 `os.path.isfile(path) and size>0 → SKIP`（templates/scene_multiview_dualwall.py:277/293/309 三处逐 view 判断）。**被点名重生成的视图恰恰是盘上已存在的文件 → 必然全跳过**。指令本身要求「重生成已存在文件」却自带「存在即跳过」开关，逻辑自锁。

**第 2 层 — 反馈根本没到达 delegate（比初判-1 更深的实情）**。p07 有 fix-required 消费回路（p07_scene_generation.py:1781-1807：读 fix-required → 校验 `rollback_to in (PHASE_ID,"p07")` → 注入 goal → 写日志 `"fix-required feedback injected"`）。**该日志八轮全数 0 命中**（`grep -c "fix-required feedback injected" run.log` = 0）。原因：每轮 p07 拒绝写入的 fix-required（runner.py:4404）在 **100ms 后**就被同进程 p11b 的 Layer4 失败覆写成 `{rollback_to: p11b_final_render, error_type: schema_validation}`（runner.py:4556-4567）——现存 `.pipeline-assets/fix-required.json` 即此覆写产物。下一轮 p07 读到 p11b 条目，:1785 校验不过，静默跳过。**八轮 p07 delegate 没有一次收到过门的 fix feedback**；「Fix feedback:」字样只存在于 runner 自己的 log（runner.py:4390），从未进过任何 goal。

**第 3 层 — rounds 1-2 的 delegate 根本没跑完**。两个 p07 delegate 会话恰在 600s 整被掐断：`Turn ended: reason=interrupted_by_user ... response_len=0`（L373：20:47:09→20:57:09 整 600s；L510：21:08:58→21:18:58 整 600s），随后走文件系统兜底 `p07 fallback: recovered 9/10 scene images from disk`（L369/501）——**把盘上旧图原样捞回来**，然后送门抽签。注：run.sh 设 `KAIS_DELEGATE_TIMEOUT=1200`，实际 600s 掐断来源（runtime 层 watchdog）未深查，标待验证。

**第 4 层 — 即使重生成也会被拒（接主题 3）**。门判定输入是 content-free 标签串（见主题 3），与图新不新无关。

### S03 为何例外（初判-1 的追问，已完整定谳）
S03 三图于 10-17 01:41:26-01:43:38 重生成，**是第 8 轮 p07 delegate 自己干的，不是门反馈驱动**：
- 该轮 p07 delegate 会话 `20261017_013240_ebd2e4`（01:32:40-01:47:34, 22 API calls, L1389）。其 tool 调用与文件 mtime 秒级吻合：01:36:53 归档旧图（`_stale_1017_pre_mv02rescript/`, 01:36:52）→ 01:39:59 169s 生成（过暗，`_stale_1017_darkpass/`, 01:40:22）→ 01:40:22 重写 scenes.json + generation_prompts_final.json → 01:43:35 180s 最终生成（batch.json 01:43:38, S03 三图 01:41-01:43）→ 01:44:09 自写 `run_vision_verify_s03_1017.py` → 01:45:07 跑出 `vision_verify_results_1017.json`（0.95/0.88/0.88 全 PASS）。
- 动因：**同轮 mv02 重跑改了剧本**（mv02 于 01:32:40 完成，start_idx=1 轮次），S03 描述从「the same long neon street…」（generation_prompts_extracted.json, 10-15 22:34）变为「A brilliantly illuminated night city intersection…footbridge…」（generation_prompts_final.json, 01:40）——delegate 发现 S03 图文不符主动重生成；S01/S02 描述未变 → 未动（同时印证 skip-existing 语义在正常路径下如何工作）。
- **结论：delegate 4 分钟前自检 0.88 PASS 的图，被 01:49:50 的门以 conf=0.50 拒掉**（L1406，对拍见主题 3）。

### 根因定谳
初判-1 **✅ 方向成立，机制需修正**：`--skip-existing` no-op 与「点名重生成」的矛盾**确实存在且是设计缺陷**（第 1 层）；但它不是死循环的充分解释——**fix feedback 从未到达 delegate**（第 2 层，覆写 bug）+ **门判定输入本身坏**（主题 3）才是即使反馈通畅也无法收敛的根本。四层独立缺陷叠加 = 结构性死循环，操作者批准与否、delegate 是否勤奋都改变不了结局。

### 严重度与修复方向 — **P0**
1. 反馈覆写：p11b Layer4 覆写 fix-required 前，p07 条目未被消费 → 同 slot 单条目设计无法承载多相反馈。修复：fix-required 按 phase_id 分键（`fix-required/{phase_id}`），或 Layer4 写前检查「本 attempt 是否已有未消费的别的相条目」（至少 append 不覆盖）。
2. 指令自锁：:2037 删除 `--skip-existing` 字面量，改为「先 `rm <named views>` 再跑脚本（不带 --skip-existing）」或给脚本加 `--force-views S03_angle_left,...` 参数。
3. 600s delegate 掐断（待验证项）：确认 runtime watchdog 与 KAIS_DELEGATE_TIMEOUT 的传导链。

---

## 主题 2：Gate 20 握手课题定谳（初判-2）

### 时序考证（初判-2 的核心断言被推翻）

`.pipeline-assets/review-outcomes.json`（mtime 冻结在 10-15 22:14:17）三条 approve：12:30:57 / 13:06:28 / 14:14:17 UTC = 本地 20:30:57 / 21:06:28 / 22:14:17。与 run.log 对拍：

| approve | mv01-gate 提交 | resolve | 间隔 | 消费证据 |
|---------|--------------|---------|------|---------|
| #52 | 20:21:27 (L10) | 20:30:57 (L13) | **9.5 min，等待窗口内** | 同进程 20:30:58 立即跑 mv02 (L14-15) |
| #54 | 21:02:28 (L424) | 21:06:28 (L427) | **4 min，等待窗口内** | 同进程 21:06:28 跑 mv02 (L428-429) |
| #56 | 21:21:15 (L555) | 22:14:17 (L558) | **53 min，等待窗口内** | 同进程 22:14:17 跑 mv02 (L559-560) |

**「approve 全部落在轮次间隙、未被在等轮次消费」不成立**——三次审批全部被等待中的轮次实时消费。握手机制（plugins/review_gates/runner_hooks.py:568-727 `pause_and_wait_for_review`）：提交（:616 `pause_for_review(strict=True)` → 平台拿 review_id + `_write_awaiting_review_state` 写 awaiting_review, :217-237）→ 30s 轮询循环（:628-725）→ Path 2 跨进程发现：`query_review_status(gate.review_id)`（:653）见 COMPLETE → `resolve_direct` 镜像本地（:677）→ 返回继续 DAG。三条 `gate 'mv01-gate' ... resolved: decision=approve` 日志（L13/427/558，来自 gate.resolve）即此路径。

### 回答初判-2 的具体追问
- **review_id/gate_id 对得上吗？** gate_id 恒为 `mv01-gate`（gates.yaml:456-467，Gate 20：blocking、timeout_sec 3600、reviewer_role script、max_retries 2）。轮换的是**平台 review_id**：#52→54→56（批准）→58→60→62→64→66（超时）→68（最终态，state 现存 `mv01 awaiting_review review_id=68`）。三次 approve 都落在**当时的活卡**上，不存在「批在旧 id 上」。
- **operator 通道**：KAP 审核台。证据：run.sh 注释「runner 原地等 KAP 审核台 verdict」；`plugins/kais_aigc/review_platform.py:69-70`（`POST/GET /api/v1/reviews`）+ :33 `DEFAULT_BASE_URL = http://192.168.71.140:8090`；run.log 每次提交时的 JWT minting 警告（`InsecureKeyLengthWarning`, L11-12 等）；实测 `GET http://192.168.71.140:8090/api/v1/reviews/52` 返回 `{"detail":"Authentication required"}`（平台活、卡在、鉴权挡）——review #52/58/67/68 端点全部可达（密钥不在分析环境，卡状态未能实读，待验证但非必需）。
- **正确审批路径**：在 runner 的 3600s 等待窗口内，于审核台批准**最新提交的那张卡**（review_id 最大者）。批旧卡无效——轮询只查本次提交的 review_id。10-15 22:14 后操作者未再在任何窗口内审批 → 六次 3600s 烧尽（超时点 L716/863/1016/1150/1271/1427 全部 `human_gate_timeout ... fail-closed`）。

### 真正的课题（初判-2 方向感对、机理错）
1. **审批通胀（P1）**：resume 主循环**没有按相状态跳过的闸门**——`start_idx` 是唯一游标（`_compute_start_index`，runner.py:2009-2089；主循环对 `phases[mv01].status=completed` 视而不见）。start_idx=0/1 的轮次无条件重跑 mv01 → **同一份未变的 song-package 被要求批了 9 次**（#52-68 九连卡；内容自 20:21 首提后从未变过，20:21/21:21 两次提交日志的 song-package 摘要逐字节相同，L9 vs L554）。人审疲劳是超时的直接土壤。
2. **孤儿卡污染（P1）**：17 张平台卡中 14 张永久悬垂——5 张超时 mv01 卡（58-66）+ 8 张 p11b 卡（53-67，见主题 4）+ 1 张活卡 68。无 resubmit-时-关旧卡机制。
3. **start_idx=0 复位的引擎**（本项属 P0，见主题 4/registry 双缺陷）：若非孤儿 checkpoint 把游标打回 0，mv01 根本不会每轮重入门等待。

### 严重度与修复方向
- P1：对 `asset_bus_slots_to_lock`（song-package）做 content_hash 记忆——hash 未变且上卡已 approve → 自动沿用判定（或降级为 advisory 提示），消灭重复 HIL 需求。
- P1：重提门时关闭/撤销旧 review（平台侧 `POST /reviews/{id}/close` 或提交 payload 带取代语义）。
- P0（registry 双缺陷）见主题 4——修掉它，mv01 重提交频率即从「每轮」降回「每次 song-package 实际变化」。

---

## 主题 3：S07 复核-门背离定谳（初判-3）

### 对拍（同引擎、同阈值、同图，唯输入不同）

| 判定方 | 时间 | 输入 expected | 引擎/阈值 | S03_angle_left 结果 |
|--------|------|--------------|-----------|--------------------|
| 管线门（`_run_vision_verify_pass`） | 10-17 01:49:50 (L1406) | **`"S03 scene image (angle_left view)"`** | glm-5.3-flash / 0.7 | **FAIL conf=0.50** |
| delegate 自检复核件 | 10-17 01:45:07 | 完整英文场景描述（真实内容） | glm-5.3-flash（`engine_order=['glm-5.3-flash']` 显式）/ 0.7 | **PASS conf=0.88** |

四个复核件全部 PASS（conf 0.75-0.97）：`vision_verify_results_prior_session.json`（10-16 23:06）、`_rerun_1016.json`（23:10，九图 0.85-0.97）、`_final.json`、`_1017.json`（01:45）——与门八轮 0.50-0.65 系统性背离。

### 背离根因：门喂给判官的是占位标签，不是场景描述

判定链（pipeline/phases/p07_scene_generation.py:471-560 `_run_vision_verify_pass`）：
- :508 `expected = scene.get("description") or f"{scene_id} scene image"` —— scene 条目缺 `description` 字段时回退到 **`"{scene_id} scene image"` 字面量**；
- :513 views 路径再拼 `f"{expected} ({view_name} view)"`；
- :529-531 `verify_image_content(abs_path, expected_content=expected, stratum="text2image")`；
- vision_verify.py:1207-1216 把 expected 原样嵌入问题：**「这张图片是否包含以下内容？…内容：S03 scene image (angle_left view)？」**——判官被要求判断「这张城市夜景图是否包含『S03 场景图』这个字符串所指之物」，参照物为空 → 置信度只能在 0.5-0.65 徘徊，0.7 阈值（vision_verify.py:150 `_CONFIDENCE_THRESHOLD=0.7`；stratum 覆盖读 `~/.hermes/config.yaml vision_verify.thresholds`，本机 grep 无该配置块，走默认）上下随机落点。
- 而 description 为何缺：**delegate 输出 schema 根本没这个字段**——goal 的 `.schema(shape=...)` 声明 `"scene_images": "[{scene_id, views: {...}, path}]"`（p07_scene_generation.py:1748）。文件系统兜底路径本可从 scenes.json 富化 description（:370-396 `scene_desc_map`），但 rounds 3-8 全部走 delegate 输出路径（`Turn ended` 正常 + 无 fallback 日志），schema 无字段 → 恒 label。
- **八轮日志反证**：所有拒绝消息的 expected 截断串（:2028 `[:80]`）都是标签形态——rounds 1-2 平铺形态 `"S03_angle_left scene image"`（L389/390/518），rounds 3-8 views 形态 `"S03 scene image (angle_left view)"`（L694-695/834-835/973-975/1127-1129/1248-1250/1403-1406）。若 expected 是真描述，消息里应出现英文场景文本片段——一次都没有。
- **非确定性实证**：同一文件（mtime 冻结）同一 expected，S03_angle_left 八轮 conf = 0.55/—/0.65/0.55/0.60/PASS/PASS/0.50，S01/S02 各视图同样乱序轮换中招。缓存在 p06 的 `plugins/kais_aigc/vision_verify.py:106` 是**进程内 dict**——run.sh 每 attempt 新进程 → 缓存清零 → 每轮重掷骰子。

### 复核结果有没有回流？
**没有**。门的判定链只消费 expert_output 的 scene_images；四个 `vision_verify_results*.json` 是盘面化石，无任何代码路径读取（grep 全仓无消费者）；delegate 自检亦纯 informational（goal 无「读取上次复核」指令）。

### 严重度与修复方向 — **P0**
1. schema 补 `description`（:1748），或在 `_run_vision_verify_pass` 内对缺 description 的条目**从 workdir/assets/S07/scenes.json 现读富化**（复用 :370-396 的 map 逻辑——scene-images slot 里的 scene_id 是 S01/S02/S03，可直接对上）。
2. 兜底标签（:508）应视为门失效条件：expected 无实义时 fail-loud（拒绝在本轮判分），而非静默用标签判分。
3. 复核回流：delegate/门共享同一 expected SSOT（scenes.json），复核 PASS 记录可作为门的上诉证据通道（op 级，可选）。
4. 语义提示：该门在 drama 链同样带病（此缺陷非 MV 特有）——p07 首台之后所有 drama episode 的 vision 门若走 delegate 路径同样在抽签（历史 episode 未爆是因为 p06 场景少 + 抽签偶尔全过）。

---

## 主题 4：p11b video-clips=0 连锁语义

### 定谳：**纯连锁为主 + 两个独立缺陷放大为结构故障**

**连锁面（无辜）**：p11b 每轮 ~100ms 秒败，输入是空的 `video-clips` slot（`.pipeline-assets/video-clips.json` `value: []`，mtime 01:49:50 = 每轮 p11b 聚合覆写）。上游 p07 从未通过 → 无图 → 无 clip。p11b 相代码本身诚实：聚合空列表 → 触发门 → 返回（pipeline/phases/p11b_final_render.py:3620-3693），Layer4 校验 `expected ≥1 items, got 0`（phase_output_schema.py:305，run.log L398 等 ×8）如实拒绝。

**独立缺陷 1（P0）— registry 盲检索把 p11b 变成错误回滚落点**：
- runner.py:4463 `rollback_idx = _phase_id_to_index(exc.rollback_to)` —— **不带 registry**，而 :374-380 的默认是 **drama PHASE_REGISTRY**。drama 里 p07_scene_generation 在 idx **7**（phases/__init__.py:306-328 数到第 8 项）；MV registry（同文件 :421-435）idx 7 是 **p11b_final_render**（:429）。于是 `idx = rollback_idx - 1`（:4470）+ 循环顶 `idx += 1` → **每次 p07 拒绝后本进程不重跑 p07，而是重跑 p11b**。铁证：L391→392（"checkpoint set to p04..." 紧跟 "phase=p11b_final_render (idx=7)"），八轮全部如此（L520/697/840/981/1135/1256/1412 前后）。
- 同病第二处：runner.py:4581-4584 Layer4 分支调 `_save_retry_rollback` **漏传 `registry=`** → :468 用 drama 解析 p11b=17 → :470 取 drama[16]=**p11a5_preview_audio** → `save_checkpoint("p11a5_preview_audio", {status:"completed", rollback_to:p11b, _retry_state})`。**p11a5 根本不在 MV 链里**（:421-435 无此相，:417 注释明说「预览链 p11a0/p11a/p11a5 不进链」），却每轮被写成 completed——state 化石：`phases.p11a5_preview_audio = {status: completed, completed_at: 01:49:51, result: {rollback_to: p11b_final_render, _retry_state: …}}`，与 :471-476 载荷逐字段吻合。注意对照：同函数在 gate-rejection 相的拒绝处理里是**带** registry 的正确调用（runner.py:4417-4436，日志 "checkpoint set to p04_character_design" 正确）——说明这是两处漏传，不是设计。
- **孤儿 checkpoint → start_idx=0 的因果闭环**：下次 attempt `load_latest_checkpoint`（plugins/pipeline_state/store.py:418-431）返回 `phases[current_phase_id]` = p11a5 伪记录 → `_compute_start_index`（runner.py:2055-2089）拿 `result.phase="p11a5_preview_audio"` 在 MV registry 查不到 → :2071-2072 orphan → **return 0** → mv01 重入。这精确解释八轮里全部 5 次 `start_idx=0`（L421/710/857/990/1265/1421）。对照组：mv01 门超时轮（HumanGateTimeout 不写 checkpoint，awaiting_review 记录由 `_write_awaiting_review_state` 写入并置 `current_phase_id=mv01`，runner_hooks.py:236）→ 下轮 checkpoint=phases[mv01]，0819 补丁（runner.py:3601-3613）填 phase=mv01 → idx 0 → return **1** ✓（L742/889/1176/1297 四次 start_idx=1 全部是超时轮之后）——**两组观测值与代码推导逐一吻合，零反例**。
- 若 `_save_retry_rollback` 带了 registry：checkpoint 会正确落在 mv04_vocal_track（MV[6]），下轮 start_idx=7 重入 p11b——仍会秒败于空 clips（连锁仍在）但**不再拖 mv01 陪葬**，3600s ×6 的门等待全部不会发生。

**独立缺陷 2（P1）— p11b 门提交先于输出校验**：p11b 在返回前触发 `trigger_gate("p11b-gate")`（p11b_final_render.py:1277 GATE_ID、:3674-3675；非阻塞 submit-and-return 形态，与 mv01 的 `trigger_gate_blocking` 不同，mv01_song_intake.py:574-624）。于是每个错误回滚轮都往平台**先交一张新卡再暴死**——review 53/55/57/59/61/63/65/67 八张 p11b 孤儿卡全部由此产生。

**awaiting_review 挂台后的 resume 重入路径健康吗？** 机制本身健康：awaiting_review 记录 + 0819 补丁使游标正确落回该相（start_idx=1 轮次实证）。且「resume 重跑本相」成本可控（mv02 delegate 2-5 min、p04 REUSE-01 秒过、mv01 重提门是语义缺陷非重入缺陷）。但本集中 p11b 的 awaiting_review **从未实际充当过 resume 游标**——它的 `current_phase_id=p11b` 每次都被 100ms 后的伪 p11a5 checkpoint 覆盖。重入路径未被这条故障链真正压测到。

### 严重度与修复方向
- **P0**：runner.py:4463 与 :4581 两处补 `registry=registry`（与 :4417 处对齐）。这是全案性价比最高的一行级修复——直接切断「p07 拒 → p11b 陪葬 → 孤儿 checkpoint → start_idx=0 → mv01 重提门」的传动轴。建议同时加回归锚：MV/NC registry 下断言 QualityGateRejection 回滚后下一执行相 == rollback_to。
- **P1**：p11b（及一切 submit-only 门相）在触发门之前先做输出完备性短路——clips 为空时 raise 质量拒绝（回滚上游）而不是交卡后让 Layer4 收尸。
- **P2**：`_retry_state` 持久化读取失配——runner.py:3751 `checkpoint.get("_retry_state")` 读顶层，而 save_checkpoint 把载荷嵌在 `result` 下（store.py:403-406）→ 计数每进程清零，八轮拒绝恒显 `1/9 cumulative`（L387 等 ×8）、Layer4 恒 `1/6`（L398 等 ×8），累计帽（9/6）永不可达，**循环没有自我终止路径**。修复：读 `checkpoint.get("result", {}).get("_retry_state")`。（此 bug drama 链同病。）

---

## 主题 5：MV 变体管线整体健康

### 已完成相产物抽查
| 相 | 产物 | 判定 |
|----|------|------|
| mv01 | `assets/MV01/song-package/{full-mix,vocal,instrumental}.wav` + song-package.json（3 段/8 歌词行/beat_grid 14 键/license/provenance） | **真实可用**（YuE2 渲外成品在盘）。但 `degraded=True`（bpm 实测 61.4 vs 标称 96，偏差 36%>8%，L9/L554）→ beat_grid 不可靠，按 Gate 20 要求须人工核 0.5x/2x 档——操作者从未获得裁决机会（门超时） |
| mv02 | script-draft.json + spatio-temporal-script.json（最终版 01:32，3 场景 8 镜组） | 结构完整；创意质量未经 mv03-gate 审（未到达）。注意它被**重跑了 8 次**（01:32 版与 10-15 版的 S03 场景内容已漂移——见主题 1 S03 例外），门通过≠版本稳定 |
| p04 | 1 角色 night_walker turnaround（character-assets.json，10-15 20:44） | **带病放行**：首轮真实生成后 vision-seam QC `checked=6 passed=3 failed=3` 拒绝（L281-283）；次轮起 REUSE-01 缓存 7 连跳（L304/440/571/757/904/1041/1191/1320——"Skipping P04 generation, returning cached assets"），QC 失败的 3 张图**从未被重生成，也从未复审**。skip-existing 病的 p04 变体：QC 只挂在生成路径，缓存路径免检 |
| p07 | S01/S02 六图（10-15 22:29）+ S03 三图（10-17 01:41-43） | S03 新版有 delegate 自检 0.88-0.95 背书（真实描述）；S01/S02 仅门抽签通过过，内容从未被人眼或真描述复核。md5 显示 S01_front 与 `_raw_premaster`/`originals` 均不同（22:29 写入非简单拷贝；具体产线待验证） |
| p11a5 | **无任何产物** | **从未运行过**。state 里的 `completed` 是主题 4 所述 registry bug 写入的伪 checkpoint（rollback_to=p11b 的载荷形态与之自证）。MV 链也不含此相 |
| p11b 及以后 | 无 | 未到达。`video-clips.json` 恒空 |

### 复跑设计是否放大浪费？
**实情与背景假设相反——不烧 GPU，烧的是 GLM tokens + 墙钟 + 审批注意力**：
- p04 七轮重入全部 REUSE-01 缓存命中（0 GPU）；p11a5 从未跑（0 GPU）。背景所述「每轮重烧 p04/p11a5 GPU 时」不成立。
- 实际每轮烧：mv02 delegate（2-3 calls，单 call 输入 124-145K tokens，cache 90-95%，L1037 等）+ p07 delegate（10-24 calls，输入 135-206K，cache 76-100%，L2026-2029、L1118、L1389）+ 9 图 vision_verify（glm-5.3-flash）≈ 每轮 15-25 min delegate 墙钟；外加八轮里 6 次 3600s 门空转（约 6 小时纯等待）+ 17 张平台卡。
- run.sh 的 6 连试循环（run.sh:14-24）在「结构性死循环」面前只是把同一故障重放六遍：rc=1 重试对确定性失败无修复力，反而每轮新增 2-3 张孤儿 review 卡。

### 整体判定
MV 变体管线的**新写相（mv01/mv02）与复用相接线本身是通的**：song intake→gate→approve→mv02→p04→p07 全链真实走通过三次（三次 approve 后 DAG 都正确推进到 p07）。杀死首跑的是三个跨相交互缺陷（registry 盲检索 ×2、fix-required 单槽覆写、门 expected 标签化）+ 一个机制缺口（HIL 审批无内容记忆）。全部修复前，**任何 operator 侧重试（重跑 run.sh、人工批卡、手动补图）都无法让管线走到 p11b 之后**。

---

## P0/P1/P2 清单（按修复性价比排序）

| # | 级别 | 缺陷 | 位置 | 一行修复 |
|---|------|------|------|---------|
| 1 | **P0** | QualityGateRejection 回滚跳转用 drama 默认 registry → p07 拒绝后重跑的是 p11b | runner.py:4463（对照正确写法 :4417） | 补 `registry=registry` |
| 2 | **P0** | Layer4 retry checkpoint 用 drama registry → 每轮写伪 p11a5 completed → 游标孤儿 → start_idx=0 → mv01 重提门 | runner.py:4581 + :450-488 | 同上 |
| 3 | **P0** | vision 门 expected 回退 content-free 标签 + delegate schema 无 description → 门=0.7 阈值抽签 | p07_scene_generation.py:508、:1748；vision_verify.py:1207 | schema 补 description / 判定前从 scenes.json 富化，标签 expected 时 fail-loud |
| 4 | **P0** | fix-required 单槽：p11b Layer4 100ms 覆写 p07 反馈 → 八轮 delegate 零反馈（"feedback injected" 0 命中） | runner.py:4556 vs p07_scene_generation.py:1781-1807 | 按 phase 分键或消费前禁覆写 |
| 5 | P1 | HIL 门无内容记忆：未变 song-package 被要求批 9 次；重提门产生新 review_id，旧卡悬垂（14 张孤儿） | gates.yaml:456-467 + runner_hooks.py:568-727 + 主循环无状态跳闸 | content_hash approve 沿用 + resubmit 关旧卡 |
| 6 | P1 | p11b 门提交先于输出校验 → 8 张 p11b 孤儿卡 | p11b_final_render.py:3674 | clips 空时先 raise，后交卡 |
| 7 | P1 | `_retry_state` 持久化读取失配 → 累计帽永不可达，死循环无自终止 | runner.py:3751 vs store.py:403-406 | 读 `result._retry_state` |
| 8 | P1 | fix feedback 文本自带 `--skip-existing`，与「重生成已存在文件」自锁 | p07_scene_generation.py:2037 vs scene_multiview_dualwall.py:277/293/309 | 指令改为 rm+重跑或 --force-views |
| 9 | P2 | p04 vision-seam QC 拒后被 REUSE-01 缓存免检放行（QC 只挂生成路径） | runner log L281 vs L304+ | REUSE 命中时对上轮 QC failed 子集复检或拒绝缓存 |
| 10 | P2 | vision_verify 结果缓存实为进程内 dict（跨进程方差即抽签来源），注释宣称 24h-TTL | vision_verify.py:106 | 文档对齐或落盘缓存 |
| 11 | P2 | p07 delegate 600s 整被掐（run.sh 设 1200），rounds 1-2 由此堕入文件兜底 | run.sh:12 vs run.log L373/510 | 核实 runtime watchdog 传导（待验证） |

---

## 摘要（≤400 字）

ep-mv-trial01 六轮 rc=1 不是六个故障，是**一个结构性闭环转了八圈**：p07 vision 门拒 → 回滚跳转因 `_phase_id_to_index` 缺 registry（runner.py:4463）误落 p11b（drama idx7 == MV idx7）→ p11b 交空 clips 提门后秒败 Layer4 → fix-required 被覆写（p07 反馈八轮零送达）→ `_save_retry_rollback` 再缺 registry（runner.py:4581）写出 MV 链不存在的 p11a5 伪 checkpoint → 下轮游标孤儿 → start_idx=0 → mv01 无条件重跑重提 HIL 门（同一 song-package 要批第 N 次）→ 批了则 15-25 分钟后再次拒于 p07，不批则 3600s 烧尽。门本身也在抽签：schema 无 description 字段，expected 回退成「S03 scene image」占位串（p07:508/:1748），判官对标签打分恒 0.50-0.65 震荡；四个操作者侧复核件同图同引擎全 PASS 0.75-0.97，从无回流。

**P0**：① runner.py:4463/4581 两处 registry 盲检索；② 门 expected 标签化（schema 补 description）；③ fix-required 单槽覆写。

| 初判 | 判定 | 修正 |
|------|------|------|
| 1 skip-existing 死循环 | ✅ 修正 | no-op 属实（dualwall:277/293/309），但反馈根本没到 delegate（被 p11b 覆写），且门输入坏使其即使重生成也拒；S03=第 8 轮 delegate 因 mv02 改稿主动重生成并自检 0.88-0.95 |
| 2 审批-等待握手断裂 | ❌ 推翻 | 三次 approve 全部在等待窗口内被 30s 轮询消费并推进 DAG（L13/427/558）；真课题=每轮重提门的审批通胀（9 卡/同内容）+ 14 张孤儿卡 |
| 3 S07 复核-门背离 | ✅ 修正 | 背离确凿但非阈值/模型差异——同引擎 glm-5.3-flash 同阈值 0.7，差异全在输入：门喂标签串，复核喂真实描述（01:45 vs 01:49 同图 0.88 vs 0.50）；复核零回流 |
