@gitruck/cli 1.0.1 → 1.0.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.
@@ -1,165 +1,174 @@
1
- ---
2
- name: gtrk-mg
3
- description: MG 动态图颗粒铺轨器——成片 SOP 第 步,在 B-roll 定下来之后,把栏目的 html-particle 动态图颗粒(透明叠加 / 满屏底层)叠铺到 B-roll 之上。先由栏目 MG 生产 skill 按派单各槽位产颗粒,再驱动 `gtrk mg` 命令 lint + 铺进 `.gtrk` 工程的 beat_track。当用户想「铺 MG 颗粒 / 上动态图 / 铺动效 / 给这段配动画铺进工程 / 把 MG 派单铺轨 / 消费 dispatch.mg」时使用本 skill。凡涉及把 MG 动态图颗粒铺进已剪好的成片工程,优先用本 skill 驱动 gtrk CLI,别让用户自己去终端敲 `gtrk mg`。
4
- ---
5
-
6
- # MG 动态图铺轨(gtrk-mg)
7
-
8
- 把 `gtrk split` 派好的 **MG 槽位**(`dispatch.mg`),先由**栏目的 MG 生产 skill** 产成 html-particle 动态图颗粒,再交给 `gtrk mg` 命令 lint + 铺进 `.gtrk` 工程的 `beat_track`——**叠在已经定下来的 B-roll 之上**。**CLI 是手(lint / 铺轨 / 写回),你是脑(认 SOP 位置、驱动栏目生产 skill、管用户检查点、判 lint 该不该硬铺)。栏目生产 skill 只产纯净颗粒、不知 gtrk 命令,由你驱动。**
9
-
10
- > **本 skill 已含你需要的全部信息**(SOP 位置、业务分离、逐槽位工作流、命令参数、lint 铁律、排错、交棒)。命令参数细节以 `gtrk mg --help` 为准;颗粒的视觉/内容规范**不在这里**——那是栏目资产,由栏目 MG 生产 skill 全权负责。
11
-
12
- ## 你在成片 SOP 的哪一步(先认位置,别抢跑)
13
-
14
- 成片是**有序 SOP + 用户检查点**,不是并行一次铺完。全序:
15
-
16
- > ① `/gtrk-oralcut`(剪口播)→ ② `/gtrk-splitter`(拆分派单出 `dispatch.json`)→ **③ `/gtrk-matrix` 先铺 B-roll 用户 opencut 挑选/调整确认** **④ 本 skill:再铺 MG(叠在 B-roll 之上)** ⑤ `/gtrk-ai-drama`(最后上 AI 再现)→ `gtrk render` 收口
17
-
18
- **你是第 步。MG 颗粒是叠层——底下那层 B-roll 必须先定死,否则 MG 会盖在还没挑好的画面上白铺。** 所以动手前先过前置硬门。
19
-
20
- ### 前置硬门(不满足就别铺,先回上一步)
21
-
22
- 1. **B-roll 已铺且用户已确认**:若 `dispatch.film_broll` 非空,必须 ③ 已跑过 `gtrk matrix` **且用户已在 opencut 里挑选/调整确认**。用户没确认 → **别铺 MG**,先回 ③ 让用户定 B-roll,明确告诉他「B-roll 定了我再上 MG」。(`dispatch.film_broll` 为空 = 本片没 B-roll 底层,可直接进 ④。)
23
- 2. **有 split 产物**:需要一个跑过 `gtrk split` 的产物目录(含 `split/dispatch.json` 与工程 `.gtrk`)。没有 → 先回 ② `/gtrk-splitter`。
24
- 3. **`dispatch.mg` 非空**:为空 = 本片没有 MG 车道 → **别硬造**,直接交棒 ⑤(见末节)。
25
- 4. **CLI 在**:`gtrk` 找不到 → 让用户装 `npm i -g @gitruck/cli@latest`(需先有 Node.js)。
26
-
27
- ## 业务分离:谁产颗粒(栏目),谁铺轨(本 skill)
28
-
29
- **本框架 skill 不硬编任何栏目的视觉风格/生产内容。** MG 颗粒长什么样、用什么视觉语法,全由**栏目的 MG 生产 skill** 决定;本 skill 只负责「在对的时候、按派单、驱动它产,然后把成品铺进工程」。
30
-
31
- **车道 栏目生产 skill 的解析(照此,别猜)**:读**有效栏目配置**的 `style.skills[]`(配置文件 `~/.gitruck/columns/<id>.json`;栏目 id `--column <id>` config `defaultColumn` 选取;零配置 = L0 内置默认栏目,**不携带 style 清单** 必然走下方「无匹配」分支)。在 `style.skills[]` 里取 **`produces` 归一后(旧 `RRV_MG` → `MG`)等于 `MG`** 的条目 → 触发它 `ref` 指向的 skill 产颗粒。
32
- - 命中多条按栏目约定取其一(一般栏目只登记一个 MG 生产 skill)。
33
- - 条目带 `routing:"none"`(管线外产物,如封面)→ 跳过,不当 MG 生产 skill。
34
- - **无匹配** = 本栏目没有 MG 生产 skill 别硬铺;告诉用户「本栏目还没有 MG 生产 skill,先用 `/gtrk-style-maker` 建一个,或换个已配置的栏目(`--column`)」。
35
-
36
- > **生产 skill 是栏目的纯净资产**:它只懂本栏目的视觉语法、只产 html-particle 颗粒,**不知道 gtrk 命令、不知道产物落哪**。由本 skill 驱动它、并**由本 skill 负责把它产出的颗粒存到 `gtrk mg` 要读的路径**:`<产物目录>/mg/<composition_id>.html`。举例(仅示意解析机制,非硬编):`real-roam-guide` 栏目配置里 `style.skills` 有一条 `{produces:"MG", ref:"…/real-roam-viz"}` → 驱动它产颗粒;换个栏目、换个 ref,产颗粒的就是另一个生产 skill。**本 skill 正文里不绑死任何栏目的生产 skill。**
37
-
38
- ## 逐槽位工作流(产 lint 铺,循环到铺满)
39
-
40
- > **产物落点纪律(MUST · 全文见随包 `AGENT.md` 同名一节)**:
41
- > 一切产物(颗粒 HTML / 成片 / 预览 / 素材 / 工程文件)只落**工程目录**(颗粒恒存 `<产物目录>/mg/`)或**用户显式指定的输出路径**;
42
- > **MUST NOT** 把成片、预览或任何大媒体文件复制到 agent 自有工作目录(如用户文档目录下 agent 产品自建的目录、agent 家目录缓存、会话工作区)——需要引用媒体时**用原路径引用**,不做副本;
43
- > 临时文件(抽帧图等)一律放系统 temp 且**用完即删**(含中断 / 失败路径)。违者后果 = 用户系统盘被静默吃满(真机事故,非假设)。
44
-
45
- ### 1. 看板起手:先看 `dispatch.mg` 有哪些槽位、铺到哪了
46
-
47
- ```bash
48
- gtrk mg status --project "<split产物目录>" --json
49
- ```
50
-
51
- - 汇总 MG 流水线:`dispatch.mg` beat 槽位总数 / 已产源 HTML 数 / 已铺进 `.gtrk` 数,并**逐 beat 标注**(缺 HTML / 已产未铺 / 已铺)。
52
- - 每个槽位有 `composition_id`(主颗粒 = `<工程slug>-<beatId>`;`overlay` 叠层派生颗粒 = `<工程slug>-<beatId>-aux<n>`)与 `handoff`(`theme` / `duration_hint`(秒)/ `category` 等)。**这些是你交给栏目生产 skill 的产片订单。**
53
-
54
- ### 2. 逐槽位产颗粒(驱动栏目 MG 生产 skill)
55
-
56
- 对每个「缺 HTML」的槽位:把它的 `composition_id` + `handoff`(`theme` / `duration_hint` / `category`:`overlay` 透明叠加·不挡主体 / `fullscreen` 不透明满屏)+ beat 语义上下文,**交给第「业务分离」节解析出的栏目 MG 生产 skill 产一颗 html-particle**。产完把颗粒**存到 `<产物目录>/mg/<composition_id>.html`**(`gtrk mg` 就从这里读)。
57
- - **产前先抽帧看底轨(`overlay` 槽位必做,别只凭派单盲产)**:颗粒最终要叠在真实画面上,构图必须因势象形。对该槽位挂点用本地 ffmpeg 抽 1-2 帧(`ffmpeg -ss <track_st秒> -i <底轨视频> -frames:v 1 "<系统temp>/<beat>.jpg"`,成本≈0;抽帧图是临时文件——落系统 temp、用完即删,**别落 cwd / agent 自有目录**)看清三件事——①真人主体/人脸的位置(颗粒 bbox 避开,呼应栏目「不盖说话人」铁律);②该处是否已有烧入包装或 AI 画面(有 → 别铺这颗,报用户裁决——二次过毛片高发);③画面明暗基调(深底/浅底影响衬底与配色取舍)。把这些**连同抽帧图一起附进产片订单**交给栏目生产 skill;`fullscreen` 槽位可免(满屏不透明无避让问题)。
58
- - **产片订单必须附带坑位硬约束(gsap-emit v1 铁律⑦,2026-07-24 主理人硬性规定)**:颗粒 GSAP 时间线总长 ≥ **坑位时长**(该槽位 `track_ed − track_st` 包络,**不是** `duration_hint`)+ 0.3s 余量;`duration_hint` 只是动画主叙事节奏参考。主叙事播完后颗粒必须**定格保持或有限循环驻留到坑位末尾**——坑位内任意一帧核心内容都可见;**禁全局渐隐/整体退场/清空画面**(渐隐与剪辑层转场冲突,淡出由剪辑层决定);定格不动是合法终态。违反的观感 = 动画一过完颗粒突兀消失。
59
- - **`-aux<n>` 叠层颗粒同样处理**:`gtrk split` 若在某 beat 的 `aux_layers` 派了 `overlay`,会派生 `<beat>-aux<n>` 进 `dispatch.mg`(多为 B-roll 底轨之上叠透明概念图解)——照样产、照样存到对应 `composition_id.html`。
60
- - **category 决定叠法**:`overlay` 颗粒背景透明、盖在 B-roll 上不挡主体;`fullscreen` 不透明满屏。最终透明度由颗粒 HTML `background` 声明反推的 `opaque` 定,生产 skill 要让二者自洽(lint 会查)。**「实心底该写在哪个元素上」的正本条款是 `contracts/gsap-emit-v1.md` 铁律 4(含真机证据锚)——本 skill 不复述元素位置,改了要以契约为准**;`fullscreen` 颗粒把实心底写错地方会吃非致命 `4-bg-on-root`(见下节)。
61
-
62
- ### 3. lint 门:铺之前先单测每颗(不过就退回生产 skill,别硬铺)
63
-
64
- ```bash
65
- gtrk mg lint "<产物目录>/mg/<composition_id>.html" --dispatch "<产物目录>/split/dispatch.json"
66
- ```
67
-
68
- - 纯本地静态校验颗粒 HTML 的**铁律机器可判定子集**:`<template>` 包裹、`data-composition-id` + 1920×1080、`gsap.timeline({ paused: true })`、`window.__timelines` 注册、无 `Math.random` / `Date.now`(可逐帧 seek 的确定性)、自包含无相对外链、`background` 声明与 `opaque` 自洽…;给 `--dispatch` 会额外校验 `composition_id` 命中派单。
69
- - **`1-cid-expect`(致命)——复制改名必查**:颗粒内部的 `data-composition-id` 必须等于期望 id(`--dispatch` 命中时 = 该条派单的 `composition_id`,否则 = 文件名)。**你从别的颗粒复制模板时最容易漏改内部 id**:那样铺出来的 clip 指向 A、文件注册的却是 `__timelines["B"]`,渲染必错,且两颗粒抢同一个 `[data-composition-id]` 样式作用域。改名的临时副本(`./tmp.html`)不比对,不会误伤。
70
- - **铁律④「实心底与透明度」两项恒非致命**(正本条款 = `contracts/gsap-emit-v1.md` 铁律 4,含 2026-07-26 真机证据锚;**本处只说看到该码怎么办,元素位置以契约为准**):
71
- - `4-bg-on-root`:这颗把**实心底写在了根元素的 `style` 上**。**根元素的绘制属性会在子合成挂载时被丢弃**——那层底在成片里**一个像素都不落地**:前景照常渲出、底没了、底轨透出来,观感是「浮空面板」;而**本地播放器与客户端预览都看不出**(预览会按登记的 `opaque` 位自己给根盒打底,对这个问题结构性失明)。**报了要回步骤 2 让生产 skill 把实心底下沉为子层**——改法是机械的(把那条 `background` 声明整体搬到根下第一个全幅子层,根上改写 `background:transparent`)。⚠️ 它**不影响退出码、不拦铺轨**(避免存量颗粒一夜之间铺不进去),但**不是可以放着不管的噪音**:不改就是出片丢底。
72
- - `4-bg-explicit`:根与根下首个全幅子层**都**没有 `background` 声明 → lint 只能按「透明叠加」处理。契约要求**透明与否显式**:满屏颗粒在全幅子层写实心底,透明叠加颗粒在根写 `background:transparent`。**别靠「不写」表达透明**——作者与机器都分不清「想透明」和「忘了想」。
73
- - 两项都**只看 `background` 声明摆在哪**,不看色值(色值属栏目审美,契约不管)。`opaque` 的推导面 = 「根 `style` ∪ 根下首个全幅子层 `style`」,与契约铁律 4 同源;**合规的子层写法不会再被误判成 `opaque=false`**(旧版 CLI 会,导致满屏颗粒被登记成透明叠加)。
74
- - **铁律⑦ 估长三项恒非致命、不是放行凭据**(`--dispatch` 命中派单条目才跑,因为要拿该条的坑位包络):
75
- - `7-fill-slot`:静态估长 < 坑位包络 → 「疑未占满」。估长是**下界**(表达式 position、非字面量 duration 那些调用算不了、跳过不计),报出来基本就是真短,**回步骤 2 让生产 skill 把驻留补到坑位末尾**。
76
- - `7-no-estimate`:一条时长调用都解析不到 → **明说「铁律⑦这颗没校验」**,不是通过。这时 tl 总长只能靠真引擎 seek 或人读代码确认,别当它过了。
77
- - `7-infinite-repeat`:颗粒里写了 `repeat:-1` 总长变 `Infinity`、铁律⑦不可验证(契约 2026-07-26 已明文禁)。让生产 skill 改成按坑位算死的有限次数:`repeat = ceil((坑位 循环起点) / 单圈) 1`。
78
- - 三项都**不影响退出码、不拦铺轨**——真判据是渲染引擎逐帧,静态估长只做提醒。**但「没报 7-fill-slot」≠「时长够了」**,要看是否同时出了 `7-no-estimate`。
79
- - **铁律⑧「重复图元合并」为恒非致命提示,但看见必须处理**:
80
- - `8-primitive-merge`:这颗有一批由循环直接创建、或由循环调用具名工厂创建的可合并重复图元;它们落到同一父节点,且没有逐元素动画驱动。纯数字循环可算且同父累计 **≥ 8** 时会报数;边界算不出时会报「条数未知」。逐元素 `gsap.set` / tween、或作为 tween 首实参使用的元素数组会被排除。
81
- - 本项报的是「这批图元可**无损**合并,合并后画面逐像素不变」这一写法事实,**不是**「该颗粒有缺陷」或「超过某个数量会出问题」;真实触发轴未知。反过来,没报也**不代表安全**,真判据仍是真渲染出片抽帧。
82
- - **处置**:回步骤 2,把原始提示完整交给栏目 MG 生产 skill,让它把整组同步驱动的网格 / 排线 / 刻度 / 点阵合成单元素(SVG 用一条 `<path>` 多子路径;同色分档可分档合成),然后重产、重 lint。**别硬铺,也别当没看见**;CLI 为兼容存量把它做成**非致命、不影响退出码、不拦铺轨**,不等于 agent 可以跳过修正。确需 stagger / 逐条画入 / 逐个变色的逐元素动画批次属于契约豁免,不要为了消项删掉动画身份。
83
- - **「回调与 seek 语义」三项恒非致命**(契约同名一节,2026-07-26 增补;**报了不用改颗粒**):
84
- - `x-callback-driven`:这颗的画面靠 `onUpdate` 等时间线回调写 DOM 驱动,且没带任何 seek 兜底(GSAP `seek(t)` `suppressEvents` 缺省为 `true`,会吞掉回调)。**该写法合规**——回调可达性由契约压在**引擎侧**的 MUST 条款保证(引擎定帧 MUST 用 `seek(t,false)` / `time(t)` / `progress(p)`),**且该条款已于 2026-07-26 经真渲染引擎核实**(producer `0.6.101`,纯回调驱动无垫片颗粒三帧读数各不相同)。本项**核实之后照留**做**哨兵**:结论绑死引擎版本,引擎换实现或失守时补间属性照常插值、回调不跑 → 画面**静默定格在初始态**(不是黑屏,本地播放器和预览都看不出)。**别因为它去让生产 skill 改写法,更别让它自己加垫片。**
85
- - `x-engine-api-override`:颗粒运行时覆写了 `tl.seek`(老颗粒常见的 `rr-seek-shim`)或把 `__timelines[…]` 换成了包装对象。它会推翻引擎显式传的 `seek(t, true)`,且引擎改走 `time()`/`progress()` 就完全失效。**既有垫片属过渡态**:2026-07-26 引擎侧结论已核实(引擎本就不抑制回调),垫片已无保护作用、也无害,**可择期清理**(删后须重跑 lint 并重渲复验),不清也不拦;新颗粒别再加。
86
- - `x-raf-interval`:颗粒里有 `requestAnimationFrame(` / `setInterval(`。这类自有时钟**不被 seek 驱动**,逐帧渲染时等于冻结(契约明令:所有视觉变化必须挂在 tl 上)。静态正则分不清用途,报了要**人眼确认它是不是在驱动画面**;若是 回步骤 2 让生产 skill 改挂 tl。
87
- - 另:引擎不抑制回调 = 逐帧 scrub 时 `onComplete`/`onStart`/`onRepeat` 会**反复触发**。颗粒里**别写「只跑一次」的回调**(累加计数 / `push` 数组 / 一次性 DOM 插入),要写成每次从补间状态**重算**的幂等形式。
88
- - **成本项 `c-filter-*` 三项恒非致命、当期全部不拦铺轨**(正本条款 = `contracts/gsap-emit-v1.md`「渲染成本:真卷积滤镜」一节):这组查的是**每帧成本**、不是正确性——命中的颗粒**画面是对的,只是渲得慢**。
89
- - `c-filter-animated`:**时间线补间直接驱动了真卷积滤镜**(`filter:blur()/drop-shadow()`,或补间驱动 SVG `feGaussianBlur` `stdDeviation`)。滤镜值一变,上一帧的卷积结果当场失效、缓存彻底失灵,是这组里**最贵**的形态。**处置**:回步骤 2 让生产 skill 改用 `opacity` / `transform`(`scale`/位移)表达同一叙事动作;确需滤镜就做成**静态两态切换**。**不拦铺轨**。
90
- - `c-filter-static-fullbleed`:**整幅静态真卷积滤镜**(该声明自身就是 `position:absolute;inset:0` 一类铺满形态)。每帧对整幅做一次卷积。**首选改法是缩小被滤镜覆盖的几何面积**(面积一项同时压掉卷积与整幅逐帧合成两笔成本);次选把静态滤镜结果预烘成图,且**必须是 RGBA PNG**(透明叠加颗粒的 alpha 是成片合成的必需通道,烘成 JPEG 或无 alpha 格式会在成片里塌成不透明色块),但预烘只消得掉卷积、消不掉整幅逐帧合成,**收益有上限**。去不去滤镜属审美取值,**判断权在作者**,本项只给信息与改法。**不拦铺轨**。
91
- - `c-filter-indeterminate`:补间的 `filter` 值不是字符串字面量(变量 / 模板串 / 函数返回),lint **对该处没作判定**——既不是「判过且通过」,也不是命中。**人眼确认它到底会不会驱动 blur / drop-shadow**;会就按 `c-filter-animated` 的改法处理。**不拦铺轨**。
92
- - **`box-shadow` 整族不在射程内**(含 `box-shadow: 0 0 0 Npx` 这类零卷积脉冲写法,也含带模糊半径的写法)——看到 `box-shadow` 没被报**不是漏报**,是既定射程边界。
93
- - ⚠️ **没报 这颗便宜**:这三项是**形态提示**,真判据永远是**真渲染出片计时**。收益也别外推——现网既有栏目语料(21 颗)去掉滤镜只省 **0~3.1%**(2026-07-30 真机实测,仅对该语料成立),这组规则的价值在**滤镜重的新语料进管线前先把门立好**。
94
- - **id 前缀读法**(三个命名空间,别按前缀反推错阻断行为):**数字前缀 `1-`~`8-`** = 契约铁律项,致命性**按项声明**(`4-*` / `5-*` / `7-*` / `8-*` 就都不致命);**`x-`** = 哨兵项,**恒不拦**;**`c-`** = 成本项,致命性按项声明,**当前三项均不拦**。
95
- - **不过(非 0 退出、逐条报因)→ 把报错原样丢回栏目 MG 生产 skill 修,重产重 lint,别硬铺**。铺一颗不合规颗粒会污染工程。
96
- - 只想批量干校验不写回:`gtrk mg --project <dir> --lint-only`(有 beat 没过就 `ok:false` + **非 0 退出**,工程一个字节都不动)。
97
-
98
- ### 4. 铺轨:全槽位就绪后铺进工程(叠在 B-roll 之上)
99
-
100
- ```bash
101
- gtrk mg --project "<split产物目录>" --json
102
- ```
103
-
104
- - `dispatch.mg` beat `<project>/mg/<composition_id>.html` 取源颗粒 lint → 铺进 `.gtrk` 的 `beat_track`,把 `struct_meta.mg` 原子写回。**幂等**:重铺先剥旧自产轨再 append,用户在 opencut 手加的轨零连带。
105
- - **剥离面口径**(= 「本次会剥掉什么」,和「本次铺什么」是两件事):
106
- - **`--only <beat>` = 只剥命中的那几颗**(真增量合并)——轨上其余已铺颗粒连同用户手调**原样保留**。
107
- - **全量重铺 = 剥掉登记里的全部自产轨再整轨重建**,**唯一例外**:本次派单里有、却因缺 HTML / lint 未过 / 重投影后零存活而**没铺成**的那些(`skipped` 里那几颗),它们上一轮的 clip **留在轨上**——不会因为新的做坏了就把旧的也毁掉。反过来,**派单里已不存在**的已铺条目(你重跑过 `gtrk split`、这个 beat 不做 MG 了)仍照剥:那是计划变更,不是做坏了。
108
- - 所以「轨上共几颗」**不一定**等于「本次铺了几颗」——差额就是 `kept`(见下 `--json`),**必须一起读**。
109
- - 真要**重置整轨**(连其余已铺颗粒一起剥掉重来):加 `--replace-all` 显式授权。
110
- - **素材表不再囤积**(剥离键按「自产身份 × 零引用」判,不认客户端可改写的 `html_material` 前缀):
111
- 在 opencut 里编辑过工程之后重铺,旧的自产素材条目照样剥得掉,`mg-` 素材数**恒等于轨上颗粒数**;
112
- 历史遗留的重复 / 孤儿条目会在下一次重铺时一并清掉。**非自产素材零连带**——`broll-*`、`ex-solid-*`
113
- 垫轨、你自己加的素材一条不碰(哪怕它当前没被任何 clip 引用)。盘上 `assets/mg/` html 副本从不删。
114
- - `--json` 输出:`{ ok, mode:"lay", laid, track_total, kept, kept_ids, removed, skipped, reason?, integrity?, … }`。
115
- - **`laid`** = **本次**铺成数;**`track_total`** = **轨上现存**已铺数;**`kept`** = 其中**上轮遗留**(本次没重铺)的颗数。三个数一起读——只看 `laid` 会让「铺 1 颗、剥 20 颗」跟「补铺 1 颗」长得一模一样。恒有 `track_total = laid + kept`。
116
- - **`kept_ids`** = 上轮遗留的 `composition_id` 清单。**要判断轨上某颗是不是这一轮的版本,看它在不在这里**——`kept > 0` 就意味着轨上内容与本次派单不完全对应(要全部刷新:去掉 `--only` 全量重铺)。
117
- - **`removed`** = 本次被剥掉的旧自产颗粒数(= 上一轮已铺里没被保留下来的,含「剥了再铺」的那些)。
118
- - **`skipped`** = 缺 HTML / lint 失败的 beat(不拦其余)——**回步骤 2 补产、重铺**,别当没看见。**注意它和 `kept_ids` 会重叠**:某颗这轮没铺成(进 `skipped`)、上一轮那条还留在轨上(进 `kept_ids`),画面在但不是新版本,跟用户说清楚。
119
- - **`reason`** = 非全绿时的机读判据:`skipped`(部分没铺上)/ `empty_queue`(**拒写回**,工程未被改动)/ `no_project`(工程缺失未铺轨)。
120
- - **`reprojection`** = 本次落轨时码的来源与漂移摘要(恒出,`--lint-only` 也有):`{ mode:"reprojected"|"dispatch_snapshot", degraded, reason?, drifted, max_offset, shrunk:[…], dropped:[…] }`。
121
- **时码是现场重投影出来的**:命令每次都用 `transcript × 当刻 .gtrk` 重算每个 beat 的窗口(与 `gtrk split` 落地同一段代码),`dispatch.json` 里的时码只是投影那一刻的快照。**所以用户在 split 之后微调口播轨不用回去重跑 `gtrk split`**,只有**拆分稿本身**变了才要重跑。
122
- `drifted > 0` = 这次铺的位置和派单上写的不一样(正是它该做的),把条数与 `max_offset` 报给用户;`dropped` 里的 beat = 那段已被整个剪出成片,**故意不铺**(不会按快照塞回去)。
123
- - **`integrity`** = **素材落盘自检**(与 `gtrk matrix` 同名同形):写回工程之后自动查一遍
124
- 「`materials[].path` 是不是真的都落盘了」。**只在真写回过的运行里出现**(`no_project` / 拒写回 /
125
- `--lint-only` 时**字段缺席** = 本次没查,别当成「查过且干净」)。
126
- `dangling` = 悬空引用全量(相对路径素材登记在、文件不在,每条带 `referenced` 与引用位置 `refs`);
127
- `danglingReferenced` / `danglingOrphan` = 被时间线引用数 / 孤儿数——**两者严重度差一个量级,回报时分开说**;
128
- `external` = 绝对路径素材找不到文件(另一档,不进 `dangling`)。
129
- **告知不拦阻**:查出悬空不改 `ok`、不改退出码、不删任何东西;非零就报给用户(哪几条、在哪一段),
130
- 多半是历史遗留(如客户端「确认原片」下载中断),修法在客户端而不在这里。**别自己去删素材或文件。**
131
- - **退出码**:`ok:false` 一律连带**非 0 退出**(含「有 beat skip」这种循环中途的正常态)。**别把非 0 读成「命令崩了」**——它说的是「这一轮没全铺成」,按 `reason` / `skipped` 处理后重跑即可。
132
- - **只铺单个 beat**:`--only <beatId>`(收的是 **beat id** 如 `B12`,不是 `composition_id`;主颗粒 + 其 `-aux<n>` 叠层一并选)。
133
- - **语义 = 真增量合并**:只重铺命中的那几颗,轨上**其余已铺颗粒原样保留**——连它们的透明度与用户在 opencut 的手调一起活着(保留的是既有 clip 原件,不是照登记重建的)。适合迭代改单段。
134
- - 保留下来的那几颗**不重新 lint、不重新复制源 HTML**:工程是自包含的,`<project>/mg/` 下对应源文件即便已经删了也不影响。
135
- - 代价看 `kept` / `kept_ids`:轨上会同时存在「本次这版」和「上轮那版」。要把全部颗粒刷成最新(含按当刻时间线重投影的新位置),**去掉 `--only` 全量重铺**(幂等、多铺几颗不花钱)。
136
- - 确实要**重置整轨**(连其余已铺颗粒一起剥掉重来)才加 `--replace-all` 显式授权。
137
- - **仍会拒写的唯一情形**:本次**一条都没定位到**(`--only` 打错 beat id、`dispatch.mg` 为空、或本次条目全被 skip)**而轨上已有已铺颗粒**——那是派单或选择器出问题的信号,不是清空指令,CLI 拒绝写回并报因(`.gtrk` 逐字节不变)。
138
- - **铺完必核「clip 占满坑位」**:读回 `.gtrk`,各 beat clip 的时长必须 = 槽位包络(`track_ed − track_st`)。若你的 CLI 版本按 `dispatch.mg[].duration`(旧 `duration_hint` 语义)落轨、导致 clip 短于坑位(颗粒在 beat 中途突兀消失,2026-07-24 真机实测),**把 `dispatch.mg[]` 各条 `duration` 改为包络秒数(`track_ed − track_st`)后重铺**(铺轨幂等、直接覆盖)。CLI 侧根治(落轨恒用包络)落地后此步可省。
139
-
140
- ### 5. 循环到铺满
141
-
142
- MG 槽位就**循环「产 lint 铺」直到 `dispatch.mg` 全部铺满**(`gtrk mg status` 逐 beat 全标「已铺」、`gtrk mg` 的 `skipped` 为空、`ok:true` 且退出码 0)。**循环中途 `skipped` 非空时命令按 `ok:false` + 非 0 退出如实上报**,那是「还没铺满」不是「命令失败」——照常补产重铺即可;`--lint-only` 同口径。
143
-
144
- > **循环里别用 `--only` 逐颗铺**:`--only` 是增量的(安全,不会铲掉别的),但它**只刷新命中的那几颗**——轨上其余颗粒会一直停在上一轮的版本与上一轮的落轨位置(`kept_ids` 会如实点名)。循环的正确姿势是**每轮都全量重铺**:铺轨幂等,多铺几颗不花钱,而且顺带把全部颗粒按当刻时间线重投影一遍。`--only` 留给「已经铺满、只想改某一段」。
145
-
146
- > 旧名 `gtrk rrv` 是去品牌化前的弃用别名(仍能跑但会打提示)——**一律用 `gtrk mg`**。
147
-
148
- ## 读结果、给用户交代(别只说「铺好了」)
149
-
150
- - **铺了哪些**:`laid[]` 的 `composition_id`,对应哪些 beat;其中哪些是 `overlay` 透明叠加(盖在 B-roll 上)、哪些是 `fullscreen` 满屏。
151
- - **没铺上的**:`skipped[]` + 原因(缺 HTML 还是 lint 失败 / 重投影后零存活)——如实说,别谎报全铺;已补产重铺的说清楚补了哪几颗。
152
- - **落轨位置变了要说**:`reprojection.drifted > 0` 时报出「本次按当刻时间线重投影,N 个 beat 的位置与派单不同、最大偏移 X 秒」。这是对的(用户改过口播轨),但**必须让他看见**,别悄悄改掉。
153
- - **报「已降级至派单快照时码」**(`reprojection.degraded:true`):不是故障、没拦你,是算不出当刻窗口、退回了可能已过期的快照。照 `reprojection.reason` 给出路——`transcript_missing` → 把 `transcript.json` 补回产物目录(`transcript/` 或 `json/` 下),或用新版 `gtrk oralcut` 重出产物;`no_project`/`gtrk_unreadable` → 把工程放回 `<产物目录>/gtrk/project.gtrk` 或 `--project` 指对目录;`no_material_clip` → 口播主轨被整条删了 / relink 换了素材 id / 拿了另一个工程的 dispatch。用户接受快照也行,但要如实说「这批位置按的是上一次投影的时间线」。
154
- - **轨上有几颗不是这一轮的**:`kept > 0` 时点名 `kept_ids`——「这次只重铺了 N 颗,轨上另外 K 颗是上一轮的(位置和内容都还是旧版),要全刷新就全量重铺一次」。**别让「铺轨完成」读起来像轨上全是新的。**
155
- - 想在 opencut 里精修颗粒(手调参数/时长)→ 提示用户可打开工程手调。**但要把话说全**:手调只在「这颗**没被**下一次重铺命中」时活得下来——`--only <别的 beat>` 或全量重铺时被 skip 掉的那几颗会原样保留(含手调);**一旦某次重铺真的铺到了这颗,CLI 自产的新 clip 会整条覆盖它,手调就没了**。要长期保留的手调,别放在 CLI 自产的 MG clip 上。
156
-
157
- ## 交棒 ⑤(别停在铺完)
158
-
159
- `dispatch.mg` 全铺满、`gtrk mg status` 全绿后**别收工**——按 SOP 顺势接力到第 **AI 再现**:
160
- - `dispatch.ai_drama` 非空 → 触发 `/gtrk-ai-drama`(持通用分镜 craft + 读栏目 style-lock,产 AI 再现分镜稿——四段描述 + 独立视觉基调 + 时长预算;用户去可灵 / Vidu 等外部平台出片回铺;**此车道产物即分镜稿、无 gtrk 命令**)。一句话交代即推进:「MG 颗粒已叠铺完,我接着安排最后一步 AI 再现」。
161
- - `dispatch.ai_drama` 为空 本片没有 AI 车道,可直接 `gtrk render` 收口成片。
162
-
163
- 除非用户表示只铺这一版 MG、暂不往下。
164
-
165
- > 原则:**agent 替用户跑 CLI / 接力 skill、驱动栏目生产 skill,用户只对话**——别让用户自己去终端敲 `gtrk mg`,也别让用户手动去 call 栏目生产 skill。
1
+ ---
2
+ name: gtrk-mg
3
+ description: MG 动态图颗粒铺轨器——成片 SOP 第 步(**最后叠上**),在 B-roll 底轨三源(影视素材 / 本地素材 / AI 情景片段)全部铺齐、且 ④ 全局抽帧检查构图通过之后,把栏目的 html-particle 动态图颗粒(透明叠加 / 满屏底层)叠铺到已定稿的底轨之上。先由栏目 MG 生产 skill 按派单各槽位产颗粒,再驱动 `gtrk mg` 命令 lint + 铺进 `.gtrk` 工程的 beat_track。当用户想「铺 MG 颗粒 / 上动态图 / 铺动效 / 给这段配动画铺进工程 / 把 MG 派单铺轨 / 消费 dispatch.mg」时使用本 skill。凡涉及把 MG 动态图颗粒铺进已剪好的成片工程,优先用本 skill 驱动 gtrk CLI,别让用户自己去终端敲 `gtrk mg`。
4
+ ---
5
+
6
+ # MG 动态图铺轨(gtrk-mg)
7
+
8
+ 把 `gtrk split` 派好的 **MG 槽位**(`dispatch.mg`),先由**栏目的 MG 生产 skill** 产成 html-particle 动态图颗粒,再交给 `gtrk mg` 命令 lint + 铺进 `.gtrk` 工程的 `beat_track`——**叠在已经定稿的底轨之上(B-roll 三源全落齐、构图已核)**。**CLI 是手(lint / 铺轨 / 写回),你是脑(认 SOP 位置、驱动栏目生产 skill、管用户检查点、判 lint 该不该硬铺)。栏目生产 skill 只产纯净颗粒、不知 gtrk 命令,由你驱动。**
9
+
10
+ > **本 skill 已含你需要的全部信息**(SOP 位置、业务分离、逐槽位工作流、命令参数、lint 铁律、排错、交棒)。命令参数细节以 `gtrk mg --help` 为准;颗粒的视觉/内容规范**不在这里**——那是栏目资产,由栏目 MG 生产 skill 全权负责。
11
+
12
+ ## 你在成片 SOP 的哪一步(先认位置,别抢跑)
13
+
14
+ 成片是**有序 SOP + 用户检查点**,不是并行一次铺完。全序:
15
+
16
+ > ① `/gtrk-oralcut`(剪口播)→ ② `/gtrk-splitter`(拆分派单出 `dispatch.json`)→ **③ B-roll 底轨全铺齐**(`/gtrk-matrix` 铺影视/本地素材 + `/gtrk-ai-drama` 产稿→外部出片→用户手动回铺,**两条腿同一阶段**)→ **④ 全局抽帧检查画面构图(用户确认)****⑤ 本 skillMG(含 ov)最后叠上** → `gtrk render` 收口
17
+
18
+ **你是第 步、也是最后一层。** MG 颗粒是**唯一的叠加层**——底下那整层底轨必须先定死(**三源全落齐**),否则你的排版避让是对着一个不完整的画面做的。
19
+
20
+ > ⚠️ **AI 情景片段属于底轨 B-roll 画面家族,不是叠加层**。旧序把你排在 AI 再现之前、理由写「越往后叠得越上层」——**那是把「工序次序」误当成了「图层次序」**。AI 片段在你之后回铺,底轨构图就变了,你先产的颗粒必然避让错位、甚至盖住 AI 画面主体。
21
+
22
+ 所以动手前先过前置硬门。
23
+
24
+ ### 前置硬门(不满足就别铺,先回上一步)
25
+
26
+ 1. **影视/本地素材 B-roll 已铺且用户已确认**:若 `dispatch.film_broll` 非空,必须 ③ 已跑过 `gtrk matrix` **且用户已在 opencut 里挑选/调整确认**。没确认 → **别铺 MG**,先回 ③。(为空 = 本片没这条腿,看下一门。)
27
+ 2. **AI 情景片段已回铺,或用户明示先跳过**:若 `dispatch.ai_drama` 非空,必须已回铺完(用户已把外部平台出的片子拖进工程)**或**用户**明示**「先跳过 AI、先把 MG 铺上」。
28
+ - 外部平台抽卡可能数天,严格串行会把你无限期卡住,故留这个口子。
29
+ - **走跳过时你 MUST 付这个对价**:把**与 AI beat 相邻或重叠区间的 MG 颗粒**逐一标记为「**AI 回铺后待复查构图**」,并在交棒 `render` 时把该清单复述给用户。**MUST NOT 静默跳过** —— 用户得知道哪几颗将来可能要返工。
30
+ - (为空 = 本片没 AI 车道,此门自动通过。)
31
+ 3. **④ 全局抽帧检查已过、用户已确认构图**:对**三源合并后的最终底轨**抽帧看主体位置 / 安全区 / 画面朝向 / 明暗,用户确认无误。**这与 那次「挑选 B-roll」的确认是两次不同的确认**,别拿前一次顶替。没做先做 再回来。
32
+ 4. **有 split 产物**:需要一个跑过 `gtrk split` 的产物目录(含 `split/dispatch.json` 与工程 `.gtrk`)。没有 先回 `/gtrk-splitter`。
33
+ 5. **`dispatch.mg` 非空**:为空 = 本片没有 MG 车道 → **别硬造**,直接 `gtrk render` 收口(见末节)。
34
+ 6. **CLI 在**:`gtrk` 找不到让用户装 `npm i -g @gitruck/cli@latest`(需先有 Node.js)。
35
+
36
+ ## 业务分离:谁产颗粒(栏目),谁铺轨(本 skill
37
+
38
+ **本框架 skill 不硬编任何栏目的视觉风格/生产内容。** MG 颗粒长什么样、用什么视觉语法,全由**栏目的 MG 生产 skill** 决定;本 skill 只负责「在对的时候、按派单、驱动它产,然后把成品铺进工程」。
39
+
40
+ **车道 栏目生产 skill 的解析(照此,别猜)**:读**有效栏目配置**的 `style.skills[]`(配置文件 `~/.gitruck/columns/<id>.json`;栏目 id 由 `--column <id>` 或 config `defaultColumn` 选取;零配置 = L0 内置默认栏目,**不携带 style 清单** → 必然走下方「无匹配」分支)。在 `style.skills[]` 里取 **`produces` 归一后(旧 `RRV_MG` → `MG`)等于 `MG`** 的条目 → 触发它 `ref` 指向的 skill 产颗粒。
41
+ - 命中多条 按栏目约定取其一(一般栏目只登记一个 MG 生产 skill)。
42
+ - 条目带 `routing:"none"`(管线外产物,如封面)→ 跳过,不当 MG 生产 skill。
43
+ - **无匹配** = 本栏目没有 MG 生产 skill → 别硬铺;告诉用户「本栏目还没有 MG 生产 skill,先用 `/gtrk-style-maker` 建一个,或换个已配置的栏目(`--column`)」。
44
+
45
+ > **生产 skill 是栏目的纯净资产**:它只懂本栏目的视觉语法、只产 html-particle 颗粒,**不知道 gtrk 命令、不知道产物落哪**。由本 skill 驱动它、并**由本 skill 负责把它产出的颗粒存到 `gtrk mg` 要读的路径**:`<产物目录>/mg/<composition_id>.html`。举例(仅示意解析机制,非硬编):`real-roam-guide` 栏目配置里 `style.skills` 有一条 `{produces:"MG", ref:"…/real-roam-viz"}` → 驱动它产颗粒;换个栏目、换个 ref,产颗粒的就是另一个生产 skill。**本 skill 正文里不绑死任何栏目的生产 skill。**
46
+
47
+ ## 逐槽位工作流(产 → lint → 铺,循环到铺满)
48
+
49
+ > **产物落点纪律(MUST · 全文见随包 `AGENT.md` 同名一节)**:
50
+ > 一切产物(颗粒 HTML / 成片 / 预览 / 素材 / 工程文件)只落**工程目录**(颗粒恒存 `<产物目录>/mg/`)或**用户显式指定的输出路径**;
51
+ > **MUST NOT** 把成片、预览或任何大媒体文件复制到 agent 自有工作目录(如用户文档目录下 agent 产品自建的目录、agent 家目录缓存、会话工作区)——需要引用媒体时**用原路径引用**,不做副本;
52
+ > 临时文件(抽帧图等)一律放系统 temp 且**用完即删**(含中断 / 失败路径)。违者后果 = 用户系统盘被静默吃满(真机事故,非假设)。
53
+
54
+ ### 1. 看板起手:先看 `dispatch.mg` 有哪些槽位、铺到哪了
55
+
56
+ ```bash
57
+ gtrk mg status --project "<split产物目录>" --json
58
+ ```
59
+
60
+ - 汇总 MG 流水线:`dispatch.mg` beat 槽位总数 / 已产源 HTML / 已铺进 `.gtrk` 数,并**逐 beat 标注**(缺 HTML / 已产未铺 / 已铺)。
61
+ - 每个槽位有 `composition_id`(主颗粒 = `<工程slug>-<beatId>`;`overlay` 叠层派生颗粒 = `<工程slug>-<beatId>-aux<n>`)与 `handoff`(`theme` / `duration_hint`(秒)/ `category` 等)。**这些是你交给栏目生产 skill 的产片订单。**
62
+
63
+ ### 2. 逐槽位产颗粒(驱动栏目 MG 生产 skill)
64
+
65
+ 对每个「缺 HTML」的槽位:把它的 `composition_id` + `handoff`(`theme` / `duration_hint` / `category`:`overlay` 透明叠加·不挡主体 / `fullscreen` 不透明满屏)+ beat 语义上下文,**交给第「业务分离」节解析出的栏目 MG 生产 skill 产一颗 html-particle**。产完把颗粒**存到 `<产物目录>/mg/<composition_id>.html`**(`gtrk mg` 就从这里读)。
66
+ - **产前先抽帧看底轨(`overlay` 槽位必做,别只凭派单盲产)**:颗粒最终要叠在真实画面上,构图必须因势象形。对该槽位挂点用本地 ffmpeg 抽 1-2 帧(`ffmpeg -ss <track_st秒> -i <底轨视频> -frames:v 1 "<系统temp>/<beat>.jpg"`,成本≈0;抽帧图是临时文件——落系统 temp、用完即删,**别落 cwd / agent 自有目录**)看清三件事——①真人主体/人脸的位置(颗粒 bbox 避开,呼应栏目「不盖说话人」铁律);②该处是否已有烧入包装或 AI 画面(有 → 别铺这颗,报用户裁决——二次过毛片高发);③画面明暗基调(深底/浅底影响衬底与配色取舍)。把这些**连同抽帧图一起附进产片订单**交给栏目生产 skill;`fullscreen` 槽位可免(满屏不透明无避让问题)。
67
+ - **产片订单必须附带坑位硬约束(gsap-emit v1 铁律⑦,2026-07-24 主理人硬性规定)**:颗粒 GSAP 时间线总长 ≥ **坑位时长**(该槽位 `track_ed − track_st` 包络,**不是** `duration_hint`)+ 0.3s 余量;`duration_hint` 只是动画主叙事节奏参考。主叙事播完后颗粒必须**定格保持或有限循环驻留到坑位末尾**——坑位内任意一帧核心内容都可见;**禁全局渐隐/整体退场/清空画面**(渐隐与剪辑层转场冲突,淡出由剪辑层决定);定格不动是合法终态。违反的观感 = 动画一过完颗粒突兀消失。
68
+ - **`-aux<n>` 叠层颗粒同样处理**:`gtrk split` 若在某 beat `aux_layers` 派了 `overlay`,会派生 `<beat>-aux<n>` `dispatch.mg`(多为 B-roll 底轨之上叠透明概念图解)——照样产、照样存到对应 `composition_id.html`。
69
+ - **category 决定叠法**:`overlay` 颗粒背景透明、盖在 B-roll 上不挡主体;`fullscreen` 不透明满屏。最终透明度由颗粒 HTML `background` 声明反推的 `opaque` 定,生产 skill 要让二者自洽(lint 会查)。**「实心底该写在哪个元素上」的正本条款是 `contracts/gsap-emit-v1.md` 铁律 4(含真机证据锚)——本 skill 不复述元素位置,改了要以契约为准**;`fullscreen` 颗粒把实心底写错地方会吃非致命 `4-bg-on-root`(见下节)。
70
+
71
+ ### 3. lint 门:铺之前先单测每颗(不过就退回生产 skill,别硬铺)
72
+
73
+ ```bash
74
+ gtrk mg lint "<产物目录>/mg/<composition_id>.html" --dispatch "<产物目录>/split/dispatch.json"
75
+ ```
76
+
77
+ - 纯本地静态校验颗粒 HTML 的**铁律机器可判定子集**:`<template>` 包裹、`data-composition-id` + 1920×1080、`gsap.timeline({ paused: true })`、`window.__timelines` 注册、无 `Math.random` / `Date.now`(可逐帧 seek 的确定性)、自包含无相对外链、`background` 声明与 `opaque` 自洽…;给 `--dispatch` 会额外校验 `composition_id` 命中派单。
78
+ - **`1-cid-expect`(致命)——复制改名必查**:颗粒内部的 `data-composition-id` 必须等于期望 id(`--dispatch` 命中时 = 该条派单的 `composition_id`,否则 = 文件名)。**你从别的颗粒复制模板时最容易漏改内部 id**:那样铺出来的 clip 指向 A、文件注册的却是 `__timelines["B"]`,渲染必错,且两颗粒抢同一个 `[data-composition-id]` 样式作用域。改名的临时副本(`./tmp.html`)不比对,不会误伤。
79
+ - **铁律④「实心底与透明度」两项恒非致命**(正本条款 = `contracts/gsap-emit-v1.md` 铁律 4,含 2026-07-26 真机证据锚;**本处只说看到该码怎么办,元素位置以契约为准**):
80
+ - `4-bg-on-root`:这颗把**实心底写在了根元素的 `style` 上**。**根元素的绘制属性会在子合成挂载时被丢弃**——那层底在成片里**一个像素都不落地**:前景照常渲出、底没了、底轨透出来,观感是「浮空面板」;而**本地播放器与客户端预览都看不出**(预览会按登记的 `opaque` 位自己给根盒打底,对这个问题结构性失明)。**报了要回步骤 2 让生产 skill 把实心底下沉为子层**——改法是机械的(把那条 `background` 声明整体搬到根下第一个全幅子层,根上改写 `background:transparent`)。⚠️ 它**不影响退出码、不拦铺轨**(避免存量颗粒一夜之间铺不进去),但**不是可以放着不管的噪音**:不改就是出片丢底。
81
+ - `4-bg-explicit`:根与根下首个全幅子层**都**没有 `background` 声明 → lint 只能按「透明叠加」处理。契约要求**透明与否显式**:满屏颗粒在全幅子层写实心底,透明叠加颗粒在根写 `background:transparent`。**别靠「不写」表达透明**——作者与机器都分不清「想透明」和「忘了想」。
82
+ - 两项都**只看 `background` 声明摆在哪**,不看色值(色值属栏目审美,契约不管)。`opaque` 的推导面 = 「根 `style` 根下首个全幅子层 `style`」,与契约铁律 4 同源;**合规的子层写法不会再被误判成 `opaque=false`**(旧版 CLI 会,导致满屏颗粒被登记成透明叠加)。
83
+ - **铁律⑦ 估长三项恒非致命、不是放行凭据**(`--dispatch` 命中派单条目才跑,因为要拿该条的坑位包络):
84
+ - `7-fill-slot`:静态估长 < 坑位包络 「疑未占满」。估长是**下界**(表达式 position、非字面量 duration 那些调用算不了、跳过不计),报出来基本就是真短,**回步骤 2 让生产 skill 把驻留补到坑位末尾**。
85
+ - `7-no-estimate`:一条时长调用都解析不到 **明说「铁律⑦这颗没校验」**,不是通过。这时 tl 总长只能靠真引擎 seek 或人读代码确认,别当它过了。
86
+ - `7-infinite-repeat`:颗粒里写了 `repeat:-1` 总长变 `Infinity`、铁律⑦不可验证(契约 2026-07-26 已明文禁)。让生产 skill 改成按坑位算死的有限次数:`repeat = ceil((坑位 循环起点) / 单圈) − 1`。
87
+ - 三项都**不影响退出码、不拦铺轨**——真判据是渲染引擎逐帧,静态估长只做提醒。**但「没报 7-fill-slot」≠「时长够了」**,要看是否同时出了 `7-no-estimate`。
88
+ - **铁律⑧「重复图元合并」为恒非致命提示,但看见必须处理**:
89
+ - `8-primitive-merge`:这颗有一批由循环直接创建、或由循环调用具名工厂创建的可合并重复图元;它们落到同一父节点,且没有逐元素动画驱动。纯数字循环可算且同父累计 **≥ 8** 时会报数;边界算不出时会报「条数未知」。逐元素 `gsap.set` / tween、或作为 tween 首实参使用的元素数组会被排除。
90
+ - 本项报的是「这批图元可**无损**合并,合并后画面逐像素不变」这一写法事实,**不是**「该颗粒有缺陷」或「超过某个数量会出问题」;真实触发轴未知。反过来,没报也**不代表安全**,真判据仍是真渲染出片抽帧。
91
+ - **处置**:回步骤 2,把原始提示完整交给栏目 MG 生产 skill,让它把整组同步驱动的网格 / 排线 / 刻度 / 点阵合成单元素(SVG 用一条 `<path>` 多子路径;同色分档可分档合成),然后重产、重 lint。**别硬铺,也别当没看见**;CLI 为兼容存量把它做成**非致命、不影响退出码、不拦铺轨**,不等于 agent 可以跳过修正。确需 stagger / 逐条画入 / 逐个变色的逐元素动画批次属于契约豁免,不要为了消项删掉动画身份。
92
+ - **「回调与 seek 语义」三项恒非致命**(契约同名一节,2026-07-26 增补;**报了不用改颗粒**):
93
+ - `x-callback-driven`:这颗的画面靠 `onUpdate` 等时间线回调写 DOM 驱动,且没带任何 seek 兜底(GSAP `seek(t)` 的 `suppressEvents` 缺省为 `true`,会吞掉回调)。**该写法合规**——回调可达性由契约压在**引擎侧**的 MUST 条款保证(引擎定帧 MUST 用 `seek(t,false)` / `time(t)` / `progress(p)`),**且该条款已于 2026-07-26 经真渲染引擎核实**(producer `0.6.101`,纯回调驱动无垫片颗粒三帧读数各不相同)。本项**核实之后照留**做**哨兵**:结论绑死引擎版本,引擎换实现或失守时补间属性照常插值、回调不跑 → 画面**静默定格在初始态**(不是黑屏,本地播放器和预览都看不出)。**别因为它去让生产 skill 改写法,更别让它自己加垫片。**
94
+ - `x-engine-api-override`:颗粒运行时覆写了 `tl.seek`(老颗粒常见的 `rr-seek-shim`)或把 `__timelines[…]` 换成了包装对象。它会推翻引擎显式传的 `seek(t, true)`,且引擎改走 `time()`/`progress()` 就完全失效。**既有垫片属过渡态**:2026-07-26 引擎侧结论已核实(引擎本就不抑制回调),垫片已无保护作用、也无害,**可择期清理**(删后须重跑 lint 并重渲复验),不清也不拦;新颗粒别再加。
95
+ - `x-raf-interval`:颗粒里有 `requestAnimationFrame(` / `setInterval(`。这类自有时钟**不被 seek 驱动**,逐帧渲染时等于冻结(契约明令:所有视觉变化必须挂在 tl 上)。静态正则分不清用途,报了要**人眼确认它是不是在驱动画面**;若是 → 回步骤 2 让生产 skill 改挂 tl。
96
+ - 另:引擎不抑制回调 = 逐帧 scrub `onComplete`/`onStart`/`onRepeat` 会**反复触发**。颗粒里**别写「只跑一次」的回调**(累加计数 / `push` 数组 / 一次性 DOM 插入),要写成每次从补间状态**重算**的幂等形式。
97
+ - **成本项 `c-filter-*` 三项恒非致命、当期全部不拦铺轨**(正本条款 = `contracts/gsap-emit-v1.md`「渲染成本:真卷积滤镜」一节):这组查的是**每帧成本**、不是正确性——命中的颗粒**画面是对的,只是渲得慢**。
98
+ - `c-filter-animated`:**时间线补间直接驱动了真卷积滤镜**(`filter:blur()/drop-shadow()`,或补间驱动 SVG `feGaussianBlur` 的 `stdDeviation`)。滤镜值一变,上一帧的卷积结果当场失效、缓存彻底失灵,是这组里**最贵**的形态。**处置**:回步骤 2 让生产 skill 改用 `opacity` / `transform`(`scale`/位移)表达同一叙事动作;确需滤镜就做成**静态两态切换**。**不拦铺轨**。
99
+ - `c-filter-static-fullbleed`:**整幅静态真卷积滤镜**(该声明自身就是 `position:absolute;inset:0` 一类铺满形态)。每帧对整幅做一次卷积。**首选改法是缩小被滤镜覆盖的几何面积**(面积一项同时压掉卷积与整幅逐帧合成两笔成本);次选把静态滤镜结果预烘成图,且**必须是 RGBA PNG**(透明叠加颗粒的 alpha 是成片合成的必需通道,烘成 JPEG 或无 alpha 格式会在成片里塌成不透明色块),但预烘只消得掉卷积、消不掉整幅逐帧合成,**收益有上限**。去不去滤镜属审美取值,**判断权在作者**,本项只给信息与改法。**不拦铺轨**。
100
+ - `c-filter-indeterminate`:补间的 `filter` 值不是字符串字面量(变量 / 模板串 / 函数返回),lint **对该处没作判定**——既不是「判过且通过」,也不是命中。**人眼确认它到底会不会驱动 blur / drop-shadow**;会就按 `c-filter-animated` 的改法处理。**不拦铺轨**。
101
+ - **`box-shadow` 整族不在射程内**(含 `box-shadow: 0 0 0 Npx` 这类零卷积脉冲写法,也含带模糊半径的写法)——看到 `box-shadow` 没被报**不是漏报**,是既定射程边界。
102
+ - ⚠️ **没报 ≠ 这颗便宜**:这三项是**形态提示**,真判据永远是**真渲染出片计时**。收益也别外推——现网既有栏目语料(21 颗)去掉滤镜只省 **0~3.1%**(2026-07-30 真机实测,仅对该语料成立),这组规则的价值在**滤镜重的新语料进管线前先把门立好**。
103
+ - **id 前缀读法**(三个命名空间,别按前缀反推错阻断行为):**数字前缀 `1-`~`8-`** = 契约铁律项,致命性**按项声明**(`4-*` / `5-*` / `7-*` / `8-*` 就都不致命);**`x-`** = 哨兵项,**恒不拦**;**`c-`** = 成本项,致命性按项声明,**当前三项均不拦**。
104
+ - **不过(非 0 退出、逐条报因)→ 把报错原样丢回栏目 MG 生产 skill 修,重产重 lint,别硬铺**。铺一颗不合规颗粒会污染工程。
105
+ - 只想批量干校验不写回:`gtrk mg --project <dir> --lint-only`(有 beat 没过就 `ok:false` + **非 0 退出**,工程一个字节都不动)。
106
+
107
+ ### 4. 铺轨:全槽位就绪后铺进工程(叠在 B-roll 之上)
108
+
109
+ ```bash
110
+ gtrk mg --project "<split产物目录>" --json
111
+ ```
112
+
113
+ - `dispatch.mg` 逐 beat 从 `<project>/mg/<composition_id>.html` 取源颗粒 → lint → 铺进 `.gtrk` 的 `beat_track`,把 `struct_meta.mg` 原子写回。**幂等**:重铺先剥旧自产轨再 append,用户在 opencut 手加的轨零连带。
114
+ - **剥离面口径**(= 「本次会剥掉什么」,和「本次铺什么」是两件事):
115
+ - **`--only <beat>` = 只剥命中的那几颗**(真增量合并)——轨上其余已铺颗粒连同用户手调**原样保留**。
116
+ - **全量重铺 = 剥掉登记里的全部自产轨再整轨重建**,**唯一例外**:本次派单里有、却因缺 HTML / lint 未过 / 重投影后零存活而**没铺成**的那些(`skipped` 里那几颗),它们上一轮的 clip **留在轨上**——不会因为新的做坏了就把旧的也毁掉。反过来,**派单里已不存在**的已铺条目(你重跑过 `gtrk split`、这个 beat 不做 MG 了)仍照剥:那是计划变更,不是做坏了。
117
+ - 所以「轨上共几颗」**不一定**等于「本次铺了几颗」——差额就是 `kept`(见下 `--json`),**必须一起读**。
118
+ - 真要**重置整轨**(连其余已铺颗粒一起剥掉重来):加 `--replace-all` 显式授权。
119
+ - **素材表不再囤积**(剥离键按「自产身份 × 零引用」判,不认客户端可改写的 `html_material` 前缀):
120
+ opencut 里编辑过工程之后重铺,旧的自产素材条目照样剥得掉,`mg-` 素材数**恒等于轨上颗粒数**;
121
+ 历史遗留的重复 / 孤儿条目会在下一次重铺时一并清掉。**非自产素材零连带**——`broll-*`、`ex-solid-*`
122
+ 垫轨、你自己加的素材一条不碰(哪怕它当前没被任何 clip 引用)。盘上 `assets/mg/` html 副本从不删。
123
+ - `--json` 输出:`{ ok, mode:"lay", laid, track_total, kept, kept_ids, removed, skipped, reason?, integrity?, … }`。
124
+ - **`laid`** = **本次**铺成数;**`track_total`** = **轨上现存**已铺数;**`kept`** = 其中**上轮遗留**(本次没重铺)的颗数。三个数一起读——只看 `laid` 会让「铺 1 颗、剥 20 颗」跟「补铺 1 颗」长得一模一样。恒有 `track_total = laid + kept`。
125
+ - **`kept_ids`** = 上轮遗留的 `composition_id` 清单。**要判断轨上某颗是不是这一轮的版本,看它在不在这里**——`kept > 0` 就意味着轨上内容与本次派单不完全对应(要全部刷新:去掉 `--only` 全量重铺)。
126
+ - **`removed`** = 本次被剥掉的旧自产颗粒数(= 上一轮已铺里没被保留下来的,含「剥了再铺」的那些)。
127
+ - **`skipped`** = 缺 HTML / lint 失败的 beat(不拦其余)——**回步骤 2 补产、重铺**,别当没看见。**注意它和 `kept_ids` 会重叠**:某颗这轮没铺成(进 `skipped`)、上一轮那条还留在轨上(进 `kept_ids`),画面在但不是新版本,跟用户说清楚。
128
+ - **`reason`** = 非全绿时的机读判据:`skipped`(部分没铺上)/ `empty_queue`(**拒写回**,工程未被改动)/ `no_project`(工程缺失未铺轨)。
129
+ - **`reprojection`** = 本次落轨时码的来源与漂移摘要(恒出,`--lint-only` 也有):`{ mode:"reprojected"|"dispatch_snapshot", degraded, reason?, drifted, max_offset, shrunk:[…], dropped:[…] }`。
130
+ **时码是现场重投影出来的**:命令每次都用 `transcript × 当刻 .gtrk` 重算每个 beat 的窗口(与 `gtrk split` 落地同一段代码),`dispatch.json` 里的时码只是投影那一刻的快照。**所以用户在 split 之后微调口播轨不用回去重跑 `gtrk split`**,只有**拆分稿本身**变了才要重跑。
131
+ `drifted > 0` = 这次铺的位置和派单上写的不一样(正是它该做的),把条数与 `max_offset` 报给用户;`dropped` 里的 beat = 那段已被整个剪出成片,**故意不铺**(不会按快照塞回去)。
132
+ - **`integrity`** = **素材落盘自检**(与 `gtrk matrix` 同名同形):写回工程之后自动查一遍
133
+ 「`materials[].path` 是不是真的都落盘了」。**只在真写回过的运行里出现**(`no_project` / 拒写回 /
134
+ `--lint-only` 时**字段缺席** = 本次没查,别当成「查过且干净」)。
135
+ `dangling` = 悬空引用全量(相对路径素材登记在、文件不在,每条带 `referenced` 与引用位置 `refs`);
136
+ `danglingReferenced` / `danglingOrphan` = 被时间线引用数 / 孤儿数——**两者严重度差一个量级,回报时分开说**;
137
+ `external` = 绝对路径素材找不到文件(另一档,不进 `dangling`)。
138
+ **告知不拦阻**:查出悬空不改 `ok`、不改退出码、不删任何东西;非零就报给用户(哪几条、在哪一段),
139
+ 多半是历史遗留(如客户端「确认原片」下载中断),修法在客户端而不在这里。**别自己去删素材或文件。**
140
+ - **退出码**:`ok:false` 一律连带**非 0 退出**(含「有 beat 被 skip」这种循环中途的正常态)。**别把非 0 读成「命令崩了」**——它说的是「这一轮没全铺成」,按 `reason` / `skipped` 处理后重跑即可。
141
+ - **只铺单个 beat**:`--only <beatId>`(收的是 **beat id** 如 `B12`,不是 `composition_id`;主颗粒 + 其 `-aux<n>` 叠层一并选)。
142
+ - **语义 = 真增量合并**:只重铺命中的那几颗,轨上**其余已铺颗粒原样保留**——连它们的透明度与用户在 opencut 的手调一起活着(保留的是既有 clip 原件,不是照登记重建的)。适合迭代改单段。
143
+ - 保留下来的那几颗**不重新 lint、不重新复制源 HTML**:工程是自包含的,`<project>/mg/` 下对应源文件即便已经删了也不影响。
144
+ - 代价看 `kept` / `kept_ids`:轨上会同时存在「本次这版」和「上轮那版」。要把全部颗粒刷成最新(含按当刻时间线重投影的新位置),**去掉 `--only` 全量重铺**(幂等、多铺几颗不花钱)。
145
+ - 确实要**重置整轨**(连其余已铺颗粒一起剥掉重来)才加 `--replace-all` 显式授权。
146
+ - **仍会拒写的唯一情形**:本次**一条都没定位到**(`--only` 打错 beat id、`dispatch.mg` 为空、或本次条目全被 skip)**而轨上已有已铺颗粒**——那是派单或选择器出问题的信号,不是清空指令,CLI 拒绝写回并报因(`.gtrk` 逐字节不变)。
147
+ - **铺完必核「clip 占满坑位」**:读回 `.gtrk`,各 beat clip 的时长必须 = 槽位包络(`track_ed − track_st`)。若你的 CLI 版本按 `dispatch.mg[].duration`(旧 `duration_hint` 语义)落轨、导致 clip 短于坑位(颗粒在 beat 中途突兀消失,2026-07-24 真机实测),**把 `dispatch.mg[]` 各条 `duration` 改为包络秒数(`track_ed − track_st`)后重铺**(铺轨幂等、直接覆盖)。CLI 侧根治(落轨恒用包络)落地后此步可省。
148
+
149
+ ### 5. 循环到铺满
150
+
151
+ MG 槽位就**循环「产 → lint → 铺」直到 `dispatch.mg` 全部铺满**(`gtrk mg status` 逐 beat 全标「已铺」、`gtrk mg` 的 `skipped` 为空、`ok:true` 且退出码 0)。**循环中途 `skipped` 非空时命令按 `ok:false` + 非 0 退出如实上报**,那是「还没铺满」不是「命令失败」——照常补产重铺即可;`--lint-only` 同口径。
152
+
153
+ > **循环里别用 `--only` 逐颗铺**:`--only` 是增量的(安全,不会铲掉别的),但它**只刷新命中的那几颗**——轨上其余颗粒会一直停在上一轮的版本与上一轮的落轨位置(`kept_ids` 会如实点名)。循环的正确姿势是**每轮都全量重铺**:铺轨幂等,多铺几颗不花钱,而且顺带把全部颗粒按当刻时间线重投影一遍。`--only` 留给「已经铺满、只想改某一段」。
154
+
155
+ > 旧名 `gtrk rrv` 是去品牌化前的弃用别名(仍能跑但会打提示)——**一律用 `gtrk mg`**。
156
+
157
+ ## 读结果、给用户交代(别只说「铺好了」)
158
+
159
+ - **铺了哪些**:`laid[]` `composition_id`,对应哪些 beat;其中哪些是 `overlay` 透明叠加(盖在 B-roll 上)、哪些是 `fullscreen` 满屏。
160
+ - **没铺上的**:`skipped[]` + 原因(缺 HTML 还是 lint 失败 / 重投影后零存活)——如实说,别谎报全铺;已补产重铺的说清楚补了哪几颗。
161
+ - **落轨位置变了要说**:`reprojection.drifted > 0` 时报出「本次按当刻时间线重投影,N beat 的位置与派单不同、最大偏移 X 秒」。这是对的(用户改过口播轨),但**必须让他看见**,别悄悄改掉。
162
+ - **报「已降级至派单快照时码」**(`reprojection.degraded:true`):不是故障、没拦你,是算不出当刻窗口、退回了可能已过期的快照。照 `reprojection.reason` 给出路——`transcript_missing` → 把 `transcript.json` 补回产物目录(`transcript/` 或 `json/` 下),或用新版 `gtrk oralcut` 重出产物;`no_project`/`gtrk_unreadable` → 把工程放回 `<产物目录>/gtrk/project.gtrk` 或 `--project` 指对目录;`no_material_clip` → 口播主轨被整条删了 / relink 换了素材 id / 拿了另一个工程的 dispatch。用户接受快照也行,但要如实说「这批位置按的是上一次投影的时间线」。
163
+ - **轨上有几颗不是这一轮的**:`kept > 0` 时点名 `kept_ids`——「这次只重铺了 N 颗,轨上另外 K 颗是上一轮的(位置和内容都还是旧版),要全刷新就全量重铺一次」。**别让「铺轨完成」读起来像轨上全是新的。**
164
+ - 想在 opencut 里精修颗粒(手调参数/时长)→ 提示用户可打开工程手调。**但要把话说全**:手调只在「这颗**没被**下一次重铺命中」时活得下来——`--only <别的 beat>` 或全量重铺时被 skip 掉的那几颗会原样保留(含手调);**一旦某次重铺真的铺到了这颗,CLI 自产的新 clip 会整条覆盖它,手调就没了**。要长期保留的手调,别放在 CLI 自产的 MG clip 上。
165
+
166
+ ## 交棒 `render` 收口(你是最后一层,别停在铺完)
167
+
168
+ `dispatch.mg` 全铺满、`gtrk mg status` 全绿后**别收工**——你已是最后一层,顺势 `gtrk render` 收口成片。一句话交代即推进:「MG 颗粒已叠铺完,我接着出片」。
169
+
170
+ ★ **若你是走前置硬门 2 的「明示跳过 AI」进来的**:收口前 MUST 把那份「**AI 回铺后待复查构图**」清单复述给用户(哪几颗颗粒、对应哪几个 AI beat 区间),并说明「AI 片段回铺后这几颗可能要重产」。**MUST NOT 静默收口。**
171
+
172
+ 除非用户表示只铺这一版 MG、暂不出片。
173
+
174
+ > 原则:**agent 替用户跑 CLI / 接力 skill、驱动栏目生产 skill,用户只对话**——别让用户自己去终端敲 `gtrk mg`,也别让用户手动去 call 栏目生产 skill。
@@ -49,6 +49,8 @@ gtrk split --project "<oralcut产物目录>" --json
49
49
 
50
50
  **抽帧确认底轨画面(凡毛片可能已含视觉包装时必做,勿只凭文稿派单)**:view.json 只给你文字,看不见画面——但毛片未必是素的。**二次过 / 补 ov 场景**(毛片本身是已烧入 MG、AI 再现或其他包装的成片再加工)尤其危险:只凭时码派 overlay 会撞上已有包装叠罗汉。姿势:对候选挂点(尤其打算派 `overlay` 的句区间)用本地 ffmpeg 按 `track_st` 抽 1 帧看一眼(`ffmpeg -ss <秒> -i <毛片> -frames:v 1 "<系统temp>/<句id>.jpg"`,成本≈0;抽帧图是临时文件——落系统 temp、用完即删,**别落 cwd / agent 自有目录**),确认该处画面性质——**裸口播 → 正常派;已有包装 → 避开该区间或另选挂点;拿不准 → 列给用户裁决**。首次过全素毛片可免;一旦毛片来历含「粗剪成片 / 待 ov 补充 / 二次过」字样,此步为硬门。抽帧顺带看清真人主体位置与画面明暗,写进 beat 的语义上下文,供下游产颗粒时构图避让。
51
51
 
52
+ > 📌 **这一步与 SOP ④ 的全局抽帧检查不是同一件事,两者都要**:这里抽的是**毛片原始画面**(派单前,判该处是裸口播还是已有包装);④ 抽的是**B-roll 三源全铺齐后的最终底轨**(产 MG 前,供排版避让)。前者防「派单派到包装上」,后者防「MG 对着不完整底轨做避让」。
53
+
52
54
  ### 3. 写拆分稿 JSON
53
55
 
54
56
  按 `references/field-schema.md` 的契约写。骨架:
@@ -115,19 +117,26 @@ gtrk split "<拆分稿.json>" --project "<oralcut产物目录>" --md --json
115
117
 
116
118
  ### 7. 交棒下游 SOP(有序,别停在派单)
117
119
 
118
- dispatch 落地后**不要收工**——但下游各车道是**有先后的 SOP、每步用户可介入**,**不是并行一次铺完**。次序(有理由:MG 叠在 B-roll 之上,要先把底层定下来):
120
+ dispatch 落地后**不要收工**——但下游各车道是**有先后的 SOP、每步用户可介入**,**不是并行一次铺完**。次序:
121
+
122
+ > **③ B-roll 底轨全铺齐(影视素材 / 本地素材 / AI 情景片段)→ ④ 全局抽帧检查画面构图 → ⑤ MG(含 ov)叠上 → `gtrk render` 收口**
123
+
124
+ **为什么是这个序**:**AI 情景片段属于底轨 B-roll 画面家族,不是叠加层**——叠加层只有 MG(含 ov)。MG 的排版决策是「因势象形避主体」,**依赖底轨的最终画面构图**;若 AI 片段在 MG 之后才回铺,底轨构图就变了,先产的 MG 是对着「还没有 AI 画面的底轨」做的避让,AI 片段落位后必然错位、甚至盖住 AI 画面主体。
119
125
 
120
- > **③ 先铺 B-roll(定底层)→ 用户调整确认 → ④ 再铺 MG(叠在 B-roll 上)→ 最后上 AI 再现 → `gtrk render` 收口**
126
+ > ⚠️ 旧序(MG AI 再现之前)的理由写的是「越往后叠得越上层」——**那是把「工序次序」误当成了「图层次序」**。工序上 AI 片段必须先落位;图层上它本来就在底轨。
121
127
 
122
- 按序推进、每步替用户跑命令,**关键处(尤其 B-roll 铺完)停下等用户确认**再进下一步;哪条车道 dispatch 队列为空就跳过。
128
+ 按序推进、每步替用户跑命令,**关键检查点停下等用户确认**再进下一步;哪条车道 dispatch 队列为空就跳过。
123
129
 
124
- - **③ B-roll**(`dispatch.film_broll` 非空):跑 `gtrk matrix --project <目录>`(检索 + 候选铺轨)→ **提示用户 opencut 里挑选/调整 B-roll**(小眼睛切换对比),确认后再进 ④。
125
- - **④ MG**(`dispatch.mg` 非空):先由**栏目 MG 生产 skill** 按各槽位 `handoff`(theme/duration_hint/category)产 html-particle 颗粒,再跑 `gtrk mg --project <目录>`(lint + 铺轨,叠在 B-roll 上)。
126
- - **⑤ AI 再现**(`dispatch.ai_drama` 非空):触发 `/gtrk-ai-drama` skill(持通用分镜 craft + 读栏目 style-lock)产 AI 再现分镜稿(四段描述 + 独立视觉基调 + 时长预算)→ 用户去可灵 / Vidu 等外部平台出片、回铺(**此车道产物即分镜稿、无机械尾巴 → 只 skill、无 gtrk 命令**,同 `/gtrk-style-maker`)。
130
+ - **③ B-roll 底轨(两条腿,同一阶段)**
131
+ - **影视 / 本地素材腿**(`dispatch.film_broll` 非空):跑 `gtrk matrix --project <目录>`(检索 + 候选铺轨)→ **提示用户 opencut 里挑选/调整 B-roll**(小眼睛切换对比)。
132
+ - **AI 情景片段腿**(`dispatch.ai_drama` 非空):触发 `/gtrk-ai-drama` skill(持通用分镜 craft + 读栏目 style-lock)产分镜稿(四段描述 + 独立视觉基调 + 时长预算)→ 用户去可灵 / Vidu 等外部平台出片、**手动回铺**(此车道产物即分镜稿、无机械尾巴 → 只 skill、无 gtrk 命令,同 `/gtrk-style-maker`)。
133
+ - ⚠️ **异步等待的口子**:AI 出片是手动异步(外部平台抽卡可能数天),严格串行会把后续无限期卡住。故 `dispatch.ai_drama` 非空时,进 ⑤ 的硬门是「**AI 片段已回铺 ∨ 用户明示先跳过**」。走「明示跳过」时你 MUST 把**与 AI beat 相邻或重叠区间的 MG 颗粒**标记为「AI 回铺后待复查构图」,并在交棒 `render` 时把该清单复述给用户——**MUST NOT 静默跳过**。
134
+ - **④ 全局抽帧检查画面构图**(关键检查点,无专属 skill、是 agent 纪律):对**三源合并后的最终底轨**抽帧,看主体位置 / 安全区 / 画面朝向 / 明暗,供 ⑤ 的 MG 排版避让决策使用。**MUST 停下等用户确认构图无误**再进 ⑤(这与 ③ 铺完那次确认是两次不同的确认)。
135
+ - **⑤ MG(含 ov),最后叠上**(`dispatch.mg` 非空):先由**栏目 MG 生产 skill** 按各槽位 `handoff`(theme/duration_hint/category)产 html-particle 颗粒,再跑 `gtrk mg --project <目录>`(lint + 铺轨,叠在已定稿的底轨之上)。
127
136
 
128
137
  **各车道的生产 skill 由栏目配置解析(业务分离)**:读 `style.skills[]`,取 `produces` 归一(旧 `RRV_MG`→`MG`)== 该车道 的条目 → 触发其 `ref` 指向的 skill;`routing:"none"` 跳过;无匹配 = 无生产 skill(B-roll 无需、A_ROLL 就是口播本身)。生产 skill 是栏目资产、留纯净、不知 gtrk 命令。
129
138
 
130
- > 每车道有专属**驱动 skill**(懂 SOP 位置 + 管用户检查点):拆分派单后**直接交棒 ③ `/gtrk-matrix`**(先铺 B-roll),它再按 SOP 交棒 `/gtrk-mg`、⑤ `/gtrk-ai-drama`。你(agent)触发 `/gtrk-matrix` 起步即可。**agent 替用户跑 CLI,用户只对话。**
139
+ > 每车道有专属**驱动 skill**(懂 SOP 位置 + 管用户检查点):拆分派单后**直接交棒 ③ `/gtrk-matrix`**(B-roll 底轨的影视/本地素材腿),AI 车道非空时它再交棒同阶段的 `/gtrk-ai-drama`;三源落齐 + ④ 抽帧检查过后,才交棒 ⑤ `/gtrk-mg`。你(agent)触发 `/gtrk-matrix` 起步即可。**agent 替用户跑 CLI,用户只对话。**
131
140
 
132
141
  ---
133
142
 
@@ -15,7 +15,7 @@ description: gtrk 单点工具与媒体转换能力的调用向导,覆盖 `gtr
15
15
 
16
16
  | 工具名 | 触发语(用户可能怎么说) | 输入要求 | 产物形态 | 计费 | 可用状态 |
17
17
  |---|---|---|---|---|---|
18
- | `image_move` | 「把这张图做成运镜视频 / 让图动起来 / 图转视频」 | 单张图片 | 运镜视频 | 运行前实时查询 | 已上线 |
18
+ | `image_move` | 「把这张图做成运镜视频 / 让图动起来 / 图转视频 / 往右推镜 / 拉远」 | 单张图片;可选 `--motion` 指定 26 种运镜之一(见下文枚举表) | 运镜视频 | 运行前实时查询 | 已上线 |
19
19
  | `image_matting` | 「给图片抠像 / 抠出主体 / 去背景 / 出透明 png」 | 单张图片 | 透明背景 png | 运行前实时查询 | 已上线 |
20
20
  | `image_blackborder_remove` | 「图片去黑边 / 裁掉四周黑边 / 保留有效画面」 | 单张本地图片 | 去黑边图片 | 运行前实时查询 | 已上线 |
21
21
  | `image_canvas_adapt` | 「图片比例转换 / 调整画布尺寸 / 转成矩形或方形裁剪」 | 单张本地图片;模式只支持 `normal` / `rectangle` / `square` | 比例适配图片 | 运行前实时查询 | 已上线 |
@@ -100,6 +100,14 @@ description: gtrk 单点工具与媒体转换能力的调用向导,覆盖 `gtr
100
100
 
101
101
  图片比例转换常用形态:`gtrk tool image_canvas_adapt ./photo.jpg --canvas-width 1080 --canvas-height 1920 --canvas-type rectangle --json`。`--canvas-type` 只接受实际运行时契约 `normal`、`rectangle`、`square`;不要传旧文档中的 `fit`。省略画布参数时不替服务端写死默认值。
102
102
 
103
+ 图转运镜可指定运镜方式:`gtrk tool image_move ./photo.jpg --motion zoom_in_center --json`。`--motion` 未传时云端自动选择(构图 + 主体识别 + 随机,同图重跑结果会变);显式指定后同图同参重跑结果一致。合法值 26 个、分三组,用户说「往右推 / 拉远 / 从左往右扫」这类自然语言时按语义对号入座,对不上就问清,别瞎猜:
104
+
105
+ | 组 | 取值 | 语义 |
106
+ |---|---|---|
107
+ | 平移 8(值=运动朝向) | `up_to_down` `down_to_up` `left_to_right` `right_to_left` `left_up_to_right_down` `right_down_to_left_up` `right_up_to_left_down` `left_down_to_right_up` | 画面沿该方向平移扫过 |
108
+ | 放大 9(值=画布锚点方位) | `zoom_in_center` `zoom_in_up` `zoom_in_down` `zoom_in_left` `zoom_in_right` `zoom_in_left_up` `zoom_in_right_up` `zoom_in_left_down` `zoom_in_right_down` | 以中心 / 边中点 / 角为锚点推近 |
109
+ | 缩小 9(锚点同上) | `zoom_out_center` 及 `zoom_out_` 同九方位 | 以对应锚点拉远 |
110
+
103
111
  这七个公共视频工具(去黑边、比例转换、防抖、蒸汽波、净化、超分、插帧)都只接本地文件,允许扩展名为 `.mp4/.avi/.mpg/.mov/.flv/.mxf/.mpeg/.ogg/.3gp/.wmv/.h264/.m4v/.ts`;不要把 `.mkv`、`.webm` 或 URL 交给它们。
104
112
 
105
113
  - 视频比例转换:`gtrk tool video_canvas_adapt ./clip.mp4 --canvas-width 1080 --canvas-height 1920 --canvas-type rectangle --clip-start 12 --clip-end 60 --without-audio --json`。`--clip-start/--clip-end` 传起止帧序号;省略选项就沿用服务端默认,需要保留音轨时不要传 `--without-audio`。