@lingjingai/scriptctl 0.47.5 → 0.49.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/changes/0.48.0.md +14 -0
  2. package/changes/0.49.0.md +17 -0
  3. package/dist/bin.js +2 -2
  4. package/dist/bin.js.map +1 -1
  5. package/dist/cli.js +2 -0
  6. package/dist/cli.js.map +1 -1
  7. package/dist/domain/ingest/govern.js +25 -0
  8. package/dist/domain/ingest/govern.js.map +1 -1
  9. package/dist/domain/ingest/production-validation.d.ts +7 -0
  10. package/dist/domain/ingest/production-validation.js +52 -0
  11. package/dist/domain/ingest/production-validation.js.map +1 -0
  12. package/dist/domain/ingest/serial-context.js +11 -6
  13. package/dist/domain/ingest/serial-context.js.map +1 -1
  14. package/dist/domain/ingest/validation.js +25 -3
  15. package/dist/domain/ingest/validation.js.map +1 -1
  16. package/dist/domain/ingest/video-apply.js +6 -2
  17. package/dist/domain/ingest/video-apply.js.map +1 -1
  18. package/dist/domain/ingest/video-context.js +3 -0
  19. package/dist/domain/ingest/video-context.js.map +1 -1
  20. package/dist/domain/script/names.d.ts +1 -0
  21. package/dist/domain/script/names.js +4 -0
  22. package/dist/domain/script/names.js.map +1 -0
  23. package/dist/domain/script/patch/helpers.d.ts +2 -0
  24. package/dist/domain/script/patch/helpers.js +55 -1
  25. package/dist/domain/script/patch/helpers.js.map +1 -1
  26. package/dist/domain/script/patch/inline-speaker.d.ts +2 -0
  27. package/dist/domain/script/patch/inline-speaker.js +50 -0
  28. package/dist/domain/script/patch/inline-speaker.js.map +1 -0
  29. package/dist/domain/script/patch/ops-action.js +30 -4
  30. package/dist/domain/script/patch/ops-action.js.map +1 -1
  31. package/dist/domain/script/patch/ops-asset.js +18 -0
  32. package/dist/domain/script/patch/ops-asset.js.map +1 -1
  33. package/dist/domain/script/patch/ops-dialogue.js +7 -37
  34. package/dist/domain/script/patch/ops-dialogue.js.map +1 -1
  35. package/dist/domain/script/patch/ops-state.js +14 -1
  36. package/dist/domain/script/patch/ops-state.js.map +1 -1
  37. package/dist/domain/script/schema.js +1 -1
  38. package/dist/domain/script/schema.js.map +1 -1
  39. package/dist/help-text.js +10 -4
  40. package/dist/help-text.js.map +1 -1
  41. package/dist/llm/tasks/ingest/episode-assets.js +1 -1
  42. package/dist/llm/tasks/ingest/episode-assets.js.map +1 -1
  43. package/dist/llm/tasks/ingest/text-normalize.js +13 -5
  44. package/dist/llm/tasks/ingest/text-normalize.js.map +1 -1
  45. package/dist/llm/tasks/ingest/video-serial.js +11 -1
  46. package/dist/llm/tasks/ingest/video-serial.js.map +1 -1
  47. package/dist/llm/tasks/schemas.js +5 -5
  48. package/dist/llm/tasks/schemas.js.map +1 -1
  49. package/dist/usecases/ingest/pipeline.js +15 -2
  50. package/dist/usecases/ingest/pipeline.js.map +1 -1
  51. package/dist/usecases/ingest/video-pipeline.js +15 -2
  52. package/dist/usecases/ingest/video-pipeline.js.map +1 -1
  53. package/dist/usecases/script/insert.js +5 -1
  54. package/dist/usecases/script/insert.js.map +1 -1
  55. package/dist/usecases/script/lib.js +21 -2
  56. package/dist/usecases/script/lib.js.map +1 -1
  57. package/package.json +15 -16
  58. package/skills/scriptctl/SKILL.md +36 -12
  59. package/skills/scriptctl/references/atomic-write-workflow.md +33 -13
  60. package/skills/scriptctl/references/ingest-workflow.md +30 -11
  61. package/skills/scriptctl/references/production-writing-standard.md +83 -0
  62. package/skills/scriptctl/references/state-reference-repair.md +3 -1
@@ -4,6 +4,8 @@
4
4
 
5
5
  核心理念:**写手是你**。你自己想好每一句正文,用原子能力把它灌进结构化剧本里。scriptctl 负责「合法的骨架 + 引用完整性 + 校验」,不负责「写得好不好」。
6
6
 
7
+ 人物、路人群体、地点粒度、门口跨空间、蒙太奇、对白、Action 和场内状态变化统一执行 [production-writing-standard.md](production-writing-standard.md)。
8
+
7
9
  ---
8
10
 
9
11
  ## 端到端流程
@@ -13,18 +15,18 @@ create(空白剧本,既有剧本略过)
13
15
  → worldview 设世界观
14
16
  → 资产批次
15
17
  add-actor / add-location / add-prop 注册或完善资产
16
- state-add / describe 定义持久视觉状态
18
+ state-rename / state-add / describe 定义默认与持久视觉状态
17
19
  do assets.txt --apply → 读回资产与 states
18
20
  → 正文批次
19
21
  add-episode / synopsis 建分集与梗概
20
22
  insert <ep> --location 仅在真实场界处建 scene
21
- scene-ref 绑定本场资产与 state
23
+ scene-ref --state 绑定本场全部资产与实际 state
22
24
  insert <ep/scn> --type ... 按 action 批次连续写正文
23
25
  → scenes / actions / validate 收尾自查
24
26
  → publish 入库(沙箱必做)
25
27
  ```
26
28
 
27
- > 发声源写在**对白行内联**(`dialogue <at> --actor/--kind`,或 `insert --actor`);造型挂在**场景 cast 引用**上(`scene-ref <ep/scn> <kind:id> --state`)。
29
+ > 发声源写在**对白行内联**(`dialogue <at> --actor/--kind`,或 `insert --actor/--kind`);造型挂在**场景 cast 引用**上(`scene-ref <ep/scn> <kind:id> --state`)。正文插入前,本场必须已有地点,并且本场全部地点/人物/道具引用都绑定已建立的 state。空镜、环境动作或非角色发声场可以没有人物引用。
28
30
 
29
31
  资产/分集/场景的 id **自动按序分配**:第一个 actor 是 `act_001`、location 是 `loc_001`、prop 是 `prp_001`、episode 是 `ep_001`、它下面第一场是 `scn_001`……所以你能在后续命令里直接引用这些可预测的 id(也可以 `--id` 显式指定)。
30
32
 
@@ -40,13 +42,22 @@ scriptctl worldview 现代
40
42
  scriptctl add-actor 林夏 --role 主角 --description "高三女生,沉默寡言"
41
43
  scriptctl add-actor 陈默 --role 配角 --description "便利店夜班店员"
42
44
  scriptctl add-location 便利店 --description "24h 便利店,冷白光"
45
+ scriptctl state-rename actor:act_001/default "平日造型"
46
+ scriptctl describe actor:act_001/default "整洁校服,黑色长发"
47
+ scriptctl state-rename actor:act_002/default "夜班造型"
48
+ scriptctl describe actor:act_002/default "便利店制服,胸前佩戴工牌"
49
+ scriptctl state-rename location:loc_001/default "常态"
50
+ scriptctl describe location:loc_001/default "冷白灯全部亮起"
43
51
  scriptctl add-episode --title "第一集:相遇"
44
52
  scriptctl synopsis "雨夜便利店里,林夏与夜班店员陈默因一场意外相遇。"
45
53
  scriptctl synopsis ep_001 "林夏雨夜进入便利店,发现陈默似乎认识她。"
46
54
  scriptctl insert ep_001 --location loc_001 --time night --space interior # → scn_001
55
+ scriptctl scene-ref ep_001/scn_001 location:loc_001 --state default
56
+ scriptctl scene-ref ep_001/scn_001 actor:act_001 --state default
57
+ scriptctl scene-ref ep_001/scn_001 actor:act_002 --state default
47
58
  scriptctl insert ep_001/scn_001 --type action --content "雨夜,林夏推门进店,浑身湿透。" --emotion "狼狈"
48
59
  scriptctl insert ep_001/scn_001 --type dialogue --content "欢迎光临。" --actor act_002
49
- scriptctl insert ep_001/scn_001 --type inner_thought --content "又是他。" --actor act_001
60
+ scriptctl insert ep_001/scn_001 --type inner_thought --content "陈默又出现了。" --actor act_001
50
61
  scriptctl validate
51
62
  ```
52
63
 
@@ -76,11 +87,16 @@ add-actor 林夏 --role 主角 --description "高三女生,沉默寡言"
76
87
  add-actor 陈默 --role 配角 --description "便利店夜班店员"
77
88
  add-location 便利店 --description "24h 便利店,冷白光"
78
89
  add-prop 黑伞 --description "林夏随身携带的旧黑伞"
79
- state-add actor:act_001 "平日造型" --state-id default --description "整洁校服,黑色长发"
90
+ state-rename actor:act_001/default "平日造型"
91
+ describe actor:act_001/default "整洁校服,黑色长发"
80
92
  state-add actor:act_001 "雨天造型" --state-id st_rain --description "校服湿透,发梢滴水"
81
- state-add location:loc_001 "常态" --state-id default --description "冷白灯全部亮起"
93
+ state-rename actor:act_002/default "夜班造型"
94
+ describe actor:act_002/default "便利店制服,胸前佩戴工牌"
95
+ state-rename location:loc_001/default "常态"
96
+ describe location:loc_001/default "冷白灯全部亮起"
82
97
  state-add location:loc_001 "停电" --state-id st_outage --description "冷白灯熄灭,应急灯发绿"
83
- state-add prop:prp_001 "常态" --state-id default --description "伞面完整,伞骨可正常开合"
98
+ state-rename prop:prp_001/default "常态"
99
+ describe prop:prp_001/default "伞面完整,伞骨可正常开合"
84
100
  state-add prop:prp_001 "破损" --state-id st_torn --description "伞面裂开,一根伞骨外翻"
85
101
  ```
86
102
 
@@ -92,14 +108,14 @@ synopsis "雨夜便利店里,林夏与夜班店员陈默因一场意外相遇
92
108
  synopsis ep_001 "林夏雨夜进入便利店,发现陈默似乎认识她。"
93
109
  insert ep_001 --location loc_001 --time night --space interior
94
110
  scene-ref ep_001/scn_001 actor:act_001 --state st_rain
95
- scene-ref ep_001/scn_001 actor:act_002 --state none
111
+ scene-ref ep_001/scn_001 actor:act_002 --state default
96
112
  scene-ref ep_001/scn_001 location:loc_001 --state default
97
113
  scene-ref ep_001/scn_001 prop:prp_001 --state default
98
114
  insert ep_001/scn_001 --type action --content "雨夜,林夏推门进店。" --emotion "狼狈"
99
115
  insert ep_001/scn_001 --type dialogue --content "欢迎光临。" --actor act_002
100
116
  ```
101
117
 
102
- 地点、时段和动作连续时,后续节拍继续向 `ep_001/scn_001` 追加 action。互动式写作可把长场拆成多个 action 批次依次 `do --apply`,每批都指向同一 scene。场界规则以 SKILL.md「从灵感写剧本」为准。
118
+ 地点、时段、叙事线和全部资产 state 连续时,后续节拍继续向 `ep_001/scn_001` 追加 action。持久视觉 state 变化时在变化动作后建立同地点的新 scene,并绑定新 state。互动式写作可把长场拆成多个 action 批次依次 `do --apply`,每批都指向同一 scene。场界规则以 SKILL.md「标准剧本通用流程」为准。
103
119
 
104
120
  动词与单条命令完全一致(参数见 `scriptctl <verb> --help`)。`do` 也读 stdin:`… | scriptctl do -`。
105
121
 
@@ -128,10 +144,11 @@ insert ep_001/scn_001 --type dialogue --content "欢迎光临。" --actor act_00
128
144
 
129
145
  ## 校验语义(重要)
130
146
 
131
- 「没填满」不拦路,「结构坏了」才拦:
147
+ 空骨架可以逐步搭建,但正文入口有更严格的前置门:
132
148
 
133
- - **只提醒(warning,不影响 `validate` 通过)**:空剧本、空集、空场、场景没地点、资产缺描述。所以你可以先把骨架搭出来、逐步填,中途 `validate` 也能过。
134
- - **硬错误(拦截)**:悬挂引用、重复 id、非法枚举、缺 id/name、scene_id 不递增、非人类注册成 actor —— 这些会破坏 DB 图结构,必须修。
149
+ - **骨架阶段**:可以先建空剧本、空集和空场,再逐项补资产引用。
150
+ - **正文插入门**:`insert <ep/scn>` 要求本场已有地点,且本场全部地点/人物/道具引用都带已物化 state;对白/心声使用 actor 时,该 actor 必须已在本场 cast。空镜、环境动作或非角色发声场可以没有人物引用。
151
+ - **全局硬错误**:悬挂引用、重复 id、人物真名重复、说话人物不在本场、非法枚举、缺 id/name、非人类注册成 actor。
135
152
 
136
153
  随时 `scriptctl validate` 看整体,`scriptctl issues --severity warning` 专看「还没填」的清单。
137
154
 
@@ -141,6 +158,9 @@ insert ep_001/scn_001 --type dialogue --content "欢迎光临。" --actor act_00
141
158
 
142
159
  - 资产 state 判定(哪些进 `states[]`)见 SKILL.md「资产 state 判定」。
143
160
  - 非角色发声源(系统/广播/画外/群体)用 `dialogue <at> --kind system|broadcast|offscreen|group [--label ...]`(对白行内联),**不要**注册成 actor。
144
- - 角色名保持规范:别在名字里塞状态注解(`林夏(受伤)`会被拒),外观档位用 `state-add`。
161
+ - 人物真名全剧唯一且稳定:动作中只用 `actor_name`;称呼、绰号、职位放 aliases,只能出现在自然对白等不要求资产解析的文本里。别在名字里塞状态注解(`林夏(受伤)`会被拒),外观档位用 `state-add`。
162
+ - action 禁止“他 / 她 / 对方 / 其中一人 / 另一个人”等指代;逐个写明行动者真名。对白内容允许自然使用人称代词。
163
+ - action 写明具体动作、作用对象、空间方向和可见结果;对白的短促伴随动作放 `emotion`,影响走位、道具或连续性的动作单独写 action。
164
+ - 一个 scene 只绑定一个地点和每项资产的一个 state;多地点或多状态参考需求按 [production-writing-standard.md](production-writing-standard.md) 处理并报告结构限制。
145
165
  - action 情绪放 `emotion` 字段:插入时用 `insert ... --emotion "紧张"`,修改时用 `emotion <ep/scn#idx> "紧张"` / `emotion <ep/scn#idx> --clear`,不要把 `[紧张]` 这类标记塞进 content。
146
166
  - 参数 / 退出码以 `scriptctl <cmd> --help` 为准。
@@ -1,10 +1,10 @@
1
1
  # ingest workflow — 素材直转入库(文本 / 视频)
2
2
 
3
- 适用:有外部素材要**转成 v3 剧本并入库**。统一入口 `scriptctl ingest`,看 source 后缀**自动分流**文本 / 视频;两条管线在同一个 govern 收尾汇合,产出**完全相同的 v3 `script.json`**。
3
+ 适用:有外部素材要**转成 v3 剧本并入库**。统一入口 `scriptctl ingest`,看 source 后缀**自动分流**文本 / 视频;两条管线在同一个 govern 收尾汇合,产出相同结构的 v3 `script.json`。视频、小说和非标准剧本统一执行 [production-writing-standard.md](production-writing-standard.md)。
4
4
 
5
5
  ```
6
- ingest --source-path <file|dir> → view / ingest status → publish
7
- (抽取,产 workspace/script.json) (自查/看进度) (校验+入库)
6
+ ingest --source-path <file|dir> → 标准化复核 → view / ingest status → publish
7
+ (抽取,产 workspace/script.json) (内容完成门) (自查/看进度) (校验+入库)
8
8
  ```
9
9
 
10
10
  - 支持输入:**文本** txt / md / docx;**视频** 单个正片文件或**分集目录**(需 `GEMINI_API_KEY`)。pdf/json/xlsx 会被拒。
@@ -28,10 +28,28 @@ scriptctl ingest --source-path uploads/正片/
28
28
  - `--force`:**同源**重跑,清掉产物重来(**不能换源**)。
29
29
 
30
30
  管线(了解即可,产物都在 `workspace/`):
31
- - **文本**:pass1 切块 → pass2 归一化(廉价模型出 markdown,确定性解析,**逐块 checkpoint**)→ pass3 合并 → 组装 `body.json`(正文骨架;台词/动作**逐字保真、不改写**)→ **串行 govern**(逐集:模型带累积上下文,从正文自己认人物 / importance(featured=出图/background=龙套) / 提造型(每个=一张造型图,带描述) / 做身份合并;`serial/context_NNN.md`=喂模型的完整上下文、`serial/ep_NNN.md`=模型每集决策,**逐集 checkpoint、重跑续**)→ `script.json`(v3 校验)。
32
- - **视频**:pass1 Gemini 转录pass2 解析pass3 跨集花名册归并 + 状态归并(**贵,`roster.json`/`context.merged.md` 会复用**)→ pass4 二次画面校正 pass5 纯剧情发声源审计 pass6 apply + 汇入 govern 收尾。时间戳挂在 `extend.timestamp`。
31
+ - **文本**:正文起点定位 切块 → 生产化归一(对白逐字保留;叙述转成具象 Action;按地点、时段、叙事线和持久状态变化分场)→ 合并组装 `body.json` 串行资产/身份/state 治理 确定性编号 v3 结构校验 + 生产规范 warning → `script.json`。逐块与串行窗口都有 checkpoint。
32
+ - **视频**:逐集串行观看原视频,同时维护跨集人物花名册、剧情进展和造型;每集直接输出逐镜头 scenes + 资产增量 确定性人物归一、群体发声归一、编号和 state 物化 v3 结构校验 + 生产规范 warning`script.json`。时间戳写入 `extend.timestamp`,逐集 `ep/*.json` `context.json` 支持断点续跑。
33
33
 
34
- ## 二、看进度 / 自查
34
+ ### 提取与解析原则
35
+
36
+ - 先忠实提取源素材可验证的对白、动作、顺序、人物状态和场景切换,再整理成标准 v3 资产与正文。
37
+ - 视频以画面和声音为准;小说与非标准剧本把叙述转换成可拍摄 Action,同时保留原文事实、因果和人物关系。
38
+ - 保留对白原文;允许为结构化和可拍摄性规范化叙述措辞,同时保持事实、因果、顺序、动作结果和状态不变。
39
+ - 将无法确认的人物身份、动作主体、地点和状态保留为待复核项,不补写源素材没有表达的事实。
40
+ - 使用同一套人物、路人群体、地点粒度、蒙太奇、对白、Action 和状态变化规则,保证不同输入最终落成一致的标准剧本。
41
+
42
+ ## 二、标准化复核
43
+
44
+ `ingest` 生成且 `validate` 通过只代表结构与引用合法。publish 前按 [production-writing-standard.md](production-writing-standard.md) 逐集复核:
45
+
46
+ 1. 用 `actors / locations / props / states` 检查资产、去重、importance 和持久视觉状态。
47
+ 2. 用 `scenes --in <ep>` 检查唯一地点、场界、蒙太奇顺序和状态变化边界。
48
+ 3. 用 `actions --in <ep>` 检查说话人、群体发声、人物真名、动作链和可拍摄性。
49
+ 4. 视频对照画面与声音;文本对照原文,确认对白逐字保真,事实、因果、顺序、动作结果和状态没有改变或补造。
50
+ 5. 用 scriptctl 读写动词修正 `workspace/script.json`,再次运行 `validate`,完成内容复核后再 publish。
51
+
52
+ ## 三、看进度 / 自查
35
53
 
36
54
  ```bash
37
55
  scriptctl ingest status # 人读:kind / state / 各 pass 进度(transcribe 40/57 (2 failed) ...)
@@ -41,9 +59,9 @@ scriptctl view --watch [--port N]# 实时监听面板:分阶段进度条 + 逐
41
59
  scriptctl summary --script-path workspace/script.json # 抽完当普通剧本读
42
60
  ```
43
61
 
44
- `state`:`empty`(没开始)/ `incomplete`(在跑或中断、无硬错,重跑续)/ `failed`(有失败单元或校验没过)/ `ready`(`script.json` 生成且 v3 校验通过)。进度**纯从工作区真实文件推导**,不看任何独立状态机文件——不会出现"状态文件说完了但其实没完"。它报的是**管线事实**,不代表"已人工复核"(复核是你的完成门,另算)。
62
+ `state`:`empty`(没开始)/ `incomplete`(在跑或中断、无硬错,重跑续)/ `failed`(有失败单元或校验没过)/ `ready`(`script.json` 生成且 v3 结构校验通过)。`validation.json` 的 production warning 标出仍需复核的内容规范问题。进度从工作区真实文件推导;它报的是管线事实,源素材一致性仍由复核完成门确认。
45
63
 
46
- ## 三、🔴 抖动与重跑(大规模转剧本的常态)
64
+ ## 四、🔴 抖动与重跑(大规模转剧本的常态)
47
65
 
48
66
  模型抖动 / 限流 / 单集超时 / 偶发解析失败在几十集体量下**是正常现象,不是 bug**。护栏与恢复:
49
67
 
@@ -51,13 +69,14 @@ scriptctl summary --script-path workspace/script.json # 抽完当普通剧本
51
69
  |---|---|---|
52
70
  | `INGEST_NORMALIZE_INCOMPLETE`(文本)<br>`INGEST_TRANSCRIBE_/CORRECT_/SPEAKER_INCOMPLETE`(视频) | 部分单元失败,留下 `passN/*.error.json` sidecar | **直接重跑 `scriptctl ingest`(同 source、同 workspace)**——从 checkpoint 续,只补失败单元。跑完 `ingest status` 看还剩几个,多跑几次到收敛 |
53
71
  | `INGEST_SERIAL_FAILED`(文本串行 govern) | 某集串行解析连试几次仍失败(模型抖动) | **直接重跑**,从该集续——前面各集已缓存不重跑 |
72
+ | `INGEST_PIPELINE_MISMATCH` | 工作区的管线版本与当前版本不同 | 确认 source 未变化后,使用同一 source、同一 workspace 加 `--force` 完整重建 checkpoint |
54
73
  | `INGEST_SOURCE_MISMATCH` | 工作区是别的 source 建的 | 换一个新的 `--workspace-path`,**别 `--force` 硬覆盖** |
55
74
  | `INGEST_VALIDATION_FAILED` | 最终 v3 校验没过 | 看 `workspace/validation.json` 的具体报错,用读写动词修 `--script-path workspace/script.json` 再 `publish` |
56
75
  | 持续 401/403/404 / 模型路由错 | 网关/密钥/模型环境问题(不是抖动,重跑也不好) | 如实告诉用户,别反复空跑、别编造成功。视频需 `GEMINI_API_KEY` |
57
76
 
58
77
  🔴 **绝不**:清工作区、删 checkpoint、手塞/手改中间文件来"绕过"失败。重跑 = 唯一正解;成功单元不会重跑,贵的花名册归并(`roster.json`)也会复用。
59
78
 
60
- ## 四、入库 `publish`
79
+ ## 五、入库 `publish`
61
80
 
62
81
  ```bash
63
82
  scriptctl publish # 沙箱:自动写项目 DB 新 revision(SANDBOX_PROJECT_GROUP_NO 已注入)
@@ -70,7 +89,7 @@ scriptctl publish --remote --project-group-no 123 # 显式指定项目组
70
89
  - `SCRIPT_REVISION_CONFLICT` = DB 被别的 revision 改过:重新拉取当前剧本、合并你的改动,再 publish。
71
90
  - publish 幂等:同一份 script 重复 publish 不会产生新 revision(按内容 sha 去重)。
72
91
 
73
- ## 五、复杂场景怎么接
92
+ ## 六、复杂场景怎么接
74
93
 
75
94
  - **转完先精修再入库**:`ingest` → 用 `--script-path workspace/script.json` 跑读写动词修(改归属、并角色、标龙套、补造型……)→ `publish`。
76
95
  - **入库后再改**:`publish` 之后直接对 DB(沙箱裸命令 = remote)继续精修,每次改都是新 revision。
@@ -78,7 +97,7 @@ scriptctl publish --remote --project-group-no 123 # 显式指定项目组
78
97
  - **超大剧集(几十集)**:并发默认已调好;失败就重跑到 `ingest status` 显示 `ready`。花名册归并只跑一次并复用,重跑很快。
79
98
  - **归并质量**:跨集角色归并靠文字锚点,相似角色可能误合/合过头。用 `roster.review.md`(视频)核对归并决策;发现误合,入库后用 `merge` 拆分/改名修正。
80
99
 
81
- ## 六、抽完后的读写
100
+ ## 七、抽完后的读写
82
101
 
83
102
  抽取产物就是标准 v3 剧本,用 SKILL.md 里所有读写能力精修(目标记得指 `--script-path workspace/script.json`,或 publish 后指 DB):
84
103
  - `summary` / `episodes` 看整本 + 分集梗概;`actions --in <ep>` 带 timestamp 看节奏。
@@ -0,0 +1,83 @@
1
+ # 标准剧本生产写作规范
2
+
3
+ 适用:从零创作、视频提取、小说或非标准剧本解析、洗稿、对标仿写、转绘。目标是生成可供后期生产直接读取的 Schema v3 `script.json`。
4
+
5
+ ## 一、输入原则
6
+
7
+ - 从零创作时,根据题材、集纲、人物关系和世界观补全可执行正文。
8
+ - 视频提取时,以画面和声音为准,保留可验证的对白、动作、人物状态、场景切换和时间顺序。
9
+ - 小说与非标准剧本解析时,把叙述转换成结构化人物、地点、道具、scene 和 action,保留原文事实与因果关系。
10
+ - 提取与解析保留对白原文;允许为结构化和可拍摄性规范化叙述措辞,同时保持事实、因果、顺序、动作结果和状态不变。
11
+ - 洗稿、对标和转绘时,从原剧读取结构与节奏,只把新内容写入目标剧本。
12
+ - 提取与解析遇到不确定信息时保留待复核标记;不为满足格式补写源素材没有表达的动作、身份、状态或镜头。
13
+
14
+ ## 二、每集与每场的开写清单
15
+
16
+ 开始每一集和每一场前:
17
+
18
+ 1. 读取现有人物、地点、道具及其 states。
19
+ 2. 确定本场唯一地点、全部出场人物、全部使用道具和各自实际 state。
20
+ 3. 注册缺少的资产,定义需要独立视觉参考的持久状态。
21
+ 4. 建立 scene,绑定地点、人物、道具及实际 state。
22
+ 5. 读回 scene-ref,确认正文中的每项资产都能映射到本场引用。
23
+ 6. 写入正文;发现新增资产或状态时,先完成资产与引用再继续。
24
+
25
+ ## 三、人物、路人与群体
26
+
27
+ - 为承担独立对白、动作、道具交接或剧情结果的个体建立 actor;一次性小角色使用 `importance background`。
28
+ - 将固定人数、固定服装、固定站位或跨场连续出现的群体拆成可识别人物资产。
29
+ - 将无法区分成员、无需连续造型的环境人群写成群体 Action。
30
+ - 将群体共同发声写成 `--kind group --label <群体名>`。`group` 只属于该条 dialogue,不创建 actor、state 或视觉参考资产。
31
+ - 当某个群体成员开始独立说话或行动时,先为该成员建立 actor 并绑定到 scene。
32
+ - 仅有 group 发声、没有可识别 actor 的场面直接使用 group speaker;scene 绑定实际 location 与关键道具,不创建虚假人物。
33
+
34
+ ## 四、地点、门口与关联空间
35
+
36
+ - 将可独立布置、可独立生成参考图、可重复引用的稳定物理空间建立为 location。客厅、卧室、卫生间、大厅、广场分别建地点。
37
+ - 使用“豪宅·客厅”“豪宅·卧室”“剧院·舞台”“剧院·后台”这类统一命名表达空间归属,并在 description 中写明共享建筑风格和连接关系。
38
+ - 摄影机留在当前空间时,scene 继续引用当前地点;门内可见空间写入 Action。
39
+ - 摄影机或主要表演进入另一空间时建立新 scene,并引用新地点。
40
+ - 舞台与后台交叉剪辑按每次切换建立相邻 scene;连续跟拍跨过空间边界时在边界处切换 scene。
41
+ - 当前每个 scene 只支持一个 location。画面需要同时使用两个正式地点参考图时,报告结构限制;“客厅/卧室”只会形成一个复合地点资产,不能代替两个地点引用。
42
+ - 当前没有地点组、父地点或共享美术继承。统一命名和 description 是现阶段的归属约定。
43
+
44
+ ## 五、地点时间与地点状态
45
+
46
+ - 使用 scene 的 `environment.time` 表达白天、夜晚、黄昏等时间信息。
47
+ - 当光线、布景、损毁或季节变化需要反复引用或独立生成视觉资产时,为 location 建立 state,例如“广场·夕阳”“大厅·停电”。
48
+ - 将一次性的时间描述保留在 environment 或 Action 中;将持久、可复用的视觉变化建立为 state。
49
+
50
+ ## 六、Action 与 dialogue
51
+
52
+ - 将 Action 写成可拍摄的行为链:行动者真名 + 具体动作 + 作用对象 + 空间方向 + 可见结果。
53
+ - 使用人物真名指明每个行动者;对白内容可以自然使用人称代词。
54
+ - 根据生产需要补充景别、机位、镜头运动和画面焦点。
55
+ - 将抽象心理和评价转换成表情、肢体、道具变化、环境反应或明确对白。
56
+ - 为每条 dialogue 绑定 `--actor` 或非角色发声源。将情绪、语气和短促伴随动作写入 `emotion`;将影响走位、道具或连续性的动作单独写成 Action。
57
+ - 两人同时说话时写成相邻两条 dialogue,第二条的 `emotion` 以“同时”开头。当前结构不提供对白重叠时间轴。
58
+
59
+ ## 七、蒙太奇与并行剪辑
60
+
61
+ - 同一地点、同一组视觉状态下的快速动作组合写成同一 scene 的连续 Action。
62
+ - 跨地点蒙太奇为每个地点建立短 scene,按剪辑顺序排列,并用 transition 标明蒙太奇开始、切换和结束。
63
+ - 为蒙太奇中需要参考图或连续性的地点、人物、道具建立资产,并在各自 scene 绑定实际 state。
64
+ - 当前没有 montage group。使用相邻 scene、transition 和统一文本标记表达组合关系。
65
+ - 纯空镜或完全无人镜头单独建 scene,绑定实际 location 与关键道具,不创建虚假人物。
66
+
67
+ ## 八、场内状态变化
68
+
69
+ - 一个 scene 中,每个人物、地点和道具绑定一个有效 state。
70
+ - 需要更换视觉参考资产的持久状态变化构成生产场界,即使地点和时间连续也建立新 scene。
71
+ - 变化前 scene 绑定旧 state,在末尾写清变化动作;需要生成过程画面时给该 Action 添加 `transition_prompt`。
72
+ - 变化后 scene 绑定新 state。同地点、同时段的状态边界保持独立,不参与场景合并。
73
+ - 当前同一 scene 不能同时引用同一资产的多个 state。一个镜头需要变化前后两张状态图时报告结构限制。
74
+
75
+ ## 九、完成门
76
+
77
+ 1. 读回本集 `scenes` 与 `actions`。
78
+ 2. 检查每场唯一地点、全部出场人物、道具和 state 引用。
79
+ 3. 检查 Action 的真名、动作链、空间结果和可拍摄性。
80
+ 4. 检查 dialogue 的说话人、emotion 和群体发声类型。
81
+ 5. 检查场界、蒙太奇顺序和状态变化边界。
82
+ 6. 提取与解析任务对照源素材复核对白原文,以及事实、因果、顺序、动作结果和状态。
83
+ 7. 运行 `validate`。把结构通过与内容标准、源素材一致性分别报告。
@@ -42,7 +42,7 @@ scriptctl state-delete actor:act_001/st_old --strategy replace --replacement st_
42
42
  scriptctl state-delete actor:act_001/st_old --strategy remove
43
43
  ```
44
44
 
45
- 期望:引用该 state 的场景 ref 被保留、但 `state_id` 被清(角色仍在场,只是没造型);`refs actor:act_001/st_old` 为空;`validate` 通过。
45
+ 期望:引用该 state 的场景 ref 被保留、但 `state_id` 被清(角色仍在场,只是没造型);`refs actor:act_001/st_old` 为空。这个结果是修复中间态:为该 ref 重新设置合法 state 前,CLI 会拒绝向该场继续插入正文。
46
46
 
47
47
  4. **只想清某场的造型**(不删 state):
48
48
 
@@ -51,6 +51,8 @@ scriptctl scene-ref ep_001/scn_003 actor:act_001 --clear # 保留在场,
51
51
  scriptctl scene-ref ep_001/scn_003 actor:act_001 --remove # 整个移出该场
52
52
  ```
53
53
 
54
+ `--clear` / `--state none` 只用于修复中间态;从零创作不能用它们跳过状态绑定。
55
+
54
56
  ## 核验要点
55
57
 
56
58
  - 引用只有一层:`scene.{actors|props}[].state_id` 和 `scene.location.state_id`。`replace`/`remove` 会自动处理这一层。