# ep-demo-pixar 创作日志深度分析报告

**分析对象**: ep-demo-pixar（demo皮克斯，毛毛虫阿毛 × 独角仙父亲花青）2026-08-14 23:38 → 2026-08-15 03:51 两次 run
**证据基准**: `/tmp/pipeline_ep-demo-pixar.log`（下称 **L<n>** = 主 log 行号）；`creation-ep-demo-pixar.jsonl`（下称 **CJ**，时间戳为 UTC，= 本地时间 −8h）；`phase-execution-log.jsonl`（下称 **PE**）；`.pipeline-state.json`（下称 **PS**）；代码以 `文件:行号` 引用。
**约束**: 只分析，不改代码。

---

## A. 时间线重建

### A.1 Run 边界与 Phase 起止

**Run1**: L1 (23:38:44 启动) → L463-488 (01:46:18 P04 崩溃退出)。
**中间人工干预**: 01:46 → 01:59，P04 手动注册（PS 中 `p04_character_design.completed_at = 2026-08-14T17:58:40Z` = 本地 01:58:40，早于 Run2 启动 33 秒；操作手册见 `skills/kais-movie-pipeline/p04-delegate-timeout-manual-registration/SKILL.md`）。
**Run2 (resume)**: L489 (01:59:11 启动, `start_idx=4 checkpoint=True` L512) → L1306-1321 (03:51:12 P10 崩溃退出)。

| Phase | 开始 | 结束 | 耗时 | 证据 |
|---|---|---|---|---|
| P01 hook_topic | 23:38:47 | 23:54:40 | **953s (16min)** | L26, L125-127; PE `953.027` |
| P02 outline | 23:54:40 | 23:59:24 | **284s** | L127, L174; PE `284.048` |
| P03 script_audit (Form C) | 23:59:24 | 01:06:18 | **4014s (67min)** | L174, L364-365; PE `4014.184` |
| P04 character_design (Run1) | 01:06:18 | 01:46:18 | **2400s 超时崩溃** | L366, L463; PE `delegate_parse_retry` |
| P04 手动注册 | ~01:58 | 01:58:40 | 人工 ~13min | PS completed_at; skill 手册 |
| （resume + retroactive canvas sync） | 01:59:13 | 01:59:15 | 2s | L512-570 |
| P06 blackboard | 01:59:15 | 02:44:07 | **2692s (45min)** | L572, L1046; PE `2692.122` |
| P07 scene_generation | 02:44:07 | 03:09:14 | **1507s (25min)** | L1046, L1152-1159; PE `1506.712` |
| P08 scene_selection | 03:09:14 | 03:11:29 | **135s** | L1159, L1186 |
| P09 shot_breakdown | 03:11:30 | 03:37:24 | **1555s (26min)** | L1187, L1219; PE `1554.746` |
| P09b shot_audit | 03:37:25 | 03:37:25 | **0.17s**（纯确定性） | L1259-1260 |
| P09c storyboard_board | 03:37:25 | 03:46:34 | **548s** | L1261-1263 |
| P10 voice | 03:46:35 | 03:51:12 | **277s 崩溃** | L1272, L1306; PE `delegate_parse_retry` |

墙钟总计: Run1 2h08m + 人工 13min + Run2 1h52m ≈ **4h13m，止步于 P10**。

### A.2 每 phase 的 delegate 计数与浪费

| Phase | delegate 数 | 明细 | 隐性浪费 |
|---|---|---|---|
| P01 | 9 | 编排×3（v1: 10 api L59, v2: 2 api L74, v3: 3 api L92）+ hook_retention 评分×3（各 3 api L102/111/120）+ audience judge ×1（L124） | 评分 subagent 每个都重新 `skill_view` 同一 skill（28138 chars ×3，L96/106/115）——cache 命中但仍是 3 次重复装载；三变体得分 0.980/0.972/0.972（L172 P02 同款现象），近并列，区分度低 |
| P02 | 3 | 三路并行 screenwriter（L131-133），api 4+3+3 | 三路输出 response_len 全部 ≈6700（L167-171），高度同质 |
| P03 | 8 | gravedigger+prophet 并行（L176-178）→ alchemist_r1（L219）→ blacksmith_r1（L249）→ traitor_r1（L271）→ r2 三连（L298/316/348） | **r2 整轮 = 40min**，起因 traitor_r1 评 7.0 < 7.5 阈值（L295，`p03_form_c/orchestrator.py:65`） |
| P04 | 1 | 42/50 api calls 被超时打断（L485） | 整个 2400s 白费（资产在盘上被救回，见 B.1） |
| P06 | ~9 | L1 编排（L576-581）+ 5 个 L2 并行（L584-586 等）+ editor（L760）+ physics_precheck（L965）+ 若干 self-improvement review turn | L2 各 agent 把大量 api 花在 `skill_manage` 失败重试上（见 B.7） |
| P07 | 1 | 43/50 api calls（L1148）+ 后置 vision_verify 确定性检查（L1151） | — |
| P08 | 1 | 7/16 api（L1182） | — |
| P09 | 1 | 8/50 api，但单次调用 #8 输出 **86k tokens / 901s 延迟**（L1217-1218） | 单点巨量生成是 P09 耗时主因 |
| P09c | 0 | 纯本地拼板（548s 全在图像拼贴） | — |
| P10 | 1 | 9/50 api（L1299）+ 引擎内 design_voice×3 + clone×31 | 引擎 3×design_voice 全 500（L1300-1305）后仍然串行打了全部 31 个 clip 的合成（31/31 degraded），无引擎级熔断 |

**隐性重试汇总**：GLM 侧 529 过载重试仅 1 次（L194-196，P03 prophet，37s 后成功吸收——**非** P04 崩溃原因）；`skill_manage` 失败 30 次（L69-70、L778-820、L907-957、L998-1035 等）；`Subagent appears stale` 误报 5 次（L320, L659, L875, L929, L1216——全部对应 356~901s 的长 API 调用，见 B.4/B.5）。

---

## B. KMC 管线问题

### B.1 【P0】P04 崩溃链：delegate 2400s 超时

**现象**: P04 单 delegate 在 2399.9s 被 `DelegateTimeoutError` 打断，summary 为空，`parse_delegate_output` 抛 `ValueError: delegate_task summary is empty`（L463-485；`pipeline/phases/p04_character_design.py:998` → `pipeline/structured_output.py:254`）。

**根因（证据链）**:
1. **不是 GLM 故障**。整个 Run1 只有 1 次 529 过载（L194，P03 阶段，重试成功）。P04 的 42 次 API 调用全部正常返回，延迟最长 188.7s（L387）。
2. **是「subagent 串行跑图像生成 + 单 delegate 预算不足」**。P04 delegate 的 `process` 工具出现 **7 次精确 180.00s 完成**（L403, 407, 409, 411, 413, 427, 429, 433——输出仅 89~117 chars），这是 dreamina 图像批任务的轮询在 180s 工具超时边界被截断的表现；L437 (30.3s)、L443 (89.9s)、L462 (95.2s) 是幸存的批次。P04 需产出 4 角色 × (L1 anchor + 20 L2 fittings + 20 turnarounds + age timeline + props)（PS 中 `character_assets`: l1_anchors=4, l2_scene_fittings=20, scene_costume_turnarounds=20, age_timelines=1, l4_props=2；L527-569 canvas 同步可见 45+ 张图）。串行 + 每批 ≤3min 的节奏吃满 2400s。
3. **打断时 subagent 仍在正常工作**：L485 `Interrupted during API call, api_calls=42/50, tool_turns=41`——不是 stall，是预算耗尽时正巧在飞行中。
4. `sandbox invoked from non-main thread: HARD timeout disabled` 警告**未出现在 P04**（只出现在 P02/P03，L128-130, L179-180），且 L463 证明 delegate 级 2400s 软超时正常生效——所以「硬超时被禁用导致拖到 2400s」不成立；2400s 就是 `KAIS_DELEGATE_TIMEOUT` 本身按设计触顶。真正的设计缺口是：**图像类重资产 phase 的产出预算（~40 张图）与单 delegate 2400s 上限不匹配**，且超时即弃全部 42 次 api call 的上下文。

**stall warning 是否掩盖真信号**：P04 全程只有 1 条 stall warning（L384, 01:07:18），信噪干扰小；但全局 28 条 stall warning 里 0 条对应真 stall（见 B.4），反而让操作者对警告脱敏。

**resume 后 P04 为何快速通过**：不是管线自身恢复——是**人工手动注册**。Run2 启动时 `start_idx=4`（L512）直接跳到 P06，P04 状态在两次 run 之间由人按 `p04-delegate-timeout-manual-registration/SKILL.md` 手工写入（PS `completed_at=01:58:40`；该 skill 文档明确记录 "Validated ep-demo-pixar 2026-08-15"）。L514-570 的 retroactive canvas sync 把手动注册的资产补进画布（amao/huaqing/tanglang/wugong + 20 L2 + 20 turnaround，L519-569）。

**严重度**: **P0**——主线「从需求到 master.mp4」在此断掉，需人工 13min 救援且救援路径本身是高危手工操作（skill 文档自述为 "landmine"：L2 矩阵不全会在 P09 再爆）。

**修复建议**:
- P04 拆分为「设计 delegate（纯 JSON，无图像）」+「确定性图像批量（`gen_iframes`/dreamina 批脚本，参照 memory: 长任务 setsid 脱离 + 文件系统轮询）」，图像不占 delegate 预算；
- 或 delegate 超时前 checkpoint 化：`process` 工具每完成一批就把批次 manifest 写盘，超时 resume 从批次断点续跑而非全弃；
- `parse_delegate_output` 对「超时但资产在盘」的情形自动走磁盘恢复（把现有人工 playbook 代码化），而非要求人工。

### B.2 【P0】P10 静音硬门控：引擎故障被当成内容劣化，fix_hint 驴唇不对马嘴

**现象**: 03:51:09-03:51:12 三角色 `design_voice` 连续 HTTP 500（L1300-1305: `tts_engine degraded: HTTP 500` ×3）→ 31/31 clip 全部劣化 → `engine mute hard-gate` raise（L1306-1321；`pipeline/phases/p10_voice.py:823-826`）。

**证据**:
- 引擎侧：KAP `/api/v1/tts/speak` 返回 500，`plugins/kais_aigc/tts_engine.py:183-184` 把 ≥500/429 统一折成 `{"degraded": True, "reason": "HTTP 500"}`——**reason 只有 "HTTP 500" 四个字符**，不含 KAP 返回体里的 `TTS failed: ...` 真实原因（`_post` 在 184 行直接丢弃 `response.text`）。
- 门控侧：`p10_voice.py:788-826` 的 mute hard-gate 不区分「引擎不可达」（HTTP 500/ConnectError）与「生成质量差」（mean_volume ≤ -80dB），两种都进 `_degraded_clips`，都触发同一 fix-required。
- **fix_hint 错位**（实锤）：`fix-required.json` 的 fix_hint 是 *"Your previous output could not be parsed. Error: ... Ensure you emit a valid JSON block in a ```json fenced section..."*——这是 delegate JSON 解析失败的标准话术。但本次 delegate 输出解析完全正常（PE 里 P10 是 `delegate_parse_retry`，错误实际来自引擎硬门控，被 runner 统一归类成 `delegate_output_parse_failure`，`fix-required.json` `error_type: delegate_output_parse_failure`）。让 resume 后的 subagent「emit valid JSON」对修引擎毫无作用，会白烧一整轮 delegate。
- **二次风险**：按 `p10_voice.py:793-808`，带 `_MUTE_RETRY_MARKER` 的第二次尝试会 **warn + 静默丢弃全部 31 个 clip** 继续往下走——即重试后管线会产出**无对白的无声 master.mp4** 而标记 success。引擎级 100% 故障时这是最坏行为。

**严重度**: **P0**（主线第二次中断；且 retry 路径会静默产无声成片）。

**修复建议**:
1. `_degrade` envelope 增加 `kind: "engine_unavailable" | "quality"`：HTTP 5xx/连接失败 → 前者；volume gate → 后者；
2. 门控对 `engine_unavailable` 占比 ≥ 阈值（如 100%）时**直接 fail-fast** 并给出「修引擎再 resume」的 fix_hint，不走 delegate 重试、绝不静默丢 clip；
3. fix-required 写入处按真实 error_type 分流话术（引擎故障 ≠ JSON 解析失败）；
4. P10 开始前做一次引擎 preflight（见 C.3）。

### B.3 【P1】canvas_sync `no such column: filePath`

**现象**: L465（Run1 崩溃时）与 L518（Run2 retroactive sync 时）两次 `canvas_sync: voice asset sync failed: no such column: filePath`。

**根因（代码+DB 双向证据）**:
- 写入侧 `plugins/kais_aigc/canvas_sync.py:3714-3719`: `SELECT id, name, characterId, type, meta, filePath, isPrimaryView, state FROM o_assets WHERE ...`——直接向 **o_assets** 表索要 `filePath` 列。
- DB 实际 schema（db2.sqlite 实测）: `o_assets` 表**没有** `filePath` 列（列为 id/name/prompt/remark/type/describe/scriptId/imageId/assetsId/projectId/flowId/.../meta/...）；`filePath` 在 **o_image** 表（`CREATE TABLE o_image (id, filePath, ...)`）。
- 即：声纹同步 SQL 把 o_image 的列名用在了 o_assets 上。正确写法应 `JOIN o_image ON o_assets.imageId = o_image.id` 取 `o_image.filePath`，或退回 `_meta.get("ref_audio_path")`。

**后果**: P04 声纹资产**从未**同步进画布（异常被 `canvas_sync.py:3747-3748` 吞掉只留 warning）；每次 P04 canvas sync 必报。当前无下游消费者读画布声纹（待验证），故 P1 而非 P0。

**修复建议**: 改 JOIN 或删掉该列改用 meta fallback；给 canvas_sync 的 SQL 加单测（对真实 schema fixture 跑一遍）。

### B.4 【P1】stall warning 噪音：28 条全误报，信噪比 0

**证据（计数）**: 全 log 1324 行中：
- `delegate_task stall suspected` × **28**（60s 一条，如 L37 在 P01 API call #3 正常飞行中就报；P04 仅 1 条 L384）
- `parallel_delegate ... stall suspected` × 3（L648-650, 761, 786）
- `Subagent appears stale (no progress for 15 heartbeat cycles)` × **5**（L320, L659, 875, 929, 1216）——每一条都紧跟着一次 356~901s 的合法长 API 调用完成（如 L1216 之后 8 秒，L1217 显示 901.4s 延迟的调用成功返回 86k tokens）
- `Skill security warning` × **72**（每个 subagent 每次 skill_view 都重复报同一批 skill，如 hook_retention 在 L31/35/63/77/89/95/98/105/108/114/117 反复出现）
- `skill_manage returned error` × **30**（subagent 猜 skill 命名空间失败：L69-70, L778, L796, L807, L813, L815, L820, L826, L830, L836, L840, L851...——movie-experts 前缀猜了 4 种写法都没中）

**根因**: stall 检测以「60s 无 turn 结束」为信号，但 GLM 单次调用常态 60~900s（本次 log 中 >120s 的调用 ≥15 次），警告器完全无法区分「模型在慢慢生成」与「真卡死」；heartbeat stale 判定同理。

**严重度**: P1——28+5 条全误报意味着真 stall 时警告会被忽略（狼来了）；同时刷屏稀释关键告警（P04 的 1 条真预警、P10 的引擎 500 都淹没在噪音里）。

**修复建议**: stall 计时器改为「距上次 **API 流式心跳/工具调用完成** 的间隔」而非「delegate 开始起的 wall clock」；同 phase 去重只报一次 + 状态行汇总；skill security warning 每 skill 每 run 只报一次（或直接把 movie-experts 加进 trusted dir 根治）。

### B.5 【P2】`sandbox invoked from non-main thread: HARD timeout disabled`

**现象**: 5 条（L128-130 P02 三路并行, L179-180 P03 双 agent 并行）。并行 dispatch 的 worker 线程里无法启用 sandbox 硬超时。

**后果评估**: 本次事件中**无实际危害**——P04（唯一超时崩溃的 phase）是单 delegate、主线程路径，其 2400s delegate 超时正常生效（L463）。该警告的真实暴露面是 P02/P03/P06 的并行 worker：若其中一个 worker 真挂死，只能等整个 run 被外层杀掉。属于已知 stdlib threading 限制（log 文本自述），但当前无 watchdog 兜底。

**严重度**: P2。**修复建议**: 并行 worker 改进程池（`multiprocessing`）以获得可杀性；或至少记录 per-worker elapsed 上限告警升级路径。

### B.6 【P1】P03 用时 67min：r2 整轮 40min 的合理性

**证据分解**（FormC 8 个 agent 的耗时）:
- gravedigger ‖ prophet 并行: 23:59:24 → 00:03:15 (**3.8min**, L176-217)
- alchemist_r1: 00:03:15 → 00:08:56 (**5.7min**, L219-247)
- blacksmith_r1: 00:08:56 → 00:15:15 (**6.3min**, L249-269；单次 API 335s/23.7k tokens, L264)
- traitor_r1: 00:15:15 → 00:25:56 (**10.7min**, L271-294)
- **判iterate**: `overall=7.0 < 7.5 → iterate`（L295；阈值 `p03_form_c/orchestrator.py:65 _ITERATE_THRESHOLD=7.5`）
- alchemist_r2: 7.6min (L298-315)
- **blacksmith_r2: 22.7min** (00:33:35 → 00:56:19, L316-346)——其中 3 次 API 分别 509.5s（L321, 34.7k tokens）、356.0s（L329, 20.7k tokens）、468.6s（L336, 32.4k tokens），纯模型生成时间 ≈22min
- traitor_r2: 10min (L348-363)
- 终局: `audit_score=0.85, rounds_run=2`（L364）

**判断**: 多 agent 对抗结构本身合理（r1 7.0 分确实低于 7.5 硬阈值，iterate 是代码按设计执行）；**瓶颈是 GLM 长生成的吞吐**（r2 铁匠一个 agent 占全 phase 1/3 时间）。可质疑点：
1. 7.0 vs 7.5 只差 0.5 就触发整轮 40min 重做——阈值没有缓冲带/置信度概念，评分本身是 LLM 主观打分（traitor），0.5 的差距在噪声范围内；
2. r2 的 alchemist/blacksmith/traitor 是**串行**链（L298→L316→L348），其中 alchemist_r2 与 traitor_r1 的审计结果无并行可能，但 blacksmith_r2 的 3 次超长生成无法再切。
3. **附带发现（跨剧集污染，P1）**: L212 `gravedigger: metadata-shell detected, glob-recovered artifact from /data/.../episodes/ep-shencongshenyuan-ep01/assets/p03_gravedigger_主角.json`——**glob 恢复捡到了另一个剧集（ep-shencongshenyuan）的 gravedigger 产物**。本次 keys 恰好匹配侥幸可用，但恢复逻辑未按 episode 目录收口，存在把别的剧集角色向量混进本剧的实锤风险。应把 glob 根锁死在当前 episode workdir。

**修复建议**: iterate 阈值加滞回带（如 7.0 以下才强制，7.0-7.5 记 warning 放行）；glob-recovery 加 episode 前缀过滤；r2 铁匠的超长输出考虑按 scene 分片生成。

### B.7 其余异常（附加发现）

| # | 现象 | 证据 | 根因 | 严重度 |
|---|---|---|---|---|
| 1 | **skill_manage 命名空间猜谜 ×30**：L2 subagent 依次试 `production_designer` / `movie-experts/production_designer` / `movie-experts:production_designer` / `p06-production-designer-...` 全 404 | L778-820, L826-851, L907-957, L998-1035 | self-improvement review turn 的 skill 创建/更新入口与 skill 实际注册名不一致（hermes profile 里只有 `movie-experts:p06-...` 这类全名）；每个 L2 agent 平均烧 5-8 次 api 在此 | P2（浪费 token+时间，P06 45min 的隐形贡献者） |
| 2 | **skill_view 崩溃**: `Object of type date is not JSON serializable` | L896-898 | skill 元数据含 date 类型未序列化 | P2 |
| 3 | **P09c canvas project_id unresolved** | L1262 `canvas project_id unresolved — writing sheets to .../assets/storyboard_sheets (paths will need /local-file proxy)`；而 .canvas.json 明明 pin 了 1786721927385（L23, L509） | `p09c_storyboard_board.py:82` 只从 `.pipeline-state.json` 找 project_id（该文件无此字段），没读 `.canvas.json`——与 runner 的 canvas 配置链（CLI>.canvas.json>env）不一致 | P2（分镜板走 local-file 代理，画布体验降级） |
| 4 | **P09 storyboard 同图跨场景复用可疑**: S6_0418/S6_0447/S6_0450 → o_image=1330，与 S1_0000/0003/0012/0020/0032 相同（L1223-1253）；场景图 1-6 全部 → o_image=1329（L1153-1158） | canvas_sync 以图像内容/路径去重 | S6 三个 shot 复用 S1 的分镜图是「同源参考图」还是碰撞错配——**待验证**（需比对 1330 实际文件内容） | P2 待验证 |
| 5 | **`process` 工具 180s 硬顶 ×12**: 7 次在 P04（见 B.1），4 次在 P07（L1081, 1085, 1089, 1128）+ L437 等 | 工具级超时 | 长图像批任务被 180s 切片，subagent 只能反复重启轮询，放大 delegate 耗时 | P1（与 B.1 同根：批任务应脱离 delegate 工具沙箱） |
| 6 | **GLM 并发护栏 N=4 与文档 3 不符** | L28 `GLM concurrency guard enabled: N=4`；CLAUDE.md 约束 `MAX_CONCURRENT_GL=3`（2026-07-01 实测 5 并发触发 429） | 配置漂移 | P2 待验证（本次未见 429，可能护栏已放宽或实测边界变化） |
| 7 | **P06 L2 patch 大量失败**: `Found 14/35/9 matches for old_string`（L665, 763, 678） | L2 写 blackboard 的 patch 锚点不唯一 | blackboard 并发写同构条目，patch 工具不适用 | P2（最终 L2 complete version=540 L964，未阻断） |
| 8 | **P02 三候选 0.980/0.972/0.972 近并列**（L172） | 评分缺乏区分度 | 评审 prompt/刻度问题 | P3 |

---

## C. KAP 平台问题

### C.1 【P0】TTS 路由 500 的传播路径与错误契约

**传播链（全链路证据）**:
```
KMC p10_voice (p10_voice.py:378 engine.design_voice)
  → plugins/kais_aigc/tts_engine.py:168  POST {KAP}/api/v1/tts/speak
  → KAP src/routes/v1/tts/speak.ts:245   submitPrompt → POST {ComfyUI}/prompt (172.17.0.1:8188)
  → ComfyUI custom_nodes/ComfyUI-QwenTTS (AILab_Qwen3TTSVoiceDesign 节点)
  → 节点 import qwen_tts / transformers 失败 → prompt rejected / execution error
  → speak.ts:248-249 / 268-273  catch → res.status(500).json(error(err.message))
  → tts_engine.py:183-184  status≥500 → _degrade("HTTP 500")   ← response.text 被丢弃
  → p10_voice.py 全部 clip劣化 → mute hard-gate 崩溃（B.2）
```

**实测（分析时复现）**: `POST /api/v1/tts/speak {"mode":"voice_design",...}` 返回 `{"code":400,"data":null,"message":"fetch failed"}`——ComfyUI 侧连接失败被最外层 catch 兜住，消息只有 `"fetch failed"` 五个字符，**HTTP 码还与 catch 分支语义对不上**（网络故障应为 5xx/503，实际返回 400 系）。容器状态：`comfyui-primary Up 30 seconds`（刚被重建/重启），佐证「容器重建后引擎缺失」。

**错误契约问题（实锤）**:
1. KAP 把「后端引擎不存在/不健康」「工作流被拒」「合成超时」「真的合成失败」四种性质完全不同的故障**全部折成 500 + 一句 message**（speak.ts:249, 254, 273）。下游无法机判。
2. KAP **已有**现成的健康检查端点 `/api/production/qwen-tts/status`（`status.ts`：探测 ComfyUI `/system_stats` + `/object_info` 里是否注册了 `AILab_Qwen3TTS*` 节点，返回 `comfyui.status` + `plugin_loaded`），但：
   - v1 TTS 路由（KMC 实际调用的那个）**从不调用它**做 preflight；
   - KMC 侧也从不调用它——`tts_engine.py` 没有 health 方法。
3. KMC `tts_engine.py:184` 在折 degrade envelope 时丢弃 KAP 返回体，进一步把信息压成 `"HTTP 500"`。

**修复建议**:
- KAP: v1 speak 在 submitPrompt 前做一次 object_info 节点探测，引擎缺失返回 **503 + 结构化错误** `{"error":{"kind":"engine_unavailable","engine":"qwen_tts","detail":"node AILab_Qwen3TTSVoiceDesign not registered"}}`；网络 fetch 失败归 502/503 而非 400/500 混用；
- KMC: `_degrade` 保留 response body 前 200 chars（对齐 4xx 分支 L187 已有的做法）；P10 preflight 调 status 端点，`plugin_loaded=false` 时直接 fail-fast，提示修引擎而不是进 delegate 重试。

### C.2 【P0】基础设施韧性：关键依赖活在容器可写层

**清单（docker-compose.v9.yml 卷挂载 vs 容器实测比对）**:

| 依赖 | 应在位置 | 是否有 volume/挂载 | 证据 |
|---|---|---|---|
| 增量 custom_nodes（LTXVideo/TRELLIS2/IndexTTS2/minimax-T8 等 15 个） | host `/data/workspace/comfyui-incremental-nodes` → 容器 custom_nodes | ✅ 挂载（compose v9 L87-100） | host 目录 ls 与 compose 一致 |
| **ComfyUI-QwenTTS 节点 + qwen_tts 引擎 + patches** | 容器 `/root/ComfyUI/custom_nodes/ComfyUI-QwenTTS` | ❌ **无任何挂载**：compose v9 volumes（L82-111）不含它；host incremental-nodes 目录 ls **没有** QwenTTS；但容器内 ls **有** `ComfyUI-QwenTTS/`（含 `AILab_QwenTTS.py`, `qwen_tts/`） | 三方交叉验证 |
| **/opt 下的 voicedesign venv + qwen_tts patches** | 容器 `/opt/` | ❌ 无挂载；实测容器 `/opt` 只剩 `nvidia/` + `voicedesign_server.py`——**venv 已丢失**（与题述旁证一致：transformers 4.57.6 的 venv 没了；容器主环境 transformers 是 5.9.0，`python3 -c "import transformers"` 在 exec shell 报 ModuleNotFoundError，说明依赖环境碎片化） | docker exec 实测 |
| 模型库（qwen-tts 权重、LTX、IndexTTS 等） | `/data/models/comfyui` → `/root/ComfyUI/models` | ✅ rw 挂载（compose L84），宿主机持久 | compose L84, L107-110 |
| ComfyUI user 状态 / HF cache | named volumes `comfyui-user`, `comfyui-cache` | ✅（L86, L111） | compose |
| KAP 主服务（:10588） | host tsx dev 进程，非容器 | —（设计如此，compose L189-192 注释明确容器后端已移除） | compose 注释 |

**结论**: 唯独 **QwenTTS 整条链（节点代码 + python venv + 补丁）装在容器可写层**——容器一重建即全灭，这正是本次 P10 全灭的根因。且没有任何 install-qwen* 脚本（host `scripts/` 目录只有 kornia/insightface/training/aiia/indextts2/facerestore 六个，无 qwen）可以把环境一键建回来。

**修复建议**: 把 ComfyUI-QwenTTS 移入 `/data/workspace/comfyui-incremental-nodes`（照 IndexTTS2/minimax-T8 的既有模式 compose 挂载）；为其 venv/补丁写 `install-qwen-tts-deps.sh` 挂到 `/root/user-scripts/`（compose L101-106 已有先例）；容器重建后用 `/api/production/qwen-tts/status` 验收 `plugin_loaded=true` 再放行 P10。

### C.3 【P1】KAP→KMC 错误语义：KMC 还能拿到什么

现状 KMC 只能拿到: HTTP 状态码 + `err.message`（且被 tts_engine 丢弃）。缺：
1. **结构化错误**（kind/engine/detail 如 C.1 建议）；
2. **能力/健康端点的 KMC 侧消费**——status 端点已存在但双方都没接线；
3. 顺带: `TTS_CONFIG.pollTimeoutMs=300_000`（`v1/tts/config.ts`）与 KMC `DEFAULT_TIMEOUT=300.0`（`tts_engine.py:105`）**精确相等**——KAP 还在轮询 ComfyUI 时 KMC 客户端可能先超时，产生边界竞态（建议 KMC ≥ 360s）。

### C.4 KAP 其他发现

| # | 现象 | 证据 | 严重度 |
|---|---|---|---|
| 1 | **status 端点路由挂在 `/api/production/qwenTts/status`，而 KMC 用的 v1 路由无对应健康端点**（实测 `/api/v1/tts/health` 404） | router.ts:224-226; curl 404 | P2 |
| 2 | **v1 与 production 两套 TTS 路由代码重复**（workflow builder / poll / extract 三件套各写一遍，v1 `speak.ts:174-228` vs production `speak.ts:218-291`），fix 要改两处易漏 | 两文件 diff | P2 |
| 3 | **batch 端点只有 production 有**（production speak.ts:443+），v1 无——KMC 31 个 clip 走的是逐条串行，P10 引擎健康时也会慢 | v1 speak.ts 无 batch | P2 |
| 4 | **ComfyUI-QwenTTS 在 incremental-nodes 装载器名单外**（T8/SolAttn 已有「kais-incremental 认不出 → 独立挂载」的先例注释，compose L96-99），QwenTTS 连独立挂载都没有 | compose 注释 vs volumes | 已并入 C.2 |

---

## D. 修复优先级矩阵

| # | 问题 | 严重度 | 修复成本(h) | 建议顺序 | 阻塞了什么 |
|---|---|---|---|---|---|
| 1 | C.2 QwenTTS 依赖入卷 + 安装脚本（移 incremental-nodes + install 脚本 + status 验收） | P0 | 3-5 | **1**（不做这个，P10 永远会再灭） | P10→P15 全部音频/成片 |
| 2 | B.2+C.1 P10 门控区分引擎故障/质量劣化 + KAP 结构化错误(503) + 双侧接 status preflight | P0 | 4-6 | **2** | 主线恢复语义；防止静默无声 master |
| 3 | B.2b fix_hint 按 error_type 分流（引擎故障≠JSON 解析） | P0 | 1 | **3**（搭 2 的车） | resume 重试不再白烧 |
| 4 | B.1 P04 图像生产脱离 delegate 预算（确定性批脚本/断点续跑/磁盘自动恢复） | P0 | 6-10 | 4 | 主线首个夜间崩溃点；人工救援高危 |
| 5 | B.3 canvas_sync filePath→JOIN o_image | P1 | 0.5 | 5（最便宜的实锤修复） | 画布声纹资产 |
| 6 | B.6 P03 glob 恢复按 episode 收口 | P1 | 1 | 6 | 跨剧集内容污染 |
| 7 | B.4 stall/heartbeat 判定改心跳信号 + 告警去重；skill 警告去重 | P1 | 3-4 | 7 | 运维信噪比（真 stall 可见性） |
| 8 | B.7-5 process 工具 180s 顶 & 批任务脱离（与 4 同根） | P1 | 并入 4 | — | P04/P07 耗时 |
| 9 | B.7-3 p09c 读 .canvas.json 取 project_id | P2 | 0.5 | 8 | 分镜板画布体验 |
| 10 | C.3 KMC 超时 300→360s；C.4-1 v1 health 端点 | P2 | 1 | 9 | 边界竞态/可观测性 |
| 11 | C.4-2/3 v1 与 production TTS 路由合并 + v1 batch | P2 | 4 | 10 | 维护性/P10 速度 |
| 12 | B.7-1 skill_manage 命名空间统一；B.7-2 date 序列化；B.7-6 GLM N=4 与文档对齐 | P2 | 2 | 11 | token 浪费/配置卫生 |
| 13 | B.5 并行 worker 进程池化 | P2 | 8 | 12 | 挂死 worker 可杀性 |
| 14 | B.6 P03 iterate 阈值滞回带 | P2 | 1 | 13 | 40min 级重做频率 |
| 15 | B.7-4 storyboard o_image 跨场景复用排查 | P2 待验证 | 1 | 14 | 画布正确性存疑 |

---

## 附：与题述「已知事实」的核对结论

| 题述 | 核对结果 |
|---|---|
| Run1 崩 P04，delegate 2400s 超时，api 42/50 | ✅ 证实（L463/L485）；但根因是图像批量串行吃满预算，**非** GLM 故障 |
| GLM-5.3 api_calls 42/50 被打断 → 疑似 529 | ❌ 529 全 log 仅 1 次且在 P03 被吸收（L194-196），与 P04 无关 |
| Run2 P01-P09c 十个 phase 完成 | ⚠️ 需修正：P01-P03 在 **Run1** 完成；Run2 直接从 P06 开始（P04 是人工注册，L512 `start_idx=4`） |
| 3 角色 design_voice 全 HTTP 500 → 31/31 劣化 → 静音硬门控 | ✅ 证实（L1300-1321）；补充：二次重试会**静默丢全部 clip** 产出无声片（p10_voice.py:796-808） |
| 容器重建丢失 /opt VoiceDesign venv → KAP TTS 500 | ✅ 证实（容器 /opt 只剩 voicedesign_server.py；且 QwenTTS 节点本身也在可写层无挂载，C.2） |
| canvas_sync `no such column: filePath` | ✅ 定位：canvas_sync.py:3715 对无该列的 o_assets 查询；列在 o_image（B.3） |
