Files
hyperframes/skills/website-to-hyperframes/scripts
ukimsanovandClaude Opus 4.7 f4a7961bc1 fix(skill): w2h-verify v2 — kill false positives from real-agent debrief
A fresh agent session ran the v1 verify script and the disclosure pasted
into their final summary showed 3 FAIL rows for things that weren't
actually defects:

  Headline font-size: flagged Beat 2 (wordmark SVG), Beat 3 (UI grid),
    Beat 5 (terminal). None of these legitimately have text headlines.
  Timeline coverage: flagged 5/6 beats because the script's regex only
    saw `tl.X(..., 2.5)` literal positions and missed forEach loops,
    variable-position tweens, and long-duration scaler tweens.
  Beat durations: flagged 2 beats because my "duration X.Xs near beat
    label" fallback false-matched non-beat durations
    (e.g., "shader runs — duration 0.7s" near a "Beat 1" mention).

The agent had to write ~5 paragraphs defensively justifying each false
FAIL. That's friction we can fix.

Tested against the agent's actual project (huly-launch-v4): went from
4 FAIL (3 false positives + 1 real bare-table parser miss) to 0 FAIL.
Also re-verified huly-v3 still correctly catches its 3 real issues
(48px wordmark, missing shaders, 3 SFX drifts) — no regression.

**Brand visuals check**

Switched from "≥30% asset usage" (gameable, rewards quantity over quality)
to "at least 1 beat references a captured hero/image/svg" — quality
signal that's cheap to satisfy when real, hard to fake. Excludes fonts,
logos, favicons, contact-sheets.

**Headline check**

Now only flags beats where the LARGEST font-size is in the 40–<80px
range — the "aspiring headline but too small" zone. Below 40px = beat
has no text headline by design (terminal, UI labels, SVG-only); skip.
≥80px = proper headline; pass. Eliminates the false positives on
SVG-dominated and UI-grid beats while still catching the real "headline
too small" failure (Beat 4 at 72px in this run; Beat 1 wordmark at 48px
in another).

**Timeline coverage check**

Three improvements:
1. Detects forEach loops + for-loops containing tl.X() calls — beats
   with these have events at positions the static parser can't read;
   mark as INFO-skipped rather than failed.
2. Detects long-duration tweens — if a single tween's duration covers
   ≥70% of the beat duration (camera dolly, breathing animation), the
   beat has full coverage via persistent motion; skip the position check.
3. New paren-balanced parser for extracting tl.X() position arguments —
   the v1 regex was matching `rgba(86,131,218,0.35)` and capturing 0.35
   as a tween position. The new parser walks paren depth and only
   captures top-level trailing numeric args. No more rgba false matches.

**Shader transitions check**

Two fixes:
1. Filter out inventory lines — lines listing 3+ shader names are
   "what's available," not "what's planned for use." Real use
   mentions one or two shaders per line.
2. Apply the same SFX-context exclusion to the declared side that the
   present-check side already had — "glitch" inside `sfx/glitch-1.mp3`
   no longer counts as a declared shader transition.

For huly-v3: was 6 declared (1 phantom from inventory + 5 + glitch
from SFX), now 2 declared (light-leak, cinematic-zoom) — matches the
storyboard's actual plan.

**Beat duration check**

1. Dropped the "duration X.Xs within 200 chars of beat label" fallback
   — too loose; matched shader durations, animation durations, anything
   labeled "duration". This was the source of the 0.70s misread in the
   debrief.
2. Added a bare-number timing-table parser for the format
   `| 1 | 0.00s | 5.20s | 5.20s | ... |` (with optional `>` blockquote
   prefix). Computes duration = end - start.
3. Added a negative lookahead so `\bB3\b` doesn't false-match "B3.1"
   sub-beats and grab the wrong row.
4. Filter buildBeatIds to only numbered beats — skips the root
   composition (`data-composition-id="main"`) so it doesn't inflate
   "parseable" count.

**Brand visuals + asset count**

Excluded fonts/ subdirectory (always-used via @font-face → would
always pass) and contact-sheet-*.jpg (pipeline outputs, not website
inputs). Both inflated the denominator and weakened the signal.

**Edge case fixes**

- Removed `basename` unused import (oxlint).
- Fixed shader-name substring overlap: longest-name-first matching so
  "cross-warp-morph" doesn't double-count as "cross-warp".
- SFX timestamps now collect ALL audio tags per file (multi-timestamp
  SFX like click×3); picks closest index timestamp to each storyboard
  timestamp instead of just keeping the last.

**Step 6 doc**

Updated the skill's "w2h-verify — the source of truth" section to
describe the new checks accurately and what failure mode each catches.

2 files changed, +486/-109. Format + lint clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 09:03:35 -07:00
..