fix(skill): hard landmine — search asset-descriptions.md before composing a logo

Verified root cause of the heygen + huly logo miss across the last two
real-AI-test runs:

  - SVG capture filenames are content-hash slugs (svg-<8char>.svg), so
    the brand name is NOT in the filename. The real heygen lockup is at
    svg-54ea56cd.svg; the real huly wordmark is at svg-ec034b11.svg.
  - In BOTH project captures, 0 / 32 (heygen) and 0 / 19 (huly) SVGs got
    the DOM-derived `isLogo: true` flag, so the `logo-<hash>.svg` prefix
    path from commit 5f290345 never fired. (Separate fix incoming for
    the detector itself.)
  - asset-descriptions.md CORRECTLY identifies both logos via Gemini
    Vision ("wordmark reading 'HeyGen' next to a four-lobed diamond" /
    "white wordmark... featuring a stylized 'H' icon to the left of the
    lowercase letters 'huly'") — agents just didn't search it before
    composing a fake.

The first run agent self-critique on both projects: "I had the workers
compose the [brand] mark from scratch... instead of dropping in the
actual captured logo... that was the wrong tradeoff for brand fidelity."

Doc changes (no code in this commit — code fixes for isLogo detection
+ no-Gemini fallback come in separate commits):

1. beat-builder-guide.md — new section "Logo discovery — search
   asset-descriptions.md BEFORE composing one" as a hard rule. Walks the
   agent through the 3-step procedure (grep brand name → open SVG to
   verify → reference from beat). Calls out the brand-fidelity violation
   explicitly: composing a logo when a captured one exists ships as
   off-brand. Notes the valid path of RECOLORING captured monochrome SVGs
   (which the heygen agent's later swap-in pass did correctly with the
   aurora gradient).

2. beat-builder-guide.md — new section "Captured videos — they're in
   the manifest, not on disk" documenting that capture/extracted/video-
   manifest.json carries every <video>'s URL + preview PNG, but the
   actual mp4s are not downloaded (intentional — sites with dozens of
   feature videos would blow up capture size). Includes the on-demand
   curl pattern for fetching just the one video the beat needs (e.g.
   heygen.com's "Orb" hero video = video-0 in the manifest, 768x768,
   "Turn your ideas into videos in minutes"). Don't bulk-download.

3. step-5-build.md — orchestrator's dispatch packet template updated:
   the placeholder `capture/assets/logo.svg — brand wordmark, white on
   transparent` was misleading because filenames are hashed, not
   `logo.svg`. Replaced with the realistic example
   `capture/assets/svg-54ea56cd.svg — wordmark "HeyGen" + four-lobed
   diamond icon (the real header logo)`, plus an explicit instruction:
   if the beat needs a logo and no captured SVG is resolved in the
   packet, the worker WILL compose a fake one. Resolve it explicitly
   in the dispatch, not as a "see asset-descriptions.md" pointer.

Net: zero code change. The capture pipeline already produces everything
agents need (descriptions in asset-descriptions.md, hash-named SVGs on
disk, video manifest with URLs). The miss was a doc-level discoverability
gap — agents didn't know to search the descriptions file or that videos
exist in a manifest. These landmines close that gap.

Followup commits (separate):
- Broaden isLogo DOM detection so `logo-<hash>.svg` prefix actually fires
  on real header/nav logos.
- Strengthen the no-Gemini fallback so asset-descriptions.md is still
  useful for teams without a Gemini API key.
This commit is contained in:
ukimsanov
2026-06-12 01:02:44 -07:00
parent cd5f6bcc7e
commit e6aa7feda9
2 changed files with 45 additions and 4 deletions
@@ -56,11 +56,41 @@ Four hidden pitfalls account for most rework in a single beat run — scan them
**Always open the captured assets folder before designing the beat:** **Always open the captured assets folder before designing the beat:**
- `capture/assets/svgs/` — brand logos, icons, decorative marks. SVGs are infinitely scalable and stroke-animatable (path drawing, dash offset). A logo SVG drawing itself onto frame can carry an entire beat. - `capture/assets/svgs/` — brand logos, icons, decorative marks. SVGs are infinitely scalable and stroke-animatable (path drawing, dash offset). A logo SVG drawing itself onto frame can carry an entire beat.
- `capture/assets/` — hero illustrations, screenshots, product art, gradients, photography. These are first-class beat subjects, not background decoration. A breathing hero illustration with a single line of kinetic type is a complete shot. - `capture/assets/` — hero illustrations, screenshots, product art, gradients, photography, AND the SVGs that came from inline DOM extraction (header logo, wordmarks). These are first-class beat subjects, not background decoration. A breathing hero illustration with a single line of kinetic type is a complete shot.
- `capture/assets/videos/previews/` — every `<video>` on the source site got a preview PNG and a manifest entry. See the "Captured videos" rule below for how to fetch the actual mp4 when you need it.
- VIEW every image before placing text on it. Check safe zones, contrast, actual content, where the focal point sits. - VIEW every image before placing text on it. Check safe zones, contrast, actual content, where the focal point sits.
**If your beat spec names a captured asset, USE it.** Don't substitute a CSS recreation. The user captured these from the real brand site precisely so the video carries the brand's actual visual identity. **If your beat spec names a captured asset, USE it.** Don't substitute a CSS recreation. The user captured these from the real brand site precisely so the video carries the brand's actual visual identity.
### Logo discovery — search `asset-descriptions.md` BEFORE composing one
**This is a hard rule.** SVG filenames are content-hash slugs (`svg-54ea56cd.svg`, `svg-ec034b11.svg`) — the brand name is NOT in the filename. The real logo IS in the capture, just hash-named. So:
1. **First** open `capture/extracted/asset-descriptions.md` and `Grep`/`search` for the brand name (e.g. `HeyGen`, `huly`, `Stripe`). The descriptions identify wordmarks and logos by what they actually show — e.g. `svg-54ea56cd.svg — wordmark reading "HeyGen" next to a four-lobed diamond-shaped icon`. That's how you find which `svg-<hash>.svg` is the real logo.
2. **Second** open the matching SVG to verify and to see its colors / glyph paths.
3. **Then** reference it from the beat as `<img src="capture/assets/svg-XXXXXXXX.svg" ... />`.
**Composing a logo (CSS shapes, fake wordmark) when a captured one exists is a brand-fidelity violation** — it ships in the final video and reads as off-brand. It IS valid to RECOLOR or extract specific paths from a captured monochrome SVG to match the site's accent palette (the agent that ran heygen.com correctly extracted the diamond facets and recolored them with the aurora gradient). The line is: **start from the captured geometry**, never from scratch.
If `asset-descriptions.md` has no Gemini Vision descriptions (the heading says "no Gemini key set" or descriptions are just filename slugs), fall back to opening each candidate SVG in a previewer or via `sharp` to render it. Cost: a few extra reads. Worth it for brand fidelity.
### Captured videos — they're in the manifest, not on disk
The capture pipeline writes `capture/extracted/video-manifest.json` listing every `<video>` element on the source page (URL, dimensions, heading, caption, preview PNG). It does **not** download the actual mp4s — that would balloon the capture size on sites with many videos.
When a beat genuinely needs the hero video (e.g. heygen.com's "Orb" — a 3D-rendered animation that's hard to approximate in CSS), fetch just that one:
```bash
# Find the entry in capture/extracted/video-manifest.json — note its `url`.
# Then download it to assets/videos/:
mkdir -p assets/videos
curl -sL "<url-from-manifest>" -o assets/videos/<filename-from-manifest>
```
Embed as a `<video>` element with `data-start` / `data-duration` like any other clip. See the `/hyperframes` skill's video-composition reference for the contract.
Don't bulk-download every video in the manifest — most aren't relevant to your beat. Pick the one the beat actually needs.
## Step 2: Build the composition ## Step 2: Build the composition
Save to the path the main agent specified (usually `compositions/beat-N-<slug>.html`). Copy-paste this starter and fill in the named placeholders. Every attribute, ID, and timeline key shown is load-bearing — the assembler (final action of Step 5) hard-fails if `data-duration` drifts from your dispatch packet's `estimatedDuration_s` by more than 0.01s. Save to the path the main agent specified (usually `compositions/beat-N-<slug>.html`). Copy-paste this starter and fill in the named placeholders. Every attribute, ID, and timeline key shown is load-bearing — the assembler (final action of Step 5) hard-fails if `data-duration` drifts from your dispatch packet's `estimatedDuration_s` by more than 0.01s.
@@ -280,12 +280,23 @@ Key component styles:
[paste relevant lines from DESIGN.md] [paste relevant lines from DESIGN.md]
═══ CAPTURED ASSETS FOR THIS BEAT ═══ ═══ CAPTURED ASSETS FOR THIS BEAT ═══
[Paste ACTUAL file paths + descriptions from asset-descriptions.md: [Paste ACTUAL file paths + descriptions from asset-descriptions.md.
SVG filenames are content-hash slugs (`svg-<8char>.svg`), NOT human-
readable. The brand name lives in the DESCRIPTION, not the filename.
Before pasting, search asset-descriptions.md for the brand name (e.g.
`HeyGen`, `huly`, `Stripe`) to find which `svg-<hash>.svg` is the real
logo:
- capture/assets/hero-dashboard.png — full-bleed product dashboard, dark theme - capture/assets/hero-dashboard.png — full-bleed product dashboard, dark theme
- capture/assets/logo.svg — brand wordmark, white on transparent - capture/assets/svg-54ea56cd.svg — wordmark "HeyGen" + four-lobed diamond icon (the real header logo)
Do NOT say "see asset-descriptions.md". Paste the paths here.] If the beat needs a logo and you DIDN'T resolve a captured SVG here, the
worker will compose a fake one — which ships as off-brand in the final
video. Resolve the captured logo path explicitly in the dispatch packet,
not as a "see asset-descriptions.md" pointer.
Do NOT say "see asset-descriptions.md". Paste the resolved paths here.]
``` ```
The storyboard beat already contains everything — the concept, the visual choreography with exact timings, the CSS values, the SFX cues. The sub-agent's job is to translate that description into working HTML/CSS/GSAP, not to re-invent the creative direction. If you want, you can also paste any other relative and useful context to subagents if think it's good, why not. The storyboard beat already contains everything — the concept, the visual choreography with exact timings, the CSS values, the SFX cues. The sub-agent's job is to translate that description into working HTML/CSS/GSAP, not to re-invent the creative direction. If you want, you can also paste any other relative and useful context to subagents if think it's good, why not.