Skip to content

feat(skills): add contrast audit + animation map quality skills#267

Merged
miguel-heygen merged 11 commits intomainfrom
feat/quality-skills
Apr 15, 2026
Merged

feat(skills): add contrast audit + animation map quality skills#267
miguel-heygen merged 11 commits intomainfrom
feat/quality-skills

Conversation

@miguel-heygen
Copy link
Copy Markdown
Collaborator

@miguel-heygen miguel-heygen commented Apr 14, 2026

Summary

Two new quality skills + CLI integration that give agents feedback loops they currently lack — pixel-level contrast auditing and structured animation analysis.

What this unlocks for agents

Agents can now catch accessibility failures that humans and LLMs consistently miss. The contrast audit runs automatically on every hyperframes validate and reports WCAG AA violations as warnings. In the eval, 4 out of 5 palettes had failing contrast — every baseline composition shipped broken, every treatment composition caught and fixed it.

Agents can now reason about animation choreography. The animation map produces a structured JSON report with:

  • Per-tween natural language summaries ("card1 slides 23px up over 0.5s, fades in, ends at (120, 200)")
  • ASCII timeline showing the full choreography as a Gantt chart
  • Stagger detection with actual intervals ("3 elements stagger at 120ms" — validates against brief specs)
  • Dead zone detection (periods >1s with no animation — missing entrance or intentional hold?)
  • Element lifecycles (first/last animation, final visibility — catches elements that enter but never exit)
  • Scene snapshots at 5 timestamps (what's on screen at any moment)

Changes

Skills (new)

  • `skills/hyperframes-contrast/` — WCAG contrast audit skill + script
  • `skills/hyperframes-animation-map/` — animation analysis skill + script

CLI

  • `hyperframes validate` now runs contrast audit by default (warnings, not errors)
  • `hyperframes validate --no-contrast` to skip
  • `hyperframes render --html-only` compiles HTML without video encoding
  • Browser-side WCAG code in `contrast-audit.browser.js`, inlined at build time via esbuild text loader

Producer

  • Exported `compileForRender` for the `--html-only` flag

Eval results

5 prompts x 2 arms = 10 compositions. Arm A = baseline skills. Arm B = +contrast +animation-map.

Prompt Failing color Before After
Halflife Cement on Ink 2.98:1 5.33:1
Meridian Ash on Midnight 2.08:1 5.44:1
Typesmith Pencil on Paper 3.19:1 5.50:1
Lattice Gray-600 on Terminal 2.59:1 7.50:1

Animation map correctly enumerated 142 tweens across 5 compositions, detected stagger groups, flagged pacing issues, and produced scene snapshots.

Pitch video

https://itnjfahrnzqvcluhrtif.supabase.co/storage/v1/object/public/assets/uploads/8f043e1c-6882-4fa9-98fd-efb6b3583afa.mp4

Dedicated evals

https://www.heygenverse.com/a/2cac956b-3d14-47bf-90e8-3c1f50e671f3

Test plan

  • Eval: 10 compositions (5 baseline, 5 treatment), all rendered
  • Contrast audit caught 4/4 failing palettes, 0 missed
  • `hyperframes validate` shows contrast warnings by default (exit 0)
  • `hyperframes validate --no-contrast` skips audit
  • `hyperframes validate --json` includes contrast data
  • Animation map tested on 3 compositions (17, 27, 51 tweens)
  • Stagger detection, dead zones, snapshots, timeline all verified
  • `bun run build` passes
  • `bun run lint` passes (0 errors, 0 warnings, 0 skill lint issues)

Two new composition quality skills that give LLMs feedback loops
they currently lack:

hyperframes-contrast — pixel-level WCAG contrast auditing
- Seeks to N timestamps, samples bg pixels behind text elements,
  computes WCAG 2.1 ratios, outputs JSON report + annotated overlay PNG
- Eval: caught failing contrast in 4/5 palettes that baseline missed
  (Cement 2.98:1→5.33:1, Ash 2.08:1→5.44:1, Pencil 3.2:1→5.5:1,
  Gray-600 2.59:1→7.5:1)

hyperframes-animation-map — sprite sheet visualization of GSAP tweens
- Reads window.__timelines, renders N frames per tween with bbox overlay,
  emits sprite sheet PNGs + timeline JSON with flags (offscreen, collision,
  invisible, paced-fast, paced-slow)
- Eval: correctly mapped 142 tweens across 5 compositions, raised
  actionable flags for review

Both skills use @hyperframes/producer's file server for auto runtime
injection — works on raw authoring HTML without a build step.
Adds --contrast flag to the validate command. When enabled, after the
standard console-error check, the command:

1. Reads composition duration from window.__hf or data-duration attribute
2. Seeks to 5 evenly-spaced timestamps via the runtime seek protocol
3. Takes a screenshot at each timestamp
4. Injects a browser-side audit script that walks the DOM for text elements,
   samples background pixels via canvas from the screenshot, and computes
   WCAG 2.1 contrast ratios
5. Reports failures as CLI errors with selector, text, ratio, and timestamp

Zero new Node dependencies — all pixel work runs in the browser via
canvas getImageData. The WCAG math is injected as a raw script string
to avoid esbuild transform issues with page.evaluate.

Usage:
  hyperframes validate --contrast
  hyperframes validate --contrast --json

Contrast failures exit with code 1, same as console errors.
Contrast check now runs automatically on every validate — no flag needed.
Failures are reported as warnings (visible in output, don't affect exit code).
The --contrast flag still exists for explicit control but defaults to true.

Before: hyperframes validate --contrast  (opt-in, failures = errors, exit 1)
After:  hyperframes validate             (always on, failures = warnings, exit 0)
The skill lint script flags inline backticks containing `!` because
Claude Code interprets it as bash history expansion. Replaced with
plain text.
- Move WCAG audit code from inline string to contrast-audit.browser.js
- Use esbuild text loader to inline at build time (no runtime file reads)
- Extract seekTo() and getCompositionDuration() helpers
- Extract printContrastFailures() for the output formatting
- Remove redundant comments throughout
- Pass screenshot directly via page.evaluate args instead of globals
- Remove sprite sheet generation (sharp dependency, PNGs agents can't
  read well at thumbnail scale)
- Add per-tween natural language summaries: direction, distance,
  opacity transitions, size changes, final position
- Add opacity + visibility tracking to bbox samples
- Output is a single animation-map.json — no sprites/ directory
- Drop sharp dependency entirely
The animation map now outputs structured choreography analysis:

- Text timeline: ASCII Gantt chart showing all tweens across the
  composition duration. Agents see the full choreography at a glance.
- Stagger detection: groups consecutive tweens with same props/duration
  and reports actual interval (e.g. "3 elements stagger at 120ms").
  Agents can validate against brief specs.
- Dead zones: periods >1s with no animation. Surfaces missed entrances
  or unintentional gaps between shots.
- Element lifecycles: per-element first/last animation time, tween count,
  final visibility. Catches elements that enter but never exit.
- Snapshots: visible element state at 5 key timestamps (0%, 25%, 50%,
  75%, end). Answers "what's on screen right now" at any point.

Removed sharp dependency and sprite sheet generation.
… skill

The Output Checklist now includes:
- Contrast audit via hyperframes validate (runs by default, fix WCAG warnings)
- Animation map via the standalone script (check summaries, timeline, flags)

These run after lint/validate pass, before declaring the composition done.
Comment thread skills/hyperframes-animation-map/SKILL.md Outdated
Comment thread skills/hyperframes/SKILL.md Outdated
Copy link
Copy Markdown
Collaborator

@jrusso1020 jrusso1020 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strong PR — the eval results speak for themselves (4/4 failing palettes caught and fixed, 142 tweens mapped). The two-tier approach (fast inline check in validate + full standalone scripts) is well-designed.

Two bugs to fix before merge:

  1. contrast-audit.browser.js: missing img.onerror handler — promise hangs if screenshot is malformed
  2. contrast-audit.browser.js: empty pixel sample guard — median([]) returns undefinedNaN ratios for off-viewport elements

Docs gaps:

  • PR description mentions --html-only / compileForRender export that aren't in the diff
  • animation-map SKILL.md doesn't document the composition-level output (choreography, staggers, deadZones, snapshots) — the most valuable part of the report
  • Checklist items in hyperframes/SKILL.md should cross-reference the standalone skills for remediation guidance

Nits:

  • animation-map.mjs seekTo settle time (50ms) may be too short vs contrast's 150ms
  • Two WCAG implementations to keep in sync — add a comment noting the coupling
  • contrast SKILL.md could trim ~15 lines of WCAG basics Claude already knows

Comment thread packages/cli/src/commands/contrast-audit.browser.js
Comment thread packages/cli/src/commands/contrast-audit.browser.js
Comment thread skills/hyperframes-animation-map/scripts/animation-map.mjs
Comment thread skills/hyperframes-animation-map/SKILL.md Outdated
Comment thread skills/hyperframes/SKILL.md Outdated
Comment thread skills/hyperframes-contrast/SKILL.md Outdated
Comment thread packages/cli/src/commands/validate.ts
… skill

Address review feedback: skills should be self-contained, not
cross-reference other skills.

- Remove standalone SKILL.md for hyperframes-contrast and
  hyperframes-animation-map (scripts stay as tools)
- Add "Quality Checks" section to the main hyperframes skill
  with full inline docs for both: contrast (how validate works,
  how to fix warnings) and animation map (how to run the script,
  how to read the JSON output, what each field means)
- Output Checklist now references the inline sections, not
  external skills
- Add onerror handler on Image load to prevent promise hang on corrupt
  base64 (contrast-audit.browser.js)
- Guard against empty pixel samples when bbox is fully offscreen
- Bump animation-map seek settle from 50ms to 100ms for complex timelines
- Add sync note between browser-side and standalone WCAG implementations
@miguel-heygen miguel-heygen merged commit d3f2295 into main Apr 15, 2026
13 checks passed
Copy link
Copy Markdown
Collaborator Author

Merge activity

ularkim pushed a commit that referenced this pull request Apr 15, 2026
Code fixes:
- snapshot.ts: path traversal guard, browser leak (try/finally), div-by-zero
  for --frames 1, port bind error handling, rAF-based render settle
- index.ts: remove invalid thinkingConfig for gemini-2.5-flash, fix Gemini
  batch/rate-limit comments, fix video preview viewport y-coordinate
- tokenExtractor.ts: remove dead seen[si] dedup code
- gsap.ts: index ALL classes for inline-style transform conflict detection

Skill architecture rewrite (4-phase → 7-step):
- Replace phase-1 through phase-4 with step-1 through step-7
- Add techniques.md (10 visual techniques with code patterns)
- Fix /hyperframes-compose → /hyperframes (skill doesn't exist)
- Fix captures/arc-browser reference → shader-setup.md (file doesn't exist)
- Fix step-7 hardcoded captures/stripe path
- Document Gemini API free/paid rate limits in step-1

Cleanup:
- CLAUDE.md: restore from Stripe-capture overwrite, update 4-phase → 7-step
- .gitignore: add PR #267 skills (hyperframes-animation-map, hyperframes-contrast)
- Delete old phase-*.md, animation-recreation.md, tts-integration.md

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ularkim pushed a commit that referenced this pull request Apr 15, 2026
Code fixes:
- snapshot.ts: path traversal guard, browser leak (try/finally), div-by-zero
  for --frames 1, port bind error handling, rAF-based render settle
- index.ts: remove invalid thinkingConfig for gemini-2.5-flash, fix Gemini
  batch/rate-limit comments, fix video preview viewport y-coordinate
- tokenExtractor.ts: remove dead seen[si] dedup code
- gsap.ts: index ALL classes for inline-style transform conflict detection

Skill architecture rewrite (4-phase → 7-step):
- Replace phase-1 through phase-4 with step-1 through step-7
- Add techniques.md (10 visual techniques with code patterns)
- Fix /hyperframes-compose → /hyperframes (skill doesn't exist)
- Fix captures/arc-browser reference → shader-setup.md (file doesn't exist)
- Fix step-7 hardcoded captures/stripe path
- Document Gemini API free/paid rate limits in step-1

Cleanup:
- CLAUDE.md: restore from Stripe-capture overwrite, update 4-phase → 7-step
- .gitignore: add PR #267 skills (hyperframes-animation-map, hyperframes-contrast)
- Delete old phase-*.md, animation-recreation.md, tts-integration.md

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
jrusso1020 pushed a commit that referenced this pull request Apr 16, 2026
* feat(cli): add website capture with AI-powered DESIGN.md generation

Adds `hyperframes capture <url>` command that extracts a complete design
system from any website, producing AI-agent-ready output:

- Full-page screenshot (lazy-load aware, nav at top)
- AI-generated DESIGN.md via Claude API (colors, typography, elevation,
  components, do's/don'ts) with programmatic asset catalog (136+ assets
  with HTML context annotations like img[src], css url(), link[rel=preload])
- CSS-purged compositions (87% size reduction via PurgeCSS)
- HTML-prettified compositions (one-tag-per-line for AI readability)
- CLAUDE.md + .cursorrules auto-generated for AI agent instructions
- Asset deduplication (srcset variants) and tracking pixel filtering

* feat(cli): add gemini 3.1 pro, playwright screenshots, replica refinement

- switch to gemini 3.1 pro (gemini-3.1-pro-preview) with claude fallback
- playwright for full-page screenshots (fixes puppeteer gradient/fixed bugs)
- replica refinement loop: generate, screenshot, compare, fix
- extract inline svgs (50 max, 10kb each) to assets/svgs/
- extract visible text in dom order for content accuracy
- detect js libraries (gsap, three.js, scrolltrigger) via globals
- improved asset catalog grouping and naming
- reverse-engineered aura system prompt documentation
- comprehensive session handoff doc

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: update session handoff with slack research findings

- key finding: team already wants DESIGN.md integration (James, Bin, Vance)
- skills quality matters enormously - must invoke /hyperframes-compose
- eval infrastructure exists (Abhay's dashboards, Teodora's 78-criteria guide)
- templates at templates/ need study before finalizing skill
- session handoff updated with critical next steps

* refactor(cli): simplify capture pipeline, remove replica generator

* feat(capture): add Lottie detection and WebGL shader extraction

Captures Lottie animations via network interception and WebGL shader
source via gl.shaderSource hooking during site crawl. Updates
website-to-hyperframes skill with asset planning guidance, Lottie/shader
reading instructions, and stronger creative direction for scene planning.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor(capture): clean pipeline + shader-first creative workflow

Capture pipeline:
- Remove dead deps (puppeteer-extra, stealth plugin, duplicate devDeps)
- Remove duplicate generateAgentPrompt() call (first lied about DESIGN.md)
- Remove dead canvas-to-image code in htmlExtractor (post canvas removal)
- Parallelize image downloads (batches of 5 via Promise.allSettled)
- Fix pre-existing TS error (match[1] guard in font downloader)
- Default capture output to captures/<hostname>

Skill creative overhaul:
- Add shader transition selection to creative director step (Step 4)
- Add shader wiring instructions to engineer step (Step 5)
- Replace 4-line energy modifiers with visual vocabulary table
- Strip rigid scene-by-scene templates from video-recipes.md
- Strip example fill data from scene plan tables
- Add "read transition refs before planning" instruction
- Add creative ambition language ("how the hell did they make this")

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: add skill architecture redesign spec

Comprehensive redesign of website-to-hyperframes skill and capture
pipeline based on code review findings and Claude Code architecture
research. Key changes: remove AI auto-generation, restructure skill
into phases, embed shader boilerplate in scaffold, fix color format.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: add implementation plan for skill architecture redesign

13-task plan covering: capture pipeline cleanup (remove AI generation,
fix colors to HEX, add asset descriptions, shader-ready scaffold),
skill restructuring (4 phases with artifact gates), and compose skill
Visual Identity Gate upgrade.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(capture): remove AI auto-generation and SDK dependencies

* fix(capture): convert extracted colors to HEX format

* refactor(capture): remove AI key path, add asset descriptions generator

* refactor(capture): update agent prompt, remove hasDesignMd, add asset descriptions

* feat(capture): pre-wire shader transitions in index.html scaffold

* chore: remove duplicate visual-styles.md (canonical is in hyperframes/)

* refactor(skill): rewrite website-to-hyperframes as phase-based orchestrator

* feat(skill): add Phase 1 understand reference

* feat(skill): add Phase 2 design reference with full DESIGN.md schema

* feat(skill): add Phase 3 creative direction reference

* feat(skill): add Phase 4 build reference with inline shader example

* feat(skill): upgrade Visual Identity Gate to produce full DESIGN.md

* docs: update CLAUDE.md skill references for phase-based workflow

* fix: address code review findings

- Remove orphaned `false` argument in generateAgentPrompt call (critical:
  was shifting hasLottie, hasShaders, catalogedAssets parameters)
- Add HSL color handling in rgbToHex via temp element resolution
- Remove build artifact commit section from phase-4-build.md
- Fix __GSAP_TIMELINE reference to __timelines

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(capture): regex double-escape + simplify scaffold + fix asset descriptions

- Double-escape regex in tokenExtractor template literal (\s→\\s, \d→\\d, \(→\\()
  so browser receives valid regex patterns via page.evaluate()
- Simplify index.html scaffold: scene slots + audio + timeline + comment pointing
  to shader-setup.md reference (no broken inline shader boilerplate)
- Fix asset descriptions: use CatalogedAsset.contexts/notes instead of
  nonexistent htmlContext field

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: code review — 16 bugs, 7-step skill rewrite, cleanup

Code fixes:
- snapshot.ts: path traversal guard, browser leak (try/finally), div-by-zero
  for --frames 1, port bind error handling, rAF-based render settle
- index.ts: remove invalid thinkingConfig for gemini-2.5-flash, fix Gemini
  batch/rate-limit comments, fix video preview viewport y-coordinate
- tokenExtractor.ts: remove dead seen[si] dedup code
- gsap.ts: index ALL classes for inline-style transform conflict detection

Skill architecture rewrite (4-phase → 7-step):
- Replace phase-1 through phase-4 with step-1 through step-7
- Add techniques.md (10 visual techniques with code patterns)
- Fix /hyperframes-compose → /hyperframes (skill doesn't exist)
- Fix captures/arc-browser reference → shader-setup.md (file doesn't exist)
- Fix step-7 hardcoded captures/stripe path
- Document Gemini API free/paid rate limits in step-1

Cleanup:
- CLAUDE.md: restore from Stripe-capture overwrite, update 4-phase → 7-step
- .gitignore: add PR #267 skills (hyperframes-animation-map, hyperframes-contrast)
- Delete old phase-*.md, animation-recreation.md, tts-integration.md

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: remove dev artifacts, research docs, wrong lockfiles

Remove files that shouldn't ship in this PR:
- docs/research/ (aura analysis, prompt catalogs)
- docs/session-*.md, docs/SESSION-HANDOFF.md (dev notes)
- docs/superpowers/ planning and spec docs
- pnpm-lock.yaml at root and cli (repo uses bun, not pnpm)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(CLAUDE.md): align with main — slim format, add website-to-hyperframes mention

Main PR #283 removed the full skills table from CLAUDE.md and moved it
to AGENTS.md. Align with that decision: use main's slim dev-focused
format, fix pnpm→bun references, add one-line /website-to-hyperframes
pointer.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): add capture command to help groups

The capture command was registered in cli.ts but missing from
the help groups, so it wouldn't appear in `hyperframes --help`.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* style: format skill reference files (oxfmt)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: regenerate bun.lock after rebase

The lockfile was stale after rebasing onto main — bun install
--frozen-lockfile failed in CI because new dependencies (google/genai,
patchright, purgecss) weren't reflected in the lockfile.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: address PR review comments + improve capture quality

Review fixes (16 comments from jrusso1020 + vanceingalls):
- screenshotCapture: remove Playwright dep, use Puppeteer for all screenshots
- screenshotCapture: dynamic screenshot count based on page height (30% overlap)
- snapshot.ts: fix duration() function-vs-property bug, cross-platform path guard
- htmlExtractor: fix code injection via parameterized evaluate
- index.ts: video preview re-measures position after scroll, .env file loading
- capture.ts: BLOCKED.md on timeout failures
- gsap.ts: 5 inline-style lint tests added (all pass)
- Remove Playwright, patchright deps; @google/genai to optionalDependencies
- Gitignore: generic patterns instead of 20 hardcoded directories
- Remove asset-sourcing.md, video-recipes.md (unused, duplicated guidance)

Capture quality improvements (tested on 10+ websites):
- Color extraction: canvas-based oklch/lab resolver, pixel sampling via
  elementFromPoint, broad sweep for accent colors, gradient/shadow extraction
- Section detection: broadened selectors for div-based layouts, height cap
  to skip page-level wrappers, parent bg walkup for dark sites
- Font downloads: cap 6 per family / 30 total (Cal.com: 306→30)
- CTA detection: text pattern matching + nav context filtering
- Heading text: innerText with whitespace normalization
- Gemini captioning: maxOutputTokens 100→300, .env auto-loading
- .env.example updated with GEMINI_API_KEY docs
- TTS ranking: Kokoro first with Python 3.10+ note

* fix: address PR review comments + improve capture quality

Review round 2 fixes (jrusso1020 + vanceingalls):
- verify/index.ts: add path traversal guard (relative + isAbsolute)
- verify/index.ts: fix sections[i] undefined typecheck error (CI green)
- index.ts: escape Lottie JSON with \u003c to prevent </script> breakout
- step-4-storyboard: fix technique count contradiction (2-3 per beat, not
  across whole video)
- step-6-build: perspective tilt uses gsap.set() instead of CSS transform
  (avoids GSAP overwrite conflict)
- step-1-capture: reorder — command first, Gemini note after (zero-config
  is the default path, API key is optional enhancement)
- step-7-validate: add tsx fallback for snapshot command
- step-3-script: vary hook patterns, don't default to number every time
- assetDownloader: exempt SVGs from 10KB minimum filter (company logos
  like Hubspot/Intel/DHL are 2-6KB; HeyGen capture: 13→75 assets)

Note: adm-zip was NOT removed (reviewer #3) — it's still in
packages/cli/package.json:30. The root package.json had patchright
and purgecss removed, not adm-zip.

Note: ANTHROPIC_API_KEY not restored in .env.example — grep confirms
zero references in the entire codebase. The @anthropic-ai/sdk dependency
was removed earlier in this branch.

* refactor(capture): split index.ts (1175 to 566 lines) into modules

Mechanical extraction, zero logic changes.

New files:
- mediaCapture.ts (345 lines): Lottie preview, video manifest/screenshots
- contentExtractor.ts (314 lines): library detection, text, Gemini, asset descriptions
- scaffolding.ts (135 lines): .env loading, project scaffold generation

Also fixes false-positive BLOCKED.md with structural Cloudflare detection.
Tested on 20 websites, pre/post output identical.

* chore(capture): remove --split flow (splitter, verify, cssPurger, purgecss)

The --split feature auto-generates compositions from captured HTML — a
different approach from the /website-to-hyperframes skill workflow where
agents build compositions from scratch using the storyboard.

No skill file, no step reference, and no test session ever used --split.
Removes 923 lines of unused code + purgecss dependency.

Backed up to ~/Desktop/capture-split-backup/ for reference.

* fix(security): add ssrf protection, lottie injection fix, oom guard

- assetDownloader: add isPrivateUrl() guard blocking private IP ranges
  (127.x, 10.x, 172.16-31.x, 192.168.x, 169.254.x), cloud metadata
  endpoints, localhost, and non-HTTP schemes
- mediaCapture: fix Lottie JSON injection by loading shell HTML first
  then passing animation data via parameterized page.evaluate()
- index.ts: check Content-Length header before response.buffer() in
  Lottie network interception to avoid OOM on multi-GB responses

* fix(capture): security fixes, timeout, sub-agent dispatch instructions

Security (from miguel-heygen review):
- assetDownloader: export isPrivateUrl() SSRF guard
- htmlExtractor: add isPrivateUrl check before CSS fetch
- mediaCapture: add isPrivateUrl check before Lottie fetch
- mediaCapture: fix previewPage leak (try/finally)
- mediaCapture: skip Lottie files > 2MB for preview (CDP limit)
- contentExtractor: skip images > 4MB for Gemini captioning
- index.ts: check Content-Length before response.buffer() (OOM guard)
- snapshot.ts: register error handler before server.listen()

Capture improvements:
- Default timeout 30s to 120s (Shopify needs ~90s for Cloudflare)
- step-6-build: sub-agent dispatch template with explicit rules:
  pass file PATHS not contents, use local fonts not Google Fonts,
  verify ../assets/ references after each beat

* fix(capture): catalog before DOM mutation, networkidle2, faster Gemini

Critical: asset cataloger now runs BEFORE extractHtml which converts img
src to data URLs. Framer sites like heykuba.com went from 2 to 78 images.

- networkidle2 instead of networkidle0 (unblocks SPAs with WebSockets)
- Lazy-load wait: scroll to bottom, wait for img.complete
- CSS background-image cataloging for Framer/Webflow
- SVG naming: checks class, id, parent, inner text (not just aria-label)
- Gemini batch 5->20, pause 12s->2s (paid tier: 2000 RPM, ~0.001/img)
- maxOutputTokens 300->500, descriptions sorted captioned-first
- Remove tsx fallback from step-1 (reviewer nit, published CLI has it)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants