@lingjingai/scriptctl 0.60.13 → 0.61.1

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 (72) hide show
  1. package/changes/0.61.0.md +19 -0
  2. package/changes/0.61.1.md +15 -0
  3. package/dist/bin.js +16127 -11
  4. package/dist/bin.js.map +7 -1
  5. package/dist/cli/{register-batch.d.ts → register-review.d.ts} +1 -1
  6. package/dist/cli/register-review.js +19 -0
  7. package/dist/cli/register-review.js.map +1 -0
  8. package/dist/cli/register-script.d.ts +3 -0
  9. package/dist/cli/register-script.js +256 -0
  10. package/dist/cli/register-script.js.map +1 -0
  11. package/dist/cli/register-workflows.js +37 -42
  12. package/dist/cli/register-workflows.js.map +1 -1
  13. package/dist/cli.js +6 -16
  14. package/dist/cli.js.map +1 -1
  15. package/dist/domain/ingest/environment.d.ts +2 -3
  16. package/dist/domain/ingest/environment.js +1 -4
  17. package/dist/domain/ingest/environment.js.map +1 -1
  18. package/dist/domain/script/names.d.ts +1 -1
  19. package/dist/domain/script/names.js +1 -3
  20. package/dist/domain/script/names.js.map +1 -1
  21. package/dist/domain/script/shared/types.d.ts +1 -18
  22. package/dist/domain/script/shared/types.js +4 -8
  23. package/dist/domain/script/shared/types.js.map +1 -1
  24. package/dist/domain/script/shared/validation.d.ts +1 -12
  25. package/dist/domain/script/shared/validation.js +2 -22
  26. package/dist/domain/script/shared/validation.js.map +1 -1
  27. package/dist/domain/script/timestamp.d.ts +1 -23
  28. package/dist/domain/script/timestamp.js +2 -126
  29. package/dist/domain/script/timestamp.js.map +1 -1
  30. package/dist/domain/script/v3/validation.d.ts +2 -3
  31. package/dist/domain/script/v3/validation.js +1 -232
  32. package/dist/domain/script/v3/validation.js.map +1 -1
  33. package/dist/domain/script/v4/ids.d.ts +2 -24
  34. package/dist/domain/script/v4/ids.js +19 -40
  35. package/dist/domain/script/v4/ids.js.map +1 -1
  36. package/dist/domain/script/v4/validation.d.ts +2 -2
  37. package/dist/domain/script/v4/validation.js +1 -410
  38. package/dist/domain/script/v4/validation.js.map +1 -1
  39. package/dist/llm/config.js +4 -0
  40. package/dist/llm/config.js.map +1 -1
  41. package/dist/output.js +5 -0
  42. package/dist/output.js.map +1 -1
  43. package/dist/package-root.d.ts +2 -0
  44. package/dist/package-root.js +38 -0
  45. package/dist/package-root.js.map +1 -0
  46. package/dist/review-agent.js +2956 -0
  47. package/dist/review-agent.js.map +7 -0
  48. package/dist/usecases/changelog.js +3 -8
  49. package/dist/usecases/changelog.js.map +1 -1
  50. package/dist/usecases/script/action-span.d.ts +3 -19
  51. package/dist/usecases/script/action-span.js +19 -146
  52. package/dist/usecases/script/action-span.js.map +1 -1
  53. package/dist/usecases/script/review.d.ts +3 -0
  54. package/dist/usecases/script/review.js +185 -0
  55. package/dist/usecases/script/review.js.map +1 -0
  56. package/dist/usecases/update.js +2 -14
  57. package/dist/usecases/update.js.map +1 -1
  58. package/package.json +11 -3
  59. package/skills/scriptctl/SKILL.md +157 -214
  60. package/skills/scriptctl/references/ingest-workflow.md +1 -1
  61. package/skills/scriptctl/references/state-reference-repair.md +23 -19
  62. package/skills/scriptctl/references/video-transcript-repair.md +27 -29
  63. package/dist/cli/register-batch.js +0 -28
  64. package/dist/cli/register-batch.js.map +0 -1
  65. package/dist/cli/register-edits.d.ts +0 -4
  66. package/dist/cli/register-edits.js +0 -234
  67. package/dist/cli/register-edits.js.map +0 -1
  68. package/dist/cli/register-query.d.ts +0 -4
  69. package/dist/cli/register-query.js +0 -95
  70. package/dist/cli/register-query.js.map +0 -1
  71. package/skills/scriptctl/references/atomic-edit-workflow.md +0 -47
  72. package/skills/scriptctl/references/bulk-authoring.md +0 -50
@@ -1,287 +1,230 @@
1
1
  ---
2
2
  name: scriptctl
3
- description: "剧本 script.json 的本地查询、无 ID 可读创作稿编译、文件化批量写作、原子精修、素材 ingest 与 revision publish CLI。处理 Script v3/v4、两个 script.json、剧本资产/state、Action、场景引用或 authoring 时使用。"
3
+ description: "剧本 script.json 的本地阅读、定位、原子修改、整场整集回写、素材 ingest 与 revision publish CLI。处理 Script v3/v4、剧本资产与 state、Action、场景引用或视频证据核对时使用。"
4
4
  metadata:
5
- version: "0.29.4"
6
- scriptctl_version: "0.60.13"
5
+ version: "0.31.0"
6
+ scriptctl_version: "0.61.1"
7
7
  author: "official"
8
8
  ---
9
9
 
10
10
  # scriptctl
11
11
 
12
- `scriptctl` 始终对 `-p` 指向的本地 `script.json` 工作。远端剧本先
13
- `checkout`,完成本地查询、修改和 `validate` 后再 `publish`。
12
+ `scriptctl` 始终对 `-p` 指向的本地 `script.json` 工作。远端剧本先 `checkout`,
13
+ 完成本地阅读、修改和 `validate` 后再 `publish`。
14
14
 
15
- 实际调用和示例优先使用短参数:`-p/-w/-s/-o/-i/-g/-t/-a/-k/-n/-h/-v`。
16
- 没有短名的参数保持完整长写。
15
+ Agent 直接运行命令并阅读结果就是正常用法,默认文本输出即为给人和给 agent 看的形态。
17
16
 
18
- ## 输出模式
17
+ ## 地址
19
18
 
20
- Agent 直接运行命令并阅读结果属于正常使用,使用默认文本输出;查询表格默认为 TSV。
21
- 定位、查看正文、核对时间范围、读回修改和运行校验都使用默认输出。只有命令 stdout
22
- 将由脚本、程序、测试或前端按字段消费时,才使用 `-j` JSON 输出。
19
+ **一个字符串,读写通用**:
23
20
 
24
- ## 先识别版本
21
+ | 形式 | 例 | 指向 |
22
+ |---|---|---|
23
+ | 序号(1-based) | `3` / `3-2` / `3-2-5` | 第 3 集 / 第 3 集第 2 场 / 该场第 5 条 action |
24
+ | 正式 ID | `acB4xR8p` `scnQ7mN2v` `actA3kP9x` | 对应节点 |
25
+ | 资产名或别名 | `向北` `林教练` | 那个 actor / location / prop |
26
+ | 状态 | `向北/23号球衣` `actQYEeTr/default` | 该资产的一个造型状态 |
27
+ | 空 | (不传) | 剧本根 |
25
28
 
26
- 读取 `script.json.version`:
29
+ 歧义会报错并列出候选,不做猜测。**查询返回的锚点可以原样用于修改**,没有单独的
30
+ "可写地址"概念。v3 与 v4 用同一套语法——v3 没有 action ID,锚点退化成序号。
27
31
 
28
- - Script v4:新建和 ingest 的默认方言。episode、scene、Action、asset 使用带类型前缀的短随机 ID;修改只用正式 ID。
29
- - Script v3:线上既有项目的冻结方言。查询、修改、authoring 和 publish 继续使用 v3 地址与字段。
30
-
31
- 不要根据字段形状猜版本。命令会按显式 `version` 自动分流。
32
-
33
- ## 标准剧本通用流程
34
-
35
- 1. **忠实理解输入**:创作时落实题材、集纲和人物关系;提取与解析时保留源素材可验证的对白、动作、顺序、场界和状态变化。把不确定信息标为待复核,不补写源素材未表达的事实。
36
- 2. **注册资产**:先读现有人物、地点、道具;正文将出现的资产必须先注册。普通 Agent/LLM 创作用 `compose` 可读草稿的 `assets` 声明,CLI 自动生成 ID 和引用;高级批量 authoring 才使用 `<create>`。人物保留一个稳定的 `actor_name` 作为真名,称呼、绰号、职位放 `aliases[]`,同一人物共用一个 actor。
37
- 3. **建好资产状态**:每个新资产必须有唯一的 `default` state ID;它是底层基础状态键,不是用户可见造型名。`state_name` 与普通创作的 variant 名写实际可辨认外观,如“深灰通勤装”“夜班白大褂”。新资产声明的第一项 variant 是基础状态。持久、可复用、需要独立生成视觉资产的服装/造型差异才建立独立 state。人物 `description` 只写稳定身份形态,每个 variant 的 `description` 独立写成从头到脚可复现的完整造型。引用尚未登记的 variant 时,即使人物已经存在,也在本场草稿 `assets.actors` 中声明该人物与新 variant。
38
- 4. **建立真实场并绑定资产**:完整 scene 显式声明本场 `environment.time`,取 `day`、`night`、`dawn`、`dusk` 之一,并声明地点、全部人物、全部道具及其实际 state。V4 同一资产只出现一条场景引用,通常只绑定本场实际造型;只有本场正文明确发生持久外观变化时才同时绑定多个状态,并在 Action 中写清变化。V3 按其既有单状态引用结构处理。
39
- 5. **写入或标准化正文**:Agent/LLM 从零创作和续写优先输出无 ID 的可读 JSON,再执行 `compose` plan/apply;CLI 负责 ID、资产、引用、时间戳和相邻同场合并。`.scriptctl` authoring 保留给确定性程序、高级人工批量事务、旧流程兼容和迁移;已有目标的大块结构化替换仍可先 `export` 再 `write`。
40
- 6. **逐场复核**:每批正文落盘后读回 `scenes / actions`;一集完成后运行 `validate`。`validate` 通过只代表结构与引用合法,仍需完成内容标准和源素材一致性复核。
41
-
42
- ## 四条工作流
43
-
44
- 1. 素材转剧本:`ingest` → 内容复核 → `view` / `validate` → `publish`。见
45
- [references/ingest-workflow.md](references/ingest-workflow.md)。
46
- 2. 普通创作或续写:可读场景 JSON → `compose` plan → `compose --apply --plan` → 读回。模型不接触 ID、精确时间戳或 `.scriptctl`。
47
- 3. 高级完整块创作或替换:`ids` → `export` 或新写 `.scriptctl` → `write` plan →
48
- `write --apply --plan <digest>`。见
49
- [references/bulk-authoring.md](references/bulk-authoring.md)。
50
- 4. 少量精修:查询定位 → 单 ID 原子 verb;同构多点用 selector;异构多点用
51
- `do`。见 [references/atomic-edit-workflow.md](references/atomic-edit-workflow.md)。
52
-
53
- ## 无 ID 可读创作稿
54
-
55
- 模型只写一场的可读内容,本地 CLI 将它编译进明确的 Script v4:
32
+ ## 读
56
33
 
57
34
  ```bash
58
- scriptctl compose /tmp/scene-draft.json -p "$SCRIPT" -j
59
- scriptctl compose /tmp/scene-draft.json -p "$SCRIPT" --apply --plan '<plan_digest>' -j
60
- scriptctl actions -i '@ep:1' -p "$SCRIPT"
35
+ scriptctl scan 3 -p "$S" # 一次拿全:本集场结构 + 全部正文 + 校验问题
36
+ scriptctl read -p "$S" # 剧本卡:题材 + 全部资产 + 每集一行
37
+ scriptctl read 3 -p "$S" # 整集正文
38
+ scriptctl read 3 --outline -p "$S" # 只要场头
39
+ scriptctl read 3-1 -p "$S" # 单场正文
40
+ scriptctl read acCNFfN1 --context 3 -p "$S" # 单条 + 上下文
41
+ scriptctl read 向北 -p "$S" # 人物卡:描述 + 全部状态 + 出场统计 + 未使用状态
42
+ scriptctl read 向北/default -p "$S" # 状态卡:绑在哪些场、被多少 speaker 引用
61
43
  ```
62
44
 
63
- 草稿顶层为 `version: 1`,并含 `episode`、`scene` 与可选 `assets`。`scene` 使用可读地点、人物、道具和造型名;Action 只写 `type`、`content`、可选 `speaker` / `speakerVariant` / `parenthetical`,以及 `durationMs` 或 1–5 的 `weight`。人物对白未写 `speakerVariant` 时沿用该人物的本场造型;只有对白发生在本场另一项已声明造型时才写 `speakerVariant`。`assets` 既可登记新资产,也可为已有资产声明本场首次使用的新 variant。相邻地点、内外景和日夜相同时默认并入上一场;地点 state 变化不单独切场。只有确需新场时设置 `scene.boundary: "new"`。
64
-
65
- 人物声音归属于人物:角色自述或画外叙述写人物名为 `speaker`,在 `parenthetical` 写 `V.O.`、声音状态或来源;角色内心语言用 `inner_thought` 并写人物名。`speaker: "旁白"` 只表示没有角色身份的客观叙述者;已知人物在电话、门外、回忆或画外说话仍使用该人物名。
66
-
67
- `compose` 只支持 Script v4,使用确定性 ID 和 plan digest,正式写入前必须审核当前计划。模型不得把 `compose` 的内部输出字段抄回创作稿。
68
-
69
- ## 本地文件边界
45
+ **一个 `read` 覆盖全部阅读,粒度由地址决定。** 开始审一集时先 `scan`,它把上下文
46
+ 建立从多次调用压成一次。
70
47
 
71
- - 普通命令默认读取 `<cwd>/workspace/script.json`;操作其他文件时始终显式传
72
- `-p <file>`。
73
- - `-w` 只属于 `ingest` 命令族和 `view`。
74
- - 视频 ingest 还会在 workspace 的 `evidence/` 下写原片证据 sidecar 与抽帧;这些是
75
- 可重建的来源证据,不属于 `script.json`,不要作为剧本语义字段写回。
76
- - 已有带时间戳的 Script v4 也可在关联原视频后运行
77
- `scriptctl evidence -p <script.json> -s <视频目录> -w <workspace>`。它只根据最终
78
- Action 时间戳和人物/状态引用选择锚点并用本地 ffmpeg 抽帧,不调用模型、不重跑 ingest;
79
- `--force` 会重抽已有的确定性图片路径。
80
- - 同时处理原剧与目标剧时,每条命令都显式带对应 `-p`,只从原剧读,
81
- 只向目标剧写。
82
- - `checkout` 不覆盖未管理文件或本地修改;`publish` 按工作副本 revision 严格写入。
48
+ 正文格式(`read` 输出、`write` 接受的**同一种**):
83
49
 
84
- ## 查询与定位
85
-
86
- 默认文本查询输出 TSV。脚本消费查询结果时使用 `-j`:顶层固定包含
87
- `ok`、`exit_code`,表格数据位于 `rows`,列顺序位于 `row_columns`。地址流使用
88
- `--format addr`。写命令的 JSON 使用 `op`、`changed`、`plan_digest`、
89
- `validation`、`script_path` 等命令自身字段,不包含展示用的标题或结果区块。
90
- JSON 错误包含 `error_code`、`message` 和可选 `hint`。
50
+ ```text
51
+ ## 3-1 scnMMEb8A EXTERIOR/DAY 学校球场 34 actions
52
+ # cast: 李壮, 王志, 向北 props: 篮球
53
+ acMjTL1a 00:00 中景,仰拍。李壮满脸不可置信地张大嘴巴。
54
+ acKoaixN 00:00 李壮(目瞪口呆地惊呼):我去!
55
+ acR8cV4n → 三天后。
56
+ ```
91
57
 
92
- 查询用于定位和读回,不以整份文档的语义校验结果作为前置条件。文档存在引用、
93
- 状态或身份校验问题时,继续查询仍可寻址的数据;用 `issues` / `validate` 单独查看
94
- 全局校验结果。
58
+ - 左槽是锚点(v4 是稳定 `action_id`,v3 是序号)。
59
+ - `名字(提示):` 是对白;提示首段为 `心声` 表示 inner_thought;`→` 开头是转场。
60
+ - **存在的字段一定显示**:speaker 状态写成 `名字·状态`,时间戳紧跟锚点。
61
+ - 人物显示名取全局唯一的最短别名(`雷文娜指挥官` → `雷文娜`),别名回写时可解析。
62
+ - `--plain` 去掉锚点与时间戳,**只读**:它的输出回写会被拒绝。
95
63
 
96
- 常用查询:
64
+ ## 定位
97
65
 
98
66
  ```bash
99
- scriptctl summary -p "$SCRIPT"
100
- scriptctl episodes -p "$SCRIPT"
101
- scriptctl scenes -i '@ep:3' -p "$SCRIPT"
102
- scriptctl actions -g "台下掌声" -p "$SCRIPT"
103
- scriptctl actions -i '@ep:1' --time '00:30..00:45' -p "$SCRIPT"
104
- scriptctl actions -i 'acR8cV4n..acT2fG6z' --span -p "$SCRIPT"
105
- scriptctl actors --counts -p "$SCRIPT"
106
- scriptctl states actA3kP9x -p "$SCRIPT"
107
- scriptctl refs actA3kP9x/stB4xR8p -p "$SCRIPT"
108
- scriptctl validate -p "$SCRIPT"
67
+ scriptctl find '真能蒙' -p "$S" # 按正文正则
68
+ scriptctl find '' -a 向北 -t inner_thought -p "$S" # 按说话人 + 类型
69
+ scriptctl find '球' -i 3 -t dialogue -p "$S" # 限定范围
70
+ scriptctl span 3-1 -p "$S" # 换算成集内视频时间窗口
71
+ scriptctl issues --severity error -p "$S"
72
+ scriptctl validate -p "$S"
109
73
  ```
110
74
 
111
- 序号锚点是 1-based 查询语法:
112
-
113
- - `@ep:3`
114
- - `@ep:3/scn:2`
115
- - `@ep:3/scn:2/ac:5`
116
- - `@scn:12`
117
- - `@ac:48`
75
+ `find` 返回锚点 + 位置 + 命中窗口而不是整条,命中多时不炸上下文。
76
+ `span` 给出半开区间(`start_timestamp` / `end_timestamp` / `end_open`)供视频核对使用。
118
77
 
119
- 区间包含两端,端点正反等价,按当前文档顺序解释。V4 查询返回正式 ID;V3
120
- 查询返回可写的 v3 地址。先按序号或正文查询,再把结果中的正式地址用于修改。
78
+ ## 改
121
79
 
122
- | 想做什么 | 命令 |
123
- |---|---|
124
- | **了解剧情 / 全貌**:synopsis/worldview/style/logline/theme/main_characters + 标题/集数/场数/资产数("这剧本是关于什么"先跑这个) | `scriptctl summary` |
125
- | 每集字数 / 场数 / action 数 **+ 每集剧情梗概** | `scriptctl episodes`(`--min-chars 1000` 找长集) |
126
- | 看某集的所有场(含 `t=t_start..t_end` 时段) | `scriptctl scenes -i '@ep:7'` |
127
- | 看某场的资产 + action 数 | `scriptctl scenes -i '@ep:7/scn:5'` |
128
- | **按正文搜某句话定位 action**(最常用) | `scriptctl actions -g "<片段>"` |
129
- | 列某集所有 action(含 timestamp / speaker / 正文 /表演提示) | `scriptctl actions -i '@ep:1'` |
130
- | 看单条 action 正文 | `scriptctl actions -i '@ep:1/scn:1/ac:3'` |
131
- | 按集内时间点或闭区间看正文 | `scriptctl actions -i '@ep:1' --time '00:30..00:45'` |
132
- | 把 Action / scene 范围换成可供视频处理的时间戳包络 | `scriptctl actions -i '<action-or-scene-range>' --span` |
133
- | action 多维过滤 | `scriptctl actions -i '@ep:1' -t dialogue -a <actor-id> --has speaker` |
134
- | 某角色出现的所有场 | `scriptctl scenes --has-actor <actor-id>`(另有 `--has-location`/`--has-prop`) |
135
- | **列某资产的所有 state + 状态弧线**(改造型前必查) | `scriptctl states <asset-id>` |
136
- | 资产**出场统计**(几场/几集,压成集区间) | `scriptctl actors --counts` / `locations --counts` / `props --counts` |
137
- | 某资产 / 状态反查 | `scriptctl refs <asset-id>` / `scriptctl refs <asset-id>/<state-id>` |
138
- | 当前校验问题 / 跑校验 | `scriptctl issues --severity error` / `scriptctl validate` |
139
-
140
- ### Action 范围的时间戳包络
141
-
142
- 需要按 Action、scene 或其他 action selector 获取对应视频时段时,使用 `actions --span`:
80
+ 单条命令直接生效。**没有 plan、没有确认码、没有两阶段提交**。
143
81
 
144
82
  ```bash
145
- scriptctl actions -i 'acR8cV4n..acT2fG6z' --span -p "$SCRIPT"
146
- scriptctl actions -i '@ep:3/scn:2' --span -p "$SCRIPT"
83
+ scriptctl edit acCNFfN1 --content "新台词" --paren "低声" -p "$S"
84
+ scriptctl edit acCNFfN1 --speaker 李壮 -p "$S" # 按人物名,不用先查 ID
85
+ scriptctl edit acCNFfN1 --no-paren -p "$S" # 删字段(--paren "" 是设空串)
86
+ scriptctl edit acCNFfN1 --ts 00:41 -p "$S"
87
+ scriptctl edit 3-1 --space interior --time night -p "$S" # 场的内外景 / 日夜
88
+ scriptctl edit 3 --title "第三集" --synopsis "…" -p "$S" # 集元数据
89
+ scriptctl edit "" --logline "…" --theme "…" -p "$S" # 剧本元数据(地址留空)
90
+ scriptctl edit 向北 --role 主角 --alias 小北,7号 -p "$S" # 资产
91
+ scriptctl edit 向北/default --name 主场球衣 -p "$S" # 状态
147
92
  ```
148
93
 
149
- 结果只含一行,并给出 `episode_id`、`ep_no`、`start_timestamp`、
150
- `last_selected_timestamp`、`end_timestamp`、`end_open`、起止 Action 地址和
151
- `end_boundary_action`。区间按文档顺序解释:
152
-
153
- - `start_timestamp` 是第一个命中 Action 的时间戳。
154
- - `last_selected_timestamp` 是最后一个命中 Action 自身的时间戳;该 Action
155
- 没有时间戳时为空。
156
- - `end_timestamp` 是最后一个命中 Action 之后第一个更晚的时间戳,作为半开区间
157
- 的排他终点;`end_exclusive` 固定为 `true`。
158
- - 选区到达本集末尾且没有后续时间锚点时,`end_timestamp` 为空且
159
- `end_open=true`,由消费方使用源视频总时长收口。
160
-
161
- 一个 span 必须位于同一集,且第一个命中 Action 必须有合法时间戳。跨集、无命中、
162
- 起点时间戳缺失或时间戳倒退会返回明确错误;按集拆分或修正时间戳后重试。
94
+ `edit` 按地址分派,**地址决定哪些字段合法**:
163
95
 
164
- ## Script v4 写入(v3 同样使用写后校验)
96
+ | 地址 | 可改字段 |
97
+ |---|---|
98
+ | action | `--content` `--paren` `--speaker` `--ts` `--type` `--transition` |
99
+ | 场 | `--space` `--time` |
100
+ | 集 | `--title` `--synopsis` |
101
+ | 剧本(空地址) | `--title` `--worldview` `--style` `--synopsis` `--logline` `--theme` `--main` |
102
+ | 资产 | `--name` `--desc` `--importance` `--alias` `--role` |
103
+ | 状态 | `--name` `--desc` |
165
104
 
166
- V4 新 ID 是类型前缀加 6 位 Bitcoin Base58:
105
+ 字段用错会报清这类节点收哪些字段。闭集值(`type` / `importance` / `role` /
106
+ `space` / `time`)在写入前就校验,不等 `validate`。
167
107
 
168
- ```text
169
- ep…… scn…… ac…… act…… loc…… prp…… st……
170
- ```
171
-
172
- `ids` 只生成候选,不预留:
108
+ **⚠️ `--content` 是整条覆写**:传入的字符串成为这条 action 的全部内容,原文丢弃。
109
+ 只改其中一个词或一段,用 `replace`。
173
110
 
174
111
  ```bash
175
- scriptctl ids -k action --count 4
176
- scriptctl ids -k scene --count 2 -p "$SCRIPT"
112
+ scriptctl replace '林京南队教练' '林教练' -i 5 -p "$S" # 默认只预览逐行 diff
113
+ scriptctl replace '林京南队教练' '林教练' --apply -p "$S" # 才真的写
114
+ scriptctl replace '真能蒙' '真敢投' -a 王志 -t dialogue --apply -p "$S"
177
115
  ```
178
116
 
179
- 单点修改使用正式 ID:
117
+ 过滤参数与 `find` 相同(`-i` / `-a` / `-t`),不用学第二套 selector。
118
+
119
+ 结构与资产:
180
120
 
181
121
  ```bash
182
- scriptctl replace acR8cV4n --from "旧句" --to "新句" -p "$SCRIPT"
183
- scriptctl parenthetical acT2fG6z --set "低声" -p "$SCRIPT"
184
- scriptctl parenthetical acT2fG6z --set "" -p "$SCRIPT"
185
- scriptctl parenthetical acT2fG6z --remove -p "$SCRIPT"
186
- scriptctl timestamp acT2fG6z --set 00:42.533 -p "$SCRIPT"
187
- scriptctl timestamp acT2fG6z --remove -p "$SCRIPT"
188
- scriptctl dialogue acT2fG6z -a actA3kP9x --state stB4xR8p -p "$SCRIPT"
189
- ```
122
+ scriptctl insert acCNFfN1 "他关上门。" -t action -p "$S"
123
+ scriptctl insert acCNFfN1 "都回位置!" -t dialogue -a 白教练 --paren 皱眉 --before -p "$S"
124
+ scriptctl move acD4eF6g acR8cV4n --before -p "$S" # 跨场也保持 action_id
190
125
 
191
- 原子 verb 只在目标、参数或操作本身无法安全执行时失败。操作成功写入后退出 `0`;
192
- `validation.passed=false` 表示文档仍需收口,不表示本次写入失败。`warnings` 只列本次
193
- 新引入的校验问题;存在 `repair_hint` 时直接执行其中的修复命令,再读回目标。
126
+ scriptctl ref 3-1 向北 --state 23号球衣 -p "$S" # 完整状态集合,不是追加
127
+ scriptctl ref 3-1 毛巾 --remove -p "$S"
194
128
 
195
- `parenthetical` 只属于 dialogue / inner_thought。字段省略表示没有表演提示;显式
196
- 空字符串与省略不同。影响走位、道具或连续性的动作写成独立 Action。
129
+ scriptctl asset actor 苏晓 --desc "…" --alias 晓姐,经理 -p "$S"
130
+ scriptctl state 向北 受伤 --desc "…" -p "$S"
197
131
 
198
- V4 placement 使用父节点与相邻节点 ID:
132
+ scriptctl del acCNFfN1 -p "$S"
133
+ scriptctl del 向北/旧造型 --replacement 23号球衣 -p "$S" # 删状态并改写引用
134
+ scriptctl del 3-1 --force -p "$S" # 有内容的容器要 --force
135
+ scriptctl merge 李壮 王志 -p "$S" # 合并重复资产
199
136
 
200
- ```bash
201
- scriptctl insert scnK6wT3c --action-id acD4eF6g \
202
- -t action --content "陈默关上门。" --before acT2fG6z
203
- scriptctl move acD4eF6g scnH7jK9m --after acR8cV4n
204
- scriptctl split scnK6wT3c --at acT2fG6z --new-scene-id scnD4eF6g
137
+ scriptctl ext acCNFfN1 note "分镜待定" -p "$S" # 任意节点的 extend
205
138
  ```
206
139
 
207
- ## 场景资产与状态
140
+ **每次修改都会报出它新引入的校验问题**(文档本来就有的不重复刷)。看到
141
+ `introduced N issue(s)` 就按提示收口;带 `fix:` 的直接照做。
208
142
 
209
- V4 一个场景内同一资产只引用一次;引用携带完整、非空的 `state_ids` 集合。重复
210
- `--state` 传入整个集合,写入时按 state ID 排序:
143
+ 引用相关的两条硬规则:
211
144
 
212
- ```bash
213
- scriptctl scene-ref scnK6wT3c actA3kP9x \
214
- --state default --state stB4xR8p -p "$SCRIPT"
215
- scriptctl scene-ref scnK6wT3c actA3kP9x --remove -p "$SCRIPT"
216
- ```
145
+ - `ref --state` 是**完整集合**而非追加,`default` 也要显式写。
146
+ - 删不存在的引用、删地点时 ID 对不上、空状态集合都报错,不当幂等成功。
217
147
 
218
- 通过最终校验时,actor speaker 必须被当前 scene 引用;可选的 speaker state 必须属于
219
- 该 actor 在当前 scene 的 `state_ids`。可以先修改 speaker,再根据写入结果中的
220
- `repair_hint` 补齐 scene 引用。状态集合不表示对白级落点,也没有先后顺序。
148
+ ## 整场 / 整集回写
221
149
 
222
- state 修改前后都反查并校验:
150
+ `read` 的输出就是 `write` 的输入:
223
151
 
224
152
  ```bash
225
- scriptctl refs actA3kP9x/stB4xR8p -p "$SCRIPT"
226
- scriptctl state-delete actA3kP9x/stB4xR8p \
227
- --strategy replace --replacement default -p "$SCRIPT"
228
- scriptctl validate -p "$SCRIPT"
153
+ scriptctl read 3 -p "$S" > /tmp/ep3.txt # 改这个文件
154
+ scriptctl write 3 -f /tmp/ep3.txt -p "$S"
155
+ scriptctl write + -f /tmp/ep51.txt -p "$S" # `+` 追加新集
229
156
  ```
230
157
 
231
- 详见 [references/state-reference-repair.md](references/state-reference-repair.md)。
232
-
233
- ## V3 项目
158
+ **按锚点做差**:带锚点的行保留身份并编辑,无锚点的行新建,**文本里消失的锚点 = 删除**。
159
+ 这是唯一一条看输出看不出来、猜错了会误删的规则。
234
160
 
235
- V3 继续使用现有复合地址,例如:
161
+ - 整集回写时 `##` 场头带 scene id 表示保留该场,不带表示新建整场。
162
+ - action 可以在本集内跨场移动——这就是拆场与并场,不需要额外动词。
163
+ - 删整场、删光一场的 action、或整集少写几行,都需要 `--allow-delete`。
164
+ - 场头本身就是完整的场声明(环境 / 地点 / cast / 道具及其状态),所以整集回写不
165
+ 需要第二种语法。
236
166
 
237
- ```bash
238
- scriptctl replace ep_001/scn_003#5 --from "旧句" --to "新句"
239
- scriptctl emotion ep_001/scn_003#5 "低声"
240
- scriptctl timestamp ep_001/scn_003#5 --set 00:42
241
- scriptctl scene-ref ep_001/scn_003 actor:act_001 --state st_002
242
- ```
243
-
244
- 对 V3 文件运行 `export`、`write`、原子命令、`validate` 和 `publish` 时,CLI
245
- 会选择 V3 实现并保持原文件结构与既有 ID。
167
+ 批量改词用 `replace`,大块结构改用 `write`,**不要逐条 `edit` 硬凑**。
246
168
 
247
- ## 版本变更边界
169
+ ## 本地文件边界
248
170
 
249
- Agent 不得自行调用 `migrate` 命令,也不得执行任何 Script schema 升级或生成升级产物。
250
- 版本变更会重写全局身份与外部引用,可能影响项目上下文、视频锚点和下游工作流;只有用户
251
- 明确要求时才由应用层处理。面对 V3 文件,按其现有版本读取、查询、修改和校验。
171
+ - 普通命令默认读取 `<cwd>/workspace/script.json`;操作其他文件时始终显式传 `-p <file>`。
172
+ - `-w` 只属于 `ingest` 命令族和 `view`。
173
+ - 视频 ingest 会在 workspace 的 `evidence/` 下写原片证据 sidecar 与抽帧;这些是可
174
+ 重建的来源证据,不属于 `script.json`,不要作为剧本语义字段写回。
175
+ - 已有带时间戳的 Script v4 可在关联原视频后运行
176
+ `scriptctl evidence -p <script.json> -s <视频目录> -w <workspace>`。它只根据 Action
177
+ 时间戳和人物/状态引用选锚点并用本地 ffmpeg 抽帧,不调模型、不重跑 ingest。
178
+ - 同时处理原剧与目标剧时,每条命令都显式带对应 `-p`,只从原剧读、只向目标剧写。
179
+ - `checkout` 不覆盖未管理文件或本地修改;`publish` 按工作副本 revision 严格写入。
252
180
 
253
- ## 多点写与 plan
181
+ ## 流水线命令
254
182
 
255
- V4 单个明确 ID 的原子修改直接执行。任何单事务多点修改先生成完整计划:
183
+ 这些不是逐条修改的工具,是整段流程:
256
184
 
257
185
  ```bash
258
- scriptctl replace -i 'acR8cV4n..acT2fG6z' --from "。" --to "!"
259
- scriptctl replace -i 'acR8cV4n..acT2fG6z' --from "。" --to "!" \
260
- --apply --plan sha256:...
186
+ scriptctl ingest -s <素材> -w <workspace> # 素材转 Script v4
187
+ scriptctl synopsis generate -p "$S" --apply # LLM 补全剧与分集梗概
188
+ scriptctl audit-assets -p "$S" # LLM 全剧资产一致性审计
189
+ scriptctl review -p "$S" -s <视频目录> # 派发 agent 逐集审核并修正
190
+ scriptctl create --title "…" -p "$S" # 从零建空剧本
191
+ scriptctl view -w <workspace> # 渲染或起审阅页
192
+ scriptctl checkout / status / publish # 远端工作副本
193
+ ```
261
194
 
262
- scriptctl do edits.txt
263
- scriptctl do edits.txt --apply --plan sha256:...
195
+ `ingest` 见 [references/ingest-workflow.md](references/ingest-workflow.md)。
264
196
 
265
- scriptctl patch changes.json
266
- scriptctl patch changes.json --apply --plan sha256:...
267
- ```
197
+ `review` 一个进程审完整本剧:剧本只解析一次进内存,按集扇出,最后单线程做全剧收敛。
198
+ 给 `-s` 就按原视频拉片核对(agent 自己切片段送模型看画面和听原声),不给就纯剧本审核,
199
+ 媒体工具不注册。每集完成一行 NDJSON 到 stdout(`{"type":"episode",…}`,末行
200
+ `{"type":"done",…}`),所以调用方可以边跑边落盘,中途挂掉不丢已完成的集。
201
+ `--episodes 3,7` 续跑指定集,`--concurrency` 控同时在飞的集数,`--check` 只验模型与
202
+ agent 是否就绪。**Agent 不要自己调 `review` 去审自己正在改的剧本**——它会派发另一个
203
+ agent 并直接改文件。
268
204
 
269
- V4 `do` / `patch` 内的创建操作必须显式携带候选 ID,确保 dry-run 与 apply
270
- 审阅的是同一批新节点;先用 `ids` 生成候选。
205
+ ## 版本边界
271
206
 
272
- 计划会完整列出每步/目标、前后计数、精确目标、全量新增/删除/保留身份、未触及
273
- 身份或 sibling、声明、保留的孤立资产和 validation;确认码绑定这份完整计划及
274
- 本地基线。CLI 不保存 plan 文件。当前工作流假设 Agent 从读取到最终写入期间
275
- 没有外部修改。
207
+ 读取 `script.json.version`:`4` 是新建与 ingest 的默认方言,`3` 是线上既有项目的
208
+ 冻结方言。**不要根据字段形状猜版本**,命令按显式 `version` 自动分流:v3 写
209
+ `emotion`、v4 写 `parenthetical`,同一条 `edit --paren` 在两边都对。
210
+
211
+ **Agent 不得自行调用 `migrate`**,也不得执行任何 schema 升级。版本变更会重写全局
212
+ 身份与外部引用,只有用户明确要求时才由应用层处理。
276
213
 
277
214
  ## 完成标准
278
215
 
279
216
  每批修改后:
280
217
 
281
- 1. 用 `actions` / `scenes` / `refs` 读回目标。
282
- 2. 运行 `validate`。
283
- 3. 做内容层复核;结构校验通过不代表剧情、对白和画面已达标。
284
- 4. 远端项目最后运行 `publish`。
218
+ 1. 用 `read` 读回目标。
219
+ 2. 跑 `scriptctl validate`。
220
+ 3. 做内容层复核——结构校验通过不代表剧情、对白和画面已达标。
221
+ 4. 远端项目最后 `publish`。
222
+
223
+ **零修改是合格结果。** 没发现问题就如实报告,不要为了交差制造修改。
285
224
 
286
- 完整生产写作约束见
287
- [references/production-writing-standard.md](references/production-writing-standard.md)。
225
+ 内容标准见
226
+ [references/production-writing-standard.md](references/production-writing-standard.md);
227
+ 视频转录剧本的复核见
228
+ [references/video-transcript-repair.md](references/video-transcript-repair.md);
229
+ state 引用修复见
230
+ [references/state-reference-repair.md](references/state-reference-repair.md)。
@@ -134,7 +134,7 @@ scriptctl ingest status # 人读:kind / state / 各 pass 进度(tra
134
134
  scriptctl ingest status -j # 机器输出含 failure_summary / errors[];视频另含 completed / parsed / skipped / skipped_episodes / complete / next_episode
135
135
  scriptctl view # 生成 workspace/review.html(视频版可点击定位到画面)
136
136
  scriptctl view --watch [--port N]# 实时监听面板:分阶段进度条 + 逐集 context/决策 + 产物树,自动刷新(跑中也能开)。🔴 仅本地用,**沙箱内不要用**(起阻塞服务+开浏览器,会挂住;沙箱看进度用 `ingest status`)
137
- scriptctl summary -p workspace/script.json # 抽完当普通剧本读
137
+ scriptctl read -p workspace/script.json # 抽完当普通剧本读
138
138
  ```
139
139
 
140
140
  `state`:`empty`(没开始)/ `incomplete`(在跑、中断或只完成连续前缀)/ `failed`(有失败单元或校验没过)/ `ready`(全部 source units 完成,且 `script.json` 的 v4 结构校验通过)。文本与视频 ingest 的 `validation.json` 包含结构校验和 production warning。进度从工作区真实文件推导;它报的是管线事实,资产合并结论和源素材一致性仍由复核完成门确认。
@@ -1,38 +1,42 @@
1
1
  # State 引用修复
2
2
 
3
- 先反查旧 state:
3
+ 删一个仍被引用的 state,必须先决定那些引用去哪里。
4
+
5
+ ## 先看它被谁引用
4
6
 
5
7
  ```bash
6
- scriptctl refs actA3kP9x/stB4xR8p -p "$SCRIPT"
8
+ scriptctl read 向北/23号球衣 -p "$S"
7
9
  ```
8
10
 
9
- ## Script v4
11
+ 状态卡直接给出:绑在哪些场、被多少 speaker 引用。资产卡(`read 向北`)还会列出
12
+ **从没用过的 state**——那些可以直接删。
10
13
 
11
- 场景引用保存完整、非空的 `state_ids` 集合。替换 state 会在场景集合与 actor
12
- speaker 上同步替换:
14
+ ## 删并改写
13
15
 
14
16
  ```bash
15
- scriptctl state-delete actA3kP9x/stB4xR8p \
16
- --strategy replace --replacement default -p "$SCRIPT"
17
+ scriptctl del 向北/旧造型 --replacement 23号球衣 -p "$S"
17
18
  ```
18
19
 
19
- `--strategy remove` 会从每个集合移除该 state;若任何集合将变为空,命令拒绝,
20
- 应先为该场写入另一个完整状态集合。speaker 上的可选 state 被移除后可省略,由
21
- 下游依据场景集合判断具体对白落点。
20
+ 场景集合与 actor speaker 上的引用会同步改写到 `--replacement`。不给
21
+ `--replacement` 时,命令会拒绝并告诉你有多少处引用;要强行剥掉引用才用 `--force`。
22
22
 
23
- ## Script v3
23
+ `default` 是资产的基础状态键,不允许单独删除——要删整个资产用 `del 向北`(同样
24
+ 需要 `--replacement` 或 `--force`)。
24
25
 
25
- 使用 V3 state 地址和既有单值引用语义:
26
+ ## v4 与 v3 的差别
26
27
 
27
- ```bash
28
- scriptctl state-delete actor:act_001/st_002 \
29
- --strategy replace --replacement st_001 -p "$SCRIPT"
30
- ```
28
+ v4 的场景引用是**完整非空的 `state_ids` 集合**:改写后集合仍需非空,所以
29
+ `--replacement` 指向的 state 必须存在。v3 是单值 `state_id`,改写即替换。
30
+
31
+ 同一条命令在两个方言上都对——`del` 按 `script.json.version` 自动分流,不要为 v3
32
+ 另写地址形式。
31
33
 
32
34
  ## 核验
33
35
 
34
36
  ```bash
35
- scriptctl refs <旧-state-address> -p "$SCRIPT"
36
- scriptctl refs <新-state-address> -p "$SCRIPT"
37
- scriptctl validate -p "$SCRIPT"
37
+ scriptctl read 向北 -p "$S" # 状态列表与使用分布
38
+ scriptctl read 3-1 -p "$S" # 场头里的 cast 与状态
39
+ scriptctl validate -p "$S"
38
40
  ```
41
+
42
+ `del` 本身会报出它新引入的校验问题;`introduced 0 issue(s)`(无此行)才算收口。
@@ -11,14 +11,14 @@
11
11
  scriptctl validate -p "$V3"
12
12
  ```
13
13
 
14
- V3 保持其现有地址与字段;V4 使用其正式 ID 与计划写入语义。Agent 只在用户指定的
15
- 现有版本内进行复核和精修,不改变 Script schema。任一版本有多个 blocking issue 时,
16
- 把完整修复组织成一个 `do` 或 `patch` 事务;计划的最终状态通过校验后再 apply。
14
+ V3 保持其现有地址与字段;V4 使用其正式 ID。Agent 只在用户指定的现有版本内进行复核和
15
+ 精修,不改变 Script schema。每条修改命令都会报出它新引入的校验问题,看到
16
+ `introduced N issue(s)` 就当场收口,不要攒到最后。
17
17
 
18
18
  人物重名按剧情身份判断:
19
19
 
20
20
  - 同一人物被重复建档:先核对 `refs`、states、aliases、importance 和实际对白,再把信息
21
- 补到保留人物,最后 `merge <source> --into <survivor>`。
21
+ 补到保留人物,最后 `merge <被并> <保留>`。
22
22
  - 不同人物共用外观标签:把各自 `actor_name` 改为真实稳定身份,外观或称呼放 aliases。
23
23
  - 人物名改成已有 alias 后,同步移除与正式名相同的 alias。
24
24
 
@@ -32,38 +32,37 @@ V3 保持其现有地址与字段;V4 使用其正式 ID 与计划写入语义
32
32
  同一场中多个同时发生的 Action 可以使用相同时间戳;后面的 Action 不能早于前一个有时间戳的 Action。
33
33
 
34
34
  ```bash
35
- scriptctl actions -i '@ep:4' -p "$SCRIPT"
36
- scriptctl actions -g "台词片段" -p "$SCRIPT"
37
- scriptctl timestamp <action-id> --set 00:42.533 -p "$SCRIPT"
35
+ scriptctl read 4 -p "$SCRIPT" # 整集正文,时间戳就在锚点后面
36
+ scriptctl find '台词片段' -p "$SCRIPT" # 按正文定位到锚点
37
+ scriptctl edit <action> --ts 00:42.533 -p "$SCRIPT"
38
+ scriptctl span 4-1 -p "$SCRIPT" # 该场对应的视频时间窗口
38
39
  ```
39
40
 
40
41
  校时使用视频中该动作或对白真正开始的画面。保留亚秒级精度。没有视频证据时保留待复核,
41
- 不根据相邻行平均分配。
42
+ 不根据相邻行平均分配。改完时间戳若造成倒序,`edit` 会当场报出
43
+ `timestamp_out_of_order`,不用等 `validate`。
42
44
 
43
45
  ## 3. 补漏 Action 或对白
44
46
 
45
- 先取得相邻 Action、场景和说话人的正式 ID,再生成一个 Action ID:
47
+ `insert` 一步完成,Action ID 由 CLI 生成,不需要先取候选 ID:
46
48
 
47
49
  ```bash
48
- scriptctl ids -k action --count 1 -p "$SCRIPT"
50
+ scriptctl insert <相邻action> "她推门进屋。" -t action -p "$SCRIPT"
51
+ scriptctl insert <相邻action> "我回来了。" -t dialogue -a 向北 -p "$SCRIPT"
49
52
  ```
50
53
 
51
- 把插入和时间戳写在同一个 `do` 事务中。动作示例:
54
+ 默认插在目标之后,`--before` 插在之前;说话人用**人物名**即可,不必查 actor ID,
55
+ 需要指定造型时写 `名字·状态`。补完时间戳:
52
56
 
53
- ```text
54
- insert <scene-id> --action-id <new-action-id> -t action --content "她推门进屋。" --after <previous-action-id>
55
- timestamp <new-action-id> --set 00:42.533
57
+ ```bash
58
+ scriptctl edit <新action> --ts 00:42.533 -p "$SCRIPT"
56
59
  ```
57
60
 
58
- 对白示例:
59
-
60
- ```text
61
- insert <scene-id> --action-id <new-action-id> -t dialogue --content "我回来了。" -a <actor-id> --after <previous-action-id>
62
- timestamp <new-action-id> --set 00:42.533
63
- ```
61
+ 人物必须已被本场引用;若尚未引用,`insert` 会报出
62
+ `actor_not_in_scene` 并给出修复命令,照做即可(`scriptctl ref <场> <人物> --state …`)。
64
63
 
65
- 人物必须已经出现在本场 scene ref 中;需要指定造型时同时传 `--speaker-state <state-id>`。
66
- 先运行 `scriptctl do edits.txt -p "$SCRIPT"` 查看计划,再用返回的 digest 精确 apply。
64
+ 要一次补多条、或顺带调整顺序时,改用整场回写:`read 4-1 > f.txt`,在文件里增删行,
65
+ 再 `write 4-1 -f f.txt`。**无锚点的行会被新建,消失的锚点会被删除。**
67
66
 
68
67
  ## 4. 合并被误拆的连续对白
69
68
 
@@ -76,15 +75,15 @@ timestamp <new-action-id> --set 00:42.533
76
75
  5. 视频确认它们属于同一次连续表达。
77
76
 
78
77
  保留第一条 Action ID,正文按原视频顺序拼接,时间戳取第一句真正开始的时间,删除后续
79
- Action。使用一个 `do` 事务:
78
+ Action:
80
79
 
81
- ```text
82
- replace <first-action-id> --from "第一段" --to "第一段第二段"
83
- timestamp <first-action-id> --set 00:42.533
84
- delete <second-action-id>
80
+ ```bash
81
+ scriptctl edit <first> --content "第一段第二段" --ts 00:42.533 -p "$SCRIPT"
82
+ scriptctl del <second> -p "$SCRIPT"
85
83
  ```
86
84
 
87
- 多个连续碎片依次并入第一条。不同人物重复表达同一态度仍是多条对白;剧情功能相同不代表
85
+ 碎片多、或顺带要调顺序时改用整场回写(`read 4-1` → 改文件 → `write 4-1`):把几行
86
+ 并成一行、只保留第一条的锚点,消失的锚点即删除,一次落盘。不同人物重复表达同一态度仍是多条对白;剧情功能相同不代表
88
87
  物理 Action 可以合并。
89
88
 
90
89
  ## 5. 人与 Agent 的分工
@@ -101,7 +100,6 @@ Agent 执行:
101
100
 
102
101
  - 查询 Action、资产、refs 和缺失时间戳;
103
102
  - 生成 V4 ID;
104
- - 组织 `do` 计划;
105
103
  - 应用经确认的插入、校时、合并和人物修复;
106
104
  - 读回目标并运行 `validate`;
107
105
  - 输出仍需人工复核的清单。