@lingjingai/scriptctl 0.51.0 → 0.51.2
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.
- package/README.md +1 -0
- package/changes/0.51.1.md +15 -0
- package/changes/0.51.2.md +13 -0
- package/dist/cli/register-workflows.js +9 -0
- package/dist/cli/register-workflows.js.map +1 -1
- package/dist/domain/ingest/assembler.d.ts +1 -0
- package/dist/domain/ingest/assembler.js +8 -2
- package/dist/domain/ingest/assembler.js.map +1 -1
- package/dist/domain/ingest/video-apply.js +6 -3
- package/dist/domain/ingest/video-apply.js.map +1 -1
- package/dist/domain/ingest/video-context.js +2 -2
- package/dist/domain/ingest/video-context.js.map +1 -1
- package/dist/domain/ingest/video-records.d.ts +6 -5
- package/dist/domain/ingest/video-serial-md.d.ts +6 -5
- package/dist/domain/ingest/video-serial-md.js +11 -4
- package/dist/domain/ingest/video-serial-md.js.map +1 -1
- package/dist/domain/script/v4/parse.d.ts +1 -0
- package/dist/domain/script/v4/parse.js +18 -0
- package/dist/domain/script/v4/parse.js.map +1 -1
- package/dist/llm/tasks/ingest/video-serial.js +26 -19
- package/dist/llm/tasks/ingest/video-serial.js.map +1 -1
- package/dist/llm/tasks/schemas.js +5 -5
- package/dist/llm/tasks/schemas.js.map +1 -1
- package/dist/usecases/ingest/video-pipeline.js +1 -1
- package/dist/usecases/ingest/video-pipeline.js.map +1 -1
- package/dist/usecases/script/lib.js +3 -3
- package/dist/usecases/script/lib.js.map +1 -1
- package/dist/usecases/script/migrate-v4.d.ts +3 -0
- package/dist/usecases/script/migrate-v4.js +194 -0
- package/dist/usecases/script/migrate-v4.js.map +1 -0
- package/dist/usecases/script/v4/mutations.js +2 -2
- package/dist/usecases/script/v4/mutations.js.map +1 -1
- package/package.json +1 -1
- package/skills/scriptctl/SKILL.md +59 -38
- package/skills/scriptctl/references/atomic-edit-workflow.md +6 -6
- package/skills/scriptctl/references/ingest-workflow.md +20 -20
- package/skills/scriptctl/references/state-reference-repair.md +6 -6
- package/skills/scriptctl/references/video-transcript-repair.md +115 -0
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { CliError, EXIT_NEEDS_AGENT, EXIT_OK, EXIT_USAGE, sha256Text, } from "../../common.js";
|
|
4
|
+
import { requireScriptV3 } from "../../domain/script/v3/parse.js";
|
|
5
|
+
import { validateScriptV3 } from "../../domain/script/v3/validation.js";
|
|
6
|
+
import { newScriptV4FromV3WithIdentity, } from "../../domain/script/v4/from-v3.js";
|
|
7
|
+
import { validateScriptV4 } from "../../domain/script/v4/validation.js";
|
|
8
|
+
import { atomicWriteJson, withScriptFileLock, } from "../../infra/script-working-copy.js";
|
|
9
|
+
function stringOption(opts, name) {
|
|
10
|
+
const value = opts[name];
|
|
11
|
+
return typeof value === "string" ? value.trim() : "";
|
|
12
|
+
}
|
|
13
|
+
function defaultIdentityMapPath(outputPath) {
|
|
14
|
+
const extension = path.extname(outputPath);
|
|
15
|
+
const stem = extension.length > 0
|
|
16
|
+
? outputPath.slice(0, -extension.length)
|
|
17
|
+
: outputPath;
|
|
18
|
+
return `${stem}.identity-map.json`;
|
|
19
|
+
}
|
|
20
|
+
function requireDistinctPaths(sourcePath, outputPath, identityMapPath) {
|
|
21
|
+
const resolved = [sourcePath, outputPath, identityMapPath].map((item) => path.resolve(item));
|
|
22
|
+
if (resolved[0] === resolved[1]) {
|
|
23
|
+
throw new CliError("The V4 destination must differ from the V3 source.", {
|
|
24
|
+
exitCode: EXIT_USAGE,
|
|
25
|
+
errorCode: "MIGRATE_SAME_PATH",
|
|
26
|
+
hint: "Choose a separate --output path. The source V3 file stays unchanged.",
|
|
27
|
+
data: { actual: [sourcePath] },
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
if (resolved[0] === resolved[2] || resolved[1] === resolved[2]) {
|
|
31
|
+
throw new CliError("The identity map needs its own file path.", {
|
|
32
|
+
exitCode: EXIT_USAGE,
|
|
33
|
+
errorCode: "MIGRATE_IDENTITY_MAP_PATH",
|
|
34
|
+
hint: "Choose an --identity-map path separate from the source and output files.",
|
|
35
|
+
data: { actual: [identityMapPath] },
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function assertWritableDestination(filePath, force) {
|
|
40
|
+
if (!force && fs.existsSync(filePath)) {
|
|
41
|
+
throw new CliError("Migration destination already exists.", {
|
|
42
|
+
exitCode: EXIT_USAGE,
|
|
43
|
+
errorCode: "MIGRATE_OUTPUT_EXISTS",
|
|
44
|
+
hint: "Choose a new path, or pass --force to replace the migration artifact.",
|
|
45
|
+
data: { actual: [filePath] },
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function readSource(sourcePath) {
|
|
50
|
+
let raw;
|
|
51
|
+
try {
|
|
52
|
+
raw = fs.readFileSync(sourcePath, "utf8");
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
throw new CliError("Cannot read the Script v3 source.", {
|
|
56
|
+
exitCode: EXIT_USAGE,
|
|
57
|
+
errorCode: "MIGRATE_SOURCE_READ_FAILED",
|
|
58
|
+
hint: "Pass an existing JSON file with --script-path.",
|
|
59
|
+
data: { actual: [sourcePath, error instanceof Error ? error.message : String(error)] },
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
return { raw, value: JSON.parse(raw) };
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
throw new CliError("The Script v3 source is not valid JSON.", {
|
|
67
|
+
exitCode: EXIT_USAGE,
|
|
68
|
+
errorCode: "MIGRATE_SOURCE_JSON_INVALID",
|
|
69
|
+
hint: "Repair the JSON syntax, then rerun migrate-v4.",
|
|
70
|
+
data: { actual: [error instanceof Error ? error.message : String(error)] },
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function v3IdentityKeys(source) {
|
|
75
|
+
const action = {};
|
|
76
|
+
for (const episode of source.episodes) {
|
|
77
|
+
for (const scene of episode.scenes) {
|
|
78
|
+
const sceneAddress = `${episode.episode_id}/${scene.scene_id}`;
|
|
79
|
+
scene.actions.forEach((_item, index) => {
|
|
80
|
+
const address = `${sceneAddress}#${index}`;
|
|
81
|
+
action[address] = address;
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return { action };
|
|
86
|
+
}
|
|
87
|
+
function readPriorIdentityMap(identityMapPath, force) {
|
|
88
|
+
if (!force || !fs.existsSync(identityMapPath))
|
|
89
|
+
return undefined;
|
|
90
|
+
let value;
|
|
91
|
+
try {
|
|
92
|
+
value = JSON.parse(fs.readFileSync(identityMapPath, "utf8"));
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
throw new CliError("Cannot reuse the existing V3-to-V4 identity map.", {
|
|
96
|
+
exitCode: EXIT_USAGE,
|
|
97
|
+
errorCode: "MIGRATE_IDENTITY_MAP_INVALID",
|
|
98
|
+
hint: "Restore the identity map, or choose a new --identity-map path.",
|
|
99
|
+
data: { actual: [identityMapPath, error instanceof Error ? error.message : String(error)] },
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
103
|
+
throw new CliError("Cannot reuse the existing V3-to-V4 identity map.", {
|
|
104
|
+
exitCode: EXIT_USAGE,
|
|
105
|
+
errorCode: "MIGRATE_IDENTITY_MAP_INVALID",
|
|
106
|
+
hint: "Restore the identity map, or choose a new --identity-map path.",
|
|
107
|
+
data: { actual: [identityMapPath] },
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
const record = value;
|
|
111
|
+
const identityMap = record["identity_map"] ?? value;
|
|
112
|
+
if (identityMap === null
|
|
113
|
+
|| typeof identityMap !== "object"
|
|
114
|
+
|| Array.isArray(identityMap)
|
|
115
|
+
|| identityMap["version"] !== 3) {
|
|
116
|
+
throw new CliError("Cannot reuse the existing V3-to-V4 identity map.", {
|
|
117
|
+
exitCode: EXIT_USAGE,
|
|
118
|
+
errorCode: "MIGRATE_IDENTITY_MAP_INVALID",
|
|
119
|
+
hint: "Restore the identity map, or choose a new --identity-map path.",
|
|
120
|
+
data: { actual: [identityMapPath] },
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
return identityMap;
|
|
124
|
+
}
|
|
125
|
+
export async function commandMigrateV4(opts) {
|
|
126
|
+
const sourceRawPath = stringOption(opts, "script_path");
|
|
127
|
+
const outputRawPath = stringOption(opts, "output");
|
|
128
|
+
if (!sourceRawPath || !outputRawPath) {
|
|
129
|
+
throw new CliError("Migration paths are required.", {
|
|
130
|
+
exitCode: EXIT_USAGE,
|
|
131
|
+
errorCode: "MIGRATE_PATH_MISSING",
|
|
132
|
+
hint: "Pass --script-path <v3.json> and --output <v4.json>.",
|
|
133
|
+
data: { expected: ["--script-path <v3.json>", "--output <v4.json>"] },
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
const sourcePath = path.resolve(sourceRawPath);
|
|
137
|
+
const outputPath = path.resolve(outputRawPath);
|
|
138
|
+
const identityMapPath = path.resolve(stringOption(opts, "identity_map") || defaultIdentityMapPath(outputPath));
|
|
139
|
+
const force = Boolean(opts["force"]);
|
|
140
|
+
requireDistinctPaths(sourcePath, outputPath, identityMapPath);
|
|
141
|
+
return withScriptFileLock(outputPath, async () => {
|
|
142
|
+
assertWritableDestination(outputPath, force);
|
|
143
|
+
assertWritableDestination(identityMapPath, force);
|
|
144
|
+
const sourceDocument = readSource(sourcePath);
|
|
145
|
+
const source = requireScriptV3(sourceDocument.value);
|
|
146
|
+
const sourceValidation = validateScriptV3(source);
|
|
147
|
+
const priorIdentityMap = readPriorIdentityMap(identityMapPath, force);
|
|
148
|
+
const converted = newScriptV4FromV3WithIdentity(source, priorIdentityMap, v3IdentityKeys(source));
|
|
149
|
+
const validation = validateScriptV4(converted.script);
|
|
150
|
+
const migrationRecord = {
|
|
151
|
+
version: 1,
|
|
152
|
+
source_version: 3,
|
|
153
|
+
target_version: 4,
|
|
154
|
+
source_path: sourcePath,
|
|
155
|
+
source_sha256: sha256Text(sourceDocument.raw),
|
|
156
|
+
identity_map: converted.identityMap,
|
|
157
|
+
};
|
|
158
|
+
atomicWriteJson(identityMapPath, migrationRecord);
|
|
159
|
+
atomicWriteJson(outputPath, converted.script);
|
|
160
|
+
const data = {
|
|
161
|
+
op: "script.migrate-v4",
|
|
162
|
+
changed: true,
|
|
163
|
+
source_script_path: sourcePath,
|
|
164
|
+
script_path: outputPath,
|
|
165
|
+
identity_map_path: identityMapPath,
|
|
166
|
+
source_version: 3,
|
|
167
|
+
target_version: 4,
|
|
168
|
+
source_validation: {
|
|
169
|
+
ok: sourceValidation.ok,
|
|
170
|
+
errors: sourceValidation.errors.length,
|
|
171
|
+
warnings: sourceValidation.warnings.length,
|
|
172
|
+
},
|
|
173
|
+
validation: {
|
|
174
|
+
ok: validation.ok,
|
|
175
|
+
errors: validation.errors.length,
|
|
176
|
+
warnings: validation.warnings.length,
|
|
177
|
+
issues: validation.errors.slice(0, 100),
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
const text = validation.ok
|
|
181
|
+
? [
|
|
182
|
+
`V4 script: ${outputPath}`,
|
|
183
|
+
`Identity map: ${identityMapPath}`,
|
|
184
|
+
"validation: ok",
|
|
185
|
+
].join("\n")
|
|
186
|
+
: [
|
|
187
|
+
`V4 script: ${outputPath}`,
|
|
188
|
+
`Identity map: ${identityMapPath}`,
|
|
189
|
+
`validation: ${validation.errors.length} errors; repair before production use`,
|
|
190
|
+
].join("\n");
|
|
191
|
+
return [{ text, data }, validation.ok ? EXIT_OK : EXIT_NEEDS_AGENT];
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=migrate-v4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate-v4.js","sourceRoot":"","sources":["../../../src/usecases/script/migrate-v4.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { applyPatchOperationsV4 } from "../../../domain/script/v4/patch/apply.js";
|
|
2
|
-
import {
|
|
2
|
+
import { requireStructurallyReadableScriptV4 } from "../../../domain/script/v4/parse.js";
|
|
3
3
|
export function applyV4Mutations(script, operations) {
|
|
4
|
-
return applyPatchOperationsV4(
|
|
4
|
+
return applyPatchOperationsV4(requireStructurallyReadableScriptV4(script), operations);
|
|
5
5
|
}
|
|
6
6
|
//# sourceMappingURL=mutations.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mutations.js","sourceRoot":"","sources":["../../../../src/usecases/script/v4/mutations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,0CAA0C,CAAC;AAClF,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"mutations.js","sourceRoot":"","sources":["../../../../src/usecases/script/v4/mutations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,0CAA0C,CAAC;AAClF,OAAO,EAAE,mCAAmC,EAAE,MAAM,oCAAoC,CAAC;AAGzF,MAAM,UAAU,gBAAgB,CAAC,MAAY,EAAE,UAAkB;IAC/D,OAAO,sBAAsB,CAAC,mCAAmC,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC;AACzF,CAAC"}
|
package/package.json
CHANGED
|
@@ -2,16 +2,19 @@
|
|
|
2
2
|
name: scriptctl
|
|
3
3
|
description: "剧本 script.json 的本地查询、文件化批量写作、原子精修、素材 ingest 与 revision publish CLI。处理 Script v3/v4、两个 script.json、剧本资产/state、Action、场景引用或 authoring 时使用。"
|
|
4
4
|
metadata:
|
|
5
|
-
version: "0.27.
|
|
6
|
-
scriptctl_version: "0.51.
|
|
5
|
+
version: "0.27.2"
|
|
6
|
+
scriptctl_version: "0.51.2"
|
|
7
7
|
author: "official"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# scriptctl
|
|
11
11
|
|
|
12
|
-
`scriptctl` 始终对
|
|
12
|
+
`scriptctl` 始终对 `-p` 指向的本地 `script.json` 工作。远端剧本先
|
|
13
13
|
`checkout`,完成本地查询、修改和 `validate` 后再 `publish`。
|
|
14
14
|
|
|
15
|
+
实际调用和示例优先使用短参数:`-p/-w/-s/-o/-i/-g/-t/-a/-k/-n/-j/-h/-v`。
|
|
16
|
+
没有短名的参数保持完整长写。
|
|
17
|
+
|
|
15
18
|
## 先识别版本
|
|
16
19
|
|
|
17
20
|
读取 `script.json.version`:
|
|
@@ -29,7 +32,7 @@ metadata:
|
|
|
29
32
|
4. **建立真实场并绑定资产**:完整 scene 显式声明本场地点、全部人物、全部道具及其实际 state。V4 同一资产只出现一条场景引用,完整状态写入无序 `state_ids` 集合;V3 按其既有单状态引用结构处理。
|
|
30
33
|
5. **写入或标准化正文**:从零、续写和连续正文修改使用 `.scriptctl` authoring 文件;已有目标先 `export`,再执行 `write` plan/apply。ingest 先完成抽取,大块标准化修改同样走 export/write。发现新资产或新 state 时,先补入 `<create>` 和 scene 引用,再继续正文。
|
|
31
34
|
6. **逐场复核**:每批正文落盘后读回 `scenes / actions`;一集完成后运行 `validate`。`validate` 通过只代表结构与引用合法,仍需完成内容标准和源素材一致性复核。
|
|
32
|
-
7. **全剧资产审计**:全剧完成后运行 `audit-assets
|
|
35
|
+
7. **全剧资产审计**:全剧完成后运行 `audit-assets -p <file>`,检查人物身份重复、同义视觉状态、未使用/落单状态,以及重复地点和道具资产。审计只给建议,不自动合并;必须核对剧情、身份、外观和跨集连续性后再修复。
|
|
33
36
|
|
|
34
37
|
## 三条工作流
|
|
35
38
|
|
|
@@ -40,19 +43,22 @@ metadata:
|
|
|
40
43
|
[references/bulk-authoring.md](references/bulk-authoring.md)。
|
|
41
44
|
3. 少量精修:查询定位 → 单 ID 原子 verb;同构多点用 selector;异构多点用
|
|
42
45
|
`do`。见 [references/atomic-edit-workflow.md](references/atomic-edit-workflow.md)。
|
|
46
|
+
4. 旧视频转录复核:V3 资产修复 → `migrate-v4` → 关联视频 → 补行、校时、
|
|
47
|
+
合并误拆对白 → `validate`。见
|
|
48
|
+
[references/video-transcript-repair.md](references/video-transcript-repair.md)。
|
|
43
49
|
|
|
44
50
|
## 本地文件边界
|
|
45
51
|
|
|
46
52
|
- 普通命令默认读取 `<cwd>/workspace/script.json`;操作其他文件时始终显式传
|
|
47
|
-
|
|
48
|
-
-
|
|
49
|
-
- 同时处理原剧与目标剧时,每条命令都显式带对应
|
|
53
|
+
`-p <file>`。
|
|
54
|
+
- `-w` 只属于 `ingest`、`ingest status` 和 `view`。
|
|
55
|
+
- 同时处理原剧与目标剧时,每条命令都显式带对应 `-p`,只从原剧读,
|
|
50
56
|
只向目标剧写。
|
|
51
57
|
- `checkout` 不覆盖未管理文件或本地修改;`publish` 按工作副本 revision 严格写入。
|
|
52
58
|
|
|
53
59
|
## 查询与定位
|
|
54
60
|
|
|
55
|
-
默认文本查询输出 TSV。需要结构化数据时使用
|
|
61
|
+
默认文本查询输出 TSV。需要结构化数据时使用 `-j`:顶层固定包含
|
|
56
62
|
`ok`、`exit_code`,表格数据位于 `rows`,列顺序位于 `row_columns`。地址流使用
|
|
57
63
|
`--format addr`。写命令的 JSON 使用 `op`、`changed`、`plan_digest`、
|
|
58
64
|
`validation`、`script_path` 等命令自身字段,不包含展示用的标题或结果区块。
|
|
@@ -61,14 +67,14 @@ JSON 错误包含 `error_code`、`message` 和可选 `hint`。
|
|
|
61
67
|
常用查询:
|
|
62
68
|
|
|
63
69
|
```bash
|
|
64
|
-
scriptctl summary
|
|
65
|
-
scriptctl episodes
|
|
66
|
-
scriptctl scenes
|
|
67
|
-
scriptctl actions
|
|
68
|
-
scriptctl actors --counts
|
|
69
|
-
scriptctl states actA3kP9x
|
|
70
|
-
scriptctl refs actA3kP9x/stB4xR8p
|
|
71
|
-
scriptctl validate
|
|
70
|
+
scriptctl summary -p "$SCRIPT"
|
|
71
|
+
scriptctl episodes -p "$SCRIPT"
|
|
72
|
+
scriptctl scenes -i '@ep:3' -p "$SCRIPT"
|
|
73
|
+
scriptctl actions -g "台下掌声" -p "$SCRIPT"
|
|
74
|
+
scriptctl actors --counts -p "$SCRIPT"
|
|
75
|
+
scriptctl states actA3kP9x -p "$SCRIPT"
|
|
76
|
+
scriptctl refs actA3kP9x/stB4xR8p -p "$SCRIPT"
|
|
77
|
+
scriptctl validate -p "$SCRIPT"
|
|
72
78
|
```
|
|
73
79
|
|
|
74
80
|
序号锚点是 1-based 查询语法:
|
|
@@ -86,18 +92,18 @@ scriptctl validate --script-path "$SCRIPT"
|
|
|
86
92
|
|---|---|
|
|
87
93
|
| **了解剧情 / 全貌**:synopsis/worldview/style/logline/theme/main_characters + 标题/集数/场数/资产数("这剧本是关于什么"先跑这个) | `scriptctl summary` |
|
|
88
94
|
| 每集字数 / 场数 / action 数 **+ 每集剧情梗概** | `scriptctl episodes`(`--min-chars 1000` 找长集) |
|
|
89
|
-
| 看某集的所有场(含 `t=t_start..t_end` 时段) | `scriptctl scenes
|
|
90
|
-
| 看某场的资产 + action 数 | `scriptctl scenes
|
|
91
|
-
| **按正文搜某句话定位 action**(最常用) | `scriptctl actions
|
|
92
|
-
| 列某集所有 action(含 timestamp / speaker / 正文 /表演提示) | `scriptctl actions
|
|
93
|
-
| 看单条 action 正文 | `scriptctl actions
|
|
94
|
-
| action 多维过滤 | `scriptctl actions
|
|
95
|
+
| 看某集的所有场(含 `t=t_start..t_end` 时段) | `scriptctl scenes -i '@ep:7'` |
|
|
96
|
+
| 看某场的资产 + action 数 | `scriptctl scenes -i '@ep:7/scn:5'` |
|
|
97
|
+
| **按正文搜某句话定位 action**(最常用) | `scriptctl actions -g "<片段>"` |
|
|
98
|
+
| 列某集所有 action(含 timestamp / speaker / 正文 /表演提示) | `scriptctl actions -i '@ep:1'` |
|
|
99
|
+
| 看单条 action 正文 | `scriptctl actions -i '@ep:1/scn:1/ac:3'` |
|
|
100
|
+
| action 多维过滤 | `scriptctl actions -i '@ep:1' -t dialogue -a <actor-id> --has speaker` |
|
|
95
101
|
| 某角色出现的所有场 | `scriptctl scenes --has-actor <actor-id>`(另有 `--has-location`/`--has-prop`) |
|
|
96
102
|
| **列某资产的所有 state + 状态弧线**(改造型前必查) | `scriptctl states <asset-id>` |
|
|
97
103
|
| 资产**出场统计**(几场/几集,压成集区间) | `scriptctl actors --counts` / `locations --counts` / `props --counts` |
|
|
98
104
|
| 某资产 / 状态反查 | `scriptctl refs <asset-id>` / `scriptctl refs <asset-id>/<state-id>` |
|
|
99
105
|
| 当前校验问题 / 跑校验 | `scriptctl issues --severity error` / `scriptctl validate` |
|
|
100
|
-
| 全剧人物/状态/地点/道具去重审计 | `scriptctl audit-assets
|
|
106
|
+
| 全剧人物/状态/地点/道具去重审计 | `scriptctl audit-assets -p workspace/script.json` |
|
|
101
107
|
|
|
102
108
|
## Script v4 写入
|
|
103
109
|
|
|
@@ -110,18 +116,18 @@ ep…… scn…… ac…… act…… loc…… prp…… st……
|
|
|
110
116
|
`ids` 只生成候选,不预留:
|
|
111
117
|
|
|
112
118
|
```bash
|
|
113
|
-
scriptctl ids
|
|
114
|
-
scriptctl ids
|
|
119
|
+
scriptctl ids -k action --count 4
|
|
120
|
+
scriptctl ids -k scene --count 2 -p "$SCRIPT"
|
|
115
121
|
```
|
|
116
122
|
|
|
117
123
|
单点修改使用正式 ID:
|
|
118
124
|
|
|
119
125
|
```bash
|
|
120
|
-
scriptctl replace acR8cV4n --from "旧句" --to "新句"
|
|
121
|
-
scriptctl parenthetical acT2fG6z --set "低声"
|
|
122
|
-
scriptctl parenthetical acT2fG6z --set ""
|
|
123
|
-
scriptctl parenthetical acT2fG6z --remove
|
|
124
|
-
scriptctl dialogue acT2fG6z
|
|
126
|
+
scriptctl replace acR8cV4n --from "旧句" --to "新句" -p "$SCRIPT"
|
|
127
|
+
scriptctl parenthetical acT2fG6z --set "低声" -p "$SCRIPT"
|
|
128
|
+
scriptctl parenthetical acT2fG6z --set "" -p "$SCRIPT"
|
|
129
|
+
scriptctl parenthetical acT2fG6z --remove -p "$SCRIPT"
|
|
130
|
+
scriptctl dialogue acT2fG6z -a actA3kP9x --state stB4xR8p -p "$SCRIPT"
|
|
125
131
|
```
|
|
126
132
|
|
|
127
133
|
`parenthetical` 只属于 dialogue / inner_thought。字段省略表示没有表演提示;显式
|
|
@@ -131,7 +137,7 @@ V4 placement 使用父节点与相邻节点 ID:
|
|
|
131
137
|
|
|
132
138
|
```bash
|
|
133
139
|
scriptctl insert scnK6wT3c --action-id acD4eF6g \
|
|
134
|
-
|
|
140
|
+
-t action --content "陈默关上门。" --before acT2fG6z
|
|
135
141
|
scriptctl move acD4eF6g scnH7jK9m --after acR8cV4n
|
|
136
142
|
scriptctl split scnK6wT3c --at acT2fG6z --new-scene-id scnD4eF6g
|
|
137
143
|
```
|
|
@@ -143,8 +149,8 @@ V4 一个场景内同一资产只引用一次;引用携带完整、非空的 `
|
|
|
143
149
|
|
|
144
150
|
```bash
|
|
145
151
|
scriptctl scene-ref scnK6wT3c actA3kP9x \
|
|
146
|
-
--state default --state stB4xR8p
|
|
147
|
-
scriptctl scene-ref scnK6wT3c actA3kP9x --remove
|
|
152
|
+
--state default --state stB4xR8p -p "$SCRIPT"
|
|
153
|
+
scriptctl scene-ref scnK6wT3c actA3kP9x --remove -p "$SCRIPT"
|
|
148
154
|
```
|
|
149
155
|
|
|
150
156
|
actor speaker 可选一个 state;若指定,必须属于该 actor 在当前 scene 的
|
|
@@ -153,10 +159,10 @@ actor speaker 可选一个 state;若指定,必须属于该 actor 在当前 s
|
|
|
153
159
|
state 修改前后都反查并校验:
|
|
154
160
|
|
|
155
161
|
```bash
|
|
156
|
-
scriptctl refs actA3kP9x/stB4xR8p
|
|
162
|
+
scriptctl refs actA3kP9x/stB4xR8p -p "$SCRIPT"
|
|
157
163
|
scriptctl state-delete actA3kP9x/stB4xR8p \
|
|
158
|
-
--strategy replace --replacement default
|
|
159
|
-
scriptctl validate
|
|
164
|
+
--strategy replace --replacement default -p "$SCRIPT"
|
|
165
|
+
scriptctl validate -p "$SCRIPT"
|
|
160
166
|
```
|
|
161
167
|
|
|
162
168
|
详见 [references/state-reference-repair.md](references/state-reference-repair.md)。
|
|
@@ -174,13 +180,28 @@ scriptctl scene-ref ep_001/scn_003 actor:act_001 --state st_002
|
|
|
174
180
|
对 V3 文件运行 `export`、`write`、原子命令、`validate` 和 `publish` 时,CLI
|
|
175
181
|
会选择 V3 实现并保持原文件结构与既有 ID。
|
|
176
182
|
|
|
183
|
+
旧 V3 转录稿进入新项目时创建独立 V4 副本:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
scriptctl migrate-v4 \
|
|
187
|
+
-p ./source-v3.json \
|
|
188
|
+
-o ./script-v4.json \
|
|
189
|
+
--identity-map ./script-v4.identity-map.json
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
命令保留源文件,输出 V4 剧本和 V3→V4 身份映射。输出仍有校验错误时,命令返回
|
|
193
|
+
`78`,文件继续作为“待人工修复”的 V4 工作副本使用;`validation.issues` 是修复清单。
|
|
194
|
+
使用 `do` 或 `patch` 在一个事务中消除全部 blocking issue,再落盘。
|
|
195
|
+
修正 V3 源后使用同一映射路径和 `--force` 重跑,既有节点复用已分配的 V4 ID。
|
|
196
|
+
结构性插入、删除或调序会改变 V3 的序号身份;完成首次迁移后直接精修 V4。
|
|
197
|
+
|
|
177
198
|
## 多点写与 plan
|
|
178
199
|
|
|
179
200
|
V4 单个明确 ID 的原子修改直接执行。任何单事务多点修改先生成完整计划:
|
|
180
201
|
|
|
181
202
|
```bash
|
|
182
|
-
scriptctl replace
|
|
183
|
-
scriptctl replace
|
|
203
|
+
scriptctl replace -i 'acR8cV4n..acT2fG6z' --from "。" --to "!"
|
|
204
|
+
scriptctl replace -i 'acR8cV4n..acT2fG6z' --from "。" --to "!" \
|
|
184
205
|
--apply --plan sha256:...
|
|
185
206
|
|
|
186
207
|
scriptctl do edits.txt
|
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
先查询,再用查询结果中的地址修改:
|
|
9
9
|
|
|
10
10
|
```bash
|
|
11
|
-
scriptctl actions
|
|
11
|
+
scriptctl actions -g "台下掌声雷动" -p "$SCRIPT"
|
|
12
12
|
scriptctl replace acR8cV4n --from "台下掌声雷动" --to "掌声骤停" \
|
|
13
|
-
|
|
13
|
+
-p "$SCRIPT"
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
V4 查询可以使用 1-based `@` 序号,但修改必须使用正式 ID。V3 查询返回原有的
|
|
@@ -21,8 +21,8 @@ V4 查询可以使用 1-based `@` 序号,但修改必须使用正式 ID。V3
|
|
|
21
21
|
V4 先运行 dry-run,读取完整目标和 `plan_digest`,再用相同命令 apply:
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
|
-
scriptctl replace
|
|
25
|
-
scriptctl replace
|
|
24
|
+
scriptctl replace -i 'acR8cV4n..acT2fG6z' --from "。" --to "!"
|
|
25
|
+
scriptctl replace -i 'acR8cV4n..acT2fG6z' --from "。" --to "!" \
|
|
26
26
|
--apply --plan sha256:...
|
|
27
27
|
```
|
|
28
28
|
|
|
@@ -37,8 +37,8 @@ scene-ref scnK6wT3c actA3kP9x --state default --state stB4xR8p
|
|
|
37
37
|
```
|
|
38
38
|
|
|
39
39
|
```bash
|
|
40
|
-
scriptctl do edits.txt
|
|
41
|
-
scriptctl do edits.txt --apply --plan sha256:...
|
|
40
|
+
scriptctl do edits.txt -p "$SCRIPT"
|
|
41
|
+
scriptctl do edits.txt --apply --plan sha256:... -p "$SCRIPT"
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
`do` 整体解析、修改和校验;任一行失败时不落盘。
|
|
@@ -3,25 +3,25 @@
|
|
|
3
3
|
适用:有外部素材要**转成 Script v4 并入库**。统一入口 `scriptctl ingest`,按 source 类型自动分流文本 / 视频;两条管线最终都产出 v4 `script.json`。视频、小说和非标准剧本统一执行 [production-writing-standard.md](production-writing-standard.md)。
|
|
4
4
|
|
|
5
5
|
```
|
|
6
|
-
ingest
|
|
6
|
+
ingest -s <file|dir> → 标准化复核 → view / ingest status → publish
|
|
7
7
|
(抽取,产 workspace/script.json) (内容完成门) (自查/看进度) (校验+入库)
|
|
8
8
|
```
|
|
9
9
|
|
|
10
10
|
- 支持输入:**文本** txt / md / docx;**视频** 单个正片文件或**分集目录**(需 `GEMINI_API_KEY`)。pdf/json/xlsx 会被拒。
|
|
11
|
-
- `ingest` **不入库**:只产 `workspace/script.json`(默认工作区 `workspace`,可
|
|
12
|
-
- 产物随后就是普通剧本:任何读写动词加
|
|
11
|
+
- `ingest` **不入库**:只产 `workspace/script.json`(默认工作区 `workspace`,可 `-w` 改)。入库是独立的 `publish`。
|
|
12
|
+
- 产物随后就是普通剧本:任何读写动词加 `-p workspace/script.json` 即可精修。
|
|
13
13
|
|
|
14
14
|
## 一、抽取 `ingest`
|
|
15
15
|
|
|
16
16
|
```bash
|
|
17
17
|
# 文本
|
|
18
|
-
scriptctl ingest
|
|
18
|
+
scriptctl ingest -s uploads/剧本.docx
|
|
19
19
|
# 视频(分集目录,文件名带集号;单文件也行)
|
|
20
|
-
scriptctl ingest
|
|
20
|
+
scriptctl ingest -s uploads/正片/
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
常用 flag:
|
|
24
|
-
-
|
|
24
|
+
- `-w <dir>`:工作区根(manifest + 各 pass 目录 + 产物)。**不传默认 `<cwd>/workspace`**;显式传可放别处。`view` / `ingest status` 使用同一 workspace;publish 用 `-p <workspace>/script.json`。
|
|
25
25
|
- `--concurrency <n>`:文本 fanout 并发,默认 30。视频逐集串行。
|
|
26
26
|
- `--fps <n>`:视频采样帧率(>1 解锁亚秒级时间码)。默认 3。
|
|
27
27
|
- `--force`:**同源**重跑,清掉产物重来(**不能换源**)。
|
|
@@ -43,21 +43,21 @@ scriptctl ingest --source-path uploads/正片/
|
|
|
43
43
|
`ingest` 生成且 `validate` 通过只代表结构与引用合法。publish 前按 [production-writing-standard.md](production-writing-standard.md) 逐集复核:
|
|
44
44
|
|
|
45
45
|
1. 用 `actors / locations / props / states` 检查资产、去重、importance 和持久视觉状态。
|
|
46
|
-
2. 用 `scenes
|
|
47
|
-
3. 用 `actions
|
|
46
|
+
2. 用 `scenes -i <ep>` 检查唯一地点、场界、蒙太奇顺序和状态变化边界。
|
|
47
|
+
3. 用 `actions -i <ep>` 检查说话人、群体发声、人物真名、动作链和可拍摄性。
|
|
48
48
|
4. 视频对照画面与声音;文本对照原文,确认对白逐字保真,事实、因果、顺序、动作结果和状态没有改变或补造。
|
|
49
|
-
5. 运行 `audit-assets
|
|
49
|
+
5. 运行 `audit-assets -p workspace/script.json`,查看 `asset-audit.json` 中的人物身份重复、同义状态、未使用/落单状态、重复地点和道具建议。不要仅凭名称相似或低频就合并、删除。
|
|
50
50
|
6. 用 scriptctl 读写动词修正 `workspace/script.json`,再次运行 `validate` 和 `audit-assets`,完成内容复核后再 publish。
|
|
51
51
|
|
|
52
52
|
## 三、看进度 / 自查
|
|
53
53
|
|
|
54
54
|
```bash
|
|
55
55
|
scriptctl ingest status # 人读:kind / state / 各 pass 进度(transcribe 40/57 (2 failed) ...)
|
|
56
|
-
scriptctl ingest status
|
|
56
|
+
scriptctl ingest status -j # 机器:.status = {kind,state,phase,passes[],units,validation,errors[]}
|
|
57
57
|
scriptctl view # 生成 workspace/review.html(视频版可点击定位到画面)
|
|
58
58
|
scriptctl view --watch [--port N]# 实时监听面板:分阶段进度条 + 逐集 context/决策 + 产物树,自动刷新(跑中也能开)。🔴 仅本地用,**沙箱内不要用**(起阻塞服务+开浏览器,会挂住;沙箱看进度用 `ingest status`)
|
|
59
|
-
scriptctl audit-assets
|
|
60
|
-
scriptctl summary
|
|
59
|
+
scriptctl audit-assets -p workspace/script.json # 全剧资产一致性复核;结果写 asset-audit.json
|
|
60
|
+
scriptctl summary -p workspace/script.json # 抽完当普通剧本读
|
|
61
61
|
```
|
|
62
62
|
|
|
63
63
|
`state`:`empty`(没开始)/ `incomplete`(在跑或中断、无硬错,重跑续)/ `failed`(有失败单元或校验没过)/ `ready`(`script.json` 生成且 v4 结构校验通过)。`validation.json` 的 production/asset-audit warning 标出仍需复核的问题,`asset-audit.json` 保存完整证据和建议。进度从工作区真实文件推导;它报的是管线事实,资产合并结论和源素材一致性仍由复核完成门确认。
|
|
@@ -71,7 +71,7 @@ scriptctl summary --script-path workspace/script.json # 抽完当普通剧本
|
|
|
71
71
|
| `INGEST_NORMALIZE_INCOMPLETE`(文本)<br>`INGEST_TRANSCRIBE_/CORRECT_/SPEAKER_INCOMPLETE`(视频) | 部分单元失败,留下 `passN/*.error.json` sidecar | **直接重跑 `scriptctl ingest`(同 source、同 workspace)**——从 checkpoint 续,只补失败单元。跑完 `ingest status` 看还剩几个,多跑几次到收敛 |
|
|
72
72
|
| `INGEST_SERIAL_FAILED`(文本串行 govern) | 某集串行解析连试几次仍失败(模型抖动) | **直接重跑**,从该集续——前面各集已缓存不重跑 |
|
|
73
73
|
| `INGEST_PIPELINE_MISMATCH` | 工作区的管线版本与当前版本不同 | 确认 source 未变化后,使用同一 source、同一 workspace 加 `--force` 完整重建 checkpoint |
|
|
74
|
-
| `INGEST_SOURCE_MISMATCH` | 工作区是别的 source 建的 | 换一个新的
|
|
74
|
+
| `INGEST_SOURCE_MISMATCH` | 工作区是别的 source 建的 | 换一个新的 `-w`,**别 `--force` 硬覆盖** |
|
|
75
75
|
| `INGEST_VALIDATION_FAILED` | 最终校验没过 | 看 `workspace/validation.json` 的具体报错,修复后再 `publish` |
|
|
76
76
|
| 持续 401/403/404 / 模型路由错 | 网关/密钥/模型环境问题(不是抖动,重跑也不好) | 如实告诉用户,别反复空跑、别编造成功。视频需 `GEMINI_API_KEY` |
|
|
77
77
|
|
|
@@ -80,18 +80,18 @@ scriptctl summary --script-path workspace/script.json # 抽完当普通剧本
|
|
|
80
80
|
## 五、入库 `publish`
|
|
81
81
|
|
|
82
82
|
```bash
|
|
83
|
-
scriptctl publish
|
|
84
|
-
scriptctl publish
|
|
83
|
+
scriptctl publish -p workspace/script.json
|
|
84
|
+
scriptctl publish -p workspace/script.json --project-group-no 123
|
|
85
85
|
```
|
|
86
86
|
|
|
87
|
-
- `publish` 读本地
|
|
87
|
+
- `publish` 读本地 `-p`(默认 `workspace/script.json`),按显式版本再次校验,通过才发布。
|
|
88
88
|
- 沙箱里转完**必须 publish**,否则后端/前端看不到剧本。
|
|
89
89
|
- 已管理工作副本 publish 采用 local-wins:CAS/网络失败后重拉 snapshot、重算 diff 并重试,最终远端内容以本地稿为准。
|
|
90
90
|
- 已管理且内容未变时 publish 本地直接 no-op,不发网络请求。服务端不保存 requestId,也不提供 publish 幂等重试。
|
|
91
91
|
|
|
92
92
|
## 六、复杂场景怎么接
|
|
93
93
|
|
|
94
|
-
- **转完先精修再入库**:`ingest` → 用
|
|
94
|
+
- **转完先精修再入库**:`ingest` → 用 `-p workspace/script.json` 跑读写动词修(改归属、并角色、标龙套、补造型……)→ `publish`。
|
|
95
95
|
- **入库后再改**:继续编辑同一个受管本地文件再 publish;若工作副本不在,先 checkout,不能直接对 DB 跑原子命令。
|
|
96
96
|
- **视频复核**:`view` 出的 `review.html` 视频版支持点击台词跳到对应画面时间码,逐场核对发声源/造型。
|
|
97
97
|
- **超大剧集(几十集)**:并发默认已调好;失败就重跑到 `ingest status` 显示 `ready`。花名册归并只跑一次并复用,重跑很快。
|
|
@@ -99,8 +99,8 @@ scriptctl publish --script-path workspace/script.json --project-group-no 123
|
|
|
99
99
|
|
|
100
100
|
## 七、抽完后的读写
|
|
101
101
|
|
|
102
|
-
抽取产物就是标准 v4 剧本,用 SKILL.md 里所有读写能力精修(目标指
|
|
103
|
-
- `summary` / `episodes` 看整本 + 分集梗概;`actions
|
|
102
|
+
抽取产物就是标准 v4 剧本,用 SKILL.md 里所有读写能力精修(目标指 `-p workspace/script.json`;远端稿先 checkout):
|
|
103
|
+
- `summary` / `episodes` 看整本 + 分集梗概;`actions -i <ep>` 带 timestamp 看节奏。
|
|
104
104
|
- `states <actor>` 看造型弧线;`actors --counts` 看出场频次决定 `importance`。
|
|
105
|
-
- 归属/造型修正:`dialogue <at>
|
|
105
|
+
- 归属/造型修正:`dialogue <at> -a/-k`、`scene-ref <ep/scn> <kind:id> --state`。
|
|
106
106
|
- 梗概/世界观:`synopsis` / `synopsis generate`(LLM 批量)/ `worldview`。
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
先反查旧 state:
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
|
-
scriptctl refs actA3kP9x/stB4xR8p
|
|
6
|
+
scriptctl refs actA3kP9x/stB4xR8p -p "$SCRIPT"
|
|
7
7
|
```
|
|
8
8
|
|
|
9
9
|
## Script v4
|
|
@@ -13,7 +13,7 @@ speaker 上同步替换:
|
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
15
|
scriptctl state-delete actA3kP9x/stB4xR8p \
|
|
16
|
-
--strategy replace --replacement default
|
|
16
|
+
--strategy replace --replacement default -p "$SCRIPT"
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
`--strategy remove` 会从每个集合移除该 state;若任何集合将变为空,命令拒绝,
|
|
@@ -26,13 +26,13 @@ scriptctl state-delete actA3kP9x/stB4xR8p \
|
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
28
|
scriptctl state-delete actor:act_001/st_002 \
|
|
29
|
-
--strategy replace --replacement st_001
|
|
29
|
+
--strategy replace --replacement st_001 -p "$SCRIPT"
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
## 核验
|
|
33
33
|
|
|
34
34
|
```bash
|
|
35
|
-
scriptctl refs <旧-state-address>
|
|
36
|
-
scriptctl refs <新-state-address>
|
|
37
|
-
scriptctl validate
|
|
35
|
+
scriptctl refs <旧-state-address> -p "$SCRIPT"
|
|
36
|
+
scriptctl refs <新-state-address> -p "$SCRIPT"
|
|
37
|
+
scriptctl validate -p "$SCRIPT"
|
|
38
38
|
```
|