fix(skill): w2h audit — resolve contradictions, path issues, missing fallbacks

10 fixes from an audit of skills/website-to-hyperframes/ targeting clarity for
AI agents following the pipeline. Each fix is a surgical edit; no behavior
changes for human readers.

**Critical contradictions resolved:**
- capabilities.md: `onUpdate`/`tl.call` was simultaneously documented as required
  (canvas/WebGL/typing patterns) and banned (determinism). Sub-agents reading
  the ban would silently strip working code from Canvas 2D and Three.js beats.
- step-1-design.md: Removed "Depth & Elevation" section template that the same
  file's Rules section forbade. Renumbered remaining sections (6→5).
- beat-builder-guide.md: Narrowed "no onUpdate for counters" rule so canvas
  rendering loops aren't caught by the prohibition.

**Path resolution fixes for sub-agents:**
Sub-agents run from `<project-dir>` (e.g. videos/foo/), not repo root, so
repo-relative paths like `skills/website-to-hyperframes/assets/sfx/manifest.json`
fail silently. Replaced with `find / -path ...` patterns that work from any CWD.
- step-3-storyboard.md: sfx/manifest.json + text-effects.md paths
- step-5-build.md: beat-builder-guide.md path

**Missing fallbacks added:**
- step-3-storyboard.md Gate: autonomous mode now propagates from Step 2 — gate
  no longer blocks on explicit approval when user said "surprise me".
- step-4-vo.md: timing-formula recalibration now has concrete steps for both
  "too short" (add pauses) and "too long" (cut highest-density beat).
- step-6-validate.md: agent-authored descriptions fallback when GEMINI_API_KEY
  is unavailable — DoD checklist no longer has a dead end.

**Quick Reference polish:**
- SKILL.md: step-1-design entry now mentions 50-line fast-path exception.

8 files changed, +32/-37 (net -5 lines). Format checks pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
ukimsanov
2026-05-21 17:57:08 -07:00
co-authored by Claude Opus 4.7
parent 74b86f6cfa
commit e47bc6c6db
8 changed files with 32 additions and 37 deletions
+1 -1
View File
@@ -120,7 +120,7 @@ Beat count is not in this table intentionally — it should come from the storyb
| File | When to read |
| ---------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| [step-0-capture.md](references/step-0-capture.md) | Step 0 — capture, understand the brand and product, write strategy-first site summary |
| [step-1-design.md](references/step-1-design.md) | Step 1 — write DESIGN.md brand cheat sheet (6 sections, 250-350 lines) |
| [step-1-design.md](references/step-1-design.md) | Step 1 — write DESIGN.md brand cheat sheet (5 sections, 250-350 lines; 50-line fast-path for billboard-style social ads) |
| [step-2-brief.md](references/step-2-brief.md) | Step 2 — align on message, narrative arc, audience with user |
| [capabilities.md](references/capabilities.md) | Steps 2 & 5 — full inventory of what HyperFrames can do (24 sections). Scan the TOC during the brief, deep-dive specific sections during build |
| [step-3-storyboard.md](references/step-3-storyboard.md) | Step 3 — storyboard + script (combined) with user review gate |
@@ -175,7 +175,7 @@ If any are missing from the beat spec, the beat is under-defined. Don't fill the
- CSS CENTERING: no `transform: translate(-50%, -50%)` with GSAP transforms. Use flexbox or `xPercent/yPercent`.
- QUERYSELECTOR: `document.getElementById("id")` with null guards. No method calls without null check.
- CHARACTER SPANS: `display:inline-block` on spaces collapses them. Use `&nbsp;` or per-word spans.
- COUNTERS: no `onUpdate` callbacks. Discrete `tl.set(el, {textContent: "42"}, 2.5)` at timestamps.
- COUNTERS: no `onUpdate` for numeric counters — use discrete `tl.set(el, {textContent: "42"}, 2.5)` at timestamps. `onUpdate` and `tl.call()` ARE supported for canvas/WebGL rendering loops and character-by-character typing — see capabilities.md §10.
- TIMELINE: `window.__timelines["beat-N-name"] = tl` synchronously. Key = `data-composition-id`.
- DETERMINISTIC: no `Math.random()`, `Date.now()`, `requestAnimationFrame`, `repeat:-1`.
- Always `tl.fromTo()` not `tl.from()` for entrances.
@@ -576,7 +576,7 @@ Full editor in packages/studio/:
- No `setTimeout` / `setInterval` in timeline construction
- No `requestAnimationFrame` (timeline-driven; engine seeks per frame)
- No `repeat: -1` (calculate exact repeats: `Math.ceil(duration / cycleDuration) - 1`)
- No `tl.call(fn)` / `tl.add(function)` / `onComplete`/`onStart`/`onUpdate`/`onRepeat` callbacks (engine doesn't fire them)
- No `onComplete`/`onStart`/`onRepeat` callbacks (engine doesn't fire them). **Exception:** `onUpdate` and `tl.call()` ARE supported — they're required for canvas/WebGL rendering, character-by-character typing, and counter patterns. See §10 (Canvas 2D procedural art) for the documented pattern.
- No `gsap.set` on clips from later scenes (use `tl.set(selector, vars, position)`)
- Synchronous timeline construction (no async)
- Master clock can clamp at composition end
@@ -33,7 +33,7 @@ Sub-agents try to use the fonts you list. The manifest tells you exactly what's
---
## The 6 sections to write
## The 5 sections to write
### `## 1. Visual Theme (one paragraph)`
@@ -256,32 +256,7 @@ Generous whitespace as confidence. Section gaps are always `60100px`. Content
---
### `## 5. Depth & Elevation`
Document the brand's shadow philosophy and the actual shadow values used.
#### Shadow table
```markdown
| Level | Value | Used for |
| ------------ | -------------------------------- | ----------------------------------------------- |
| Flat (0) | none | Default — most surfaces, inputs, body text |
| Raised (1) | `0 2px 8px rgba(0, 0, 0, 0.1)` | Cards on white, hovered surfaces, floating CTAs |
| Elevated (2) | `0 4px 12px rgba(0, 0, 0, 0.15)` | Dropdown menus, popovers |
| Floating (3) | `0 8px 24px rgba(0, 0, 0, 0.2)` | Modals, important overlays |
```
#### Shadow philosophy (one paragraph)
How does this brand use shadows? Sparingly with soft falloff, or dramatically with hard edges? Are they present by default or only on hover? On dark backgrounds, do shadows invert to glow effects?
```markdown
Shadows are minimal — used only to signal interactivity (hover) or layering (modals). All shadows are soft-edged (blur ≥ 8px). On dark backgrounds, shadows convert to subtle glow (`0 0 24px rgba(255, 99, 99, 0.15)` using the brand's accent color). Hard shadows do not exist in this system.
```
---
### `## 6. Iteration Guide` (the load-bearing section)
### `## 5. Iteration Guide` (the load-bearing section)
510 numbered rules that encode the most important brand decisions. Each rule is a **single actionable sentence stating what to do, with the specific values from this site.** These are the "if in doubt, do this" rules sub-agents consult while composing beats.
@@ -151,7 +151,13 @@ When planning beats, decide which ones deserve an HTML-in-Canvas treatment vs. a
### SFX assignment — happens here, not in Step 5
**Before writing beats,** read `skills/website-to-hyperframes/assets/sfx/manifest.json` (or your local copy at `sfx/manifest.json` if already copied to the project). Each entry has a filename, duration in seconds, and description. Assign **specific SFX files** to exact moments in the storyboard. Step 5 implements what you specify here — it makes no SFX decisions.
**Before writing beats,** read the SFX manifest. Locate it from your current directory:
```bash
find / -path '*/website-to-hyperframes/assets/sfx/manifest.json' -maxdepth 12 2>/dev/null | head -1
```
Or if you already copied SFX into the project (Step 5 does this), read your local `sfx/manifest.json`. Each entry has a filename, duration in seconds, and description. Assign **specific SFX files** to exact moments in the storyboard. Step 5 implements what you specify here — it makes no SFX decisions.
Per beat, specify SFX like:
@@ -318,7 +324,7 @@ Write this section for THIS project's actual brand and the assets audited above
### Text Animations
Every text element in this beat must name a specific effect from the catalog at `skills/hyperframes/references/text-effects.md`. The catalog lists 24 effect IDs (from the separate `pixel-point/animate-text` skill); pick what fits the brand and this beat's mood — don't default to the same effect every beat.
Every text element in this beat must name a specific effect from the catalog. The reference page is at [`../../hyperframes/references/text-effects.md`](../../hyperframes/references/text-effects.md) (or locate it with `find / -path '*/hyperframes/references/text-effects.md' -maxdepth 12 2>/dev/null | head -1`). It lists 24 effect IDs (from the separate `pixel-point/animate-text` skill); pick what fits the brand and this beat's mood — don't default to the same effect every beat.
Format (FORMAT EXAMPLES of structure, not prescriptions — pick based on brand/mood/context):
@@ -524,3 +530,5 @@ Summarize the plan clearly. Don't dump the full STORYBOARD.md — give the user
### Gate
Both STORYBOARD.md and SCRIPT.md exist AND the user has explicitly approved the plan.
**Autonomous mode exception:** if the user signaled autonomous mode in Step 2 ("surprise me" / "decide for me" / "just build it"), skip the approval wait. Present the storyboard summary inline as a heads-up and proceed straight to Step 4.
@@ -32,7 +32,13 @@ npx hyperframes tts "First sentence. Second sentence." --voice af_nova --output
# Measure: seconds ÷ words × total script words = estimated full audio length
```
If the estimate puts your video at ±15% of the planned duration, proceed. If it's more than 15% off, recalibrate the script length first.
If the estimate puts your video at ±15% of the planned duration, proceed. If it's more than 15% off, recalibrate the script length first:
- **Audio TOO SHORT** (more than 15% under planned duration) → add strategic pauses. In `narration.txt`, insert blank lines between paragraphs (≈0.6s each) or `...` between sentences (≈0.4s each). Aim for the pauses to land at storyboard beat boundaries so the silence feels intentional, not dead air.
- **Audio TOO LONG** (more than 15% over planned duration) → identify the beat in your storyboard with the highest words-per-second density. Cut one supporting sentence from THAT beat's lines — preserve the lead sentence (the one that names the beat's idea). Re-measure with another test clip before committing to full generation.
- **Audio matches plan but beat boundaries drift** → adjust the storyboard durations to match the actual narration, not the other way around. The audio is the ground truth once narration is generated.
The script formula assumes constant words-per-second, but punctuation, dramatic pauses, and silence cues all stretch real audio. Always trust a measured test clip over the formula.
## Background music
@@ -298,9 +298,13 @@ Each sub-agent reads [beat-builder-guide.md](beat-builder-guide.md) — it has e
```
Build the composition for Beat N. Save to compositions/beat-N-name.html.
FIRST: Read skills/website-to-hyperframes/references/beat-builder-guide.md end to end.
It has your full workflow, all rules, easing vocabulary, and file references.
Follow its workflow exactly:
FIRST: Locate and read the beat-builder guide. Your CWD is the project directory, so
the skill lives outside it — run this to find it:
find / -path '*/website-to-hyperframes/references/beat-builder-guide.md' -maxdepth 12 2>/dev/null | head -1
Read that file end to end. It has your full workflow, all rules, easing vocabulary,
and file references. Follow its workflow exactly:
build → lint (`npx hyperframes lint .`)
→ snapshot (`npx hyperframes snapshot . --frames 3`)
→ view contact sheet AND read snapshots/descriptions.md
@@ -86,7 +86,9 @@ npx hyperframes snapshot <project-dir> --frames <N> \
Output lands in `<project-dir>/snapshots/`. Gemini writes `snapshots/descriptions.md` automatically.
**If `descriptions.md` is missing or empty after the snapshot:** `GEMINI_API_KEY` was not set — confirm it's in `<project-dir>/.env` (the CLI loads .env from CWD) or in your shell environment. Re-run after fixing. Do not proceed without Gemini descriptions — visual inspection alone is not sufficient verification.
**If `descriptions.md` is missing or empty after the snapshot:** `GEMINI_API_KEY` was not set — confirm it's in `<project-dir>/.env` (the CLI loads .env from CWD) or in your shell environment. Re-run after fixing.
**Fallback if Gemini is genuinely unavailable** (no key, key invalid, or quota exhausted): use your own image-reading capability to inspect each frame in `snapshots/` directly. For each frame, write one sentence describing what's on screen — focus on the dimensions Gemini would catch (blank/dark frames, missing brand assets, text legibility, layout problems). Save these descriptions as `snapshots/descriptions.md` yourself so the rest of the checklist still has a single source of truth. State explicitly in your verdict that descriptions were agent-authored, not Gemini-authored, so the user knows to spot-check.
**Gemini descriptions will flag two frames as "blank/black" — these two are expected and not bugs:**