@gitruck/cli 1.3.11 → 1.3.12

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.
@@ -61,7 +61,7 @@ Then just say "**cut a version of this talking-head**", or explicitly pick `gtrk
61
61
  | ① | `/gtrk-oralcut` | `gtrk oralcut` | Smart talking-head cut → desktop client / Jianying / Premiere projects + transcript |
62
62
  | ② | `/gtrk-splitter` | `gtrk split` | Storyboard dispatch → `dispatch.json` (A_ROLL/MG/AI_DRAMA/FILM_BROLL, four lanes) |
63
63
  | ③ | `/gtrk-matrix` | `gtrk matrix` | **B-roll base · film/local-footage leg**: lays candidate tracks → **you adjust/choose** (toggle visibility in opencut) |
64
- | ③ | `/gtrk-ai-drama` | (no command, pure authoring) | **B-roll base · AI scene-clip leg (same stage as matrix, not last)**: emits four-part description docs (backstory / characters / shots / source text, in Chinese and English blocks) → generate on any external platform and re-insert by hand (the artifact is description text with no mechanical tail, same as `/gtrk-style-maker`: skill only, no command) |
64
+ | ③ | `/gtrk-ai-drama` | `gtrk ai-drama validate` (check storyboard drafts) · `lay` / `pack` / `swap` (re-insert) | **B-roll base · AI scene-clip leg (same stage as matrix, not last)**: emits four-part description docs (backstory / characters / shots / source text, in Chinese and English blocks) → generate on any external platform and re-insert by hand (the artifact is description text with no mechanical tail, same as `/gtrk-style-maker`: skill only, no command) |
65
65
  | ④ | (no skill) | (no command) | **Global frame-sampling composition check**: sample frames from the merged three-source base layer and have the user confirm the composition — a hard agent-discipline gate feeding ⑤'s placement decisions |
66
66
  | ⑤ | `/gtrk-mg` | `gtrk mg` | **MG (incl. ov) goes on last** (stacked on the settled, composition-checked base layer) |
67
67
  | ⑥ | `/gtrk-composite` | `gtrk composite` | **Composite layer** (after subtitles, before export): turn chosen time windows into composite particles — one code particle takes over the whole frame for that span (picture changes per sentence, side-by-side contrasts, list cards, subtitle layout) while the talking head and B-roll are drawn into its slots; three entry modes (cover the whole film / let the AI pick / user-given ranges), candidates show up in the client outline's CP row; purely local, zero billing. On export, `gtrk composite bake` bakes them into video locally (the first run needs `gtrk deps install --browser`) |
@@ -73,7 +73,7 @@ Then just say "**cut a version of this talking-head**", or explicitly pick `gtrk
73
73
  | 📝 | `/gtrk-transcript` | `gtrk transcript` | Local video / voice-over audio → one Markdown file with an agent-written summary, timecoded record and plain text; **not part of the production SOP** |
74
74
  | 🧰 | `/gtrk-tools` | `gtrk tool <name>` | The single-shot tool family (image-to-camera-move / image & video matting …) — single request, single result, **not part of the production SOP**, usable standalone at any time |
75
75
  | 🎵 | `/gtrk-music-visualizer` | `gtrk music-visualizer` | One song → a spectrum-visualizer video (template + optional background/cover + colour styling), **not part of the production SOP**, used standalone for audience acquisition |
76
- | 🖼️ | `/gtrk-cover` | (no command, pure authoring) | The two-stage cover workbench: design diagnosis + text-to-image prompts in three sizes and two languages → you generate images on an external platform → an HTML5 typesetting workbench (drag/scroll fine-tuning, one-click export to multiple PNG sizes). Show-specific cover aesthetics are injected through the show config's `style.skills` (`produces:"cover"`); **not part of the production SOP** (it is the "stage zero" companion to distribution) |
76
+ | 🖼️ | `/gtrk-cover` | `gtrk cover embed` (compress background images into the workbench; purely local, zero billing) | The two-stage cover workbench: design diagnosis + text-to-image prompts in three sizes and two languages → you generate images on an external platform → an HTML5 typesetting workbench (drag/scroll fine-tuning, one-click export to multiple PNG sizes). Show-specific cover aesthetics are injected through the show config's `style.skills` (`produces:"cover"`); **not part of the production SOP** (it is the "stage zero" companion to distribution) |
77
77
  | 🧭 | `/gtrk-talking-head` | orchestrates `gtrk audio` → `oralcut` → `split` → `matrix` → `mg` → `audio lay` → `subtitle lay` | **Talking-head chain blueprint**: one or more on-camera raw takes → external audio aligned and swapped in, multi-take stitching, rough cut, dispatch, B-roll / MG cards, BGM, subtitles → a client-ready project |
78
78
  | 🧭 | `/gtrk-travel-recap` | orchestrates `gtrk tool audio_tts_clone` → `project init` → `split` → `matrix` → `mg` → `audio lay` → `subtitle lay` | **Travel-recap blueprint**: a folder of travel footage → the AI reads the footage, writes a three-act narration, you confirm once → voice-over / project / dispatch / B-roll / cards / BGM / subtitles run unattended → a client-ready project |
79
79
  | 🧭 | `/gtrk-live-slicing` | orchestrates `gtrk long2short` (very long replays are segmented first) | **Live-stream slicing blueprint**: a multi-hour replay → segmentation (server-side 2 h hard limit) → topic list confirmed → a batch of per-clip rough-cut projects (gtrk + Jianying + Premiere), split-screen matched to the picture |
@@ -83,7 +83,7 @@ Then just say "**cut a version of this talking-head**", or explicitly pick `gtrk
83
83
  | 🧭 | `/gtrk-vlog-docu` | orchestrates `gtrk transcript` → `tool audio_tts_clone` → `split` → `matrix` → `mg` → `audio lay` → `subtitle lay` | **Documentary-vlog blueprint**: a batch of on-location footage → footage understanding, register choice and script, one sign-off → live-sound skeleton + narration voice-over + B-roll + subtitle layer + BGM run unattended → a client-ready project; alternates on-location sound with post-production narration, unlike the pure talking-head or pure voice-over chains |
84
84
 
85
85
  > **Skill vs command**: `/gtrk-mg` is the **brain** — it knows it belongs at SOP step ⑤ (MG only after all three B-roll sources have landed and the composition is checked), asks for your confirmation, and resolves which particle type to produce from the show config; `gtrk mg` is the **hands** — purely deterministic lint + track laying. You trigger the skill by talking, and the skill runs the command for you.
86
- > The 20 `/gtrk-X` skills above are **framework skills bundled with the CLI** (installed by `gtrk skills install`; the list is identical to the ones in "Using it with AI agents" and "Layout") — the 7 marked 🧭 are **composite blueprints** (one sentence runs a whole chain; they only orchestrate the single-command skills above and add no commands of their own); `/gtrk-long2short` independently drives long-to-short, `/gtrk-transcript` independently drives video/audio-to-transcript, `/gtrk-tools` covers only the single-shot tool family, `/gtrk-cover` handles covers, `/gtrk-ref-reading` handles reference reading, and none of the five belong to the production SOP; `/gtrk-ai-drama`·`/gtrk-style-maker`·`/gtrk-cover` are pure authoring skills (no command). Show-specific **visual style and content** come instead from your own show's production skills (created by `/gtrk-style-maker`, bound through the show config's `style.skills`) and are never hardcoded into these framework skills.
86
+ > The 20 `/gtrk-X` skills above are **framework skills bundled with the CLI** (installed by `gtrk skills install`; the list is identical to the ones in "Using it with AI agents" and "Layout") — the 7 marked 🧭 are **composite blueprints** (one sentence runs a whole chain; they only orchestrate the single-command skills above and add no commands of their own); `/gtrk-long2short` independently drives long-to-short, `/gtrk-transcript` independently drives video/audio-to-transcript, `/gtrk-tools` covers only the single-shot tool family, `/gtrk-cover` handles covers, `/gtrk-ref-reading` handles reference reading, and none of the five belong to the production SOP; `/gtrk-style-maker` is a pure authoring skill (no command), while `/gtrk-ai-drama`·`/gtrk-cover` are mostly authoring and only run commands for mechanical steps such as validation and image embedding. Show-specific **visual style and content** come instead from your own show's production skills (created by `/gtrk-style-maker`, bound through the show config's `style.skills`) and are never hardcoded into these framework skills.
87
87
 
88
88
  **How each lane's actual visuals/content get produced** — what the MG looks like, what tone the AI re-enactment has — is not hardcoded into the CLI. It comes from **your own show's production skills** (created interactively with `/gtrk-style-maker`, kept locally). They are bound through the show config's **`style.skills[].produces`** (the value is the lane name), and **general-purpose drivers** such as `gtrk mg` / `gtrk matrix` consume them accordingly. **The direction is: the CLI drives the show skills** — show skills only supply style/content and carry no "which command to run" orchestration; the framework only knows lanes and pipeline interfaces, and the look always belongs to your show. Without a show, the built-in defaults are used and everything still runs end to end.
89
89
 
@@ -350,7 +350,7 @@ Finished cut × transcript projection → beat storyboard. **No positional argum
350
350
  >
351
351
  > **Dispatch entries carry their own `span:{from,to}`** (the utterance range that entry covers; `overlay` aux entries carry **their own** span, which may be a sub-range of the main beat's). **`track_st/track_ed` are a snapshot taken at projection time** — `gtrk mg` / `gtrk matrix` **re-project on the spot** when consuming them (see below), so after editing the talking-head track you do **not** need to re-run `gtrk split`; only a change to the split doc itself requires that.
352
352
 
353
- ### `gtrk patch <move|trim|split|set>` — element-level editing (the only way to edit a project)
353
+ ### `gtrk patch <move|trim|split|set|add|replace>` — element-level editing (the only way to edit a project)
354
354
 
355
355
  Edit the timecode or parameters of a single clip / gap / particle. **Agents must not hand-edit `.gtrk` JSON** —
356
356
  a clip carries **two parallel timecode representations** (`clip_st`+`clip_ed` and `clip_st`+`duration`).
@@ -363,6 +363,8 @@ gtrk patch move --project <dir> --clip c2 --to 5.0
363
363
  gtrk patch trim --project <dir> --clip c2 --out -1s
364
364
  gtrk patch split --project <dir> --clip c2 --cut 5.5
365
365
  gtrk patch set --project <dir> --track audio:1 --at 3.0 --volume 0.5
366
+ gtrk patch add --project <dir> --track video:2 --to 263.733 --candidate <clip_id> # put a candidate into a gap
367
+ gtrk patch replace --project <dir> --clip <clip_id> --candidate <clip_id> # swap the source in place
366
368
  ```
367
369
 
368
370
  | Flag | Purpose | Default |
@@ -370,7 +372,11 @@ gtrk patch set --project <dir> --track audio:1 --at 3.0 --volume 0.5
370
372
  | `--project <dir>` / `--gtrk <path>` | Project dir (auto-locates `gtrk/project.gtrk`) or an explicit path | — |
371
373
  | `--clip <clip_id>` | Address by id. A video/audio **mirror pair** counts as one editing unit | — |
372
374
  | `--track <kind:idx> --at <sec>` | Address by position (`track_st ≤ at < track_ed`). Mutually exclusive with `--clip` | — |
373
- | `--to <sec\|Nf>` | Target position for `move` | — |
375
+ | `--to <sec\|Nf>` | Target position for `move` / `add` (`add` does not take `--at`: in this command `--at` always means addressing) | — |
376
+ | `--candidate <clip_id>` / `--material <id>` | Source for `add` / `replace`, exactly one: a B-roll candidate (the project candidate pool including neighbours first, then `split/broll-plan.json`) or a video / image material already in `materials` | — |
377
+ | `--beat <id>` | The beat the candidate belongs to (required when the same candidate appears in several beats with different windows) | — |
378
+ | `--from <sec>` | Source in-point for `add` / `replace` (a candidate uses its own source time; external candidates are converted to preview-file time) | Same window as dragging a candidate in the client: centred on `seg.best`, clamped to the material; a material starts at 0 |
379
+ | `--dur <sec\|Nf>` | Duration for `add` | The length of the gap at the target (up to the start of the next element on that track, ending on the same frame number); the candidate's window length when nothing follows |
374
380
  | `--in` / `--out` / `--set-in` / `--set-out` / `--slip` | The five `trim` semantics (first two relative, next two absolute, `--slip` shifts only the source window) | — |
375
381
  | `--cut <sec\|Nf>` | Cut point for `split`. ⚠️ Distinct from the addressing flag `--at` | — |
376
382
  | `--muted` / `--no-muted` / `--volume <gain>` / `--opaque` | Element-level parameters for `set` (`--volume` is linear gain, not dB, and must be > 0; `--volume 0` fails with `volume_zero_use_muted` — use `--muted` to silence). Track mute is a master switch: if the clip's track is muted, `--no-muted` fails with `track_muted_master` — unmute the track's speaker in the client | — |
@@ -391,6 +397,13 @@ gtrk patch set --project <dir> --track audio:1 --at 3.0 --volume 0.5
391
397
  > ⚠️ A gap cannot be addressed with `--clip ""`: the contract lets multiple gaps share that value, so it is
392
398
  > not an address. Use `--track/--at` instead.
393
399
 
400
+ **`add` / `replace` (putting candidates on the timeline and swapping sources while fine-editing)**:
401
+
402
+ - When the candidate's material is not yet in `materials`, the preview is downloaded to `assets/broll-preview/` and registered (the same landing code as `gtrk matrix lay`); a registered material is reused, never downloaded again. So right after `matrix source-import` a single `patch add` puts it on the timeline. A failed download writes nothing and exits non-zero (`preview_download_failed`: the candidate URL may have expired — re-run the search / import to refresh); a preview already on disk is kept for next time.
403
+ - `add` only uses existing video tracks; overlapping a non-gap element is refused (`add_overlap`, listing the blockers; when the blocker is a black fill patch it points to `patch replace`); explicit gaps covered by the new clip give way; no ripple, no new tracks. Image candidates are refused (they need a camera-move render first). A source that is too short is clamped with an `add_clamped` warning, never stretched. The new clip's `clip_id` is `<beat>-add-<n>`, it carries no `producer`, and a candidate source gets a solid black `background_fill`.
404
+ - `replace` swaps only `material` and the source window: `clip_id`, track, start, speed, transform, fill, transitions and keyframes stay. If the new material is too short from the in-point, the clip is shortened honestly (`replace_shortened`) — never stretched, start never moved; `producer` is removed so the next `matrix lay` keeps the track as a user track; the old material entry is kept. Mirror pairs (video + mirrored audio) are refused.
405
+ - Every change is first computed and validated with declared values; only then is anything landed. `--dry-run` downloads and writes nothing and the receipt carries `would_download`. The op receipt also carries `source` (candidate / material, `material_id`, `landed`: existing / reused / downloaded / registered) and, for `add`, `gaps_consumed`. `--ops` entries have the same shape: `{"action":"add","track":"video:2","to":263.733,"candidate":"…"}`.
406
+
394
407
  **Preserving and maintaining transitions** (`transition_in` / `transition_out` / `transition_next`; created in the client — the CLI does not produce transitions in this release and adds no flags):
395
408
 
396
409
  - `split`: the entrance transition stays on the front part; the exit transition and the transition into the next clip go to the back part (`to_clip_id` unchanged); the new cut carries no transition.
@@ -412,6 +425,29 @@ Repeat `--url`, or provide one URL per line with `--urls` (1–32 total). Suppor
412
425
 
413
426
  Each source becomes one low-resolution full-window preview candidate. `source-import` itself does not download the high-resolution source, change the timeline, or create an `online_broll_resolve` task. The client may still open the Trim dialog by double-clicking it, but the selectable range is strictly bounded by that candidate's source window; the pretrim is carried into the timeline when dragged. After the user places the candidate on a track and clicks “Confirm B-roll”, the client submits the selected source window to `online_broll_resolve`; the cloud downloads that high-resolution window and replaces the low-resolution timeline media. `更多外网候选` / `More external candidates` paginates keyword-search tasks only and never treats manually specified sources as another search page.
414
427
 
428
+ ### `gtrk matrix status` — See where a beat stands in one command (read-only)
429
+
430
+ ```bash
431
+ gtrk matrix status --project <project-dir> --beat B20 --json
432
+ gtrk matrix status --project <project-dir> --beat B20,B21
433
+ gtrk matrix status --project <project-dir> --json # every B-roll beat, one line each
434
+ ```
435
+
436
+ Accepts only `--project` / `--beat` / `--json`. It calls no cloud endpoint, needs no Key and writes no file; it reads the project on disk, not unsaved edits in the client (that is `gtrk client state`'s job). Here `--beat` may list several beats separated by commas; `matrix source-import`'s `--beat` still takes exactly one.
437
+
438
+ With `--beat`, each beat reports:
439
+
440
+ | Field | Content |
441
+ |---|---|
442
+ | `window` | Time window, re-projected on the spot (the same code `gtrk matrix` / `gtrk mg` use); when it falls back to the dispatch snapshot, `source:"dispatch_snapshot"` with a `degraded_reason` |
443
+ | `lane` / `queries` | Lane and dispatch queries |
444
+ | `candidates` | The project candidate pool in compact form: `clip_id`, `type` (online / cloud / local / image), platform and title, score, `seg` window, `review_only`, `preview_landed` (material registered and the file is on disk), `used_by` (clips already using it); no download URLs |
445
+ | `plan` | Total candidates for the beat in `split/broll-plan.json`, how many are not in the pool, and the top 5 by score; `present:false` when there is no plan |
446
+ | `clips` | Clips on every video track that intersect the window: track, `clip_id`, material, start/end, `category` (broll / raw / black_fill / user / a_roll), and whether it carries a producer identity |
447
+ | `gaps` / `black_only` | Spans above the main track with no picture (seams shorter than one frame are ignored); the part of them covered only by black fill patches |
448
+
449
+ Without `--beat`, one line per B-roll beat: window, candidate count, plan candidate count, covered seconds, number and seconds of gaps. Both forms also carry the project `revision` (usable as `gtrk patch --expected-revision`), `main_track`, the re-projection summary, the strip verdict of each candidate track and `lay.relay_refused` (whether a full re-lay would now be refused with `tracks_edited`). Beats in non-B-roll lanes get only the window, lane and clips. An unknown beat gives `ok:false`, exit code 1, and the list of all known beats.
450
+
415
451
  ### `gtrk matrix` — B-roll retrieval + candidate track laying
416
452
 
417
453
  **No positional argument = consume the dispatch**: reads the `film_broll` queue from `split/dispatch.json` → dual-endpoint retrieval → produces the candidate list `split/broll-plan.json`, downloads preview proxies, and lays N candidate tracks in the project (open it in opencut and toggle track visibility to compare and choose). **`matrix search "<query>"` = a one-off ad-hoc search** (independent of any dispatch). **`matrix fetch <clip_id...>` = pull raw footage during the fine cut** (project-independent; see below).
@@ -782,6 +818,8 @@ A QC pass runs automatically afterwards and writes `.qc.json` (`--no-qc` skips i
782
818
  - `gtrk install [--api-key … -y --skill-agents codex,cursor --all-agents --copy-skills --skills-dir …]` — install everything in one command (skills + config + health check), modelled on Feishu's `lark-cli install`.
783
819
  - `gtrk init [--api-key … --api-base … --jianying-draft-dir … -y]` — configuration only (interactive or not).
784
820
  - `gtrk doctor` — health check (including the CLI version and whether a newer one exists).
821
+ - `gtrk cover embed <workbench.html> [--bg-16x9 <img>] [--bg-4x3 <img>] [--bg-3x4 <img>] -o <out.html>` — embed background images into the cover workbench: each image is compressed to JPEG for its size (long edge 16:9 ≤1280, 4:3 ≤1600, 3:4 ≤1400) and swapped in as base64 for `__BG_16_9__` / `__BG_4_3__` / `__BG_3_4__` (exporting PNG from a `file://` page requires embedded images). `-o` is required and may equal the input; placeholders for sizes without an image are kept and reported; the workbench gets a hint above 600 KB and a warning above 1 MB. Purely local, zero billing, no intermediate image files.
822
+ - `gtrk ai-drama validate <draft-storyboard.md> [...]` — production-side contract check for AI scene storyboards (same rules and output as `scripts/validate-storyboard.mjs` bundled with `/gtrk-ai-drama`): one JSON line per file; exit 0 when all pass, 1 when any fails, 2 when no file is given.
785
823
  - `gtrk deps status` — show **where** ffmpeg/ffprobe, the render fonts and the composite-bake browser currently come from (`--ffmpeg-path` / `~/.gitruck` / system / missing), plus version, licence and source-code location.
786
824
  - `gtrk deps install [--ffmpeg] [--font] [--browser] [--force]` — install runtime assets from the Gitruck Cloud mirror, **skipping anything already present**. Without flags it installs ffmpeg and fonts; `--browser` additionally installs the pinned chrome-headless-shell for composite baking (about 110 MB, into `~/.gitruck/browsers`, BSD licence, provenance and source in the mirror's `SOURCE.md`), **only when named explicitly**.
787
825
  - **It never downloads silently**: any missing-dependency path only errors out and points at this command (the packages are 30–90 MB and the distributed artifacts carry licence obligations, so a user or agent must trigger it explicitly).
package/docs/reference.md CHANGED
@@ -67,7 +67,7 @@ gtrk skills install --copy
67
67
  | ① | `/gtrk-oralcut` | `gtrk oralcut` | 智能剪口播 → 客户端/剪映/PR 三方工程 + transcript |
68
68
  | ② | `/gtrk-splitter` | `gtrk split` | 拆分派单 → `dispatch.json`(A_ROLL/MG/AI_DRAMA/FILM_BROLL 四车道) |
69
69
  | ③ | `/gtrk-matrix` | `gtrk matrix` | **B-roll 底轨·影视/本地素材腿**:铺候选轨 → **用户调整/挑选**(opencut 小眼睛切换) |
70
- | ③ | `/gtrk-ai-drama` | (无命令,纯创作) | **B-roll 底轨·AI 情景片段腿(与 matrix 同阶段,不是最后)**:产四段描述稿(故事背景/角色/分镜/原文,中英分块)→ 任意外部平台出片、手动回铺(产物即描述文本、无机械尾巴,同 `/gtrk-style-maker` 只 skill 无命令) |
70
+ | ③ | `/gtrk-ai-drama` | `gtrk ai-drama validate`(校验分镜稿)· `lay` / `pack` / `swap`(回填) | **B-roll 底轨·AI 情景片段腿(与 matrix 同阶段,不是最后)**:产四段描述稿(故事背景/角色/分镜/原文,中英分块)→ 任意外部平台出片、手动回铺(产物即描述文本、无机械尾巴,同 `/gtrk-style-maker` 只 skill 无命令) |
71
71
  | ④ | (无 skill) | (无命令) | **全局抽帧检查画面构图**:对三源合并后的最终底轨抽帧,用户确认构图——这是 agent 纪律硬门,供 ⑤ 的排版避让决策使用 |
72
72
  | ⑤ | `/gtrk-mg` | `gtrk mg` | **MG(含 ov)最后叠上**(叠在已定稿、构图已核的底轨之上) |
73
73
  | ⑥ | `/gtrk-composite` | `gtrk composite` | **合成层**(字幕之后、出片之前):把选定时间窗做成合成颗粒——一段时间内的整个画面由一颗代码颗粒接管(逐句换画面、对照并排、并列卡片、字幕排版),讲者与 B-roll 作为槽位画进去;入口三选一(整片铺满 / AI 判定 / 指定区间),候选显示在客户端大纲 CP 行;纯本地零计费。出片时由 `gtrk composite bake` 在本机烘焙成视频(首次需 `gtrk deps install --browser`) |
@@ -79,7 +79,7 @@ gtrk skills install --copy
79
79
  | 📝 | `/gtrk-transcript` | `gtrk transcript` | 本地视频/配音音频 → 一个含 Agent 总结、时码记录和纯文本的 Markdown,**不在成片 SOP 序列内** |
80
80
  | 🧰 | `/gtrk-tools` | `gtrk tool <name>` | 单点工具族(图转运镜 / 图片·视频抠像…)——单发单收,**不在成片 SOP 序列内**、随时可独立用 |
81
81
  | 🎵 | `/gtrk-music-visualizer` | `gtrk music-visualizer` | 一首歌 → 频谱可视化成片(模板 + 可选背景/封面 + 配色样式),**不在成片 SOP 序列内**、独立引流用 |
82
- | 🖼️ | `/gtrk-cover` | (无命令,纯创作) | 封面工作台两阶段:设计诊断 + 三尺寸中英双版文生图 Prompt → 用户外部平台抽图 → H5 排字工作台(拖拽/滚轮微调、一键导出多尺寸 PNG)。栏目封面审美经栏目配置 `style.skills`(`produces:"cover"`)注入;**不在成片 SOP 序列内**(投放配套的「第 0 阶段」) |
82
+ | 🖼️ | `/gtrk-cover` | `gtrk cover embed`(背景图压缩嵌进工作台,纯本地零计费) | 封面工作台两阶段:设计诊断 + 三尺寸中英双版文生图 Prompt → 用户外部平台抽图 → H5 排字工作台(拖拽/滚轮微调、一键导出多尺寸 PNG)。栏目封面审美经栏目配置 `style.skills`(`produces:"cover"`)注入;**不在成片 SOP 序列内**(投放配套的「第 0 阶段」) |
83
83
  | 🧭 | `/gtrk-talking-head` | 编排 `gtrk audio` → `oralcut` → `split` → `matrix` → `mg` → `audio lay` → `subtitle lay` | **口播链图纸**:一条或一组真人出镜毛片 → 外录音轨对齐换轨、多段拼接、粗剪、拆分派单、B-roll/MG 字卡、BGM、字幕 → 客户端可出片工程 |
84
84
  | 🧭 | `/gtrk-travel-recap` | 编排 `gtrk tool audio_tts_clone` → `project init` → `split` → `matrix` → `mg` → `audio lay` → `subtitle lay` | **旅拍解说图纸**:旅拍素材夹 → AI 理解素材、写三段式解说稿、一次确认 → 配音/建工程/拆分/B-roll/字卡/BGM/字幕全自动跑完 → 客户端可出片工程 |
85
85
  | 🧭 | `/gtrk-live-slicing` | 编排 `gtrk long2short`(超长回放先分段) | **直播切片图纸**:数小时直播回放 → 分段(服务端 2h 硬闸)→ 选题清单确认 → 一批逐 clip 粗剪工程(gtrk + 剪映 + PR),按画面形态配分屏 |
@@ -89,7 +89,7 @@ gtrk skills install --copy
89
89
  | 🧭 | `/gtrk-vlog-docu` | 编排 `gtrk transcript` → `tool audio_tts_clone` → `split` → `matrix` → `mg` → `audio lay` → `subtitle lay` | **Vlog 纪实图纸**:一批现场素材 → 素材理解、选档写稿、一次拍板 → 同期声骨架 + 旁白配音 + B-roll + 字幕层 + BGM 全自动 → 客户端可出片工程;「现场同期声 × 后期旁白」双声道交替,区别于纯口播链与纯配音链 |
90
90
 
91
91
  > **skill 与命令的区别**:`/gtrk-mg` 是**脑**——懂它在 SOP 第 ⑤ 步(B-roll 三源全齐、构图核过才铺 MG)、带用户确认、按栏目配置解析该产哪种颗粒;`gtrk mg` 是**手**——纯确定性 lint + 铺轨。你对话触发 skill,skill 替你跑命令。
92
- > 上面 20 个 `/gtrk-X` 都是 **CLI 自带框架 skill**(`gtrk skills install` 装;名单与「给 AI Agent 用」一节、「结构」一节完全一致)——其中 🧭 标记的 7 张是**组合图纸**(一句话跑全链,只编排上面的单命令 skill、本身不新增命令);`/gtrk-long2short` 独立驱动长剪短,`/gtrk-transcript` 独立驱动视频/音频转文字稿,`/gtrk-tools` 只负责单点工具族,`/gtrk-cover` 管封面,`/gtrk-ref-reading` 管参考片精读,五者都不属成片 SOP 序列;`/gtrk-ai-drama`·`/gtrk-style-maker`·`/gtrk-cover` 是纯创作 skill(无命令)。栏目专属的**视觉风格/生产内容**另由你栏目的生产 skill(`/gtrk-style-maker` 产、经栏目配置 `style.skills` 绑定)供,不写死在这些框架 skill 里。
92
+ > 上面 20 个 `/gtrk-X` 都是 **CLI 自带框架 skill**(`gtrk skills install` 装;名单与「给 AI Agent 用」一节、「结构」一节完全一致)——其中 🧭 标记的 7 张是**组合图纸**(一句话跑全链,只编排上面的单命令 skill、本身不新增命令);`/gtrk-long2short` 独立驱动长剪短,`/gtrk-transcript` 独立驱动视频/音频转文字稿,`/gtrk-tools` 只负责单点工具族,`/gtrk-cover` 管封面,`/gtrk-ref-reading` 管参考片精读,五者都不属成片 SOP 序列;`/gtrk-style-maker` 是纯创作 skill(无命令),`/gtrk-ai-drama`·`/gtrk-cover` 以创作为主、只有校验 / 嵌图这类机械段走命令。栏目专属的**视觉风格/生产内容**另由你栏目的生产 skill(`/gtrk-style-maker` 产、经栏目配置 `style.skills` 绑定)供,不写死在这些框架 skill 里。
93
93
 
94
94
  **各车道的具体视觉/内容怎么产**——MG 动态图长什么样、AI 情景动画什么调性——不写死在 CLI 里,而由**你自己栏目的生产 skill** 提供(用 `/gtrk-style-maker` 访谈式产出、留本地)。它们经**栏目配置 `style.skills[].produces`**(值 = 车道名)绑定,`gtrk mg` / `gtrk matrix` 等**通用驱动器**据此消费。**驱动方向 = CLI 驱动栏目 skill**:栏目 skill 只供风格/内容、不含任何「跑哪条命令」的编排职责;框架只认车道与管线接口,画面风格永远归你的栏目。不建栏目就用内置默认,端到端照常跑。
95
95
 
@@ -353,7 +353,7 @@ gtrk client frame --at 31.5 --json # 时间线上的 31.5 秒,不是
353
353
  >
354
354
  > **派单条目自带 `span:{from,to}`**(该条目对应的 utterance 区间;`overlay` aux 派生条目写 **aux 自己的** span,可为主 beat span 的子区间)。**`track_st/track_ed` 是投影时刻的快照**——`gtrk mg` / `gtrk matrix` 消费时会**现场重投影**(见下),所以改完口播轨**不必**回来重跑 `gtrk split`,只有拆分稿本身变了才要重跑。
355
355
 
356
- ### `gtrk patch <move|trim|split|set>` — 元素级编辑(改工程唯一入口)
356
+ ### `gtrk patch <move|trim|split|set|add|replace>` — 元素级编辑(改工程唯一入口)
357
357
 
358
358
  改一个 clip / gap / 颗粒的时码或参数。**agent 勿裸手改 `.gtrk` JSON** —— 片段时码是两套并存的
359
359
  (`clip_st`+`clip_ed` 与 `clip_st`+`duration`),改一份不改另一份是**静默失败**:客户端优先读 `clip_ed`,
@@ -364,6 +364,8 @@ gtrk patch move --project <dir> --clip c2 --to 5.0
364
364
  gtrk patch trim --project <dir> --clip c2 --out -1s
365
365
  gtrk patch split --project <dir> --clip c2 --cut 5.5
366
366
  gtrk patch set --project <dir> --track audio:1 --at 3.0 --volume 0.5
367
+ gtrk patch add --project <dir> --track video:2 --to 263.733 --candidate <clip_id> # 把候选放上空位
368
+ gtrk patch replace --project <dir> --clip <clip_id> --candidate <clip_id> # 原地换源
367
369
  ```
368
370
 
369
371
  | 参数 | 作用 | 缺省 |
@@ -371,7 +373,11 @@ gtrk patch set --project <dir> --track audio:1 --at 3.0 --volume 0.5
371
373
  | `--project <dir>` / `--gtrk <path>` | 工程目录(自动定位 `gtrk/project.gtrk`)或直接给路径 | — |
372
374
  | `--clip <clip_id>` | 按 id 寻址。命中 video/audio **镜像对**时视为一个编辑单元 | — |
373
375
  | `--track <kind:idx> --at <sec>` | 按位置寻址(`track_st ≤ at < track_ed`)。与 `--clip` 互斥 | — |
374
- | `--to <sec\|Nf>` | `move` 的落点 | — |
376
+ | `--to <sec\|Nf>` | `move` / `add` 的落点(`add` 不收 `--at`:`--at` 在本命令里恒为寻址义) | — |
377
+ | `--candidate <clip_id>` / `--material <id>` | `add` / `replace` 的来源,二选一:B-roll 候选(先查工程候选池含邻居,再查 `split/broll-plan.json`)或 `materials` 里已登记的视频 / 图片素材 | — |
378
+ | `--beat <id>` | 候选所在 beat(同一候选在多个 beat 取窗不同时必给) | — |
379
+ | `--from <sec>` | `add` / `replace` 的源片入点(候选按它自己的源片时间,外网候选自动换成预览文件时间) | 与客户端拖候选上轨同一取窗:以 `seg.best` 居中、钳在素材范围内;素材从 0 |
380
+ | `--dur <sec\|Nf>` | `add` 的时长 | 落点所在空位的长度(到该轨上落点之后第一个元素的起点,出点与它取同一帧号);后面没有元素时取候选取窗长度 |
375
381
  | `--in` / `--out` / `--set-in` / `--set-out` / `--slip` | `trim` 的五种语义(前两个相对、中两个绝对、`--slip` 只换源窗) | — |
376
382
  | `--cut <sec\|Nf>` | `split` 的切点。⚠️ 与寻址用的 `--at` 是两个参数 | — |
377
383
  | `--muted` / `--no-muted` / `--volume <gain>` / `--opaque` | `set` 的元素级参数(`--volume` 是线性增益不是 dB,须 > 0;`--volume 0` 报 `volume_zero_use_muted`,静音用 `--muted`)。轨静音是总开关:片段所在轨已静音时 `--no-muted` 报 `track_muted_master`,请在客户端点开轨喇叭 | — |
@@ -389,6 +395,13 @@ gtrk patch set --project <dir> --track audio:1 --at 3.0 --volume 0.5
389
395
  >
390
396
  > ⚠️ 空档(gap)不能用 `--clip ""` 寻址:契约允许多个 gap 共享该取值,它不构成地址;用 `--track/--at`。
391
397
 
398
+ **`add` / `replace`(精修期放候选上轨、原地换源)**:
399
+
400
+ - 候选的素材还不在 `materials` 里时,顺手把预览下载到 `assets/broll-preview/` 并登记(与 `gtrk matrix lay` 同一份落地实现);已登记的直接复用、不重下。所以 `matrix source-import` 之后一条 `patch add` 就能上轨。下载失败零写、非 0(`preview_download_failed`:候选地址可能过期,重跑检索 / 导入刷新);已落盘的预览留作下次复用。
401
+ - `add` 只放已存在的视频轨;落点与非空档元素重叠即拒(`add_overlap`,列出挡路元素;挡路的是黑底补片时指路 `patch replace`);落点覆盖到的显式空档让位;不 ripple、不新建轨。图片候选不收(上轨要先生成运镜)。源片不够长时钳短并告警 `add_clamped`,不拉伸。新片段 `clip_id` 为 `<beat>-add-<n>`,不带 `producer`,候选来源带纯黑 `background_fill`。
402
+ - `replace` 只换 `material` 与源窗:`clip_id`、所在轨、起点、倍速、变换、填充、转场、关键帧都不动;新素材从入点起不够长时如实缩短(`replace_shortened`),不拉伸、不挪起点;删去 `producer`,下一次 `matrix lay` 把这条轨当用户轨保留;旧素材条目不删。镜像对(视频 + 镜像音频)不收。
403
+ - 先按自述值把全部改动算一遍、全档校验,通过了才落地;`--dry-run` 不下载、不写文件,回执带 `would_download`。回执的 op 另带 `source`(候选 / 素材、`material_id`、`landed`:existing / reused / downloaded / registered)与 `add` 的 `gaps_consumed`。`--ops` 条目同形:`{"action":"add","track":"video:2","to":263.733,"candidate":"…"}`。
404
+
392
405
  **转场字段的保真与维护**(`transition_in` / `transition_out` / `transition_next`;由客户端产生,CLI 本期不产出、无新参数):
393
406
 
394
407
  - `split`:入场转场留前段,出场转场与接下一段的转场归后段(`to_clip_id` 不变),新切口不带转场。
@@ -410,6 +423,29 @@ gtrk matrix source-import --project <工程目录> --beat B07 --urls links.txt -
410
423
 
411
424
  每个指定来源生成一个整段低清预览候选,`source-import` 本身不会下载高清原片、不会改时间线,也不会创建 `online_broll_resolve`。候选的时间窗就是该来源已下载预览的完整窗口。客户端对它仍可双击打开 Trim 对话框,但裁剪范围严格限制在该候选来源窗口内;预裁剪会随拖拽进入时间线。用户把候选放入轨道并点击“确认 B-roll”后,客户端才把当前源时间窗口提交给 `online_broll_resolve`,由云端下载高清窗口并置换当前低清素材。`更多外网候选` 只对关键词检索任务分页,不会把指定来源任务重复当作搜索结果。
412
425
 
426
+ ### `gtrk matrix status` — 一条命令看清某个 beat 的现状(只读)
427
+
428
+ ```bash
429
+ gtrk matrix status --project <工程目录> --beat B20 --json
430
+ gtrk matrix status --project <工程目录> --beat B20,B21
431
+ gtrk matrix status --project <工程目录> --json # 全部 B-roll beat,一行一个概要
432
+ ```
433
+
434
+ 只接受 `--project` / `--beat` / `--json`。不调云端、不需要 Key、不写任何文件;读的是盘上工程,不含客户端里未保存的改动(那是 `gtrk client state` 的事)。`--beat` 在这里可以逗号分隔给多个;`matrix source-import` 的 `--beat` 仍只认一个。
435
+
436
+ 带 `--beat` 时每个 beat 给出:
437
+
438
+ | 字段 | 内容 |
439
+ |---|---|
440
+ | `window` | 时间窗:现场重投影(与 `gtrk matrix` / `gtrk mg` 同一段代码);退回派单快照时 `source:"dispatch_snapshot"` 并带 `degraded_reason` |
441
+ | `lane` / `queries` | 车道与派单检索词 |
442
+ | `candidates` | 工程候选池,精简字段:`clip_id`、`type`(online / cloud / local / image)、平台与标题、得分、取窗 `seg`、`review_only`、`preview_landed`(素材已登记且文件在盘上)、`used_by`(已用在哪些片段上);不带下载地址 |
443
+ | `plan` | `split/broll-plan.json` 里该 beat 的候选总数、不在候选池的条数与得分最高 5 条;没有 plan 时 `present:false` |
444
+ | `clips` | 时间窗内各视频轨上的片段:轨、`clip_id`、素材、起止、`category`(broll / raw / black_fill / user / a_roll)、是否带产出方身份 |
445
+ | `gaps` / `black_only` | 主轨之上没有画面的区间(短于一帧的缝不算);其中只盖着黑底补片的区间 |
446
+
447
+ 不带 `--beat` 时,每个 B-roll beat 一行:时间窗、候选数、plan 候选数、已覆盖秒数、空缺段数与秒数。顶层另给工程 `revision`(可直接作 `gtrk patch --expected-revision`)、`main_track`、重投影摘要、各候选轨的剥离判定与 `lay.relay_refused`(现在整轮重铺会不会被 `tracks_edited` 拒)。非 B-roll 车道的 beat 只给时间窗、车道与轨上片段。beat 不存在时 `ok:false`、退出码 1,并列出全部已知 beat。
448
+
413
449
  ### `gtrk matrix` — B-roll 检索 + 候选铺轨
414
450
 
415
451
  **无 positional = 派单消费**:读 `split/dispatch.json` 的 `film_broll` 队列 → 双口检索 → 产候选清单 `split/broll-plan.json` + 下载 preview 代理、在工程里平铺 N 条候选轨(opencut 打开即可用轨道小眼睛对比挑选)。**`matrix search "<query>"` = 单条 ad-hoc 检索**(不依赖派单)。**`matrix fetch <clip_id...>` = 精剪期拉原片**(脱离工程,见下)。
@@ -825,6 +861,8 @@ gtrk render <gtrk> [-o <out.mp4>] [--crf <n>] [--codec <c>] [--ffmpeg-path <dir>
825
861
  - `gtrk install [--api-key … -y --skill-agents codex,cursor --all-agents --copy-skills --skills-dir …]` — 一条命令装全(skill + 配置 + 体检),对标飞书 `lark-cli install`。
826
862
  - `gtrk init [--api-key … --api-base … --jianying-draft-dir … -y]` — 仅配置(交互 / 非交互)。
827
863
  - `gtrk doctor` — 体检(含 CLI 版本 / 有无新版)。
864
+ - `gtrk cover embed <工作台.html> [--bg-16x9 <图>] [--bg-4x3 <图>] [--bg-3x4 <图>] -o <输出.html>` — 封面工作台嵌背景图:按尺寸把图压成 JPEG(长边 16:9 ≤1280、4:3 ≤1600、3:4 ≤1400),以 base64 换进 `__BG_16_9__` / `__BG_4_3__` / `__BG_3_4__`(`file://` 下导出 PNG 要求内嵌)。`-o` 必填、可与输入同名;没给图的尺寸占位符保留并提示;工作台超过 600 KB 提示、超过 1 MB 告警。纯本地、零计费,不写中间图片。
865
+ - `gtrk ai-drama validate <候选分镜稿.md> [...]` — AI 情景动画分镜稿的生产端硬契约校验(与 `/gtrk-ai-drama` 随包的 `scripts/validate-storyboard.mjs` 同判据、同输出):每个文件一行 JSON;全过退出 0、有不过退出 1、没给文件退出 2。
828
866
  - `gtrk deps status` — 查 ffmpeg/ffprobe、渲染字体与合成烘焙浏览器的**当前来源**(`--ffmpeg-path` / `~/.gitruck` / 系统 / 缺失)、版本、授权与源码地址。
829
867
  - `gtrk deps install [--ffmpeg] [--font] [--browser] [--force]` — 从同合云镜像安装运行时资产,**已存在则跳过**。不带开关装 ffmpeg 与字体;`--browser` 另装合成烘焙用的钉定版本 chrome-headless-shell(约 110 MB,落 `~/.gitruck/browsers`,BSD 许可,来源与源码见分发点 `SOURCE.md`),**只在显式点名时装**。
830
868
  - **不会静默自动下载**:任何缺失路径只报错并指向本命令(包体 30–90 MB,且分发物涉及授权,须由用户/agent 显式触发)。
package/package.json CHANGED
@@ -1,79 +1,79 @@
1
- {
2
- "name": "@gitruck/cli",
3
- "version": "1.3.11",
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
- "docs/reference.md",
28
- "docs/reference.en.md",
29
- "docs/workflow.md",
30
- "docs/workflow.en.md",
31
- "docs/development.md",
32
- "docs/development.en.md",
33
- "LICENSE",
34
- "CHANGELOG.md"
35
- ],
36
- "engines": {
37
- "node": ">=20.6"
38
- },
39
- "publishConfig": {
40
- "access": "public",
41
- "registry": "https://registry.npmjs.org/"
42
- },
43
- "keywords": [
44
- "gitruck",
45
- "同合云",
46
- "video",
47
- "oral-cut",
48
- "口播剪辑",
49
- "cli",
50
- "jianying",
51
- "剪映",
52
- "agent"
53
- ],
54
- "scripts": {
55
- "gtrk": "bun run src/index.ts",
56
- "test:purify": "esbuild src/commands/purify.ts --bundle --platform=node --format=esm --external:bun:sqlite --outfile=.test-build/purify-cmd.mjs && node --test test/purify-cmd.test.mjs",
57
- "build": "bun build ./src/index.ts --target=node --minify --outfile dist/index.js",
58
- "typecheck": "tsc --noEmit",
59
- "prepublishOnly": "node scripts/plugin-manifest-check.mjs && npm run typecheck && npm test && bun run build",
60
- "test": "node scripts/workspace-pollution-gate.mjs --snapshot && esbuild src/lib/compliance-notice.ts src/lib/config.ts src/lib/crash-report.ts src/lib/usage-analytics.ts src/lib/log.ts src/lib/read-json.ts src/lib/sidecar-write.ts src/lib/user-config.ts src/lib/enum-catalog.ts src/lib/first-run-tutorial.ts src/lib/desktop-client-hint.ts src/lib/command-path.ts src/lib/user-path.ts src/lib/runtime-channel.ts src/lib/self-install.ts src/lib/plugin-presence.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/project-background.ts src/lib/client-only-state.ts src/lib/gtrk-patch.ts src/lib/frame-domain.ts src/lib/clock-adapter.ts src/lib/gtrk-invariants.ts src/lib/clip-speed.ts src/lib/clip-keyframes.ts src/lib/clip-audio-fade.ts src/lib/clip-transitions.ts src/lib/transition-catalog.ts src/lib/column-config.ts src/lib/third-party-catalog.ts src/lib/mg-adopt.ts src/lib/mg-registry.ts src/lib/matrix.ts src/lib/online-broll-client.ts src/lib/online-search-journal.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/highlight-rubric.ts src/lib/highlight-input.ts src/lib/local-index.ts src/lib/character-input.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/outdir-guard.ts src/lib/landing-wait.ts src/lib/material-integrity.ts src/lib/project-health.ts src/lib/contact-sheet.ts src/lib/media-transcript.ts src/lib/media-grid.ts src/lib/media-ffmpeg.ts src/lib/solid-png.ts src/lib/mask-raster.ts src/lib/mg-lint.ts src/lib/mg-visual-job.ts src/lib/mg-track-identity.ts src/lib/particle-identity.ts src/lib/text-ir/compile.ts src/lib/text-ir/validate.ts src/lib/text-ir/compile-local.ts src/lib/text-templates.ts src/lib/text-ir-client.ts src/lib/mg-lay.ts src/lib/mg-render.ts src/lib/particle-qtrle.ts src/lib/composite-particle.ts src/lib/composite-lay.ts src/lib/composite-lint.ts src/lib/composite-browser.ts src/lib/composite-plan.ts src/lib/composite-shots.ts src/lib/composite-resolve.ts src/lib/composite-profile.ts src/lib/composite-scene.ts src/lib/composite-kit-upgrade.ts src/lib/composite-bake-plan.ts src/lib/composite-bake.ts src/lib/composite-export.ts src/lib/tool-descriptors.ts src/lib/tool-runner.ts src/lib/tool-batch.ts src/lib/tool-pricing.ts src/lib/transcript.ts src/lib/runtime-assets.ts src/lib/subtitle-lay.ts src/lib/caption-align.ts src/lib/subtitle-line-split-client.ts src/lib/audio-align.ts src/lib/audio-tighten.ts src/lib/cut-snap.ts src/lib/mg-coverage.ts src/lib/ai-drama-lay.ts src/lib/ai-drama-pack.ts src/lib/desk-locate.ts src/lib/pip-lay.ts src/lib/client-bridge.ts src/lib/client-state.ts src/lib/client-frame.ts --bundle --platform=node --format=esm --external:bun:sqlite --outdir=.test-build --out-extension:.js=.mjs && esbuild src/lib/text-ir/compile.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/text-ir-compile.mjs && esbuild src/commands/split.ts --bundle --platform=node --external:bun:sqlite --format=esm --outdir=.test-build --out-extension:.js=.mjs && esbuild src/commands/patch.ts --bundle --platform=node --external:bun:sqlite --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 --external:bun:sqlite --format=esm --outfile=.test-build/mg-cmd.mjs && esbuild src/commands/mg-text.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/mg-text-cmd.mjs && esbuild src/commands/tool.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/tool-cmd.mjs && esbuild src/commands/transcript.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/transcript-cmd.mjs && esbuild src/commands/project.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/project-cmd.mjs && esbuild src/commands/audio.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/audio-cmd.mjs && esbuild src/commands/subtitle.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/subtitle-cmd.mjs && esbuild src/commands/ai-drama.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/ai-drama-cmd.mjs && esbuild src/commands/feedback.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/feedback-cmd.mjs && esbuild src/commands/music-visualizer.ts --bundle --platform=node --external:bun:sqlite --format=esm --external:commander --outfile=.test-build/music-visualizer-cmd.mjs && esbuild src/commands/long2short.ts --bundle --platform=node --external:bun:sqlite --format=esm --external:commander --outfile=.test-build/long2short-cmd.mjs && esbuild src/commands/oralcut.ts --bundle --platform=node --external:bun:sqlite --format=esm --external:commander --outfile=.test-build/oralcut-cmd.mjs && esbuild src/commands/oralcut-result.ts --bundle --platform=node --external:bun:sqlite --format=esm --external:commander --outfile=.test-build/oralcut-result-cmd.mjs && esbuild src/commands/skills.ts --bundle --platform=node --external:bun:sqlite --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/commands/media.ts --bundle --platform=node --format=esm --external:commander --external:bun:sqlite --outfile=.test-build/media-cmd.mjs && esbuild src/commands/client.ts --bundle --platform=node --format=esm --external:commander --external:bun:sqlite --outfile=.test-build/client-cmd.mjs && esbuild src/commands/doctor.ts --bundle --platform=node --external:bun:sqlite --format=esm --external:commander --outfile=.test-build/doctor-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 --external:bun:sqlite --format=esm --outdir=.test-build/convert --out-extension:.js=.mjs && esbuild src/lib/mad/selector.ts src/lib/mad/techniques.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 --external:bun:sqlite --format=esm --outdir=.test-build/mad --out-extension:.js=.mjs && esbuild src/commands/composite.ts --bundle --platform=node --format=esm --external:bun:sqlite --external:commander --outfile=.test-build/composite-cmd.mjs && esbuild src/commands/purify.ts --bundle --platform=node --format=esm --external:bun:sqlite --outfile=.test-build/purify-cmd.mjs && esbuild src/lib/static-delivery/index.ts src/lib/static-delivery/node.ts --bundle --platform=node --format=esm --outdir=.test-build/static-delivery --out-extension:.js=.mjs && node --import ./test/helpers/test-home.mjs --test \"test/*.test.mjs\" && node scripts/workspace-pollution-gate.mjs --verify",
61
- "test:linux": "node scripts/test-linux.mjs",
62
- "openspec:gate": "node openspec/gate.mjs",
63
- "mg-registry:snapshot": "node scripts/mg-registry-snapshot.mjs",
64
- "text-template:snapshot": "node scripts/text-template-snapshot.mjs",
65
- "text-ir:parity": "node scripts/text-ir-parity.mjs",
66
- "text-ir:sync": "node scripts/text-ir-sync.mjs"
67
- },
68
- "devDependencies": {
69
- "@xmldom/xmldom": "^0.9.6",
70
- "bun-types": "^1.1.0",
71
- "commander": "^12.1.0",
72
- "esbuild": "^0.28.1",
73
- "typescript": "^5.6.0"
74
- },
75
- "dependencies": {
76
- "hash-wasm": "^4.12.0",
77
- "jszip": "^3.10.1"
78
- }
79
- }
1
+ {
2
+ "name": "@gitruck/cli",
3
+ "version": "1.3.12",
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
+ "docs/reference.md",
28
+ "docs/reference.en.md",
29
+ "docs/workflow.md",
30
+ "docs/workflow.en.md",
31
+ "docs/development.md",
32
+ "docs/development.en.md",
33
+ "LICENSE",
34
+ "CHANGELOG.md"
35
+ ],
36
+ "engines": {
37
+ "node": ">=20.6"
38
+ },
39
+ "publishConfig": {
40
+ "access": "public",
41
+ "registry": "https://registry.npmjs.org/"
42
+ },
43
+ "keywords": [
44
+ "gitruck",
45
+ "同合云",
46
+ "video",
47
+ "oral-cut",
48
+ "口播剪辑",
49
+ "cli",
50
+ "jianying",
51
+ "剪映",
52
+ "agent"
53
+ ],
54
+ "scripts": {
55
+ "gtrk": "bun run src/index.ts",
56
+ "test:purify": "esbuild src/commands/purify.ts --bundle --platform=node --format=esm --external:bun:sqlite --outfile=.test-build/purify-cmd.mjs && node --test test/purify-cmd.test.mjs",
57
+ "build": "bun build ./src/index.ts --target=node --minify --outfile dist/index.js",
58
+ "typecheck": "tsc --noEmit",
59
+ "prepublishOnly": "node scripts/plugin-manifest-check.mjs && npm run typecheck && npm test && bun run build",
60
+ "test": "node scripts/workspace-pollution-gate.mjs --snapshot && esbuild src/lib/compliance-notice.ts src/lib/config.ts src/lib/crash-report.ts src/lib/usage-analytics.ts src/lib/log.ts src/lib/read-json.ts src/lib/sidecar-write.ts src/lib/user-config.ts src/lib/enum-catalog.ts src/lib/first-run-tutorial.ts src/lib/desktop-client-hint.ts src/lib/command-path.ts src/lib/user-path.ts src/lib/runtime-channel.ts src/lib/self-install.ts src/lib/plugin-presence.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/project-background.ts src/lib/client-only-state.ts src/lib/gtrk-patch.ts src/lib/frame-domain.ts src/lib/clock-adapter.ts src/lib/gtrk-invariants.ts src/lib/clip-speed.ts src/lib/clip-keyframes.ts src/lib/clip-audio-fade.ts src/lib/clip-transitions.ts src/lib/transition-catalog.ts src/lib/column-config.ts src/lib/third-party-catalog.ts src/lib/mg-adopt.ts src/lib/mg-registry.ts src/lib/matrix.ts src/lib/online-broll-client.ts src/lib/online-broll-contract.ts src/lib/online-broll-grant.ts src/lib/source-import.ts src/lib/online-search-journal.ts src/lib/matrix-material.ts src/lib/matrix-fetch.ts src/lib/matrix-lay.ts src/lib/matrix-status.ts src/lib/broll-landing.ts src/lib/patch-place.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/highlight-rubric.ts src/lib/highlight-input.ts src/lib/local-index.ts src/lib/character-input.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/outdir-guard.ts src/lib/landing-wait.ts src/lib/material-integrity.ts src/lib/project-health.ts src/lib/contact-sheet.ts src/lib/media-transcript.ts src/lib/media-grid.ts src/lib/media-ffmpeg.ts src/lib/solid-png.ts src/lib/mask-raster.ts src/lib/mg-lint.ts src/lib/mg-visual-job.ts src/lib/mg-track-identity.ts src/lib/particle-identity.ts src/lib/text-ir/compile.ts src/lib/text-ir/validate.ts src/lib/text-ir/compile-local.ts src/lib/text-templates.ts src/lib/text-ir-client.ts src/lib/mg-lay.ts src/lib/mg-render.ts src/lib/particle-qtrle.ts src/lib/composite-particle.ts src/lib/composite-lay.ts src/lib/composite-lint.ts src/lib/composite-browser.ts src/lib/composite-plan.ts src/lib/composite-shots.ts src/lib/composite-resolve.ts src/lib/composite-profile.ts src/lib/composite-scene.ts src/lib/composite-kit-upgrade.ts src/lib/composite-bake-plan.ts src/lib/composite-bake.ts src/lib/composite-export.ts src/lib/tool-descriptors.ts src/lib/tool-runner.ts src/lib/tool-batch.ts src/lib/tool-pricing.ts src/lib/transcript.ts src/lib/runtime-assets.ts src/lib/subtitle-lay.ts src/lib/caption-align.ts src/lib/subtitle-line-split-client.ts src/lib/audio-align.ts src/lib/audio-tighten.ts src/lib/cut-snap.ts src/lib/mg-coverage.ts src/lib/ai-drama-lay.ts src/lib/ai-drama-pack.ts src/lib/desk-locate.ts src/lib/pip-lay.ts src/lib/client-bridge.ts src/lib/client-state.ts src/lib/client-frame.ts --bundle --platform=node --format=esm --external:bun:sqlite --outdir=.test-build --out-extension:.js=.mjs && esbuild src/lib/text-ir/compile.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/text-ir-compile.mjs && esbuild src/commands/split.ts --bundle --platform=node --external:bun:sqlite --format=esm --outdir=.test-build --out-extension:.js=.mjs && esbuild src/commands/patch.ts --bundle --platform=node --external:bun:sqlite --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 --external:bun:sqlite --format=esm --outfile=.test-build/mg-cmd.mjs && esbuild src/commands/mg-text.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/mg-text-cmd.mjs && esbuild src/commands/tool.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/tool-cmd.mjs && esbuild src/commands/transcript.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/transcript-cmd.mjs && esbuild src/commands/project.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/project-cmd.mjs && esbuild src/commands/audio.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/audio-cmd.mjs && esbuild src/commands/subtitle.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/subtitle-cmd.mjs && esbuild src/commands/ai-drama.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/ai-drama-cmd.mjs && esbuild src/commands/feedback.ts --bundle --platform=node --external:bun:sqlite --format=esm --outfile=.test-build/feedback-cmd.mjs && esbuild src/commands/music-visualizer.ts --bundle --platform=node --external:bun:sqlite --format=esm --external:commander --outfile=.test-build/music-visualizer-cmd.mjs && esbuild src/commands/long2short.ts --bundle --platform=node --external:bun:sqlite --format=esm --external:commander --outfile=.test-build/long2short-cmd.mjs && esbuild src/commands/oralcut.ts --bundle --platform=node --external:bun:sqlite --format=esm --external:commander --outfile=.test-build/oralcut-cmd.mjs && esbuild src/commands/oralcut-result.ts --bundle --platform=node --external:bun:sqlite --format=esm --external:commander --outfile=.test-build/oralcut-result-cmd.mjs && esbuild src/commands/skills.ts --bundle --platform=node --external:bun:sqlite --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/commands/media.ts --bundle --platform=node --format=esm --external:commander --external:bun:sqlite --outfile=.test-build/media-cmd.mjs && esbuild src/commands/client.ts --bundle --platform=node --format=esm --external:commander --external:bun:sqlite --outfile=.test-build/client-cmd.mjs && esbuild src/commands/doctor.ts --bundle --platform=node --external:bun:sqlite --format=esm --external:commander --outfile=.test-build/doctor-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 --external:bun:sqlite --format=esm --outdir=.test-build/convert --out-extension:.js=.mjs && esbuild src/lib/mad/selector.ts src/lib/mad/techniques.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 --external:bun:sqlite --format=esm --outdir=.test-build/mad --out-extension:.js=.mjs && esbuild src/commands/composite.ts --bundle --platform=node --format=esm --external:bun:sqlite --external:commander --outfile=.test-build/composite-cmd.mjs && esbuild src/commands/cover.ts --bundle --platform=node --format=esm --external:bun:sqlite --external:commander --outfile=.test-build/cover-cmd.mjs && esbuild src/commands/purify.ts --bundle --platform=node --format=esm --external:bun:sqlite --outfile=.test-build/purify-cmd.mjs && esbuild src/lib/static-delivery/index.ts src/lib/static-delivery/node.ts --bundle --platform=node --format=esm --outdir=.test-build/static-delivery --out-extension:.js=.mjs && node --import ./test/helpers/test-home.mjs --test \"test/*.test.mjs\" && node scripts/workspace-pollution-gate.mjs --verify",
61
+ "test:linux": "node scripts/test-linux.mjs",
62
+ "openspec:gate": "node openspec/gate.mjs",
63
+ "mg-registry:snapshot": "node scripts/mg-registry-snapshot.mjs",
64
+ "text-template:snapshot": "node scripts/text-template-snapshot.mjs",
65
+ "text-ir:parity": "node scripts/text-ir-parity.mjs",
66
+ "text-ir:sync": "node scripts/text-ir-sync.mjs"
67
+ },
68
+ "devDependencies": {
69
+ "@xmldom/xmldom": "^0.9.6",
70
+ "bun-types": "^1.1.0",
71
+ "commander": "^12.1.0",
72
+ "esbuild": "^0.28.1",
73
+ "typescript": "^5.6.0"
74
+ },
75
+ "dependencies": {
76
+ "hash-wasm": "^4.12.0",
77
+ "jszip": "^3.10.1"
78
+ }
79
+ }
@@ -1,11 +1,13 @@
1
1
  ---
2
2
  name: gtrk-ai-drama
3
- description: AI 情景动画分镜稿生成器——把成片 SOP 第③步(B-roll 底轨阶段)分到 AI_DRAMA 车道的 beat,逐个产**四段朴素描述(故事背景 / 角色 / 分镜 / 原文文稿)+ 独立视觉基调段 + 时长预算**,中英双版;Markdown 外壳默认严格兼容 gitruck-ai-drama-desk 解析器,可直接导入工作台,也可拿去任意外部 AI 漫剧管线(可灵 / 即梦 / Vidu / Veo / Runway / LTX / 本地开源,或 LibTV / OiiOii / TapNow 这类成片 agent 平台)上手用。创作与出片仍在 skill / 外部工作台;工作台导出的 return-v1 包用 `gtrk ai-drama lay` 确定性回填独立 AI 轨。当用户想「上 AI 情景动画 / 做 AI 分镜 / AI 动画描述 / 把这段做成 AI 视频 / 给这段配 AI 情景动画 / 弗洛伊德这段怎么做视频」时使用本 skill。通用拆镜 craft(蒙太奇段分层 / 四段描述结构 / 中英双语 / 时长预算)由本 skill 自持;栏目视觉 DNA(Style Lock)从栏目配置 style.skills 里 produces==AI_DRAMA 的条目解析注入,绝不硬编某栏目风格。凡把口播派单里 AI_DRAMA 段落转成可出片的描述稿,优先用本 skill,别手搓。
3
+ description: AI 情景动画分镜稿生成器——把派到 AI_DRAMA 车道的 beat 逐个写成四段描述(故事背景 / 角色 / 分镜 / 原文文稿)+ 视觉基调 + 时长预算,中英双版;默认兼容 gitruck-ai-drama-desk 解析器(落盘前 `gtrk ai-drama validate`),也可拿去任意外部管线出片,导出包用 `gtrk ai-drama lay` 回填独立 AI 轨。栏目视觉从 style.skills 里 produces==AI_DRAMA 的条目注入。当用户想「上 AI 情景动画 / 做 AI 分镜 / AI 动画描述 / 把这段做成 AI 视频 / 给这段配 AI 情景动画」时使用,别手搓。
4
+ metadata:
5
+ in_app_agent: true
4
6
  ---
5
7
 
6
- # AI 情景动画分镜稿生成器(gtrk-ai-drama)
7
-
8
- 用户要求间隔取关键镜头、剩余由实况补齐时,先读 [稀疏关键场景与角色参考](references/sparse-key-scenes.md)。其短 beat 窗口、时基、逐镜参考和留空规则优先于下文针对连续 AI 段落的时长预算;不转入通篇 AI 图纸。
8
+ # AI 情景动画分镜稿生成器(gtrk-ai-drama)
9
+
10
+ 用户要求间隔取关键镜头、剩余由实况补齐时,先读 [稀疏关键场景与角色参考](references/sparse-key-scenes.md)。其短 beat 窗口、时基、逐镜参考和留空规则优先于下文针对连续 AI 段落的时长预算;不转入通篇 AI 图纸。
9
11
 
10
12
  把口播派单里分到 **`AI_DRAMA` 车道**的 beat,逐个拆成分镜、为每个 beat 产 **四段朴素描述 + 独立视觉基调 + 时长预算**(中英双版),落到 `<project>/ai-drama/<beat_id>.md`,再交棒 AI Drama Desk 或任意外部平台出片;标准工作台导出包由 CLI 自动回填时间线。
11
13
 
@@ -24,7 +26,7 @@ return-v1 标准包由 `gtrk ai-drama lay` 确定性回填;其他平台没有
24
26
 
25
27
  **你与 `matrix` 同属第 ③ 步,MUST 在 MG 之前落位。** 理由:**AI 情景片段属于底轨 B-roll 画面家族,不是叠加层**——整条管线里唯一的叠加层是 MG(含 ov)。MG 的排版决策是「因势象形避主体」、**依赖底轨的最终画面构图**;若你的片段在 MG 之后才回铺,底轨构图就变了,先产的 MG 是对着「还没有 AI 画面的底轨」做的避让,你的片段落位后必然被避让错位、甚至被 MG 盖住画面主体。
26
28
 
27
- > ⚠️ **工序顺序**:AI 情景片段必须先落位;它属于底轨 B-roll,不是最后叠加的图层。之后再做全局构图检查与 MG。
29
+ > ⚠️ **工序顺序**:AI 情景片段必须先落位;它属于底轨 B-roll,不是最后叠加的图层。之后再做全局构图检查与 MG。
28
30
 
29
31
  **异步等待的口子(你造成的那个)**:你产完描述后,用户要去外部平台出片、抽卡可能数天。严格串行会把 ④⑤ 无限期卡住,故约定:进 ⑤ 的硬门是「**AI 片段已回铺 ∨ 用户明示先跳过**」。走「明示跳过」时,下游 `/gtrk-mg` MUST 把与你的 beat 相邻/重叠区间的 MG 颗粒标记为「AI 回铺后待复查构图」并在收口时复述——**你在交代进度时也要把这个代价说清**,让用户知道跳过意味着将来可能返工那几颗。
30
32
 
@@ -37,11 +39,11 @@ return-v1 标准包由 `gtrk ai-drama lay` 确定性回填;其他平台没有
37
39
  3. **中英双版地位平等,不是主辅。** ①视觉基调、②故事背景、③角色、④分镜四段每一段都给完整的中文版 + 英文版(不是把中文翻一句了事)。中文喂可灵 / 即梦 / Vidu / 通义,英文喂 Veo / Runway / LTX / Luma,用户按目标平台选。**唯独 ⑤ 原文文稿是中文口播原文、不翻译**(它是源真相 + 手动拼接的对位锚,翻译反而失真)。
38
40
  4. **内容可移植,Markdown 外壳不可自由改写。** 默认产物 MUST 通过 `gitruck-ai-drama-desk` 的 Markdown 解析契约:标题必须含 `(beat BXX)`;两大块必须叫 `## 一、中文稿…` / `## 二、English Storyboard…`;角色必须用 `#### 角色名(备注)` 标题;中文镜头必须用 `#### 分镜 01 · …`,英文镜头必须用 `#### Shot 01 · …`;元信息必须含 `区间总时长:track_st … → track_ed … ≈ … 秒`。`镜头`、粗体行、项目符号角色、`## 中文` / `## English`、`工程时间位` 都不是等价写法。**人读友好不能牺牲机读契约。**
39
41
 
40
- > **产物落点纪律(MUST · 全文见随包 `AGENT.md` 同名一节)**:
41
- > 交付物 MUST NOT 先写 agent 自有目录再拷进工程;中转本身即违规,体积不是豁免理由。
42
+ > **产物落点纪律(MUST · 全文见随包 `AGENT.md` 同名一节)**:
43
+ > 交付物 MUST NOT 先写 agent 自有目录再拷进工程;中转本身即违规,体积不是豁免理由。
42
44
  > 分镜稿只落**工程目录**(`<project>/ai-drama/<beat_id>.md`)或**用户显式指定处**;
43
45
  > **MUST NOT** 把用户媒体(毛片 / 成片 / 预览 / 外部平台出的片段)或任何大媒体文件复制到 agent 自有工作目录(如用户文档目录下 agent 产品自建的目录、agent 家目录缓存、会话工作区)——需要引用媒体时**用原路径引用**,不做副本;
44
- > 临时文件一律放系统 temp 且**用完即删**。交付物直接写入工程目录或用户显式指定的路径;引用媒体用原路径。
46
+ > 临时文件一律放系统 temp 且**用完即删**。交付物直接写入工程目录或用户显式指定的路径;引用媒体用原路径。
45
47
 
46
48
  ## 业务分离:栏目 Style Lock 从哪来(关键)
47
49
 
@@ -114,7 +116,9 @@ return-v1 标准包由 `gtrk ai-drama lay` 确定性回填;其他平台没有
114
116
 
115
117
  **Step 4 · 写四段描述(中英分块)**:先出**中文稿**(② 故事背景末句锁调 → ③ 角色结构化 + 禁变项 + 质感落点,复现理论家 pin 复用同段文字 → ④ 分镜每镜前缀复述基调 + 建议秒数 + 对应原文句 + 蒙太奇级意图 → ⑤ 原文文稿中文逐句不翻译),再整块出 **English Storyboard**(① Style Lock + ②③④ 英文原生化,不含 ⑤)。中英**分两大块、不逐段交错**(craft C)。
116
118
 
117
- **Step 5 · 校验后落盘**:先把每个 beat 的候选稿写到系统 temp,运行随 skill 分发的 `scripts/validate-storyboard.mjs <候选稿.md>`;退出码为 0 才写到 `<project>/ai-drama/<beat_id>.md`。失败就按输出逐项修正,MUST NOT 把未通过稿件落进工程。校验器不可用时,至少逐项执行下面「解析器硬契约」与交付前自检。用户直投单段时同样先校验,再落到用户指定的工程路径。临时稿无论成功失败都删掉。
119
+ **Step 5 · 校验后落盘**:先把每个 beat 的候选稿写到系统 temp,运行 `gtrk ai-drama validate <候选稿.md>`;退出码为 0 才写到 `<project>/ai-drama/<beat_id>.md`。失败就按输出逐项修正,MUST NOT 把未通过稿件落进工程。校验器不可用时(CLI 版本过旧),至少逐项执行下面「解析器硬契约」与交付前自检。用户直投单段时同样先校验,再落到用户指定的工程路径。临时稿无论成功失败都删掉。
120
+
121
+ > **在即剪内置 AI 里**:写不了系统 temp、也删不了文件——候选稿直接写 `<project>/ai-drama/<beat_id>.md`,紧接着 `gtrk ai-drama validate ai-drama/<beat_id>.md`;不通过就原地逐项改到通过为止,通过之前 MUST NOT 交给工作台、MUST NOT 往下走。交付时在回复里用 `[B03 分镜稿](ai-drama/B03.md)` 这种写法给出文件。
118
122
 
119
123
  ## 输出契约(落盘 Markdown 结构 · 中英分块)
120
124
 
@@ -133,13 +137,13 @@ return-v1 标准包由 `gtrk ai-drama lay` 确定性回填;其他平台没有
133
137
  - 蒙太奇分段只写进镜头头的 `|段:…` / `|segment: …` 字段;④ 内不要另插 `#### 蒙太奇段…` / `#### Montage…` 标题,解析器会把它吞进前一镜描述。
134
138
  - 中英文镜头序号一一对应;至少一镜;每镜建议秒数写在头部字段,不要藏在正文项目符号里。
135
139
 
136
- 校验命令(从本 `SKILL.md` 所在目录解析相对路径):
140
+ 校验命令:
137
141
 
138
142
  ```bash
139
- bun scripts/validate-storyboard.mjs <候选稿.md>
143
+ gtrk ai-drama validate <候选稿.md>
140
144
  ```
141
145
 
142
- 通过时输出单行 JSON 并退出 0;不通过时逐条列出违约项并退出非零。它校验的是生产端硬契约;工作台仍是最终权威,仓库可用时可再用其 `server/lib/parse.ts` 做回归。
146
+ 通过时输出单行 JSON 并退出 0;不通过时逐条列出违约项并退出 1(可一次传多份稿,每份一行)。判据与随 skill 分发的 `scripts/validate-storyboard.mjs` 相同;那份脚本只为旧版 CLI 兼容保留一个版本周期,新稿一律用子命令。它校验的是生产端硬契约;工作台仍是最终权威,仓库可用时可再用其 `server/lib/parse.ts` 做回归。
143
147
 
144
148
  ```
145
149
  # AI 情景动画分镜稿 · [自动标题](beat <beat_id>)
@@ -224,7 +228,7 @@ face / hair / eyes / wardrobe / signature prop + do-not-change + one line on how
224
228
 
225
229
  ## 交付前自检
226
230
 
227
- - [ ] `scripts/validate-storyboard.mjs` 已对**每个**候选稿返回 `ok:true`,或在校验器不可用时完成了「解析器硬契约」逐项核对?
231
+ - [ ] `gtrk ai-drama validate` 已对**每个**候选稿返回 `ok:true`,或在校验器不可用时完成了「解析器硬契约」逐项核对?
228
232
  - [ ] 标题、两大块、③角色标题、④分镜标题与区间元信息使用契约原词,没有用“更好看”的同义排版替换?
229
233
  - [ ] 五区块齐备(元信息 + ①视觉基调 + ②故事背景 + ③角色 + ④分镜 + ⑤原文文稿)?
230
234
  - [ ] 每镜有**明确主语 + 明确动作**?(没有就退回)
@@ -250,7 +254,7 @@ face / hair / eyes / wardrobe / signature prop + do-not-change + one line on how
250
254
 
251
255
  命令自己解析 id → 导出包目录,走两条**确定性**路径:① 工作台服务可达就问它;② 服务没起就读 `~/.gitruck/ai-drama-desk.json` 的落脚点。两条都不通会报错并给出路。
252
256
 
253
- > ⚠️ **拿到 id 之后 MUST NOT 去磁盘上找导出包**(`find` / `ls -R` / 通配一律禁止)。解析不出来就如实报,请用户启动工作台或直接给路径。
257
+ > ⚠️ **拿到 id 之后 MUST NOT 去磁盘上找导出包**(`find`、递归列目录、通配一律禁止)。解析不出来就如实报,请用户启动工作台或直接给路径。
254
258
  > 零命中时命令会列出「已查过哪些数据根」:源码部署与打包部署的数据根不同,项目找不到多半是**它在另一个部署里**,不是丢了。
255
259
 
256
260
  已经手上就有目录路径(或用的是非标准平台)时,仍可用 `--package "<exports/aidrama>"`,两者可混用、按路径去重。
@@ -258,7 +262,7 @@ face / hair / eyes / wardrobe / signature prop + do-not-change + one line on how
258
262
  命令会先按当刻口播工程重投影 beat 窗口,再把所有镜头复制到 `<gtrk目录>/assets/ai-drama/<slug>/`,共用一条新的 `video_track`;每个 beat 从起点顺排,最后一镜吸收到 beat 终点。既有 A-roll、BGM 与 B-roll 轨零改动。若已铺 AI 轨被用户手调过,缺省拒绝覆盖;只有用户明确同意丢弃手调时才加 `--replace-all`。
259
263
  3. **非标准平台才手动回铺**:外部平台没有 return-v1 清单时,才由用户把片段拖回 opencut 的 **AI_DRAMA 车道**,对齐该 beat 的 `track_st→track_ed`。AI 出片仍是外部异步、用户驱动;未拿到完整片段前要停下等用户,别替他假装出片 / 回轨完成。
260
264
  4. **回铺齐 ≠ 收口,还有两步**:你的片段回铺齐只意味着 **③ B-roll 底轨阶段**完成。接着 MUST 走 **④ 全局抽帧检查画面构图**(对三源合并后的最终底轨抽帧,看主体位置 / 安全区 / 画面朝向 / 明暗,**停下等用户确认**)→ 过了才交棒 **⑤ `/gtrk-mg`** 把 MG(含 ov)叠上 → 最后才 `gtrk render` 收口。
261
- ⚠️ **MUST NOT 从你这里直接跳到 `render`**;先完成全局构图检查与 MG,再进入字幕和渲染。
265
+ ⚠️ **MUST NOT 从你这里直接跳到 `render`**;先完成全局构图检查与 MG,再进入字幕和渲染。
262
266
 
263
267
  > 原则:**agent 替用户跑 CLI / 接力 skill,用户只对话**。但 AI_DRAMA 车道天然有「用户去外部平台出片 + 手动拼回」的手工环节——那部分是外部的手,无法替跑;除此之外的解析、生成、落盘、交代,全由你(脑)一次做完,别让用户自己去拼描述。
264
268
 
@@ -1,4 +1,8 @@
1
1
  #!/usr/bin/env node
2
+ /**
3
+ * ⚠️ 兼容保留一个版本周期:请改用 `gtrk ai-drama validate <分镜稿.md>`(link-in-app-agent-capability-shelf D2)。
4
+ * 判据已收进 CLI(`src/lib/storyboard-validate.ts`),两份由 `test/ai-drama-validate.test.mjs` 逐字节对拍——改判据两边同改。
5
+ */
2
6
 
3
7
  import { readFile } from "node:fs/promises";
4
8
  import { basename } from "node:path";