@gitruck/cli 1.0.8 → 1.1.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.
package/package.json CHANGED
@@ -1,66 +1,67 @@
1
- {
2
- "name": "@gitruck/cli",
3
- "version": "1.0.8",
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
- ],
29
- "engines": {
30
- "node": ">=20.6"
31
- },
32
- "publishConfig": {
33
- "access": "public",
34
- "registry": "https://registry.npmjs.org/"
35
- },
36
- "keywords": [
37
- "gitruck",
38
- "同合云",
39
- "video",
40
- "oral-cut",
41
- "口播剪辑",
42
- "cli",
43
- "jianying",
44
- "剪映",
45
- "agent"
46
- ],
47
- "scripts": {
48
- "gtrk": "bun run src/index.ts",
49
- "build": "bun build ./src/index.ts --target=node --minify --outfile dist/index.js",
50
- "typecheck": "tsc --noEmit",
51
- "prepublishOnly": "npm run typecheck && npm test && bun run build",
52
- "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/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 --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\"",
53
- "openspec:gate": "node openspec/gate.mjs"
54
- },
55
- "devDependencies": {
56
- "@xmldom/xmldom": "^0.9.6",
57
- "bun-types": "^1.1.0",
58
- "commander": "^12.1.0",
59
- "esbuild": "^0.28.1",
60
- "typescript": "^5.6.0"
61
- },
62
- "dependencies": {
63
- "hash-wasm": "^4.12.0",
64
- "jszip": "^3.10.1"
65
- }
66
- }
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
+ }
@@ -50,16 +50,21 @@ description: B-roll 检索铺轨编排手册——成片管线里第一个铺的
50
50
  ```
51
51
  - **变奏点**:`--top-k` 控理解成本(1 积分/张,只理解你会认真考虑的那几条);云端 plan 同样可 describe(帧从签名 url 现抽);理解产物有本地缓存,反复迭代不重复扣费。
52
52
  - **裁定要点**:`usable_flags` 是信号不是判决——结合 `desc` 复核(水印在角落的航拍也许仍可用);剔除动作=从 plan 删掉那条 result,CLI 不会替你剔。
53
+ 另读 describe 输出的**剔除风险**清单:候选数 ≤1 的 beat 一删就掏空(音频驱动 ⇒ 整段黑屏或跨 beat 借片;口播 ⇒ 露 A-roll)。先补素材再剔,MUST NOT 见 flag 就删。
54
+ ——260902 真机 P3 八个 beat 里七个只有 1 条候选;该清单只是判据,剔不剔仍归你(铁律①「零件不裁定」,见 §四层架构与三条铁律)。
53
55
 
54
56
  ### 配方 C · 时间窗匹配(电影解说式)
55
57
 
56
58
  - **适用线索**:解说顺序≈素材内时间顺序(影视解说、赛事复盘、长录像剪辑)——第 N 段解说该配影片第 N 段邻域的画面,全片乱配会剧透/错位。
57
59
  - **命令序列**(逐段推进窗口,窗口推进是你的编排逻辑,CLI 不自动推进):
58
60
  ```bash
59
- gtrk matrix index --dirs <影片所在夹> --json
61
+ # ⚠️ --dirs 钉到**这一部片的绝对路径**,不是它所在的夹——同夹邻片会抢占候选
62
+ gtrk matrix index --dirs <这一部片的绝对路径> --json
60
63
  # 对解说的每一段(第 i 段,共 n 段,影片时长 D 秒):
61
64
  # 窗口中心 ≈ D × (i/n)(解说进度比),半径 r 可调(起手 ±D/n 到 ±2D/n)
62
- gtrk matrix search "<该段画面描述>" --local --dirs <夹> --source-window <中心-r>,<中心+r> --out seg-i.json --json
65
+ gtrk matrix search "<该段画面描述>" --local --dirs <这一部片的绝对路径> --source-window <中心-r>,<中心+r> --out seg-i.json --json
66
+ # ↑ --dirs(文件域)与 --source-window(源时间域)是**两个维度**,AND 叠加:
67
+ # 前者限定「哪一部片」,后者限定「片内哪一段」。只用后者不限文件域,邻片的同时段照样进候选。
63
68
  # 空窗(results 空)→ 你裁定:扩半径重试 / 接受留空 / 放弃时序约束去全片搜
64
69
  # 汇总各段命中组一份 plan(结构照 broll-plan.json;每段一个 beat、track_st/ed=该段口播窗口)
65
70
  # ★ 每个 seg-i.json 里的 results 条目**原样搬进去**,MUST NOT 自己重写 segments
@@ -72,7 +77,9 @@ description: B-roll 检索铺轨编排手册——成片管线里第一个铺的
72
77
  - 丢 `cuts` ⇒ 铺轨的**端点残片收缩空转**(只剩帧网格吸附,还得候选带 `fps` 才生效)——成片上可能出现一闪而过的异景帧;
73
78
  - 丢 `motion` ⇒ **高运动降权不生效**(缺席=不可判,不是「平稳」);
74
79
  - 没跑过 `describe` ⇒ 美观度 / 看点 / 模糊降权三条一并不生效(那是配方 B ② 的产物)。
75
- - **两种「没有 cuts」要分开处理**:① 你重写了 segments ⇒ 改姿势原样搬回来即可;② 素材压根没扫过切点 ⇒ 跑 `gtrk matrix index --dirs <夹> --rebuild` 补上。分不清就看 `matrix lay` 的输出——它会打一条「闪帧风险**不可判**:N 颗镜头取自没扫过切点的素材」,那条告警一直在跑,**读它**。
80
+ - **两种「没有 cuts」要分开处理**:① 素材压根没扫过切点 ⇒ 跑 `gtrk matrix index --dirs <夹> --rebuild` 补上;② 你重写了 segments 把 `cuts` 抹掉了 ⇒ 重跑索引一万遍也不会消,改姿势**原样搬回** `results` 条目即可。
81
+ ⚠️ 告警本身**分不清这两档**——两者在 plan 里长得一模一样(都是 `cuts` 整键缺席)。判别法是**先跑 ①,若告警还在就是 ②**(`matrix lay` 的告警原文里也是这么写的)。
82
+ 另注:`cuts: []`(空数组)**不是**「没有 cuts」,那是「扫过了,这段里恰好没切点」,可判且无风险,不会触发告警。
76
83
 
77
84
  ### 配方 D · 理解先行编剧(vlog 式,素材→文稿)
78
85
 
@@ -130,7 +137,7 @@ description: B-roll 检索铺轨编排手册——成片管线里第一个铺的
130
137
  | 指定素材类型 | `--material-class <c>` | `real_shot` \| `concept` · 栏目策略 | 仅 internal 矩阵成员口 |
131
138
  | 填充门槛 | `--score-floor <f>` | 浮点 0–1 · `0.2` | 低于不采纳、槽位留空露黑底;调完必看空洞告警 |
132
139
  | 切点对齐字幕句 | `--cut-align <r>` | 浮点 0–1 · `0.7`(`0`=关闭) | 三七开拍板:约七成字幕句起点恰逢镜头切点、三成有意错开;句级时码取 transcript 重投影(降级自动回旧节奏并告警);开启时结果 JSON `lay.cut_align` 报实测比例 |
133
- | 主轨空洞填充 | `--gap-fill <m>` | `fast` \| `solid`(默认)\| `none` | **仅音频驱动工程主轨**(口播工程不适用零回归):fast=放宽地板随便填候选→延长相邻颗粒→黑片兜底;solid=黑片垫齐(精修一眼看出没匹配到);none=留 gap(客户端主轨磁吸会吸除 gap 致画面与配音错位,慎用);生效时结果 JSON `lay.gap_fill` 报明细 |
140
+ | 主轨空洞填充 | `--gap-fill <m>` | `fast` \| `solid`(默认)\| `none` | **仅音频驱动工程主轨**(口播工程不适用零回归):fast=放宽地板随便填候选→延长相邻颗粒→**跨 beat 借候选**→**次地板补真画面**→仍不够才黑片;借来的画面与本段稿子相关性弱、次地板槽是不到 1.2s 的快切,两者都会在日志里**指名报出**(`kind` 为 `borrowed` / `subfloor`)——那是如实告知,**不是缺陷,别当 bug 上报**;solid=黑片垫齐(精修一眼看出没匹配到);none=留 gap(客户端主轨磁吸会吸除 gap 致画面与配音错位,慎用);生效时结果 JSON `lay.gap_fill` 报明细 |
134
141
  | 编排交给云端跑 | `--arrange <m>` | **按素材来源自动定档,一般不用传** | 铺**自己电脑里的素材**→`cloud`(编排在服务端,按编排量计费);铺**素材矩阵的素材**→`local`(编排仍在本机、不计费,逐字不动)。`shadow`=本机照跑照铺轨、云端只对拍不采纳。⚠️ 本地素材路上 `--arrange local` **已不受理**(2026-08-31 拍板:编排只在服务端迭代,留旧路等于让用户在不知情时拿到另一套算法的结果);云端拿不到产物时**直接报错**,不会换算法把活干完。⚠️ **它不是省钱开关**——矩阵素材要付检索费,两条路都花钱、只是花在不同环节,MUST NOT 对用户说「用本地就不花钱」 |
135
142
  | 落轨前先质检画音对齐 | `--arrange-qc` | 开关 · 缺省关 | 只查各 beat 的**卡点句**(span.from 领衔句):画面没给到稿句说的东西就换候选重排,最多 2 轮,到限即交付 + 如实登记残余。零渲染。⚠️ 按帧计费(每卡点句 1 帧/轮),跑前报预估求确认。**默认关,用户没说就别带**。拿不到卡点句(无 dispatch / 重投影降级)时会明说「跳过 ≠ 查过」,别把那条日志读成通过 |
136
143
  | 云端编排本次上限 | `--arrange-cost-cap <n>` | 正整数 · 不限 | 超限服务端**前置拒绝**、零执行零计费(不是跑一半掐断)。只在 `--arrange shadow\|cloud` 时有意义 |
@@ -176,15 +183,40 @@ description: B-roll 检索铺轨编排手册——成片管线里第一个铺的
176
183
 
177
184
  出参逐条:`{id, note, duration, audio_type, tags, score, download_url, cover_url}`;`audio_type`(`pure` 纯音乐 / `song` 歌曲)与 `accompaniment_url`(song 类现成伴奏直链,零处理成本)**两档通用**;**只有 `is_copyright`(及 clip 的 `material_class`)是成员口独有**——公开口**没有**这个字段,零件如实缺省不伪造,你也别把「没有该字段」读成「不可商用」。`download_url` 带 24h 签名(过期重跑即重签)。
178
185
 
186
+ > ⚠️ **`is_copyright` = 能不能商用,不是「有没有被版权保护」**
187
+ >
188
+ > ```
189
+ > is_copyright: true → 可商用(自有 ∪ 已授权) ← 挑 BGM 就挑这种
190
+ > is_copyright: false → 不可商用 ← 别碰
191
+ > ```
192
+ >
193
+ > **`false` MUST NOT 读作「无版权、可以随便用」——它恰恰相反。** 决定性反证:概念素材(他人版权物)
194
+ > 入库时固定写 `is_copyright=0`;字段若真是「是否受版权保护」,那批必须是 1。
195
+ >
196
+ > **真机事故(2026-09-02,这条警示的由来)**:AI 执行方连续两轮**特意去挑 `is_copyright:false`**,
197
+ > 以为那是「没版权、随便用」的安全选项,结果把**不可商用**素材铺进了 5 个工程;唯一安全的
198
+ > `true` 反倒被主动避开。
199
+ >
200
+ > **所以选 BGM(以及任何要进成片的整条素材)MUST 按可商用口径判**:
201
+ >
202
+ > - **MUST 只从 `is_copyright: true` 的候选里挑**;`false` 的一律不推荐给用户、不落轨——
203
+ > 除非用户在对话里明确说了这条片子只自用/不发布,且你把「这条不可商用」原话告诉他;
204
+ > - 嫌手动挑麻烦就让服务端筛:成员口加 **`--commercial-only`**(传 `copyright_scope=commercial`),
205
+ > 出参逐条 `is_copyright:true`;
206
+ > - **公开口(external 档)没有这个字段**——那不是「不可商用」,而是「服务端已经在源头只放可商用素材」,
207
+ > 缺席即无需判;
208
+ > - `--json` 出参里 CLI 会**逐条派生一个人话标签 `copyright_label`**(`"可商用"` / `"不可商用"`),
209
+ > 与 `is_copyright` 恒同向、缺席同缺席。**判读以这两个键中的任一为准,MUST NOT 靠字段名去猜。**
210
+
179
211
  **upsell 口径**:`--json` 出参可能带一个**独立顶层字段** `upsell`(人读模式则是末尾一行提示)——**当且仅当**公开口档位且结果不足(0 条或少于请求量一半)时才有,内容是「加入同和新媒体矩阵可免费搜全库」+ 链接。它**不在 `results` 里、不改写任何候选**:原样转述给用户,别把它当成一条素材。成员档恒无此字段。
180
212
 
181
213
  **本地素材零件**(`matrix index` / `--local`):
182
214
 
183
215
  | 用户想要 | CLI 怎么传 | 取值 · 默认 | 说明 |
184
216
  |---|---|---|---|
185
- | 给素材夹建索引 | `gtrk matrix index --dirs <a,b,...>` | 逗号分隔目录 · — | 免切片只记时间戳;指纹增量零重算;断点续传 |
217
+ | 给素材夹建索引 | `gtrk matrix index --dirs <a,b,...>` | 逗号分隔**目录或素材文件** · — | 免切片只记时间戳;指纹增量零重算;断点续传 |
186
218
  | 本地检索模式 | `--local` | 开关 · 关 | 必配 `--dirs`;跳过身份探针、不触云端检索端点;与 `--column`/`--material-class` 互斥 |
187
- | 圈定检索域 | `--dirs <a,b,...>` | 逗号分隔目录 · — | 检索域永远显式可见;绝不与云端结果混合 |
219
+ | 圈定检索域 | `--dirs <a,b,...>` | 逗号分隔**目录或素材文件** · — | 检索域永远显式可见;绝不与云端结果混合。**传文件即把域收窄到该素材**——一稿对一片时钉到那一部片,同夹邻片就抢不走候选(实测三片同夹时 46% 的候选来自邻片) |
188
220
  | **源时间窗过滤** | `--source-window <start,end>` | 秒,`start<end` · 不过滤 | 仅 `--local`:只返回与窗口**有交集**的命中段(段边界不裁剪);与其他过滤器 AND 叠加;图片候选自动排除;**空窗 = ok 空结果非错误**,扩窗是你的裁定 |
189
221
  | 场景切分粒度 | `--scene-threshold <f>` | 浮点 (0,1) · `0.3` | 仅 index:镜头切换快调高、长镜头调低 |
190
222
  | 固定机位判稳阈值 | `--stability-threshold <f>` | 浮点 (0,1) · `0.05` | 仅 index:场景内最大帧间变化低于此值判 stable,抽帧收敛为**中点 1 帧**(60s 固定机位从 30 帧省到 1 帧);summary 分列 stable/unstable 场景数与省帧数;误判 stable 丢检索粒度、误判 unstable 只是不省钱——**宁严勿松**;默认为保守值待标定 |
@@ -201,7 +233,12 @@ description: B-roll 检索铺轨编排手册——成片管线里第一个铺的
201
233
  | 直接理解素材文件 | `--materials <a,b,...>` | 逗号分隔文件 · — | 视频按**场景中点**逐帧理解;图片文件直传;结果在 stdout JSON `items` |
202
234
  | 跳过确认 | `--yes` | 开关 · 关 | 将实际调用 >20 张才触发确认(预估积分明示);internal 豁免免确认仅提示 |
203
235
 
204
- 理解产物形态:`{desc(≤200字中文描述), tags[], mark(0-100 质量分), usable_flags{watermark, text_overlay, black_border, blurry}}`。**缓存即钱**:产物按(素材, 帧时刻)落本地索引库,同帧重复 describe 零调用零计费;素材内容变了(size:mtime 指纹变)该素材缓存自动作废。
236
+ 理解产物形态:`{desc(≤200字中文描述), tags[], mark(0-100 质量分), usable_flags{watermark, text_overlay, black_border, blurry}, at_sec(射程锚点)}`。**缓存即钱**:产物按(素材, 帧时刻)落本地索引库,同帧重复 describe 零调用零计费;素材内容变了(size:mtime 指纹变)该素材缓存自动作废。
237
+
238
+ **⚠️ 一条 describe 只代表一段,不代表整条候选**(`--plan` 形态):每个候选**只抽一帧**(`segments[0]` 的 `best`),这条判决的有效射程就是**那一帧所属的那一个 segment**。`at_sec` 就是那一帧的时刻(**素材时基**秒,与 `segments[].best` 同轴——注意与 `beats[].anchors[].at_sec` 的**工程轴**秒同名不同轴,别换算)。缺这个字段的旧 plan 按 `segments[0]` 推定,**不外推到全部段**。
239
+
240
+ - 真机 260902 量级:32 个被理解候选共带 **843 段,只有 32 段(3.8%)被看过**;95 个落轨坑位里只有 12 个(12.6%)含那一帧。命令跑完会打一行「理解覆盖率:N 帧 / M 段 = X%」(`--json` 读 `describe_coverage`),**M 是段数不是候选数**——别把「注入 N 条 result.describe」读成「这 N 条候选都看过了」。
241
+ - 转述给用户时 MUST 按段说:「这条候选的 X–Y 秒那一段有字幕」,MUST NOT 说成「这条素材有字幕」。要判更多段就得多抽帧 = 多花钱(1 积分/张),是否加抽由用户拍板,CLI 不替他加。
205
242
 
206
243
  **plan 消费零件**(`gtrk matrix lay`):
207
244
 
@@ -223,7 +260,7 @@ description: B-roll 检索铺轨编排手册——成片管线里第一个铺的
223
260
  - `result.pinned: true`:**钉选**——是**落位保证**,不只是排序特权。它豁免四条自动护栏:①派单负词 `excluded_hint`、②`--score-floor` 分数地板、③不二用抢占(钉选段不会因为**别的候选**占了同一把消费键而落不上;但同一个「候选+段」对仍只落一次)、④紧邻跳剪避让(钉选相邻照落,也不计进 `dedup.adjacentWaived`)。
224
261
  **不豁免的三条**:`--no-image-broll`(零图片上云是硬承诺,图片候选连 pinned 也进不来)、同 beat 跨轨素材归属互斥(那条给的是备选面——钉选占满每条轨,`--lay N` 就退化成 N 条一样的轨)、主轨 gap 快速填充的兜底档。
225
262
  钉多了仍可能打架(供长不足/位置冲突),让位名单在结果 JSON `lay.pinned.yielded` 与告警里**逐段**明示。
226
- - beat 的 `anchors`:**关键词锚**(拆分稿圈定、plan 检索时内插 `at_sec`)——`[{keyword, utterance, at_sec, query}]`,lay 把锚 query 最高分命中钉在 `at_sec−0.5s`(时长 min(命中段, per_shot×2)),其余槽位在锚点分割的区间内序贯填充。可编辑:**挪 `at_sec`**(微调卡点时刻)、**换 `query`**(换锚画面)、**删锚**(整条删除);`at_sec:null`=内插失败态,lay 按降级普通槽处置。锚 query 池内有 pinned 候选时**用户钉选优先占锚槽**。
263
+ - beat 的 `anchors`:**关键词锚**(拆分稿圈定、plan 检索时内插 `at_sec`)——`[{keyword, utterance, at_sec, query}]`,lay 把锚 query **原始 sim 最高的合格命中**(原始检索相似度,**不是** mark/highlight 融合分——`--mark-weight`/`--highlight-weight` 在锚槽退为同 sim 时的 tie-break)钉在 `at_sec−0.5s`(时长 min(命中段, per_shot×2)),其余槽位在锚点分割的区间内序贯填充。**锚预留优先于普通序贯槽消费**:铺轨前先为每锚锁住其 sim 第一名(每锚至多 1 对,落位或降级后立即释放),前序 beat 的泛化普通槽拿不到它;取不到第一名时锚 outcome 会**如实报名次与去向**(落的是第几名、第一名被哪个 beat/query 取走),MUST NOT 静默当成钉准了。可编辑:**挪 `at_sec`**(微调卡点时刻)、**换 `query`**(换锚画面)、**删锚**(整条删除);`at_sec:null`=内插失败态,lay 按降级普通槽处置。锚 query 池内有 pinned 候选时**用户钉选优先占锚槽**。
227
264
  - beat 的 `per_shot_sec`/`requested_shots`(节奏锚,影响槽长档位)。
228
265
 
229
266
  **不可编辑面**(动了会被 `matrix lay` 校验拒绝并指名字段):
@@ -259,7 +296,7 @@ description: B-roll 检索铺轨编排手册——成片管线里第一个铺的
259
296
 
260
297
  **前置**:需要跑过 `gtrk split` 的产物目录(`split/dispatch.json`)。`film_broll` 空 = 本片没有影视/本地素材腿 → 跳过本步,看 AI 情景片段腿(`dispatch.ai_drama` 非空则交棒 `/gtrk-ai-drama`),两腿都空才直接进 ⑤。`gtrk` 找不到 → `npm i -g @gitruck/cli@latest`。用户先在 opencut 手调过切点也不怕——命令每次都现场重投影 beat 窗口,微调口播轨不用重跑 `gtrk split`,只有拆分稿本身变了才要。
261
298
 
262
- **业务分离**:本框架 skill 不硬编任何栏目审美。B-roll 的 `queries` 在 ② 拆分时已写进派单(不触发生产 skill);栏目只供检索偏好(`--column`,internal 口生效)。档位由命令自己探(结果 JSON `memberType`),external 口固定 real_shot+有版权素材。
299
+ **业务分离**:本框架 skill 不硬编任何栏目审美。B-roll 的 `queries` 在 ② 拆分时已写进派单(不触发生产 skill);栏目只供检索偏好(`--column`,internal 口生效)。档位由命令自己探(结果 JSON `memberType`),external 口固定 real_shot + 可商用素材。
263
300
 
264
301
  ## 本地素材检索模式要点(`--local` / `matrix index`)
265
302
 
@@ -309,7 +346,7 @@ gtrk matrix --project "<split 产物目录>" [--lay N] [--score-floor F] [--top-
309
346
 
310
347
  - `--json`:人读日志走 stderr,成功时 stdout 只有一行结果 JSON:
311
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 } }`
312
- (`--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?/items? }`)
349
+ (`--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? }`)
313
350
  - **拒铺结局**(候选轨已被用户编辑):stdout 出 `{ ok:false, refused:[…], reason:"tracks_edited", planReusable:true, … }` 且非 0 退出——不是命令失败,plan 已产出,处置见下表。
314
351
  - **命令失败**(缺派单、鉴权失败、全部 query 失败、参数越界、坏 plan 被 lay 拒)→ 非 0 退出、报错在 stderr、stdout 无 JSON。先看退出码,把 stderr 报错如实回给用户。
315
352
  - 检索分钟级,耐心等返回。
@@ -319,7 +356,7 @@ gtrk matrix --project "<split 产物目录>" [--lay N] [--score-floor F] [--top-
319
356
  读 stdout 那行 JSON(字段按需读、读前判空),别只回「铺好了」:
320
357
 
321
358
  - `counts`:几个 beat、几条检索(几条失败)、几条候选——一句话概括盘子大小。
322
- - `memberType`:internal=矩阵成员口(栏目偏好/concept 生效);external=通用口(固定 real_shot 有版权)。
359
+ - `memberType`:internal=矩阵成员口(栏目偏好/concept 生效);external=通用口(固定 real_shot + 可商用)。
323
360
  - `lay.laidTracks` / `lay.laidClips`:铺了几条候选轨、几个颗粒(不含黑底轨)。
324
361
  - `lay.blackTrack`:黑底垫轨轨号(未铺时 null)。
325
362
  - `lay.blackBedHoleSec` / `lay.blackBedHoles`:**黑底空洞**(纯黑压口播时段),恒全量不按阈值过滤——非零就主动报(哪个 beat、几秒、在哪),这是粗剪期既定取舍不是故障。
@@ -367,7 +404,7 @@ gtrk matrix --project "<split 产物目录>" [--lay N] [--score-floor F] [--top-
367
404
  | 预览看不了 / 想「重签」 | 别为此重跑铺轨:`preview_url`/`cover_url` 不带签名不过期;带签名 24h 过期的是原片 `url`——工程内走客户端「确认原片」重签;**脱离工程要原片落本地走 `gtrk matrix fetch <clip_id...>`(免费重签+下载,见「精剪补素材」节)** |
368
405
  | raw 原片回落 / 体积大 | 提示用户;服务端 backfill 后重跑可换回轻量代理 |
369
406
  | `reprojection.degraded:true` | 不是故障:命令算不出当刻窗口退回快照。`transcript_missing` → 补回 transcript.json 或新版 oralcut 重出;`no_project`/`gtrk_unreadable` → 工程放回位或 `--project` 指对 |
370
- | 期望 concept 却报 external 限制 | 如实说明当前身份只出 real_shot 有版权素材,concept 需矩阵成员口 |
407
+ | 期望 concept 却报 external 限制 | 如实说明当前身份只出 real_shot 可商用素材,concept 需矩阵成员口 |
371
408
  | describe 报 `describe_endpoint_unreachable` | 服务端未上线/网络/配置指错:查 `describeUrl` / `GITRUCK_DESCRIBE_URL`;缓存与 plan 都在,修好重跑。describe 走异步任务(提交后轮询取结果):任务提交成功后即便中途断网结果也不丢(服务端照跑),可重新轮询/稍后重跑取回;上游失败服务端自动退款,只需重跑 |
372
409
 
373
410
  > **搜词规范**(ad-hoc `search` 与理解派单 queries 通用):英文长句场景描述(5–12 词,谁+在哪+做什么),一条只装一个场景意象,避多义/字面强的动词("pointing"/"hunting" 会召回特写/猎人,改用 "giving suggestions in a meeting" 这类场景语义)。