@gitruck/cli 1.1.1 → 1.1.3

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/package.json CHANGED
@@ -1,67 +1,67 @@
1
- {
2
- "name": "@gitruck/cli",
3
- "version": "1.1.1",
4
- "description": "同合云成片流水线 CLI —— agent 驱动云端任务、产物拉回本地、三方工程文件(客户端/剪映/PR)互通。",
5
- "license": "MIT",
6
- "author": "Gitruck (同合云)",
7
- "repository": {
8
- "type": "git",
9
- "url": "git+https://github.com/Gitruck/cli.git"
10
- },
11
- "homepage": "https://github.com/Gitruck/cli#readme",
12
- "bugs": {
13
- "url": "https://github.com/Gitruck/cli/issues"
14
- },
15
- "type": "module",
16
- "bin": {
17
- "gtrk": "dist/index.js"
18
- },
19
- "files": [
20
- "dist",
21
- "assets",
22
- "skills",
23
- "contracts",
24
- "AGENT.md",
25
- "README.md",
26
- "README.en.md",
27
- "LICENSE",
28
- "CHANGELOG.md"
29
- ],
30
- "engines": {
31
- "node": ">=20.6"
32
- },
33
- "publishConfig": {
34
- "access": "public",
35
- "registry": "https://registry.npmjs.org/"
36
- },
37
- "keywords": [
38
- "gitruck",
39
- "同合云",
40
- "video",
41
- "oral-cut",
42
- "口播剪辑",
43
- "cli",
44
- "jianying",
45
- "剪映",
46
- "agent"
47
- ],
48
- "scripts": {
49
- "gtrk": "bun run src/index.ts",
50
- "build": "bun build ./src/index.ts --target=node --minify --outfile dist/index.js",
51
- "typecheck": "tsc --noEmit",
52
- "prepublishOnly": "npm run typecheck && npm test && bun run build",
53
- "test": "esbuild src/lib/compliance-notice.ts src/lib/first-run-tutorial.ts src/lib/desktop-client-hint.ts src/lib/chunk-upload.ts src/lib/upload-cache.ts src/lib/upload-submit.ts src/lib/render.ts src/lib/cloud.ts src/lib/materialize.ts src/lib/jianying.ts src/lib/clip-brief.ts src/lib/media.ts src/lib/projection.ts src/lib/reproject.ts src/lib/splitdoc.ts src/lib/gtrk-writeback.ts src/lib/gtrk-patch.ts src/lib/column-config.ts src/lib/matrix.ts src/lib/matrix-material.ts src/lib/matrix-fetch.ts src/lib/matrix-lay.ts src/lib/arrange-metering.ts src/lib/arrange-wire.ts src/lib/arrange-apply.ts src/lib/arrange-client.ts src/lib/arrange-gate.ts src/lib/arrange-qc.ts src/lib/arrange-qc-bind.ts src/lib/rate-limit-wait.ts src/lib/embed-client.ts src/lib/describe.ts src/lib/local-index.ts src/lib/index-decode.ts src/lib/local-search.ts src/lib/qc.ts src/lib/alignment-qc.ts src/lib/bgm-history.ts src/lib/image-move.ts src/lib/cloud-render-guard.ts src/lib/material-integrity.ts src/lib/solid-png.ts src/lib/mg-lint.ts src/lib/mg-lay.ts src/lib/mg-render.ts src/lib/tool-descriptors.ts src/lib/tool-runner.ts src/lib/tool-pricing.ts src/lib/transcript.ts src/lib/runtime-assets.ts src/lib/subtitle-lay.ts src/lib/audio-align.ts src/lib/audio-tighten.ts --bundle --platform=node --format=esm --external:bun:sqlite --outdir=.test-build --out-extension:.js=.mjs && esbuild src/commands/split.ts --bundle --platform=node --format=esm --outdir=.test-build --out-extension:.js=.mjs && esbuild src/commands/patch.ts --bundle --platform=node --format=esm --external:commander --outfile=.test-build/patch-cmd.mjs && esbuild src/commands/matrix.ts --bundle --platform=node --format=esm --external:bun:sqlite --outfile=.test-build/matrix-cmd.mjs && esbuild src/commands/mg.ts --bundle --platform=node --format=esm --outfile=.test-build/mg-cmd.mjs && esbuild src/commands/tool.ts --bundle --platform=node --format=esm --outfile=.test-build/tool-cmd.mjs && esbuild src/commands/transcript.ts --bundle --platform=node --format=esm --outfile=.test-build/transcript-cmd.mjs && esbuild src/commands/project.ts --bundle --platform=node --format=esm --outfile=.test-build/project-cmd.mjs && esbuild src/commands/audio.ts --bundle --platform=node --format=esm --outfile=.test-build/audio-cmd.mjs && esbuild src/commands/subtitle.ts --bundle --platform=node --format=esm --outfile=.test-build/subtitle-cmd.mjs && esbuild src/commands/feedback.ts --bundle --platform=node --format=esm --outfile=.test-build/feedback-cmd.mjs && esbuild src/commands/music-visualizer.ts --bundle --platform=node --format=esm --external:commander --outfile=.test-build/music-visualizer-cmd.mjs && esbuild src/commands/long2short.ts --bundle --platform=node --format=esm --external:commander --outfile=.test-build/long2short-cmd.mjs && esbuild src/commands/oralcut.ts --bundle --platform=node --format=esm --external:commander --outfile=.test-build/oralcut-cmd.mjs && esbuild src/commands/skills.ts --bundle --platform=node --format=esm --outfile=.test-build/skills-cmd.mjs && esbuild src/commands/qc.ts --bundle --platform=node --format=esm --external:commander --external:bun:sqlite --outfile=.test-build/qc-cmd.mjs && esbuild src/lib/convert/ir_to_jsx.ts src/lib/convert/ir_to_am.ts src/lib/convert/ir_to_nv.ts src/lib/convert/am_parse.ts src/lib/convert/nv_parse.ts src/lib/convert/parse.ts src/lib/convert/download.ts src/lib/convert/bake_ops.ts --bundle --platform=node --format=esm --outdir=.test-build/convert --out-extension:.js=.mjs && esbuild src/lib/mad/selector.ts src/lib/mad/beat.ts src/lib/mad/scan.ts src/lib/mad/data.ts src/lib/mad/pool.ts src/lib/mad/cloud-beat.ts src/lib/mad/mad.ts --bundle --platform=node --format=esm --outdir=.test-build/mad --out-extension:.js=.mjs && node --import ./test/helpers/test-home.mjs --test \"test/*.test.mjs\"",
54
- "openspec:gate": "node openspec/gate.mjs"
55
- },
56
- "devDependencies": {
57
- "@xmldom/xmldom": "^0.9.6",
58
- "bun-types": "^1.1.0",
59
- "commander": "^12.1.0",
60
- "esbuild": "^0.28.1",
61
- "typescript": "^5.6.0"
62
- },
63
- "dependencies": {
64
- "hash-wasm": "^4.12.0",
65
- "jszip": "^3.10.1"
66
- }
67
- }
1
+ {
2
+ "name": "@gitruck/cli",
3
+ "version": "1.1.3",
4
+ "description": "同合云成片流水线 CLI —— agent 驱动云端任务、产物拉回本地、三方工程文件(客户端/剪映/PR)互通。",
5
+ "license": "MIT",
6
+ "author": "Gitruck (同合云)",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/Gitruck/cli.git"
10
+ },
11
+ "homepage": "https://github.com/Gitruck/cli#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/Gitruck/cli/issues"
14
+ },
15
+ "type": "module",
16
+ "bin": {
17
+ "gtrk": "dist/index.js"
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "assets",
22
+ "skills",
23
+ "contracts",
24
+ "AGENT.md",
25
+ "README.md",
26
+ "README.en.md",
27
+ "LICENSE",
28
+ "CHANGELOG.md"
29
+ ],
30
+ "engines": {
31
+ "node": ">=20.6"
32
+ },
33
+ "publishConfig": {
34
+ "access": "public",
35
+ "registry": "https://registry.npmjs.org/"
36
+ },
37
+ "keywords": [
38
+ "gitruck",
39
+ "同合云",
40
+ "video",
41
+ "oral-cut",
42
+ "口播剪辑",
43
+ "cli",
44
+ "jianying",
45
+ "剪映",
46
+ "agent"
47
+ ],
48
+ "scripts": {
49
+ "gtrk": "bun run src/index.ts",
50
+ "build": "bun build ./src/index.ts --target=node --minify --outfile dist/index.js",
51
+ "typecheck": "tsc --noEmit",
52
+ "prepublishOnly": "npm run typecheck && npm test && bun run build",
53
+ "test": "esbuild src/lib/compliance-notice.ts src/lib/first-run-tutorial.ts src/lib/desktop-client-hint.ts src/lib/chunk-upload.ts src/lib/upload-cache.ts src/lib/upload-submit.ts src/lib/render.ts src/lib/cloud.ts src/lib/materialize.ts src/lib/jianying.ts src/lib/clip-brief.ts src/lib/media.ts src/lib/projection.ts src/lib/reproject.ts src/lib/splitdoc.ts src/lib/gtrk-writeback.ts src/lib/gtrk-patch.ts src/lib/column-config.ts src/lib/matrix.ts src/lib/matrix-material.ts src/lib/matrix-fetch.ts src/lib/matrix-lay.ts src/lib/arrange-metering.ts src/lib/arrange-wire.ts src/lib/arrange-apply.ts src/lib/arrange-client.ts src/lib/arrange-gate.ts src/lib/arrange-decision-pin.ts src/lib/arrange-qc.ts src/lib/arrange-qc-bind.ts src/lib/rate-limit-wait.ts src/lib/embed-client.ts src/lib/describe.ts src/lib/local-index.ts src/lib/index-decode.ts src/lib/local-search.ts src/lib/qc.ts src/lib/alignment-qc.ts src/lib/bgm-history.ts src/lib/image-move.ts src/lib/cloud-render-guard.ts src/lib/material-integrity.ts src/lib/solid-png.ts src/lib/mg-lint.ts src/lib/mg-lay.ts src/lib/mg-render.ts src/lib/tool-descriptors.ts src/lib/tool-runner.ts src/lib/tool-pricing.ts src/lib/transcript.ts src/lib/runtime-assets.ts src/lib/subtitle-lay.ts src/lib/audio-align.ts src/lib/audio-tighten.ts --bundle --platform=node --format=esm --external:bun:sqlite --outdir=.test-build --out-extension:.js=.mjs && esbuild src/commands/split.ts --bundle --platform=node --format=esm --outdir=.test-build --out-extension:.js=.mjs && esbuild src/commands/patch.ts --bundle --platform=node --format=esm --external:commander --outfile=.test-build/patch-cmd.mjs && esbuild src/commands/matrix.ts --bundle --platform=node --format=esm --external:bun:sqlite --outfile=.test-build/matrix-cmd.mjs && esbuild src/commands/mg.ts --bundle --platform=node --format=esm --outfile=.test-build/mg-cmd.mjs && esbuild src/commands/tool.ts --bundle --platform=node --format=esm --outfile=.test-build/tool-cmd.mjs && esbuild src/commands/transcript.ts --bundle --platform=node --format=esm --outfile=.test-build/transcript-cmd.mjs && esbuild src/commands/project.ts --bundle --platform=node --format=esm --outfile=.test-build/project-cmd.mjs && esbuild src/commands/audio.ts --bundle --platform=node --format=esm --outfile=.test-build/audio-cmd.mjs && esbuild src/commands/subtitle.ts --bundle --platform=node --format=esm --outfile=.test-build/subtitle-cmd.mjs && esbuild src/commands/feedback.ts --bundle --platform=node --format=esm --outfile=.test-build/feedback-cmd.mjs && esbuild src/commands/music-visualizer.ts --bundle --platform=node --format=esm --external:commander --outfile=.test-build/music-visualizer-cmd.mjs && esbuild src/commands/long2short.ts --bundle --platform=node --format=esm --external:commander --outfile=.test-build/long2short-cmd.mjs && esbuild src/commands/oralcut.ts --bundle --platform=node --format=esm --external:commander --outfile=.test-build/oralcut-cmd.mjs && esbuild src/commands/skills.ts --bundle --platform=node --format=esm --outfile=.test-build/skills-cmd.mjs && esbuild src/commands/qc.ts --bundle --platform=node --format=esm --external:commander --external:bun:sqlite --outfile=.test-build/qc-cmd.mjs && esbuild src/lib/convert/ir_to_jsx.ts src/lib/convert/ir_to_am.ts src/lib/convert/ir_to_nv.ts src/lib/convert/am_parse.ts src/lib/convert/nv_parse.ts src/lib/convert/parse.ts src/lib/convert/download.ts src/lib/convert/bake_ops.ts --bundle --platform=node --format=esm --outdir=.test-build/convert --out-extension:.js=.mjs && esbuild src/lib/mad/selector.ts src/lib/mad/beat.ts src/lib/mad/scan.ts src/lib/mad/data.ts src/lib/mad/pool.ts src/lib/mad/cloud-beat.ts src/lib/mad/mad.ts --bundle --platform=node --format=esm --outdir=.test-build/mad --out-extension:.js=.mjs && node --import ./test/helpers/test-home.mjs --test \"test/*.test.mjs\"",
54
+ "openspec:gate": "node openspec/gate.mjs"
55
+ },
56
+ "devDependencies": {
57
+ "@xmldom/xmldom": "^0.9.6",
58
+ "bun-types": "^1.1.0",
59
+ "commander": "^12.1.0",
60
+ "esbuild": "^0.28.1",
61
+ "typescript": "^5.6.0"
62
+ },
63
+ "dependencies": {
64
+ "hash-wasm": "^4.12.0",
65
+ "jszip": "^3.10.1"
66
+ }
67
+ }
@@ -142,6 +142,8 @@ description: B-roll 检索铺轨编排手册——成片管线里第一个铺的
142
142
  | 落轨前先质检画音对齐 | `--arrange-qc` | 开关 · 缺省关 | 只查各 beat 的**卡点句**(span.from 领衔句):画面没给到稿句说的东西就换候选重排,最多 2 轮,到限即交付 + 如实登记残余。零渲染。⚠️ 按帧计费(每卡点句 1 帧/轮),跑前报预估求确认。**默认关,用户没说就别带**。拿不到卡点句(无 dispatch / 重投影降级)时会明说「跳过 ≠ 查过」,别把那条日志读成通过 |
143
143
  | 云端编排本次上限 | `--arrange-cost-cap <n>` | 正整数 · 不限 | 超限服务端**前置拒绝**、零执行零计费(不是跑一半掐断)。只在 `--arrange shadow\|cloud` 时有意义 |
144
144
  | 先估价再决定跑不跑 | `--arrange-estimate-only` | 开关 · 缺省关 | 走到云端编排的计价确认那一步就停:报出编排量后**成功**返回(`ok:true` + `estimateOnly:true`,不是「被拒绝」),零云端调用、工程零改动。机读值在 `lay.arrange.units` 与 `lay.arrange.scale`。⚠️ 它省的是**云端那一次调用与其计费**(及其后的下载落轨),不是整条链——工程/plan/重投影照样要走。素材矩阵路会报 `applicable:false` 而**不是 0**。与 `--yes` 同给时以它为准 |
145
+ | 云端编排请求体存证 | `--dump-request <file>` | 路径 · 缺省不写 | **排障专用,用户没提就别带。** 把**实际上行的**云端编排请求体逐字节落到该文件——服务端**不保存 plan 全文**,所以复现一次调用只能靠它。⚠️ **不能指向工程目录内**(工程会被打包拷走,而它含 beat 名与检索词),传了会报参数错;开 `--arrange-qc` 时每轮各一份(第 N 轮加 `.roundN`)。回执在 `lay.arrange_run.dump_request`。⚠️ 转交这份文件前 MUST 先告诉用户里面有什么,别替他做决定 |
146
+ | 外发调参仪表 | `--explain` | 开关 · 缺省关 | 缺省 `lay.dedup` 只出 `emptySlots`(判素材池够不够用,upsell 判据就是它);本开关再补 `emptySlotsByRefine` / `adjacentWaived` / `hotSlotsPlaced` / `blurrySlotsPlaced` 四个**调参仪表**,人读日志同口径。**不改任何决策**,工程产物逐字节不变。⚠️ 用户问「为什么这颗抖/糊/空」时才带,别缺省开着刷噪音 |
145
147
  | 不要黑底垫轨 | `--no-black-bed` | 开关 · 默认铺 | 黑底按 beat 包络整条铺,B-roll 期间遮口播 |
146
148
  | 已编辑轨强铺逃生门 | `--force-relay` | 开关 · 关 | 用户明确点头才带;raw 登记删除不可恢复 |
147
149
  | 同素材彻底不二用 | `--dedup-scope material` | `scene`(默认)\| `material` | 收严会加剧空洞,先看 `lay.dedup.emptySlots` |
@@ -247,7 +249,7 @@ description: B-roll 检索铺轨编排手册——成片管线里第一个铺的
247
249
  | 消费(编辑后的)plan 铺轨 | `gtrk matrix lay --project <目录>` | 目录 · — | 读 `<目录>/split/broll-plan.json`,白名单校验后按 **plan 现值**铺轨(不重新检索、零检索开销) |
248
250
  | 显式指定 plan 文件 | `--plan <path>` | 路径 · 上述默认 | 配方 C 自己组的 plan 从这进。⚠️ 组的时候把检索返回的 `results` 条目**原样搬**——`cuts` / `motion` 住在 `segments[]` 里面,自己重写 segments 就把它们丢了(后果:端点残片收缩空转、高运动降权失效,见配方 C 要点) |
249
251
  | 美观度参与排序 | `--mark-weight <w>` | 浮点 0–1 · `0`(关闭) | 仅 `matrix lay`:候选融合分 = `sim×(1-w)+(mark/100)×w`,mark 取 describe 理解缓存(素材内**就近帧**命中);无缓存候选**中性**(融合分=sim,不惩罚不加分、绝不变相剔除);score 地板仍只看原始 sim。**零件不裁定:默认关(0 时排序与产物逐字节零回归),开不开、开多大由配方/你裁定**——先 describe 过一轮才有 mark 可用(配方 B ② 之后开才有意义),开启时结果 JSON `lay` 含 `mark_weight/mark_hit/mark_neutral` |
250
- | 其余铺轨参数 | `--lay/--score-floor/--cut-align/--gap-fill/--arrange/--arrange-cost-cap/--arrange-estimate-only/--arrange-qc/--no-black-bed/--force-relay/--dedup-scope/--yes/--no-image-broll` | 同主命令 | 语义一致 |
252
+ | 其余铺轨参数 | `--lay/--score-floor/--cut-align/--gap-fill/--arrange/--arrange-cost-cap/--arrange-estimate-only/--arrange-qc/--dump-request/--explain/--no-black-bed/--force-relay/--dedup-scope/--yes/--no-image-broll` | 同主命令 | 语义一致 |
251
253
 
252
254
  ## plan 编辑口径(法定通道的边界)
253
255
 
@@ -345,7 +347,7 @@ gtrk matrix --project "<split 产物目录>" [--lay N] [--score-floor F] [--top-
345
347
  ```
346
348
 
347
349
  - `--json`:人读日志走 stderr,成功时 stdout 只有一行结果 JSON:
348
- `{ ok, mode:"plan", memberType, columnId?, planPath, lay:{ refused, laidTracks:[…], laidClips, removedTracks:[…], keptEditedTracks:[…], blackTrack, blackBedHoleSec, blackBedHoles:[…], dedup:{scope,emptySlots,adjacentWaived}, signal_coverage?:{mark?:{hit,neutral,coverage},highlight?:{hit,neutral,coverage}}, pinned?:{requested,placed,yielded}, anchors?:{planned,pinned,degraded}, anchor_details?:[{beat,keyword,at_sec,track_st,clip_id,status,reason?}], downloads:{preview,raw,reused,failed} }, integrity:{…}, reprojection:{…}, counts:{ beats, queries, results, errors } }`
350
+ `{ ok, mode:"plan", memberType, columnId?, planPath, lay:{ refused, laidTracks:[…], laidClips, removedTracks:[…], keptEditedTracks:[…], blackTrack, blackBedHoleSec, blackBedHoles:[…], dedup:{scope,emptySlots}(**调参仪表四件只在 `--explain` 时才出**), signal_coverage?:{mark?:{hit,neutral,coverage},highlight?:{hit,neutral,coverage}}, pinned?:{requested,placed,yielded}, anchors?:{planned,pinned,degraded}, anchor_details?:[{beat,keyword,at_sec,track_st,clip_id,status,reason?}], arrange_run?:{calls,source,mode,fallback?,units_total,billed,idempotency_recorded?,diff_count?,diffs?:[…],rounds:[{round,mode,source,fallback?,units?,idempotent_replay?,idempotency_recorded?,diff_count?}], dump_request?, dump_request_files?}, downloads:{preview,raw,reused,failed} }, integrity:{…}, reprojection:{…}, counts:{ beats, queries, results, errors } }`
349
351
  (`--lay 0` 时无 `lay`;`search` 模式 `{ ok, mode:"search", results:[…], counts, outPath? }`;`matrix lay` 模式 `mode:"lay"` 且 `counts.queries` 恒 0——零检索;`matrix describe` 模式 `{ ok, mode:"describe", described, cached, called, failed, credits_estimated, exempt?, planPath?/injected?, describe_coverage?:{frames,segments,ratio,image_candidates}, items? }`)
350
352
  - **拒铺结局**(候选轨已被用户编辑):stdout 出 `{ ok:false, refused:[…], reason:"tracks_edited", planReusable:true, … }` 且非 0 退出——不是命令失败,plan 已产出,处置见下表。
351
353
  - **命令失败**(缺派单、鉴权失败、全部 query 失败、参数越界、坏 plan 被 lay 拒)→ 非 0 退出、报错在 stderr、stdout 无 JSON。先看退出码,把 stderr 报错如实回给用户。
@@ -367,6 +369,16 @@ gtrk matrix --project "<split 产物目录>" [--lay N] [--score-floor F] [--top-
367
369
  覆盖率低不等于「没 describe」——一个素材通常只有一个时间点有描述行,离它太远(>15s)的段就近命中不上,**素材越长覆盖率越低**。所以:`coverage` 为 0 ⇒ 本片确实没理解过,去跑 `matrix describe --plan`;`coverage` 偏低但非 0 ⇒ **重跑 describe 不会改善**,如实告诉用户「信号只对这 N% 的候选段起了作用,其余按中性、排序主要还是语义分」,别让他以为加权在全面生效。
368
370
  - `lay.anchors` / `lay.anchor_details`(拆分稿圈了关键词锚才出现):`planned` 钉位数 / `pinned` 用户钉选占锚槽数 / `degraded` 降级数——`degraded` 非零要按 `anchor_details` 指名哪个关键词没锚上及原因(无合格命中/文本漂移/窗口不足),提示用户该处「听到关键词看到画面」的卡点没兑现、可换 query 或补素材后重跑。
369
371
  - `lay.downloads`:`raw` 原片回落 / `failed` 掉槽位非零时提一句。
372
+ - `lay.arrange_run`(**本地素材路**才出现;素材矩阵路与总闸压回本地时**整键缺席**):这一轮**云端编排**的账与归因,MUST 主动读、别当噪声跳过。⚠️ 它与 `--arrange-estimate-only` 出的 `lay.arrange` **不是同一个东西**:那个是零调用的**本地预估**,这个是**服务端复算的实收量**,MUST NOT 拿去互相核账。
373
+ - `fallback:"self_check_failed"` ⇒ **MUST 主动告诉用户**:这一轮云端产物被弃、已花掉 `units_total` 编排量、成片走的是本地编排;并把 `diffs` 前几条贴给他 / 反馈给我们(`diffs` 是**全量**,机读面不截断)。成片**没问题**(`ok` 仍是 `true`),但这笔钱花得不明不白。
374
+ - `fallback:"decision_pin_mismatch"` ⇒ 两侧跑的**不是同一版决策算法**,产物不可比而非「算得不一样」。告诉用户服务端版本与本机期望版本这两个数,让他稍后重试;持续如此就反馈给我们。这一档**没有** `diffs`(根本没比过)。
375
+ - `fallback:"unreachable"/"rejected"/"malformed"` ⇒ 没拿到可用的云端产物;`diff_count`/`diffs` 会**一起缺席**(那是「压根没对拍成」,不是「对拍过且一致」)。
376
+ - `mode:"shadow"` ⇒ 成片走的**本来就是**本地产物(设计如此,不是回落、没出事),但云端那一次**照样计了费**⇒ MUST 如实报 `units_total`,**MUST NOT** 因为 `source:"local"` 就说「没走云端」。
377
+ - `units_total > 0` ⇒ 如实报花了多少;`billed:false` ⇒ 全部命中服务端幂等回放,本轮**零新增计费**,别吓唬用户。
378
+ - `idempotency_recorded:false` ⇒ 幂等登记没写成,**提示用户重发会重新计费**(别建议他「重跑一次试试」)。
379
+ - `rounds` **恒在**(开 `--arrange-qc` 时不止一条):逐轮的账在这里,`units_total` 已按轮累加并跳过回放轮。某轮的 `units` 缺席 = 那一轮「已计费但服务端没告诉我们计了多少」,**MUST NOT** 读成「那轮没花钱」。
380
+ - `dump_request`(只在带了 `--dump-request` 时出):上行请求体的落点。**服务端不留 plan 全文**,所以这份文件是复现这次调用的唯一凭据。写了不止一份时另出 `dump_request_files` 全量清单——**按它读,MUST NOT 自己按命名规则拼后几轮的路径**。
381
+ - 服务端**频率保护**(按 key 限流 / 相似请求指纹,同回 HTTP 429)⇒ CLI 先按限流窗口对齐等待并重试,仍不通过才落到 `fallback:"unreachable"`,**零执行零计费**。此时报错原文里带的是服务端说法(「频率保护」而非「端点不可达」)——MUST 照那句转述:**不是余额问题、也不是请求写错了**,隔一会儿再来,或先用 `--arrange-estimate-only` 只看规模。⚠️ MUST NOT 建议用户立刻连着重跑(那只会把窗口撑得更满)。
370
382
  - `integrity`(素材落盘自检,只在真写回过时出现):`dangling` 悬空引用全量清单;`danglingReferenced`(时间线上没素材可放)与 `danglingOrphan`(只挂在 materials 里)严重度差一个量级,**分开说**;`external` 绝对路径找不到文件另一档。告知不拦阻,别自己删素材。
371
383
  - 单 query 失败是局部化的(`counts.errors>0` 但 `ok:true`):如实说哪几段没检到。
372
384
  - 工程缺失/非 v1 → 告警跳过铺轨但仍产 plan(`lay` 字段缺失)。
@@ -417,7 +429,24 @@ gtrk matrix --project "<split 产物目录>" [--lay N] [--score-floor F] [--top-
417
429
  ⚠️ **异步等待的口子**:外部平台抽卡可能数天,严格串行会把后续无限期卡住。故进 ⑤ 的硬门是「**AI 片段已回铺 ∨ 用户明示先跳过**」。走「明示跳过」时 MUST 把**与 AI beat 相邻或重叠区间的 MG 颗粒**标记为「AI 回铺后待复查构图」并在收口时复述该清单,**MUST NOT 静默跳过**。
418
430
  - **`dispatch.ai_drama` 为空** → 三源已齐,直接进 **④ 全局抽帧检查画面构图**:对最终底轨抽帧看主体位置 / 安全区 / 画面朝向 / 明暗,**停下等用户确认构图无误**(这与刚才「挑选 B-roll」那次确认是两次不同的确认),过了才交棒 ⑤ `/gtrk-mg`。
419
431
  - `dispatch.mg` 也为空 → 无 MG 车道,④ 检查过后直接 `render` 收口。
420
- - 用户表示暂时只要 B-roll → 停在这,尊重他的节奏。
432
+ ### 逃生门:两种信号都要认(范围 + 节奏)
433
+
434
+ 上面的往下走是**默认**,但**用户表达了范围保留或节奏保留时 SHALL 停在这一步、SHALL NOT 自动交棒**。
435
+ 两者语义正交,认漏一个都会误冲:
436
+
437
+ - **范围信号 = 走多远**(我只要这一个产物):「暂时只要 B-roll」「B-roll 就这样,先不往下」「先不出片」。
438
+ - **节奏信号 = 怎么走**(每步停等我):**「逐步推进」**(本仓公约立法定名的正式模式名,
439
+ 定义就是「每步停等确认」,用户会照着这么说)、「一步步来」「先 X 然后我们再说」
440
+ 「我看看再定」「等我确认」。
441
+
442
+ ⚠️ **词表只是举例、不是白名单**——判据是「**用户表达了节奏/范围保留**」,换个说法照样得听懂。
443
+ 特别注意「先 X **然后**我们逐步推进」:用户明说了还要往下,**范围**逃生门逐字不成立,
444
+ 但**节奏**逃生门成立 ⇒ **停**。
445
+
446
+ 停下时**必须交代下一步是什么、他说一声就继续**(例:「B-roll 这腿定了。按你说的逐步来我先停在这,
447
+ 下一步是 AI 情景片段 / 全局抽帧检查构图,你说一声我就接着做」),别退化成事事请示。
448
+
449
+ **没有这两类信号时不改默认**:仍按上文自动往下走。
421
450
 
422
451
  > 原则:**agent 替用户跑 CLI / 接力 skill,用户只对话**——别让用户自己去终端敲下一条 gtrk 命令;但关键检查点务必停下等用户确认再进下一步——本车道涉及**两处**:① B-roll 铺完让用户挑选/调整;② ④ 全局抽帧检查后让用户确认构图。
423
452
 
@@ -169,7 +169,26 @@ gtrk mg --project "<split产物目录>" --json
169
169
 
170
170
  ★ **若你是走前置硬门 2 的「明示跳过 AI」进来的**:收口前 MUST 把那份「**AI 回铺后待复查构图**」清单复述给用户(哪几颗颗粒、对应哪几个 AI beat 区间),并说明「AI 片段回铺后这几颗可能要重产」。**MUST NOT 静默收口。**
171
171
 
172
- 除非用户表示只铺这一版 MG、暂不出片。
172
+ ### 逃生门:两种信号都要认(范围 + 节奏)
173
+
174
+ 上面的「别收工、顺势收口」是**默认**,但**用户表达了范围保留或节奏保留时 SHALL 停在铺完这一步、
175
+ SHALL NOT 自动上字幕出片**(`gtrk render` 还是计费/耗时动作,更不能替他拍板)。
176
+ 两者语义正交,认漏一个都会误冲:
177
+
178
+ - **范围信号 = 走多远**(我只要这一个产物):「只铺这一版 MG、暂不出片」「先不渲」「工程给我就行」。
179
+ - **节奏信号 = 怎么走**(每步停等我):**「逐步推进」**(本仓公约立法定名的正式模式名,
180
+ 定义就是「每步停等确认」,用户会照着这么说)、「一步步来」「先 X 然后我们再说」
181
+ 「我看看再定」「等我确认」。
182
+
183
+ ⚠️ **词表只是举例、不是白名单**——判据是「**用户表达了节奏/范围保留**」,换个说法照样得听懂。
184
+ 特别注意「先 X **然后**我们逐步推进」:用户明说了还要往下,**范围**逃生门逐字不成立,
185
+ 但**节奏**逃生门成立 ⇒ **停**。
186
+
187
+ 停下时**必须交代下一步是什么、他说一声就继续**(例:「MG 颗粒已叠铺完。按你说的逐步来我先停在这,
188
+ 下一步是上字幕 + `gtrk render` 出片,你说一声我就接着做」),别退化成事事请示。
189
+ ★ 上面那份「AI 回铺后待复查构图」清单**该复述照复述**——停下不等于不交代。
190
+
191
+ **没有这两类信号时不改默认**:仍按上文顺势收口。
173
192
 
174
193
  **渲完必看质检摘要**:`gtrk render` 收口后会自动扫一遍成片(闪帧 / 段内跳切 / 黑帧 / 冻结 / 爆音 / 静音 / 音画不同步),落 `<成片名>.qc.json` 并打摘要。**「严重」条目要如实转述给用户并给出路**,别把有缺陷的片子说成出好了:
175
194
 
@@ -137,7 +137,26 @@ gtrk oralcut "<毛片绝对路径>" [--script "<txt路径>"] [--preset steady|co
137
137
 
138
138
  ## 下一步(自动接力,别停在交工)
139
139
 
140
- 口播工程剪好只是成片一条龙的第一站。确认 `ok=true`、`files.gtrk[0]` 与 transcript 就绪后,**别停下等用户开口**——顺势接力到视觉拆分:触发 `/gtrk-splitter`(把这条工程 + transcript 拆成 beat 级分镜派单,agent 再跑 `gtrk split` 产 `dispatch.json`),驱动后续各车道生产+铺轨。一句话交代即推进:「口播工程已就绪,我接着把它拆成分镜派单」,除非用户表示只要这版剪辑工程、暂不往下。
140
+ 口播工程剪好只是成片一条龙的第一站。确认 `ok=true`、`files.gtrk[0]` 与 transcript 就绪后,**别停下等用户开口**——顺势接力到视觉拆分:触发 `/gtrk-splitter`(把这条工程 + transcript 拆成 beat 级分镜派单,agent 再跑 `gtrk split` 产 `dispatch.json`),驱动后续各车道生产+铺轨。一句话交代即推进:「口播工程已就绪,我接着把它拆成分镜派单」。
141
+
142
+ ### 逃生门:两种信号都要认(范围 + 节奏)
143
+
144
+ **用户表达了范围保留或节奏保留,就停在这一步、别自动接力。** 两者语义正交,认漏一个都会误冲:
145
+
146
+ - **范围信号 = 走多远**(我只要这一个产物):「只要这版剪辑工程」「先不往下」「暂不出片」。
147
+ - **节奏信号 = 怎么走**(每步停等我):**「逐步推进」**(这是本仓公约立法定名的正式模式名,
148
+ 定义就是「每步停等确认」,用户会照着这么说)、「一步步来」「先 X 然后我们再说」
149
+ 「我看看再定」「等我确认」。
150
+
151
+ ⚠️ **上面的词只是举例、不是白名单**——判据是「**用户表达了节奏/范围保留**」,换个说法照样得听懂。
152
+ 典型误判:「先智能剪口播 **然后我们逐步推进**」——用户说了「然后」,明确表示还要往下,
153
+ **范围**逃生门逐字不成立;但**节奏**逃生门成立 ⇒ **SHALL 停**。(2026-09-04 真机事故就栽在这里:
154
+ 当时只写了范围侧,agent 一口气连跑了三个 skill。)
155
+
156
+ 停下时**必须交代下一步是什么、他说一声就继续**,别退化成事事请示。示范:
157
+ 「口播工程已就绪。按你说的逐步来,我先停在这。下一步是拆成 beat 级分镜派单,你说一声我就接着做。」
158
+
159
+ **没有这两类信号时不改默认**:仍按上文自动接力,别问「要不要继续」。
141
160
 
142
161
  > 原则:**agent 替用户跑 CLI / 接力 skill,用户只对话**——别让用户自己去终端敲下一条 gtrk 命令。
143
162
 
@@ -160,6 +160,25 @@ dispatch 落地后**不要收工**——但下游各车道是**有先后的 SOP
160
160
 
161
161
  > 每车道有专属**驱动 skill**(懂 SOP 位置 + 管用户检查点):拆分派单后**直接交棒 ③ `/gtrk-matrix`**(B-roll 底轨的影视/本地素材腿),AI 车道非空时它再交棒同阶段的 `/gtrk-ai-drama`;三源落齐 + ④ 抽帧检查过后,才交棒 ⑤ `/gtrk-mg`。你(agent)触发 `/gtrk-matrix` 起步即可。**agent 替用户跑 CLI,用户只对话。**
162
162
 
163
+ #### 逃生门:两种信号都要认(范围 + 节奏)
164
+
165
+ 上面的「别停在派单、直接交棒 `/gtrk-matrix`」是**默认**,但**用户表达了范围保留或节奏保留时
166
+ SHALL 停在派单这一步、SHALL NOT 自动交棒**。两者语义正交,认漏一个都会误冲:
167
+
168
+ - **范围信号 = 走多远**(我只要这一个产物):「只要这份拆分稿」「派单出来我先看看」「先不铺轨」。
169
+ - **节奏信号 = 怎么走**(每步停等我):**「逐步推进」**(本仓公约立法定名的正式模式名,
170
+ 定义就是「每步停等确认」,用户会照着这么说)、「一步步来」「先 X 然后我们再说」
171
+ 「我看看再定」「等我确认」。
172
+
173
+ ⚠️ **词表只是举例、不是白名单**——判据是「**用户表达了节奏/范围保留**」,换个说法照样得听懂。
174
+ 特别注意「先 X **然后**我们逐步推进」:用户明说了还要往下,**范围**逃生门逐字不成立,
175
+ 但**节奏**逃生门成立 ⇒ **停**。
176
+
177
+ 停下时**必须交代下一步是什么、他说一声就继续**(例:「派单出来了:MG N 槽 / B-roll M 段 / AI K 段。
178
+ 按你说的逐步来我先停在这,下一步是铺 B-roll 底轨,你说一声我就接着做」),别退化成事事请示。
179
+
180
+ **没有这两类信号时不改默认**:仍按上文有序推进、每步替用户跑命令。
181
+
163
182
  ---
164
183
 
165
184
  ## 拆分方法论(沿《实在界漫游指南》视觉语法精华)
@@ -79,6 +79,27 @@
79
79
  实测 **316–342 字/分**(挂钟口径),与 3.1 派生的 349.3 同量级、互为旁证。
80
80
  本条**不满足** §二 的五项(缺 ②③④ 的逐条留痕),故只作旁证、MUST NOT 单独当口径依据。
81
81
 
82
+ ### 3.4 `volc_zh_male_cixingjieshuonan_uranus_bigtts`(**五项齐备 · 双样本实测**)
83
+
84
+ | 项 | 值 |
85
+ |---|---|
86
+ | ① 音色 / 引擎 | 磁性解说男声 2.0 `volc_zh_male_cixingjieshuonan_uranus_bigtts` / 火山引擎 `volcengine`(云引擎,非自训) |
87
+ | ② 合成参数 | `speed` 未传(= 默认 1.0);`fragment_interval` **不适用**——云引擎音色不受理该参数;`split_method` 走服务端默认 |
88
+ | ③ 稿件 | 两稿,Unicode 码点口径(含标点与英文数字)。① 凯奇坎 823 码点 `sha256:fd4e4f0efaabdfa1…` ② 黄石 904 码点 `sha256:9ce70f69b9d00f20…` |
89
+ | ④ 测量 | `ffprobe -show_entries format=duration` 取 wav 总时长,**首尾静音计入**(挂钟口径的定义即如此) |
90
+ | ⑤ 结果 | 稿① 823 / 230.40s = **214.3**;稿② 904 / 248.33s = **218.4**;合并 1727 / 478.73s = **216.4 字/分**。样本 2 条,日期 2026-09-03 |
91
+
92
+ **这条记录的价值不在它自己,在它顺手验了 §3.2 那张派生表。**
93
+ 注册表给这条音色 `rate=321.77 / pause=0.31`,按 `挂钟 = rate × (1 − pause)` 派生得 **222.0**;
94
+ 两次实测 214.3 / 218.4,偏 **−3.5% / −1.6%**。
95
+ §3.2 的 49 条派生值此前**从未被任何实测检验过**(3.1 是注册表自身口径的复算,不是独立测量),
96
+ 本条是第一次拿真机音频去撞那条公式,**没撞坏**。派生表因此从「未经检验的推算」升格为「有一个实测锚点的推算」——
97
+ 仍 MUST NOT 宣称全库已标定,但对**云引擎 volc 这一档**,派生值可以当估值用,误差量级 <5%。
98
+
99
+ ⚠️ 另记一条选音色时该知道的事实:这条音色的 `pause=0.31` 是**全库最高**,挂钟 222.0 正是 §3.2 那张表的
100
+ `min` 值本人。同一份稿子交给它,比交给缺省 330 长 **48%**,比交给 `narrator`(349.3)长 **57%**。
101
+ 写稿时 MUST 按它自己的挂钟值反推字数,照缺省 330 写会让成片直接长出三成。
102
+
82
103
  ## 四、缺省值 330 是怎么来的,用在哪儿
83
104
 
84
105
  - **取值**:落在全库挂钟中位 **308.7** 与 `narrator` **349.3** 之间,覆盖真机 **316–342** 区间的中部;