@lingjingai/scriptctl 0.33.0 → 0.35.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 (41) hide show
  1. package/README.md +9 -0
  2. package/changes/0.35.0.md +22 -0
  3. package/dist/bin.js +0 -0
  4. package/dist/cli.js +4 -0
  5. package/dist/cli.js.map +1 -1
  6. package/dist/common.js +29 -6
  7. package/dist/common.js.map +1 -1
  8. package/dist/domain/direct-core.d.ts +4 -1
  9. package/dist/domain/direct-core.js +718 -177
  10. package/dist/domain/direct-core.js.map +1 -1
  11. package/dist/domain/script/validate.js +11 -0
  12. package/dist/domain/script/validate.js.map +1 -1
  13. package/dist/help-text.js +31 -7
  14. package/dist/help-text.js.map +1 -1
  15. package/dist/infra/providers.js +76 -24
  16. package/dist/infra/providers.js.map +1 -1
  17. package/dist/usecases/direct.js +25 -9
  18. package/dist/usecases/direct.js.map +1 -1
  19. package/dist/usecases/script/actions.js +1 -1
  20. package/dist/usecases/script/actions.js.map +1 -1
  21. package/dist/usecases/script/actors.js +1 -0
  22. package/dist/usecases/script/actors.js.map +1 -1
  23. package/dist/usecases/script/assets.js +2 -1
  24. package/dist/usecases/script/assets.js.map +1 -1
  25. package/dist/usecases/script/lib.d.ts +11 -0
  26. package/dist/usecases/script/lib.js +93 -3
  27. package/dist/usecases/script/lib.js.map +1 -1
  28. package/dist/usecases/script/locations.js +1 -0
  29. package/dist/usecases/script/locations.js.map +1 -1
  30. package/dist/usecases/script/props.js +1 -0
  31. package/dist/usecases/script/props.js.map +1 -1
  32. package/dist/usecases/script/states.js +58 -13
  33. package/dist/usecases/script/states.js.map +1 -1
  34. package/dist/usecases/script/summary.js +8 -0
  35. package/dist/usecases/script/summary.js.map +1 -1
  36. package/package.json +17 -14
  37. package/scripts/install-skill.mjs +120 -0
  38. package/skills/scriptctl/SKILL.md +273 -0
  39. package/skills/scriptctl/references/atomic-write-workflow.md +114 -0
  40. package/skills/scriptctl/references/direct-workflow.md +72 -0
  41. package/skills/scriptctl/references/state-reference-repair.md +72 -0
@@ -1 +1 @@
1
- {"version":3,"file":"states.js","sourceRoot":"","sources":["../../../src/usecases/script/states.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"states.js","sourceRoot":"","sources":["../../../src/usecases/script/states.ts"],"names":[],"mappings":"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"}
@@ -22,6 +22,14 @@ export async function commandSummary(opts) {
22
22
  `props: ${asList(script["props"]).length}`,
23
23
  `speakers: ${asList(script["speakers"]).length}`,
24
24
  ];
25
+ const worldview = strOf(script["worldview"]).trim();
26
+ if (worldview) {
27
+ const worldviewRaw = strOf(script["worldview_raw"]).trim();
28
+ lines.push(worldviewRaw && worldviewRaw !== worldview ? `worldview: ${worldview} (${worldviewRaw})` : `worldview: ${worldview}`);
29
+ }
30
+ const style = strOf(script["style"]).trim();
31
+ if (style)
32
+ lines.push(`style: ${style}`);
25
33
  const logline = strOf(script["logline"]).trim();
26
34
  if (logline)
27
35
  lines.push(`logline: ${logline}`);
@@ -1 +1 @@
1
- {"version":3,"file":"summary.js","sourceRoot":"","sources":["../../../src/usecases/script/summary.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"summary.js","sourceRoot":"","sources":["../../../src/usecases/script/summary.ts"],"names":[],"mappings":"AAKA,OAAO,EAIL,OAAO,GAWR,MAAM,iBAAiB,CAAC;AAkCzB,OAAO,EACL,MAAM,EAIN,KAAK,GACN,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAEL,iBAAiB,GAElB,MAAM,cAAc,CAAC;AACtB,OAAO,EACwS,WAAW,EAAE,eAAe,GAC1U,MAAM,UAAU,CAAC;AAElB,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAU;IAC7C,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAC9B,MAAM,QAAQ,GAAG,MAAM,CAAO,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;IAClD,MAAM,MAAM,GAAW,EAAE,CAAC;IAC1B,KAAK,MAAM,EAAE,IAAI,QAAQ;QAAE,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAO,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IACtE,MAAM,OAAO,GAAW,EAAE,CAAC;IAC3B,KAAK,MAAM,KAAK,IAAI,MAAM;QAAE,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,CAAO,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAC5E,MAAM,KAAK,GAAG;QACZ,UAAU,MAAM,CAAC,OAAO,CAAC,IAAI,GAAG,EAAE;QAClC,aAAa,QAAQ,CAAC,MAAM,EAAE;QAC9B,WAAW,MAAM,CAAC,MAAM,EAAE;QAC1B,YAAY,OAAO,CAAC,MAAM,EAAE;QAC5B,WAAW,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE;QAC5C,cAAc,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,EAAE;QAClD,UAAU,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE;QAC1C,aAAa,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,EAAE;KACjD,CAAC;IACF,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACpD,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC3D,KAAK,CAAC,IAAI,CAAC,YAAY,IAAI,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,cAAc,SAAS,KAAK,YAAY,GAAG,CAAC,CAAC,CAAC,cAAc,SAAS,EAAE,CAAC,CAAC;IACnI,CAAC;IACD,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5C,IAAI,KAAK;QAAE,KAAK,CAAC,IAAI,CAAC,UAAU,KAAK,EAAE,CAAC,CAAC;IACzC,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAChD,IAAI,OAAO;QAAE,KAAK,CAAC,IAAI,CAAC,YAAY,OAAO,EAAE,CAAC,CAAC;IAC/C,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5C,IAAI,KAAK;QAAE,KAAK,CAAC,IAAI,CAAC,UAAU,KAAK,EAAE,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAClD,IAAI,QAAQ;QAAE,KAAK,CAAC,IAAI,CAAC,aAAa,eAAe,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IACxE,MAAM,cAAc,GAAG,MAAM,CAAO,MAAM,CAAC,iBAAiB,CAAC,CAAC;SAC3D,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACnC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IACpB,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,oBAAoB,cAAc,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACvG,OAAO,CAAC,WAAW,CAAC,eAAe,EAAE,gBAAgB,EAAE,KAAK,EAAE,OAAO,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC,CAAC;AACjG,CAAC;AAED,+EAA+E;AAE/E,2EAA2E;AAC3E,8EAA8E;AAC9E,8EAA8E"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lingjingai/scriptctl",
3
- "version": "0.33.0",
3
+ "version": "0.35.0",
4
4
  "description": "剧本阶段统一 CLI:直转外部素材到 script.json,以及当前最终剧本的读取、校验、原子编辑与批量 patch 精修。",
5
5
  "type": "module",
6
6
  "bin": {
@@ -11,23 +11,13 @@
11
11
  "files": [
12
12
  "dist",
13
13
  "changes",
14
+ "skills",
15
+ "scripts/install-skill.mjs",
14
16
  "README.md"
15
17
  ],
16
18
  "engines": {
17
19
  "node": ">=20"
18
20
  },
19
- "scripts": {
20
- "build": "tsc",
21
- "clean": "rm -rf dist",
22
- "prepublishOnly": "pnpm run clean && pnpm run build",
23
- "pretest": "pnpm run build",
24
- "test": "vitest run",
25
- "pretest:coverage": "pnpm run build",
26
- "test:coverage": "c8 --reporter=text --reporter=html --reporter=lcov --report-dir=coverage vitest run",
27
- "test:watch": "vitest",
28
- "typecheck": "tsc --noEmit",
29
- "surface:snapshot": "node scripts/scriptctl-surface-snapshot.mjs"
30
- },
31
21
  "dependencies": {
32
22
  "@anthropic-ai/sdk": "^0.32.1",
33
23
  "commander": "^12.1.0",
@@ -51,5 +41,18 @@
51
41
  "license": "MIT",
52
42
  "publishConfig": {
53
43
  "access": "public"
44
+ },
45
+ "scripts": {
46
+ "build": "tsc",
47
+ "clean": "rm -rf dist",
48
+ "postinstall": "node scripts/install-skill.mjs",
49
+ "install-skill": "node scripts/install-skill.mjs",
50
+ "pretest": "pnpm run build",
51
+ "test": "vitest run",
52
+ "pretest:coverage": "pnpm run build",
53
+ "test:coverage": "c8 --reporter=text --reporter=html --reporter=lcov --report-dir=coverage vitest run",
54
+ "test:watch": "vitest",
55
+ "typecheck": "tsc --noEmit",
56
+ "surface:snapshot": "node scripts/scriptctl-surface-snapshot.mjs"
54
57
  }
55
- }
58
+ }
@@ -0,0 +1,120 @@
1
+ #!/usr/bin/env node
2
+ // postinstall: 把打包进 npm 包的 scriptctl skill 装到用户根目录下的三处 skill 目录
3
+ // (Claude Code / agents / codex),并把「本次安装对应的 scriptctl 版本号」戳进每份
4
+ // SKILL.md 的 frontmatter + 一个 .scriptctl-version 标记文件里。
5
+ //
6
+ // 设计要点:
7
+ // - 永不让安装失败:全程 try/catch,任何异常只打印警告并以 0 退出(skill 装不上不该
8
+ // 拖垮 `npm i -g scriptctl` 本身)。
9
+ // - 开发态跳过:源码检出(存在 src/)不是「已发布的包」,跳过,免得 dev `pnpm install`
10
+ // 覆盖你本地手改的 skill。
11
+ // - 可关闭:SCRIPTCTL_SKIP_SKILL_INSTALL=1 或 SCRIPTCTL_SKILL_INSTALL=0。
12
+ // - 幂等:每次把目标 <dir>/scriptctl 清空重写,只管这一个子目录,不碰旁边的其它 skill。
13
+ // - 手动补装:node <pkg>/scripts/install-skill.mjs(同一逻辑,可随时重跑)。
14
+
15
+ import * as fs from "node:fs";
16
+ import * as os from "node:os";
17
+ import * as path from "node:path";
18
+ import { fileURLToPath } from "node:url";
19
+
20
+ const SKILL_NAME = "scriptctl";
21
+ // 三处目标 skill 根目录(相对用户家目录)。每处装成 <root>/scriptctl 子目录。
22
+ const TARGET_SKILL_ROOTS = [
23
+ path.join(".claude", "skills"),
24
+ path.join(".agents", "skills"),
25
+ path.join(".codex", "skills"),
26
+ ];
27
+
28
+ function log(msg) {
29
+ process.stdout.write(`[scriptctl] ${msg}\n`);
30
+ }
31
+
32
+ function optedOut() {
33
+ const skip = process.env.SCRIPTCTL_SKIP_SKILL_INSTALL;
34
+ const flag = process.env.SCRIPTCTL_SKILL_INSTALL;
35
+ return skip === "1" || skip === "true" || flag === "0" || flag === "false";
36
+ }
37
+
38
+ // package root = 本脚本上一级的上一级(<root>/scripts/install-skill.mjs)。
39
+ function packageRoot() {
40
+ return path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
41
+ }
42
+
43
+ function readVersion(root) {
44
+ try {
45
+ const pkg = JSON.parse(fs.readFileSync(path.join(root, "package.json"), "utf-8"));
46
+ return typeof pkg.version === "string" ? pkg.version : "0.0.0";
47
+ } catch {
48
+ return "0.0.0";
49
+ }
50
+ }
51
+
52
+ // 把源 SKILL.md 里的 `scriptctl_version:` frontmatter 值改成实际安装的版本,让装好的
53
+ // skill 一眼看清对应的是哪个 scriptctl。没有该行时不硬插(保持 frontmatter 干净)。
54
+ function stampVersion(skillMdPath, version) {
55
+ try {
56
+ const text = fs.readFileSync(skillMdPath, "utf-8");
57
+ if (!/^scriptctl_version:/m.test(text)) return;
58
+ const stamped = text.replace(/^scriptctl_version:.*$/m, `scriptctl_version: "${version}"`);
59
+ fs.writeFileSync(skillMdPath, stamped, "utf-8");
60
+ } catch {
61
+ /* 戳版本失败不影响 skill 可用 */
62
+ }
63
+ }
64
+
65
+ function installOne(skillSrc, homeDir, skillRootRel, version) {
66
+ const target = path.join(homeDir, skillRootRel, SKILL_NAME);
67
+ fs.rmSync(target, { recursive: true, force: true });
68
+ fs.mkdirSync(path.dirname(target), { recursive: true });
69
+ fs.cpSync(skillSrc, target, { recursive: true });
70
+ stampVersion(path.join(target, "SKILL.md"), version);
71
+ fs.writeFileSync(path.join(target, ".scriptctl-version"), `${version}\n`, "utf-8");
72
+ return target;
73
+ }
74
+
75
+ function main() {
76
+ if (optedOut()) {
77
+ log("SCRIPTCTL_SKIP_SKILL_INSTALL set — skipping skill install.");
78
+ return;
79
+ }
80
+
81
+ const root = packageRoot();
82
+
83
+ // 开发态守卫:已发布的包不含 src/(package.json files 未包含它)。存在 src/ = 源码
84
+ // 检出,跳过,免得覆盖开发者本地 skill。
85
+ if (fs.existsSync(path.join(root, "src"))) {
86
+ return;
87
+ }
88
+
89
+ const skillSrc = path.join(root, "skills", SKILL_NAME);
90
+ if (!fs.existsSync(path.join(skillSrc, "SKILL.md"))) {
91
+ log(`skill source not found at ${skillSrc} — skipping.`);
92
+ return;
93
+ }
94
+
95
+ const homeDir = os.homedir();
96
+ if (!homeDir) {
97
+ log("home directory unresolved — skipping skill install.");
98
+ return;
99
+ }
100
+
101
+ const version = readVersion(root);
102
+ const installed = [];
103
+ for (const rel of TARGET_SKILL_ROOTS) {
104
+ try {
105
+ installed.push(installOne(skillSrc, homeDir, rel, version));
106
+ } catch (exc) {
107
+ log(`could not install skill into ${rel}: ${exc instanceof Error ? exc.message : String(exc)}`);
108
+ }
109
+ }
110
+ if (installed.length > 0) {
111
+ log(`installed ${SKILL_NAME} skill (v${version}) → ${installed.join(", ")}`);
112
+ }
113
+ }
114
+
115
+ try {
116
+ main();
117
+ } catch (exc) {
118
+ // 兜底:任何未预期异常都不该让 npm install 失败。
119
+ log(`skill install skipped: ${exc instanceof Error ? exc.message : String(exc)}`);
120
+ }
@@ -0,0 +1,273 @@
1
+ ---
2
+ name: scriptctl
3
+ description: "剧本 script.json 的读写 CLI:从零创建(create + add-actor/location/prop/episode)、查询(集/场/action/资产/状态/校验/时间戳/出场统计)、原子编辑(台词/类型/归属/state/资产)、选择器批量精修(一条命令扫一片,读写共享 --in/谓词)、动词脚本 do(异构批量一事务)、结构调整(插/删/移/分/合)、入库导出。本地电脑上默认直接读写本地 script.json(--script-path);沙箱里默认读写项目 DB。剧本阶段做任何剧本相关读写、以及洗稿/对标/转绘里操作原剧与新剧两个 script.json 之前都应加载。正文由你用原子能力写入。"
4
+ version: "0.18.0"
5
+ scriptctl_version: "0.35.0"
6
+ author: "official"
7
+ ---
8
+
9
+ # scriptctl
10
+
11
+ `scriptctl` 读写结构化剧本 `script.json`:资产(人物/场景/道具/发声源)、分集 → 场景 → action、状态与引用完整性、校验。**每次调用只作用于一份剧本**(由目标 flag 选定),所以「换剧本 = 换目标」。
12
+
13
+ ## 先定目标:作用在哪份剧本上
14
+
15
+ `scriptctl` 每条命令都要知道读写哪份剧本,四选一(互斥):
16
+
17
+ | 目标 | flag | 用在 |
18
+ |---|---|---|
19
+ | **本地文件** | `--script-path <file>` | 🖥️ **本地电脑首选**。直接读写这一个 JSON,无 store、无 revision。洗稿/对标/转绘、试验、离线全走它 |
20
+ | direct 中间稿 | `--draft` | 指向 `script.initial.json`(direct 抽取产物);不用写路径 |
21
+ | 项目 DB(最终剧本) | `--remote` / `--project-group-no <no>` | ☁️ **沙箱首选**。每次写进 DB 新 revision,边写边入库 |
22
+ | 本地约定 store | `--local` | `output/` 目录下的约定 store |
23
+
24
+ - 🖥️ **本地电脑上**:几乎每条命令都带 `--script-path <file>`。下文示例为简洁常省略它,实际本地使用请补上。
25
+ - ☁️ **沙箱里**:`SANDBOX_PROJECT_GROUP_NO` 已注入时,裸命令自动指向该项目 DB,无需 flag。
26
+ - 不给任何目标、又不在沙箱:CLI 拒绝猜测并报错。选一个目标。
27
+
28
+ ### 两个 script.json:洗稿 / 对标 / 转绘
29
+
30
+ 洗稿、对标仿写、转绘(换地区/换壳)里常常**同时开着原剧和新剧两份 script.json**:从原剧读结构与节奏,往新剧写。因为每条命令只作用于 `--script-path` 指的那一份,**换文件就是换这个 flag 的值**:
31
+
32
+ ```bash
33
+ ORIG=原剧/script.json
34
+ NEW=新剧/script.json
35
+
36
+ # 读原剧(了解要对标什么)
37
+ scriptctl summary --script-path "$ORIG"
38
+ scriptctl actions --in ep_001 --script-path "$ORIG" # 带 timestamp 列,看节奏
39
+ scriptctl states act_001 --script-path "$ORIG" # 看人物状态弧线
40
+
41
+ # 建/写新剧(把改写后的正文灌进去)
42
+ scriptctl create --title "新剧名" --script-path "$NEW"
43
+ scriptctl do ep01.txt --apply --script-path "$NEW"
44
+
45
+ # 逐场对照:同一集在两份里并排看
46
+ scriptctl scenes --in ep_003 --script-path "$ORIG"
47
+ scriptctl scenes --in ep_003 --script-path "$NEW"
48
+ ```
49
+
50
+ - 一次只碰一份。要「从 A 抄到 B」就是:`--script-path A` 读出来 → 你决定改法 → `--script-path B` 写进去。
51
+ - 事件级对齐:原剧 `actions` 的 `timestamp` 列 + `scenes` 的 `t=t_start..t_end` 给出每段的时间跨度;对标时按这个跨度切新剧的段落。
52
+ - 人物状态弧线:`states <actor>` 每个状态末尾的 `episodes=<区间>` 告诉你某个造型/形态在原剧哪些集出现,转绘时据此规划新剧的状态。
53
+
54
+ ## 能干什么
55
+
56
+ ### 读(永远只读、永远安全)
57
+
58
+ | 想做什么 | 命令 |
59
+ |---|---|
60
+ | **了解剧情 / 全貌**:讲什么(synopsis)、世界观(worldview)、风格(style)、一句话(logline)、主旨(theme)、主角(main_characters)+ 标题 / 集数 / 场数 / 资产数("这剧本是关于什么的"先跑这个) | `scriptctl summary` |
61
+ | 每集字数 / 场数 / action 数 **+ 每集剧情梗概** | `scriptctl episodes` |
62
+ | 找字数超 1000 的集 | `scriptctl episodes --min-chars 1000` |
63
+ | 看某集的所有场(含 `t=t_start..t_end` 时段) | `scriptctl scenes --in ep_007` |
64
+ | 看某场的资产 + action 数 | `scriptctl scenes --in ep_007/scn_005` |
65
+ | **按正文搜某句话定位 action**(最常用) | `scriptctl actions --grep "<片段>"` |
66
+ | 列某集所有 action(TSV 含 **timestamp** / 正文 / 情绪) | `scriptctl actions --in ep_001` |
67
+ | 看单条 action 正文 | `scriptctl actions --in ep_001/scn_001#3` |
68
+ | action 多维过滤 | `scriptctl actions --in ep_001 --type dialogue --actor act_001` |
69
+ | 某角色出现的所有场 | `scriptctl scenes --has-actor act_001` |
70
+ | **列某资产的所有 state + 状态弧线**(拿 state_id↔名↔描述↔出现在哪些集,改 state 前必查) | `scriptctl states act_001`(裸 id 即可,也认 `actor:act_001`) |
71
+ | 资产**出场统计**(几场 / 几集,压成集区间) | `scriptctl actors --counts` / `locations --counts` / `props --counts` |
72
+ | 某资产 / 状态 / speaker 反查 | `scriptctl refs actor:act_001` |
73
+ | 当前校验问题 | `scriptctl issues --severity error` |
74
+ | 跑校验 | `scriptctl validate` |
75
+
76
+ **读侧新特性(0.35.0 起)**——洗稿/对标/转绘的核心读法:
77
+
78
+ - `actions` TSV 列:`addr timestamp type delivery speaker actor emotion content`。`timestamp` 是该 action 的 `extend.timestamp`(集内 `M:SS`,无则空)。事件跨度 = 首末 action 时间戳之差。
79
+ - `scenes` 行尾 `t=<t_start>..<t_end>`:该场首/末带时间戳 action 的时间。
80
+ - `states <asset>`:接受裸 id(`act_001`/`loc_001`/`prp_001`);每个状态末尾 `episodes=<区间> (N eps, M scenes)` 是该状态的**集弧线**(scene context + action state_changes 里被绑定的位置)。从不绑定的状态显示 `episodes=none`。
81
+ - `actors|locations|props|assets --counts`:追加 `scenes=N episodes_count=M episodes=<区间>`(按 scene context 出场统计)。默认不带 `--counts`,保持输出精简。
82
+ - `summary`:多吐 `worldview`(有 `worldview_raw` 且不同则括号附带)与 `style`。
83
+
84
+ ### 写(单点:第一个位置参数是 address。多点:见下「选择器批量」)
85
+
86
+ | 想做什么 | 命令 |
87
+ |---|---|
88
+ | 改 action 正文(替换 / 删一段) | `scriptctl replace <ep/scn#idx> --from X --to Y`(加 `--regex` 走正则) |
89
+ | 改 action type | `scriptctl type <ep/scn#idx> <dialogue\|action\|inner_thought>` |
90
+ | 改 action 归属角色 | `scriptctl actor <ep/scn#idx> <act_id\|none>` |
91
+ | 改 / 清 action 情绪 | `scriptctl emotion <ep/scn#idx> "紧张"` / `scriptctl emotion <ep/scn#idx> --clear` |
92
+ | 加 state 变化 | `scriptctl state-change <ep/scn#idx> actor:<id> --to <state>` |
93
+ | 清 state 变化 | `scriptctl state-change <ep/scn#idx> actor:<id> --clear` |
94
+ | action 转对白 | `scriptctl dialogue <ep/scn#idx> --speakers spk_001` |
95
+ | 改资产名 / 描述 / 别名 / role | `scriptctl rename actor:<id> "X"` / `describe` / `alias --add X` / `role <主角\|配角>` |
96
+ | 给资产加 state | `scriptctl state-add actor:<id> "震惊"` |
97
+ | **改 / 删某个 state** | `scriptctl rename actor:<id>/<st_id> "新名"` / `scriptctl delete actor:<id>/<st_id> --strategy remove`(地址带 `/st_id` 即作用于 state;`state-rename` / `state-delete` 是等价别名;合并/删除 state 的引用修复核验见 [references/state-reference-repair.md](references/state-reference-repair.md)) |
98
+ | 改 scene 资产 ref | `scriptctl context <ep/scn> actor:<id> --state st_X \| --clear \| --remove` |
99
+ | 挂自由维度键值 | `scriptctl extend <addr> --key <名> --value <JSON>`(如给 action 挂 `timestamp`) |
100
+ | 合并资产 / 场景 | `scriptctl merge actor:<src> --into actor:<dst>` |
101
+ | 删 action / scene / 资产 | `scriptctl delete <addr>`(资产要 `--strategy replace\|remove`) |
102
+ | 插 action / scene | `scriptctl insert <ep/scn> --type X --content X [--emotion X]` / `insert <ep> --location <id>` |
103
+ | 移动 / 分场 | `scriptctl move <addr> <to>` / `split <ep/scn> --at <idx>` |
104
+ | 设整本 / 分集剧情梗概 | `scriptctl synopsis "整本梗概"` / `scriptctl synopsis ep_001 "本集梗概"` |
105
+ | 设世界观 | `scriptctl worldview <现代\|古代历史\|...>` |
106
+ | 新建 speaker | `scriptctl add-speaker --kind X --name Y` |
107
+
108
+ ### 选择器批量(一条命令扫一片 —— 读写共享同一套选择语法)
109
+
110
+ 把单点写动词的「address」换成一个**选择**,它就对**所有命中的 action** 一次性改。`replace / type / actor / emotion / state-change / transition` 都支持。
111
+
112
+ - **选范围 `--in`**:`ep_003..ep_007`(集区间)/ `ep/scn` 区间 / 逗号多区间 / `'*'`(全本)。
113
+ - **加谓词**(和 `actions` 查询**完全一样**的 flag,AND 组合):`--type` `--actor` `--speaker` `--grep /re/` `--has state-changes|transition|lines`。
114
+ - 🔴 **护栏:多点写默认 dry-run**(回显命中数 + blast-radius,不落盘),加 **`--apply`** 才真写。单点(给 address)仍直写。
115
+
116
+ ```bash
117
+ # 清全本所有 action 开头的 [xxx] 标记:一条正则扫全本
118
+ scriptctl replace --in '*' --regex --from '^\s*\[[^\]]*\]\s*' --to '' # 先看命中
119
+ scriptctl replace --in '*' --regex --from '^\s*\[[^\]]*\]\s*' --to '' --apply # 落地
120
+ # 第3-7集里某 speaker 的对白统一改归属(谓词直达,无需先查地址)
121
+ scriptctl actor --in ep_003..ep_007 --speaker spk_001 act_009 --apply
122
+ # 第3-7集里某 speaker 的对白统一标情绪
123
+ scriptctl emotion --in ep_003..ep_007 --speaker spk_001 "紧张" --apply
124
+ ```
125
+
126
+ > 先 discover 后 mutate 用**同一套 flag**:`scriptctl actions --in … --speaker …` 查出来是哪些,换个动词就改哪些。`actions --json` 带结构化 `rows[]`(含独立 `addr` / `timestamp` / `emotion` 字段),`actions … --format addr` 直接吐裸地址流喂 `xargs`。
127
+
128
+ ### 异构批量 `do`(一组各不相同的改动 = 一段动词脚本 = 一个事务)
129
+
130
+ 每行就是一条**去掉 `scriptctl` 的命令**,`#` 注释、空行随意;整段全成或全不成。比手写 patch JSON 省心(动词原样,不猜字段名)。
131
+
132
+ ```bash
133
+ scriptctl do edits.txt # 默认 dry-run(预演 + 校验,不写)
134
+ scriptctl do edits.txt --apply # 一次性原子落盘
135
+ cat edits.txt <<'EOF'
136
+ replace ep_001/scn_001#3 --from "台下掌声雷动" --to ""
137
+ type ep_001/scn_002#1 dialogue
138
+ merge actor:act_005 --into actor:act_001
139
+ insert ep_001/scn_006 --type action --content "暗夜,街道空无一人。"
140
+ emotion ep_001/scn_001#3 --clear
141
+ EOF
142
+ ```
143
+
144
+ `do` 也读 stdin(`scriptctl do -`)。结构性动词(insert/delete/move/split/merge)**只能**走单点或 `do`,不进选择器批量(索引会漂移)。目标 flag(如 `--script-path`)加在 `do` 命令本身上,整段脚本共用同一目标。
145
+
146
+ ### 建(从零起一本剧本,不要 address,第一个位置参数是名字)
147
+
148
+ | 想做什么 | 命令 |
149
+ |---|---|
150
+ | 建空白剧本(schema v2 骨架) | `scriptctl create [--title X]` |
151
+ | 加人物 | `scriptctl add-actor "林夏" [--role 主角\|配角] [--description X] [--alias X]` |
152
+ | 加场景地点 | `scriptctl add-location "便利店" [--description X]` |
153
+ | 加道具 | `scriptctl add-prop "怀表" [--description X]` |
154
+ | 加分集 | `scriptctl add-episode [--title X]` |
155
+
156
+ id 自动按序分配(`act_001` / `loc_001` / `prp_001` / `ep_001` / `scn_001`…),后续命令直接引用。建完资产与集,用 `insert` 建场景、灌正文。整本怎么搭见 [references/atomic-write-workflow.md](references/atomic-write-workflow.md)。
157
+
158
+ ### Address 格式(决定 verb 作用对象,自动分发)
159
+
160
+ | 形态 | 类型 |
161
+ |---|---|
162
+ | `ep_001/scn_001#3` | action |
163
+ | `ep_001/scn_001` | scene |
164
+ | `actor:act_001` / `location:loc_001` / `prop:prp_001` | asset |
165
+ | `actor:act_001/st_001` | asset state |
166
+ | `ep_001` | episode |
167
+ | `spk_001` | speaker |
168
+
169
+ > `states` 查询额外接受裸资产 id(`act_001` / `loc_001` / `prp_001`),按前缀推断种类。其它 verb 仍要完整 address。
170
+
171
+ ## 经典最短路径
172
+
173
+ **改某句台词**:grep 找地址 → replace 落字。
174
+ ```bash
175
+ scriptctl actions --grep "台下掌声雷动"
176
+ # → ep_001/scn_001#3 0:14 action ... 台下掌声雷动。
177
+ scriptctl replace ep_001/scn_001#3 --from ",台下掌声雷动" --to ""
178
+ ```
179
+ `--to` 省略即删除。一个 action 内多次命中默认拒绝,要么把 `--from` 写更长更唯一,要么显式 `--all`。
180
+
181
+ **改某角色名 + 补别名**:
182
+ ```bash
183
+ scriptctl rename actor:act_001 "陈墨"
184
+ scriptctl alias actor:act_001 --add "陈总" --add "老板"
185
+ ```
186
+
187
+ **整理重复角色**:
188
+ ```bash
189
+ scriptctl refs actor:act_005 # 先看 act_005 出现在哪
190
+ scriptctl merge actor:act_005 --into actor:act_001
191
+ ```
192
+
193
+ **读人物状态弧线(转绘/对标常用)**:
194
+ ```bash
195
+ scriptctl states act_001
196
+ # → actor:act_001/st_001 京北队球衣 desc="…" episodes=ep_001..ep_017,ep_022..ep_044 (40 eps, 43 scenes)
197
+ # → actor:act_001/st_002 石膏轮椅装 desc="…" episodes=ep_018..ep_021 (4 eps, 4 scenes)
198
+ scriptctl actors --counts # 每个人物出场几场/几集
199
+ ```
200
+
201
+ **写 / 改梗概**:
202
+ ```bash
203
+ scriptctl summary # 先看整本 worldview/style/synopsis/logline/theme
204
+ scriptctl episodes # 每集列表含 synopsis
205
+ scriptctl synopsis "一段整本剧情梗概。"
206
+ scriptctl synopsis ep_001 "第一集剧情梗概。"
207
+ ```
208
+
209
+ **插一场过渡 + 起头 action**:
210
+ ```bash
211
+ scriptctl insert ep_001 --after ep_001/scn_005 --location loc_002 --time night --space exterior
212
+ scriptctl insert ep_001/scn_006 --type action --content "暗夜,街道空无一人。" --emotion "紧张"
213
+ ```
214
+
215
+ **修校验问题**:
216
+ ```bash
217
+ scriptctl issues --severity error
218
+ # → STATE_NOT_FOUND at ep_001/scn_003#5 actor:act_001
219
+ scriptctl actions --in ep_001/scn_003 --has state-changes
220
+ scriptctl state-change ep_001/scn_003#5 actor:act_001 --to st_calm --from st_default
221
+ ```
222
+
223
+ **批量精修(同构一片 → 选择器;异构多点 → `do`)**:
224
+ ```bash
225
+ scriptctl replace --in ep_003..ep_007 --from 陈总 --to 陈墨 --all # 同构:默认 dry-run
226
+ scriptctl replace --in ep_003..ep_007 --from 陈总 --to 陈墨 --all --apply # --apply 落地
227
+ scriptctl do fixes.txt --apply # 异构:一段动词脚本一事务
228
+ ```
229
+
230
+ **从零写一集(你自己写正文,`do` 批量灌)**:
231
+ ```bash
232
+ scriptctl create --title "夏夜便利店" # 空白剧本
233
+ scriptctl do ep01.txt --apply # 每行一条建词/insert:add-actor → add-location → add-episode → insert
234
+ ```
235
+ 完整骨架与写法见 [references/atomic-write-workflow.md](references/atomic-write-workflow.md)。
236
+
237
+ ## 三种入库起点(按项目状态选)
238
+
239
+ | 项目状态 | 走 | 细节 |
240
+ |---|---|---|
241
+ | 没剧本文本,从零写(题材 / 灵感 / 集纲在手) | `create` + `add-*` + `insert` + `do`,正文你自己写 | [references/atomic-write-workflow.md](references/atomic-write-workflow.md) |
242
+ | 已有完整剧本 / 分镜素材(docx / pdf / xlsx / md / json) | `scriptctl direct ...`(LLM 抽取) | [references/direct-workflow.md](references/direct-workflow.md) |
243
+ | 只有正文 md、还没资产 md | `scriptctl parse <dir> --extract-assets`(LLM 提资产) | 只写 `人物.md`/`场景.md`/`道具.md`/`发声源.md`/`元信息.md`,不生成 script.json、不发布;复核后再跑普通 parse |
244
+ | 自己手写好一个 md 工作区 | `scriptctl parse <dir> [--publish]`(确定性组装,无 LLM) | `scriptctl parse --spec` 看 md 语法 |
245
+
246
+ 写正文 = 你(agent)想好正文,用上面「建 / 写」的原子能力灌进剧本。
247
+
248
+ `direct export` 只卡 validation:passed 才放行。但**强烈建议**导出前用 `direct review` 自查(curation/issues 总览 + `--episode N` 源文↔抽取对照),细节看 direct-workflow.md。
249
+
250
+ `direct init` 可续跑:成功批次跳过、失败批次粘性不自动重试。`scriptctl direct status` 看每集状态,`direct init --episodes <N> / --batches <key> / --retry-errors / --all` 选择性重跑(只动点名的,不碰其它集)。某集内容过滤就 `--episodes <N>` 重跑或软化源文本,不要清 run_state / 手塞文件。
251
+
252
+ ## 资产 state 判定(`state-add` 通用规则)
253
+
254
+ 只有**持久、可复用、需独立生成视觉资产的外观变体**才进 `states[]`。身份 / 年龄 / 职业 / 情绪 / 动作 / 姿态 / 临时伤病 / 混合状态**不**算状态,放 description 或 action 文本。
255
+
256
+ **默认状态(default)**:每个有 `states[]` 的资产必须有且仅有一个 asset-scoped 的 `state_id: "default"`(代表最常见的常态外观,保留可读的 state_name)。`direct`/`parse` 会自动把「默认/最常见」那一档 canonical 成 `default`;手动 `state-add` 给一个原先无状态的资产加第一个 state 后,若校验报 `DEFAULT_STATE_MISSING`,说明缺默认态——把最常见那档的 state_id 设成 `default`(改 raw JSON 或重跑 direct state-curation)。
257
+
258
+ 合并或删除 state 时,必须确认引用该 state 的场景 context 和 action state_changes 已被正确修复;操作与实现路径见 [references/state-reference-repair.md](references/state-reference-repair.md)。
259
+
260
+ ## 通用边界
261
+
262
+ - 🔴 **不要加 `--json`**。默认列表 / 查询输出是给 agent 读的 TSV / 行式文本(地址单独成列),比 JSON 更省 token、更好决策。除非真的要 parse 字段喂给下一步程序(那时 `actions --json` 有结构化 `rows[]`,或用 `--format addr` 取裸地址流)。
263
+ - 🔴 **多点写默认 dry-run**:`replace/type/actor/emotion/state-change/transition` 一旦带 `--in`/谓词就是预演(回显命中数,不落盘),确认后加 `--apply` 才真写。单点(给 address)直写、不用 `--apply`。
264
+ - 🔴 **手写批量走 `do`,不要手撸 patch JSON**。`scriptctl patch <file|->` 降级为**机器/jq 管道**的接口(`… --json | jq '[…]' | scriptctl patch -`);人/agent 手写一律用 `do`(动词原样,无翻译)。需要 op schema 用 `scriptctl patch --schema [<op>]`。
265
+ - 🔴 **本地用记得带 `--script-path <file>`**;洗稿/对标/转绘里两份剧本就是两个不同的 `--script-path`,一次只碰一份。
266
+ - 只有 `direct init` 和 `parse --extract-assets` 会请求大模型;普通 `parse`、`summary/episodes/actions` 查询、`synopsis/replace/patch/do` 等 script.json 读写命令不打模型。
267
+ - 修 direct 中间稿(`script.initial.json`):所有读写 verb 加 `--draft` 即可,不用知道文件路径;不加 `--draft` 默认操作 DB 里的最终剧本。`--draft` 与 `--script-path`/`--project-group-no` 互斥。
268
+ - 多态 verb(`delete` / `merge` / `move` / `describe` / `rename` / `insert`)按 address 格式分发;flag 用错 kind 会直接报错(不会静默忽略)。
269
+ - 互斥 flag(`context` 的 --state/--clear/--remove;`state-change` 的 --to/--clear;`transition` 的 --process+--contrast/--clear)只能传一个,多传会报 `*_FLAG_CONFLICT`。
270
+ - `mock` provider 仅测试,禁止作为交付;provider 失败不降级 mock。
271
+ - 工具失败排查根因,不手工拼装 JSON 绕过校验。
272
+
273
+ 参数 / 默认值 / 退出码以 `scriptctl <cmd> --help` 为准。功能变更用 `scriptctl changelog` 查。
@@ -0,0 +1,114 @@
1
+ # 从零原子写 — 你自己写正文,scriptctl 只搭骨架
2
+
3
+ 适用:**没有现成剧本文本**,从零写(手里只有题材 / 灵感 / 集纲)。
4
+
5
+ 核心理念:**写手是你**。你自己想好每一句正文,用原子能力把它灌进结构化剧本里。scriptctl 负责「合法的骨架 + 引用完整性 + 校验」,不负责「写得好不好」。
6
+
7
+ ---
8
+
9
+ ## 端到端流程
10
+
11
+ ```
12
+ create(空白剧本)
13
+ → worldview 设世界观
14
+ → add-actor / add-location / add-prop / add-speaker 注册资产(+ state-add 给外观档位)
15
+ → add-episode 建分集
16
+ → synopsis 写整本 / 分集梗概
17
+ → insert <ep> --location 建场景
18
+ → insert <ep/scn> --type ... --content "正文" [--emotion "情绪"] 逐 action 灌正文
19
+ → state-change / transition / context / dialogue 关系与状态层
20
+ → validate 收尾自查
21
+ ```
22
+
23
+ 资产/分集/场景的 id **自动按序分配**:第一个 actor 是 `act_001`、location 是 `loc_001`、prop 是 `prp_001`、episode 是 `ep_001`、它下面第一场是 `scn_001`……所以你能在后续命令里直接引用这些可预测的 id(也可以 `--id` 显式指定)。
24
+
25
+ ---
26
+
27
+ ## 两种写法
28
+
29
+ ### A. 增量(少量、边想边写):逐条原子 verb
30
+
31
+ ```bash
32
+ scriptctl create --title "夏夜便利店"
33
+ scriptctl worldview 现代
34
+ scriptctl add-actor 林夏 --role 主角 --description "高三女生,沉默寡言"
35
+ scriptctl add-actor 陈默 --role 配角 --description "便利店夜班店员"
36
+ scriptctl add-location 便利店 --description "24h 便利店,冷白光"
37
+ scriptctl add-episode --title "第一集:相遇"
38
+ scriptctl synopsis "雨夜便利店里,林夏与夜班店员陈默因一场意外相遇。"
39
+ scriptctl synopsis ep_001 "林夏雨夜进入便利店,发现陈默似乎认识她。"
40
+ scriptctl insert ep_001 --location loc_001 --time night --space interior # → scn_001
41
+ scriptctl insert ep_001/scn_001 --type action --content "雨夜,林夏推门进店,浑身湿透。" --emotion "狼狈"
42
+ scriptctl insert ep_001/scn_001 --type dialogue --content "欢迎光临。" --actor act_002
43
+ scriptctl insert ep_001/scn_001 --type inner_thought --content "又是他。" --actor act_001
44
+ scriptctl validate
45
+ ```
46
+
47
+ ### B. 整集 / 整本(推荐):一段 `do` 动词脚本,一个事务
48
+
49
+ 一集几十个 action 不要敲几十条命令,也**不要手撸 patch JSON**。写一段 `do` 脚本——**每行就是一条你会敲的命令**(去掉开头的 `scriptctl`),按依赖顺序排好(先建资产、再 `add-episode`、再 `insert` 场景、最后 `insert` action),一次落地。同一段 `do` 内按顺序执行,因此 `add-episode` 产出的 `ep_001` 能被靠后的 `insert` 直接引用。
50
+
51
+ ```bash
52
+ scriptctl create --title "夏夜便利店" # 先有空白剧本
53
+ scriptctl do ep01.txt # 默认 dry-run:内存里跑 + 校验,不落库
54
+ scriptctl do ep01.txt --apply # 确认后真写
55
+ ```
56
+
57
+ `ep01.txt` 形如(每行一条动词,`#` 注释、空行随意):
58
+
59
+ ```
60
+ worldview 现代
61
+ add-actor 林夏 --role 主角 --description "高三女生,沉默寡言"
62
+ add-actor 陈默 --role 配角 --description "便利店夜班店员"
63
+ add-location 便利店 --description "24h 便利店,冷白光"
64
+ add-episode --title "第一集:相遇"
65
+ synopsis "雨夜便利店里,林夏与夜班店员陈默因一场意外相遇。"
66
+ synopsis ep_001 "林夏雨夜进入便利店,发现陈默似乎认识她。"
67
+ insert ep_001 --location loc_001 --time night --space interior
68
+ insert ep_001/scn_001 --type action --content "雨夜,林夏推门进店。" --emotion "狼狈"
69
+ insert ep_001/scn_001 --type dialogue --content "欢迎光临。" --actor act_002
70
+ ```
71
+
72
+ 动词与单条命令完全一致(参数见 `scriptctl <verb> --help`)。`do` 也读 stdin:`… | scriptctl do -`。
73
+
74
+ > 机器/程序化生成的批量(如 jq 变换查询结果)才用 JSON:`scriptctl actions … --json | jq '[…ops…]' | scriptctl patch -`。手写一律 `do`。
75
+
76
+ ---
77
+
78
+ ## 写到哪里去(落库)
79
+
80
+ `create` 和所有编辑 verb 共用同一套目标解析,四选一:
81
+
82
+ | 目标 | 怎么走 | 说明 |
83
+ |---|---|---|
84
+ | **本地文件** | `--script-path <file>` | 🖥️ **本地电脑首选**。直接读写这一个 JSON,无 store、无 revision。洗稿/对标/转绘、试验都走它 |
85
+ | **DB(最终剧本)** | 不加目标 flag(沙箱默认),或 `--project-group-no <no>` | ☁️ **沙箱首选**。每个 op / patch 直接写进 DB 的新 revision,边写边入库,不需要单独的「发布」步骤 |
86
+ | **direct 中间稿** | `--draft` | 写进 `script.initial.json`;想要「先攒后审再入库」就走这条,最后 `scriptctl direct export` 落库 |
87
+
88
+ - 🖥️ **本地**:`scriptctl create --script-path new.json` 起本,之后每条编辑都带同一个 `--script-path new.json`。
89
+ - ☁️ **沙箱**:直接对 DB 写(`create` → 编辑,不加 flag),写完就在库里;想导出前人工自查就 `create --draft` → 全程 `--draft` 编辑 → `direct export`。
90
+
91
+ ### 两份 script.json(洗稿 / 对标 / 转绘)
92
+
93
+ 同时开着原剧与新剧时,一次只作用于 `--script-path` 指的那份:从原剧读(`summary`/`actions`(带 timestamp)/`states`(带弧线)/`scenes`(带时段)),往新剧写(`create` → `do --apply`)。换文件 = 换 `--script-path` 的值。详见 SKILL.md「两个 script.json」。
94
+
95
+ ---
96
+
97
+ ## 校验语义(重要)
98
+
99
+ 「没填满」不拦路,「结构坏了」才拦:
100
+
101
+ - **只提醒(warning,不影响 `validate` 通过)**:空剧本、空集、空场、场景没地点、资产缺描述。所以你可以先把骨架搭出来、逐步填,中途 `validate` 也能过。
102
+ - **硬错误(拦截)**:悬挂引用、重复 id、非法枚举、缺 id/name、scene_id 不递增、非人类注册成 actor —— 这些会破坏 DB 图结构,必须修。
103
+
104
+ 随时 `scriptctl validate` 看整体,`scriptctl issues --severity warning` 专看「还没填」的清单。
105
+
106
+ ---
107
+
108
+ ## 提醒
109
+
110
+ - 资产 state 判定(哪些进 `states[]`)见 SKILL.md「资产 state 判定」。
111
+ - 非人类发声源(系统/广播/道具音)用 `add-speaker --kind system|broadcast|prop|...`,**不要**注册成 actor。
112
+ - 角色名保持规范:别在名字里塞状态注解(`林夏(受伤)`会被拒),外观档位用 `state-add`。
113
+ - action 情绪放 `emotion` 字段:插入时用 `insert ... --emotion "紧张"`,修改时用 `emotion <ep/scn#idx> "紧张"` / `emotion <ep/scn#idx> --clear`,不要把 `[紧张]` 这类标记塞进 content。
114
+ - 参数 / 退出码以 `scriptctl <cmd> --help` 为准。