Merge pull request #1672 from heygen-com/fix/skill-authoring-fixes

fix(skills): harden music-to-video Step 3 gate, align product-launch-video with pr-to-video
This commit is contained in:
WaterrrForever
2026-06-24 01:28:54 +08:00
committed by GitHub
parent 7133c396eb
commit 2681085624
5 changed files with 26 additions and 13 deletions
+3 -3
View File
@@ -63,7 +63,7 @@ python3 <SKILL_DIR>/scripts/analyze-beatgrid.py "$PROJECT_DIR/assets/bgm.mp3" \
---
## Step 2: Frame skeleton
## Step 2: Frame skeleton (structure only)
Goal: Read the music and lay out the frames — the skeleton of `STORYBOARD.md`.
@@ -73,7 +73,7 @@ Read [`references/frame-skeleton.md`](references/frame-skeleton.md). Turn `audio
---
## Step 3: Plan (user-gated)
## Step 3: Fill the plan (user-gated)
Goal: Turn the skeleton into an approved, complete `STORYBOARD.md`.
@@ -93,7 +93,7 @@ Fix every `✗` (hard errors: duration mismatch, frames not tiling the track, a
---
## Step 4: Build frames
## Step 4: Build frames from the plan
Goal: Build every frame as a self-contained composition file.
@@ -4,7 +4,10 @@
// not exist yet), so it checks fields, not on-disk html.
//
// HARD (exit 1): frontmatter duration_s == audiomap duration; >=1 frame; each frame
// has src + positive duration; frames tile the track gap-free (sum == duration_s).
// has src + positive duration; frames tile the track gap-free (sum == duration_s);
// every frame has >=1 filled group (a frame whose `### Groups` is still
// `TBD (Step 3)`/empty is a Step-2 skeleton, not an approved plan — fail it so a
// skipped Step 3 can never reach the build step).
// WARN (exit 0): best-effort group checks — each group exactly one of
// template/free_design/asset; a template id exists under the --templates dir;
// phrase_flow frame has no beat_cut asset treatment.
@@ -114,12 +117,18 @@ for (const ln of raw.split(/\r?\n/)) {
if (cur) cur.lines.push(ln);
}
// HARD: every frame needs >=1 filled group. A frame with no parseable group head
// is still a Step-2 skeleton (`### Groups` = `TBD (Step 3)`/empty) — erroring here
// is what stops a skipped Step 3 from reaching the build step.
const framesWithGroups = new Set(blocks.map((b) => b.frameLabel));
for (const f of frames) {
const title = String(f.title ?? "").trim();
const lbl = `Frame ${f.number ?? ""}${f.title ?? f.index}`.replace(/\s+—\s+$/, "");
if (![...framesWithGroups].some((s) => s.includes(String(f.title ?? "")))) {
warns.push(
`${lbl}: no parseable groups (expected \`- **gN** — template|free_design|asset …\`)`,
const hasGroup = title !== "" && [...framesWithGroups].some((s) => s.includes(title));
if (!hasGroup) {
errors.push(
`${lbl}: no filled groups — still a Step-2 skeleton (\`### Groups\` is TBD/empty). ` +
`Run Step 3: fill its groups (\`- **gN** — template|free_design|asset …\`) before building.`,
);
}
}
@@ -34,6 +34,7 @@ If your dispatch carries lint / validate feedback from a prior pass, address eac
## What comes fixed — realize it as given
- **No plan = stop.** If your `### Groups` is `TBD`/empty (Step 3 was skipped), report back and write nothing — never invent groups, templates, or copy.
- **The plan** is set in your `## Frame` block: the groups, templates / primitives, copy, brand,
and anchors. Build it as written. If a plan is genuinely wrong (wrong template or copy), stop
and report — the orchestrator re-plans at Step 3.