@gitruck/cli 0.2.15 → 0.2.17

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/AGENT.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # gtrk-cli · Agent Playbook
2
2
 
3
3
  给 **agent** 看的操作手册:把用户「想剪一条口播」的自然语言需求,落成对 `gtrk` CLI 的一次调用,
4
- 再把产物目录 + 三端(客户端 / 剪映 / PR)打开方式回给用户。任何 agent(Claude / Cursor / …)读完
5
- 这一份就能驱动整条闭环;Claude `/口播剪辑` skill 只是这份 playbook 的薄壳。
4
+ 再把产物目录 + 三端(客户端 / 剪映 / PR)打开方式回给用户。任何 agent 读完
5
+ 这一份就能驱动整条闭环;随包分发的各 `/gtrk-*` skill 只是这份 playbook 的薄壳。
6
6
 
7
7
  > 这条 CLI 做的事:**本地抽音频/720p(毛片永不上传)→ 只传抽出物 → 云端智能口播剪辑(video_oral_cut)
8
8
  > → 拉回 gtrk/剪映/PR 三方工程文件 →(可选)本地 ffmpeg 渲染成片 → 三端打开**。云端零改动、纯结构产物,
@@ -10,6 +10,17 @@
10
10
 
11
11
  ---
12
12
 
13
+ ## 产物落点纪律(全局 MUST · 本 playbook 与随包全部 skill 通用)
14
+
15
+ - 一切产物(成片 / 预览 / 代理 / 素材 / 工程文件)只落**工程目录**(产物目录)或**用户显式指定的输出路径**。
16
+ - **MUST NOT** 把成片、预览或任何大媒体文件复制到 agent 自有工作目录
17
+ (如用户文档目录下 agent 产品自建的目录、agent 家目录缓存、会话工作区)。
18
+ 需要引用媒体时**用原路径引用**,不做副本。
19
+ - 临时文件(抽帧图 / 中间物等)一律放系统 temp 且**用完即删**(含中断 / 失败路径也要清干净)。
20
+ - 违反本条的直观后果:用户系统盘被静默吃满——这是真机发生过的事故,不是假设。
21
+
22
+ ---
23
+
13
24
  ## 0. 一句话流程
14
25
 
15
26
  ```
package/README.md CHANGED
@@ -27,11 +27,11 @@
27
27
  | ✂️ | `gtrk split [拆分稿]` | 视觉拆分派单器:成片 × transcript 投影 → beat 分镜校验落地(`struct_meta.split` + `dispatch.json`),驱动四车道派单;`--column <id>` 按栏目词表校验 |
28
28
  | ⚙️ | `gtrk init` | 引导式一次性配置(API Key + 剪映草稿目录),之后免管 |
29
29
  | 🩺 | `gtrk doctor` | 体检:配置 / 云端连通 / 剪映目录 / 运行时一键自检 |
30
- | 🤖 | `gtrk skills install` | 通过通用 `skills` 适配器和 gtrk 补充层,把 9 个 CLI 自带 skill 装进本机检测到的主流 Agent;`--all` 可覆盖全部已登记宿主 |
30
+ | 🤖 | `gtrk skills install` | 通过通用 `skills` 适配器和 gtrk 补充层,把 10 个 CLI 自带 skill 装进本机检测到的主流 Agent;`--all` 可覆盖全部已登记宿主 |
31
31
  | ⬆️ | `gtrk upgrade` | 升级 CLI 到最新版 + 刷新 skill(配置保留);`--check` 只查不装 |
32
32
  | 🎞️ | `gtrk render` | 本地渲染 gtrk 工程(EDL)→ 成片 mp4(需 ffmpeg) |
33
33
  | 🔎 | `gtrk matrix` | B-roll 检索+**候选铺轨**:消费 FILM_BROLL 派单 → 产候选清单 + 下载 preview 代理铺 N 条候选轨(`--lay N` 默认 1,opencut 打开即可用轨道小眼睛对比;`--lay 0` 只出清单);`matrix search "<词>"` 单条 ad-hoc |
34
- | 🎨 | `gtrk mg` | MG 动态图颗粒铺轨:消费 MG 派单 → 把 html-particle 颗粒(透明叠加 / 满屏底层,由你栏目的 MG 生产 skill 所产)铺进 `.gtrk` 的 beat_track;`mg lint <颗粒.html>` 六铁律静态校验、`mg status --project <dir>` 编排看板(缺 HTML / 已产未铺 / 已铺);aux 叠层颗粒同段多铺(一 beat 派生主 + `-aux<n>`)。旧名 `gtrk rrv` 保留为弃用别名 |
34
+ | 🎨 | `gtrk mg` | MG 动态图颗粒铺轨:消费 MG 派单 → 把 html-particle 颗粒(透明叠加 / 满屏底层,由你栏目的 MG 生产 skill 所产)铺进 `.gtrk` 的 beat_track;`mg lint <颗粒.html>` 铁律静态子集校验、`mg status --project <dir>` 编排看板(缺 HTML / 已产未铺 / 已铺);aux 叠层颗粒同段多铺(一 beat 派生主 + `-aux<n>`)。旧名 `gtrk rrv` 保留为弃用别名 |
35
35
  | 🧰 | `gtrk tool <name>` | 单点工具族:图转运镜、图片/视频抠像、图片去黑边/比例转换/净化/转方图/LivePhoto、视频去黑边/比例转换/防抖/蒸汽波滤镜/机械·智能分镜/运镜高光/智能字幕、人声伴奏分离/说话人分轨/变调变速、钢琴转MIDI/修复、音视频降噪、静音移除、MAD 等;`gtrk tool list` 查全部输入/产物/实时价格/状态。单发单收、共享 runner,接新工具只加一个 descriptor |
36
36
  | 🚧 | `struct` | (规划中)已有 gtrk 转三方工程 |
37
37
 
@@ -160,7 +160,7 @@ irm https://api.ai-mcn.tv:9000/broadcast/exe/install.ps1 | iex
160
160
  | ![在 Agent 中调用 gtrk 示例 1](assets/agent-example-1.png) | ![在 Agent 中调用 gtrk 示例 2](assets/agent-example-2.png) |
161
161
  | ![在 Agent 中调用 gtrk 示例 3](assets/agent-example-3.png) | ![在 Agent 中调用 gtrk 示例 4](assets/agent-example-4.png) |
162
162
 
163
- `gtrk install` 会把 9 个 CLI 自带 skill(`gtrk-oralcut`·`gtrk-splitter`·`gtrk-matrix`·`gtrk-mg`·`gtrk-ai-drama`·`gtrk-style-maker`·`gtrk-transcript`·`gtrk-tools`·`gtrk-music-visualizer`)装进本机检测到的 Agent。实现方式与 lark-cli 一致:gtrk 把本地 skill 源交给通用 `skills` CLI,由它维护 Agent 探测、目录映射及更新规则;gtrk 不再硬编码各家路径。
163
+ `gtrk install` 会把 10 个 CLI 自带 skill(`gtrk-oralcut`·`gtrk-splitter`·`gtrk-matrix`·`gtrk-mg`·`gtrk-ai-drama`·`gtrk-style-maker`·`gtrk-transcript`·`gtrk-tools`·`gtrk-music-visualizer`·`gtrk-cover`)装进本机检测到的 Agent。实现方式与 lark-cli 一致:gtrk 把本地 skill 源交给通用 `skills` CLI,由它维护 Agent 探测、目录映射及更新规则;gtrk 不再硬编码各家路径。
164
164
 
165
165
  默认使用 `~/.agents/skills` 作为统一正本,再链接到各 Agent 的兼容目录(Windows 使用 junction);链接不可用时适配器会回退复制。这样更新只有一份正本,不会让多份副本逐渐漂移。常用命令:
166
166
 
@@ -202,9 +202,10 @@ gtrk skills install --copy
202
202
  | 📝 | `/gtrk-transcript` | `gtrk transcript` | 本地视频 → 一个含 Agent 总结、时码记录和纯文本的 Markdown,**不在成片 SOP 序列内** |
203
203
  | 🧰 | `/gtrk-tools` | `gtrk tool <name>` | 单点工具族(图转运镜 / 图片·视频抠像…)——单发单收,**不在成片 SOP 序列内**、随时可独立用 |
204
204
  | 🎵 | `/gtrk-music-visualizer` | `gtrk music-visualizer` | 一首歌 → 频谱可视化成片(模板 + 可选背景/封面 + 配色样式),**不在成片 SOP 序列内**、独立引流用 |
205
+ | 🖼️ | `/gtrk-cover` | (无命令,纯创作) | 封面工作台两阶段:设计诊断 + 三尺寸中英双版文生图 Prompt → 用户外部平台抽图 → H5 排字工作台(拖拽/滚轮微调、一键导出多尺寸 PNG)。栏目封面审美经栏目配置 `style.skills`(`produces:"cover"`)注入;**不在成片 SOP 序列内**(投放配套的「第 0 阶段」) |
205
206
 
206
207
  > **skill 与命令的区别**:`/gtrk-mg` 是**脑**——懂它在 SOP 第 ④ 步(B-roll 定了才铺 MG)、带用户确认、按栏目配置解析该产哪种颗粒;`gtrk mg` 是**手**——纯确定性 lint + 铺轨。你对话触发 skill,skill 替你跑命令。
207
- > 上面 9 个 `/gtrk-X` 都是 **CLI 自带框架 skill**(`gtrk skills install` 装)——`/gtrk-transcript` 独立驱动视频转文字稿,`/gtrk-tools` 只负责单点工具族,二者都不属成片 SOP 序列;`/gtrk-ai-drama`·`/gtrk-style-maker` 是纯创作 skill(无命令)。栏目专属的**视觉风格/生产内容**另由你栏目的生产 skill(`/gtrk-style-maker` 产、经栏目配置 `style.skills` 绑定)供,不写死在这些框架 skill 里。
208
+ > 上面 10 个 `/gtrk-X` 都是 **CLI 自带框架 skill**(`gtrk skills install` 装)——`/gtrk-transcript` 独立驱动视频转文字稿,`/gtrk-tools` 只负责单点工具族,`/gtrk-cover` 管封面,三者都不属成片 SOP 序列;`/gtrk-ai-drama`·`/gtrk-style-maker`·`/gtrk-cover` 是纯创作 skill(无命令)。栏目专属的**视觉风格/生产内容**另由你栏目的生产 skill(`/gtrk-style-maker` 产、经栏目配置 `style.skills` 绑定)供,不写死在这些框架 skill 里。
208
209
 
209
210
  **各车道的具体视觉/内容怎么产**——MG 动态图长什么样、AI 再现什么调性——不写死在 CLI 里,而由**你自己栏目的生产 skill** 提供(用 `/gtrk-style-maker` 访谈式产出、留本地)。它们经**栏目配置 `style.skills[].produces`**(值 = 车道名)绑定,`gtrk mg` / `gtrk matrix` 等**通用驱动器**据此消费。**驱动方向 = CLI 驱动栏目 skill**:栏目 skill 只供风格/内容、不含任何「跑哪条命令」的编排职责;框架只认车道与管线接口,画面风格永远归你的栏目。不建栏目就用内置默认,端到端照常跑。
210
211
 
@@ -374,9 +375,10 @@ gtrk transcript "D:/素材/采访视频.mp4" --lang zh-CN --out "D:/文字稿/
374
375
  - **素材表不囤积**:素材的剥离键按「**自产身份 × 零引用**」判(自产 = `mg-`/`rrv-` 前缀 **或** 落在 CLI 独占的 `assets/mg/` 下且文件名在自产登记里),**不认客户端可改写的 `html_material` 前缀**——所以在 opencut 里编辑过工程之后重铺,旧素材照样剥得掉,`mg-` 素材数**恒等于轨上颗粒数**,历史遗留的重复 / 孤儿条目一并清掉。**非自产素材零连带**(`broll-*` / `ex-solid-*` / 你自加的,哪怕零引用也不碰);仍被存活 clip 引用的自产素材也不剥(不会剥出失联 clip);盘上 `assets/mg/` 的 html 副本从不删。
375
376
  - **「一条都没定位到」不是清空指令**:`--only` 打空、`dispatch.mg` 为空/缺失、或本次条目全被 skip,**而轨上已有已铺颗粒**时,同样拒绝写回(那是派单或选择器出问题的信号)。确要清空加 `--replace-all`。首次铺轨(轨上本就没有已铺条目)不受此限,照常走完报 `laid=0`。
376
377
  - **槽位窗口现场重投影**:铺轨与 lint 之前先用「`transcript` × 当刻 `.gtrk`」重算每条队列条目的 `[track_st, track_ed]`,之后 lint 的坑位包络(铁律⑦)与落轨 clip 时长一律以重算值为准(`--only` 同守;aux 派生颗粒按**自己的** span 重投影,不与主 beat 窗口混同)。`dispatch.mg` 里的时码只是**投影时刻快照**,仅在重投影不可行时兜底——**改完口播轨直接铺即可,不必先重跑 `gtrk split`**。`--json` 恒出 `reprojection:{mode,degraded,reason?,drifted,max_offset,shrunk,dropped}`(`--lint-only` 也有)。重投影后**零存活**的条目 skip 并计入 `skipped`(不复制 HTML、不按快照铺回去);重投影不可行(transcript 缺失 / 工程定位不到 / 主轨查不到口播素材)→ 降级用快照 + 告警 + `--json` 标注,退出码不变;工程**非 v1** 的既有行为不变(铺轨路径版本门非 0 退出、`--lint-only` 照旧出报告)。铺轨成功会把本次时码来源(`timecode_source` / `reprojected_at`)纯追加登记进 `struct_meta.mg`。
377
- - **lint**(`gtrk mg lint <颗粒.html> [--dispatch <path>]`):纯本地静态校验颗粒 HTML 的六铁律机器可判定子集(`<template>` 包裹、`data-composition-id` + 1920×1080、`gsap.timeline({ paused: true })`、`window.__timelines` 注册、无 `Math.random` / `Date.now`、自包含无相对外链、根 `background` 与 `opaque` 自洽…);给 `--dispatch` 时校验 `composition_id` 命中派单。任一致命项非 0 退出并逐条报因。
378
+ - **lint**(`gtrk mg lint <颗粒.html> [--dispatch <path>]`):纯本地静态校验颗粒 HTML 的铁律机器可判定子集(`<template>` 包裹、`data-composition-id` + 1920×1080、`gsap.timeline({ paused: true })`、`window.__timelines` 注册、无 `Math.random` / `Date.now`、自包含无相对外链、根 `background` 与 `opaque` 自洽…);给 `--dispatch` 时校验 `composition_id` 命中派单。任一致命项非 0 退出并逐条报因。
378
379
  - **期望 id 一致性**(`1-cid-expect`,**致命**):HTML 内 `data-composition-id` 必须等于期望 id(铺轨=该条派单的 `composition_id`;`mg lint`=文件名,仅当它命中派单或形如 `…-B<数字>[-aux<n>]` 时比对,`./tmp.html` 这类改过名的副本不比对)。防的是「复制 `<id>.html` 改名时漏改内部 id」——落轨会写出以文件名命名的 clip/material,而文件注册的是另一个 `__timelines` 键、还与同名颗粒抢同一个样式作用域。
379
380
  - **铁律⑦ tl 总长估长**(`7-fill-slot` / `7-no-estimate` / `7-infinite-repeat`,**恒非致命、不拦铺轨**):已知坑位包络时(铺轨逐颗;`mg lint --dispatch` 命中派单条目)对 GSAP 时间线做**静态下界估算**——逐调用降级,能解析的计入(`duration×(repeat+1) + repeatDelay×repeat`,`yoyo` 不加时长),表达式 position / 非字面量 duration 那条**跳过不计**(忽略若干调用仍是合法下界)。估长 < 包络 → 告警;一条都算不出 → 显式提示「无法静态估长,铁律⑦未校验,须真引擎 seek 验收」(**不静默**,「算不出」与「算过且通过」在输出上可区分);含 `repeat:-1` → 告警「无限循环令总长 Infinity、铁律⑦不可静态验证,请改按坑位算死的有限 repeat」。真判据永远是渲染引擎逐帧,本项只做提醒层。
381
+ - **铁律⑧重复图元合并**(`8-primitive-merge`,**恒非致命、不拦铺轨**):识别「循环体内创建,或由循环调用具名工厂创建;落到同一父节点;且没有逐元素动画驱动」的可合并 `line` / `rect` / `path` / `polyline` / `polygon` 批次。同一父节点的纯数字循环 trip count 累加后 **≥ 8** 才报数;边界含 `.length` / 具名常量而算不出时仍报「条数未知」,不做常量折叠;逐元素 `gsap.set` / tween 或被 tween 首实参使用的元素数组会被排除。本项只提示「这里有一批可**无损**合并的重复图元,合并后画面逐像素不变」,**不是风险判定**:命中不代表该颗粒会复现缺陷,未命中也不代表安全,真判据仍是真渲染出片抽帧。
380
382
  - **回调与 seek 语义**(`x-callback-driven` / `x-engine-api-override` / `x-raf-interval`,**恒非致命、不拦铺轨**):对齐契约同名一节(2026-07-26 增补)。GSAP `seek(t)` 默认抑制回调 → 补间属性照常插值、但 `onUpdate` 里的 DOM 写入不执行,翻车形态是**画面定在初始态而非黑屏**。契约把保证压在**引擎侧**(定帧 MUST 用 `seek(t,false)` / `time(t)` / `progress(p)`),故颗粒**用回调驱动画面是合规写法**;lint 这三项只是**哨兵**:`x-callback-driven` = 回调写 DOM 且无任何 seek 兜底(有兜底则沉默,避免重复提醒);`x-engine-api-override` = 颗粒运行时覆写 `tl.seek` 或把 `__timelines[…]` 换成包装对象(会推翻引擎显式传的 `seek(t,true)`,且引擎改走 `time()`/`progress()` 即失效,属过渡态);`x-raf-interval` = 含 `requestAnimationFrame(` / `setInterval(`(自有时钟不被 seek,等于冻结)。三项 MUST NOT 致命——「用回调驱动画面」不是违规。
381
383
  - **status**(`gtrk mg status --project <dir>`):汇总 MG 流水线——`dispatch.mg` beat 总数 / 已产源 HTML 数 / 已铺进 `.gtrk` 数,并逐 beat 标注(缺 HTML / 已产未铺 / 已铺)。
382
384
 
@@ -498,7 +500,7 @@ gtrk-cli/
498
500
  ├── src/index.ts # commander 入口
499
501
  ├── src/commands/ # 子命令:install / init / oralcut / transcript / split / doctor / upgrade / skills
500
502
  ├── src/lib/ # cloud / column-config / splitdoc / projection / user-config / jianying / …
501
- ├── skills/ # 打包的框架 skills:oralcut / splitter / matrix / mg / ai-drama / style-maker / transcript / tools
503
+ ├── skills/ # 打包的框架 skills:oralcut / splitter / matrix / mg / ai-drama / style-maker / transcript / tools / music-visualizer / cover
502
504
  ├── contracts/ # 框架契约库正本(gsap-emit v1 + handoff→契约映射表)
503
505
  ├── assets/ # README 配图(介绍图 / Agent 调用示例 / 剪映草稿目录指引图)
504
506
  └── AGENT.md # 可移植 agent playbook(skill 底座)
@@ -2,7 +2,7 @@
2
2
 
3
3
  > **契约版本**:gsap-emit v1(2026-07-10;2026-07-24 增补铁律 7「占满坑位 + 终态驻留」,主理人硬性规定;同日铁律 6 增补字体注册表命中规则,对齐 gitruck-infra change `align-render-font-contract`;**2026-07-26 增补「回调与 seek 语义」一节**——补此前留白,首次对**渲染引擎侧**提出 MUST 条款,对齐 change `define-seek-suppress-events-contract`;**同日该节核实状态转「已核实(行为层)」**——真渲染引擎(`@hyperframes/producer@0.6.101`)三帧实测回调可达、结论绑定该引擎版本;
4
4
  > **2026-07-26 铁律 4 按真机实测改写**——实心底 MUST 下沉为根下第一个全幅子层、根元素 MUST 保持零视觉、overlay 颗粒 MUST 在根显式写 `background:transparent`,
5
- > 附证据锚并消歧铁律编号,对齐 change `align-particle-solid-backdrop-contract`)。产 HTML 动画颗粒、经同合云渲染管线(html_animate_render)逐帧 seek 合成的 skill/工具,其产物 MUST 满足本契约。
5
+ > 附证据锚并消歧铁律编号,对齐 change `align-particle-solid-backdrop-contract`;**同日增补铁律 8「重复图元合并」**——把整组同步驱动的重复图元合并成单元素,以规避一类真渲染横带、纵向重复叠印与逐帧闪烁缺陷;触发轴未知,本条只按零成本写法成文、不设数字门槛,对齐 change `add-particle-primitive-merge-law`)。产 HTML 动画颗粒、经同合云渲染管线(html_animate_render)逐帧 seek 合成的 skill/工具,其产物 MUST 满足本契约。
6
6
  > **边界**:本契约只约束**机器可判定的管线消费属性**(封装/注册/确定性/自包含/依赖可达/禁 var()/字体名命中注册表)。画面长什么样——颜色、字体取值、构图、节奏——**一律由调用方按其栏目自身规则决定**,本契约不点名任何具体字体/颜色;文中示例取值均为中性占位。
7
7
 
8
8
  ## 原理(为什么不能用 CSS animation)
@@ -83,7 +83,7 @@
83
83
 
84
84
  **本节口径优先于任何栏目指南的招式建议。** 栏目指南若与本节冲突,以本节为准。(当前二者同向:栏目指南推荐的 `onUpdate` 驱动写法在本节下**合规**,作坊侧**无需修订**——本节不向作坊侧派发任何待办。此条照写不误,它防的是将来的分歧。)
85
85
 
86
- ## 七条铁律(违反任一条 → 整片渲染失败 / 颗粒冻结 / 全黑 / 坑位内突兀消失)
86
+ ## 八条铁律(违反任一条 → 整片渲染失败 / 颗粒冻结 / 全黑 / 坑位内突兀消失 / 画面被切成横带、内容纵向重复叠印并逐帧闪烁)
87
87
 
88
88
  1. **`<template>` 包裹根元素**:`<template><div data-composition-id="<id>" data-width="1920" data-height="1080">…</div></template>`。编译器取的是 `<template>` 内容;裸 `<div>` 会被判 "empty or could not be parsed" 整片失败。(1920×1080 为**当前引擎版本约束**,分辨率参数化预留——升版时以本契约新版为准。)
89
89
  2. **GSAP `paused` 时间线 + 注册**:`var tl = gsap.timeline({paused:true}); … window.__timelines = window.__timelines || {}; window.__timelines["<id>"] = tl;`。`<id>` 必须等于根的 `data-composition-id`。
@@ -96,6 +96,12 @@
96
96
  5. **脚本用渲染机可达的 CDN(编译期内联)**:`<script src="https://lib.baomitu.com/gsap/3.13.0/gsap.min.js"></script>` 或由渲染管线 vendor 本地。⚠️ jsdelivr 在渲染服务器不稳(实测 compile 期 `fetch failed` → GSAP 未加载 → 整片全黑)。编译器**只内联 http(s) CDN、不内联相对本地路径**(写 `src="gsap.min.js"` 运行时 404)。
97
97
  6. **颜色/字体用字面值,禁 CSS `var()` 自定义变量;字体名 MUST 命中服务端注册字体表**:编译器/挂载不可靠地解析 var()(字体映射把 `var(--font-body)` 当字面字体名;颜色 var() 不应用 → 整片全黑,实测)。直接写字面值(如 `#RRGGBB` / `'某字体名'`);SVG 属性里同样禁 var()。栏目级换色/换主题 = **生成期**替换字面值(查调用方自己的词表/token 注入),不是运行时变量。**字体名规则(2026-07-24 增补)**:font-family 的每个具名家族 MUST 逐字符命中渲染服务端注册字体表(gitruck-infra 仓 `utils/assets/text/classic_template/font_manifest.json`,中英别名等价),并 SHOULD 以 `sans-serif`/`serif` 通用族收尾兜底;表外名字渲染不失败但**字形不保证**(服务端 fail-open 系统回退,2026-07-24 真机实锤:错名导致宋体被渲成回退黑体)。具体选哪款仍由调用方栏目规则决定,本契约不点名。
98
98
  7. **占满坑位 + 终态驻留(2026-07-24 主理人硬性规定;2026-07-26 增补无限循环定性)**:颗粒时间线总长 MUST ≥ 它在成片中的**坑位时长**(落轨 clip 的实际时长,通常 = 派单槽位包络 `track_ed − track_st`,**不是** `duration_hint`);动画主叙事播完后,颗粒 MUST 以「**定格保持**」或「**有限次循环**」驻留到坑位末尾。**禁用无限循环 `repeat:-1`(2026-07-26 增补,补此前留白)**:无限循环让时间线总长为 `Infinity`,本条「总长 ≥ 坑位」就**变得不可验证**(机器与人都无从判断它是否真按坑位算过),且掩盖「作者根本没算坑位」这件事。循环次数 MUST **按坑位算死**——`repeat = ceil((坑位时长 − 循环起点) / 单圈时长) − 1`,宁可多算一两圈(末尾被 clip 裁掉无害),也不许写 `-1` 蒙混——坑位内任意时刻(含最后一帧)核心内容必须可见。**禁止**「整体渐隐到空 / 全局退场 / 清空画面」类收尾:渐隐会与剪辑层转场冲突,淡出与否由剪辑/装配层决定,不在颗粒内做。局部元素可按叙事退场(黯淡/让位),但画面在坑位内不得归零;**定格不动是完全合法的终态**(不必为凑动作密度在尾段硬加动画)。违反表现 = 观感上「动画一过完整个颗粒突兀消失」(2026-07-24 回声定位真机实测)。
99
+ 8. **重复图元合并(2026-07-26 增补 · 规避条款,根治在渲染侧)**:同一批**重复图元**——同色、同 `stroke` / `fill`、**整组同步驱动**(只有组级动画或完全静态)的网格、排线、刻度、点阵——**MUST 合并成单个元素**(SVG 用一条 `<path>` 的多子路径 `M…H…V…`;同色分档时可按档合成若干条),**MUST NOT** 用「每条线 / 每个格子一个 `<element>`」的批量构建,无论它写成字面标签还是由 `createElementNS` 循环生成。合并前后画面**逐像素相同**,故本条不涉任何视觉取值。
100
+ - **豁免**:需要**逐元素动画**(stagger / 逐条画入 / 逐个变色)的批次不在本条范围内——元素身份是该批动画所必需的。此类批次若同时是满幅大面积绘制,MUST 以真渲染出片抽帧验收;这是保守兜底,**不是**「满幅即危险」的风险判据,反向的「不满幅即安全」同样不成立。
101
+ - **违反表现**:画幅被切成等高横带、相邻带内容互相纵向重复叠印(同一元素在 `y` 与 `y±带高` 各画一次,或被顶部裁半)并逐帧闪烁;该表现与动画逻辑无关,同帧里零动画的静态元素也会重复。DOM 元素数与 `getBoundingClientRect` 均正常,本地播放器与客户端预览看不出。
102
+ - **这是规避,不是根治**:缺陷出在渲染侧已由真机行为确证——颗粒的 DOM 元素数与布局值正常,不是颗粒写错。机制层面**推断**为渲染侧按等高带做局部栅格刷新时失效区域算错,**属推断、未经渲染侧确认**;**真实触发轴至今未知**,「图元总数」「同页累积负载」「同父同类聚簇」均已被跨颗粒真渲反例否证。本条 MUST NOT 被读成「图元少 / 负载低就安全」。
103
+ - **根治登记**:根治方 = 渲染管线侧;当前状态 = **未立项(2026-07-26;决策角色 = 本 change 实施者,按 proposal 的跨仓授权边界不代提;是否立项仍待主理人另行授权)**。
104
+ - **根治后处置预案**:待渲染管线侧根治上线且经真机确认缺陷不再复现后,本条由 **MUST 降为 SHOULD**,并保留「本条曾于 2026-07-26、本证据锚所载引擎版本口径下作为规避所必需」的历史记录。
99
105
 
100
106
  > **⚠️ 铁律编号的唯一定义在本文件。** 本契约的**铁律 7 = 「占满坑位 + 终态驻留」**,这是框架侧对该条号的**唯一**定义。
101
107
  > 创作侧(栏目 skill / 作坊)的模板与 references **MUST NOT 另立同号铁律**——引用请写「gsap-emit v1 铁律 7」并指回本文件,
@@ -132,6 +138,41 @@
132
138
  `gitruck-infra` / `add-html-animate-opaque-fullscreen-cover`(**另一个独立问题**:渲染侧要不要按 `opaque` 位替颗粒兜一层黑底)。
133
139
  ⚠️ 两者**互不依赖**:上表的观测正是在后者**未 apply** 时取得的——即**本条的修法(下沉子层)当场生效,不需要渲染侧任何配合**。
134
140
 
141
+ ### 铁律 8「重复图元合并」的真机证据锚(2026-07-26)
142
+
143
+ 本条断言的是一条**作者侧规避写法**及其在真渲染中的效果,不断言已知触发轴。证据锚如下:
144
+
145
+ - **结论**:同一故障样本把 37 条满幅 `<line>` 合为一条 `<path>` 多子路径后,目标画面逐像素不变,横带重复率由 **65%~68% 降至 2%**;规避当场有效,但合并同时改变了图元数、DOM 结构与栅格化路径,故本实验**不能证明是哪一个变量生效**。
146
+ - **实验日期 / 机器**:2026-07-26 · r69(真渲,非本地无头模拟)。
147
+ - **引擎版本口径**:渲染引擎 CLI 与 producer 同版 `0.6.101` · 无头浏览器内核 `131.x`。
148
+ - **二分设计**:以同一颗粒为母本逐项只改一个构建块,每个变体各做一次真渲;每格抽取 168 帧,按等高横带间的重复像素统计复现率。装配路径、分辨率、帧率、底轨与其余颗粒代码保持一致。
149
+ - **范围限定(硬约束)**:下表全部是**同一颗粒内部**的二分结果,**MUST NOT 跨颗粒外推**;它只能说明这些改动在该颗粒内与复现率同向变化,不能推出「元素数少就安全」或任何数字门槛。
150
+
151
+ | 同一颗粒内的变体 | 重复率 | 限定读法 |
152
+ |---|---:|---|
153
+ | 原件:背景网格为 37 条满幅 `<line>` | **65%~68%**(复跑一致) | 故障基线 |
154
+ | 37 条 `<line>` 合为一条 `<path>` 多子路径 | **2%** | 本条规避正例;目标画面逐像素不变 |
155
+ | 整块删除背景网格 | **2%** | 与合并同档;只说明该块在本颗粒内参与复现 |
156
+ | 删除两个静态术语文本块 | **0%~1%** | 删除任一块负载都退烧;作用域仅限本颗粒,机制未知 |
157
+ | 删除三行静态标签文本块 | **0%~1%** | 同上 |
158
+ | 换字体族 / 去斜体 / 关闭 3D 加速 / 改入场位移 / 把文字改为 SVG `<text>` / 给根加变换提示 / 把网格改静态 | **仍为 65%+** | 均无效 |
159
+ | 增加满屏失效脉冲层 | **14%** | 作者侧强制全幅失效仍不能根治 |
160
+ | 极简结构(20 个静态 `<div>` + 1 个网格) | **0%** | 空载变体不复现;不得外推为通用预算 |
161
+
162
+ - **阳性对照(排除平凡解)**:合并版仍完整绘制与原件相同的整张网格,逐像素对拍一致;它不是「把内容删没了所以不重复」。同一颗粒内另有 24 条局部短线在合并版中继续保留,故 24 与 37 也 **MUST NOT** 被写成安全 / 故障分界。
163
+ - **跨颗粒反证(同批全量体检)**:同装配、同引擎、同机完成 **21 颗粒 + 六 beat 同页聚合,共 24 次渲染 / 约 22,000 帧**。这些结果专门限制上表的外推范围:
164
+
165
+ | 样本 | 真渲结果 | 可否证的候选轴 |
166
+ |---|---:|---|
167
+ | 另一密阵样本:884 条短划、全颗共 921 个绘制图元 | **0.0% 脏帧** | 图元总数、同父同类聚簇 |
168
+ | 六 beat 同页聚合:约 1,400 个绘制图元 | **0.0% 脏帧** | 同页累积负载 |
169
+ | 当前修复版样本(回归 / 阴性对照) | **0.0% 脏帧** | 规避在整轨分片路径下仍稳 |
170
+ | 未修版样本(阳性对照) | **70.3% 脏帧** | 缺陷仍活且可稳定复现 |
171
+
172
+ **真实触发轴至今未知**;当前已否证的候选轴 = **图元总数 / 同页累积负载 / 同父同类聚簇**。上表中「921 个图元干净」与「较少图元的阳性对照中招」同时成立,因此数字方向不存在可据此写入契约的安全门槛。
173
+ - **复现方式**:从同一母本生成上述单变量变体 → 走生产同款整轨分片渲染 → 对每格 168 帧计算等高横带间的重复率并抽取高分帧肉眼复核;再以同一口径跑 21 颗全量语料、六 beat 同页聚合、修复版阴性对照与未修版阳性对照。复现件的本地路径与文件名不进入分发契约。
174
+ - **相关 change / 根治状态**:本仓 `add-particle-primitive-merge-law` 收录作者侧规避;渲染管线侧根治**未立项(2026-07-26,本 change 实施会话按非目标不代提;待主理人另行决定)**。根治上线并经真机确认后,按铁律 8 的预案把 MUST 降为 SHOULD。
175
+
135
176
  ## 颗粒骨架(中性模板)
136
177
 
137
178
  ```html
@@ -188,4 +229,5 @@
188
229
  - **`<template>` 内的 `<script>` 默认不执行**——引擎把 template 内容克隆进文档后才执行;本地直接开浏览器不会跑,必须经引擎/player。
189
230
  - **transform-origin(SVG)**:缩放 `<g>` 用 GSAP `svgOrigin:"x y"`(SVG 用户坐标),别用 CSS transform-origin。
190
231
  - **时间线总长 ≥ 坑位时长**:颗粒 tl 总时长 ≥ 落轨 clip 时长(坑位包络),否则 seek 越界(已升格为铁律 7,含终态驻留要求)。
232
+ - **整组同步驱动的重复图元必须合并**:网格、排线、刻度、点阵用单元素表达,SVG 以一条 `<path>` 的多子路径合成;逐元素动画批次豁免。详见 gsap-emit v1 铁律 8。
191
233
  - **别用 `requestAnimationFrame`/`setInterval` 驱动画面**——不被 seek,等于冻结。所有视觉变化必须挂在 tl 上。(与「回调与 seek 语义」一节同源:任何**不经 tl** 的自有时钟都不被定帧驱动;而挂在 tl 上的回调是否被触发,则由该节的引擎侧条款保证。`gtrk mg lint` 对本条给**非致命**项 `x-raf-interval`——静态正则分不清「驱动画面」与其它用途,故只提醒不拦。)