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:**
- `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.
**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
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]
═══ 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/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.