# 骨架 · 砍线 / 合人 / 排爽点

拿全部卷摘要（或短篇原文）+ 用户参数，产出 outline.json 的**骨架四块**：`adaptation` / `characters` / `scenes` / `beats`。分集梗概**这一步不写**——骨架没拍板就写分集，方向错了全废。

## 顺序就是方法

1. **砍线**。短剧只装得下一条主线 + 至多一条副线。砍掉的写进 `adaptation.cut`，每条都要有 why。`adaptMode` 不是忠实时一条不砍会被 validate 拦。
2. **合人**。功能重复的角色合成一张脸（两个报信的 → 一个），合并进 `characters[].from` 的 ← 改动记录。然后**分档**（`tier`）：主角组 `lead` 1–5 人、有名字的重要配角 `support` ≤ 10、功能性角色 `functional` ≤ 10。功能性角色占脸不占名——`name` 用称呼标签（「急诊医生」），也不用写人物弧。无名背景人不进表。
3. **收场景**。主场景上限随集数走（4 + ⌈集数/10⌉，夹在 5–15：6 集给 5 个，60 集给 10 个），以 `validate` 报的数为准。这是 AI 短剧的宽松版——场景是生成的，多开几个景换观赏性是划算的，别把戏都憋在一个屋里。原著里只出现一次的场景，要么砍掉、要么写 `reusePlan`（复用哪个现有环境资产、换什么时段天气改出来）。
4. **排爽点**。先定 major（大爆点）落在哪几集，再拿 minor 填缝。硬规则：相邻间隔 ≤ 3 集、开头结尾无真空、最早的 major 不能在最后一集。`type` 跟着题材走——女频打脸和男频战神的爽点不是一种东西，看 `params.genre`。
5. **收道具**。**排在爽点之后不是随便排的**——叙事道具的判据是「它托起哪个爽点」，爽点没定就分不清哪件物件是道具、哪件只是陈设。上限 8 件，跟主角数量一个量级。每件写 `function`（它在戏里承载什么）与 `beatIds`（托起哪几个爽点），分集用 `propIds` 引用。

   **一件东西该不该进这张表，问一句就够了：它坏了、丢了、被换掉，剧情会不会塌。** 会塌就是叙事道具（皮箱、砚台、那封信）；不会塌就是场景陈设（船舱的挂灯、桌上的茶碗），归 `novel-art` 的场景锚点管，不进这张表。填不出 `function` 的一律不收——**填不出来的不是道具，是背景**。

每一步都基于卷摘要里的原料。**关键取舍在 `adaptation.keep` 里附 `evidence`（原文逐字片段）**——大纲要能指回原文，不是凭印象改编。

砍完、合完之后各补一句结论：`adaptation.cutNote` 写砍线的含义（「这意味着：全剧终点是……」），`adaptation.mergeNote` 写主角组入选理由（谁有完整转变弧）。这两句会出现在报告最前面的「关键决策」区块，也是拍板时给用户看的核心内容。

## 两轮规则 ⛔

骨架必须跑两轮：

- **第一轮快版**：四块填齐、能过 `validate --stage beats` 就停，**交给用户拍板**。砍了哪条线、合了哪些人、大爆点在第几集——这三件事用户不点头，后面全是白干。
- **第二轮细版**：吸收用户意见后细化，再过一次 `validate --stage beats`。

快版的意义是便宜——错了只损失一轮骨架，不是 60 集梗概。

## 自检

写完跑：

```bash
node scripts/novel-outline.mjs validate <outline.json> --stage beats
```

有违规逐条修，改完重跑，直到通过才允许进分集。
