Skip to content

Registry blocks violate determinism contract: runtime data fetches + async timeline registration (maps, vfx-iphone-device, caption components) #2107

Description

@vanceingalls

Found during systematic validation of the prompting-guide examples (every catalog block exercised via real builds). Three block families break the framework's own composition contract, all fixable with one shared pattern.

Affected blocks

Map blocks (us-map, us-map-flow, likely us-map-bubble, us-map-hex, world-map, spain-map):

  • Fetch topojson from a CDN at render time (fetch("https://cdn.jsdelivr.net/npm/us-atlas@3/states-10m.json") / d3.json(...)) — violates the no-render-time-network determinism rule.
  • Build their entire GSAP timeline inside the async .then() callback, so window.__timelines isn't registered synchronously → the producer's pollSubCompositionTimelines gate times out after 45 seconds and falls back to screenshot capture (same class as the known subcomp poll-timeout issue).
  • us-map additionally paints its background on the composition root (the documented black-frame anti-pattern), and us-map / us-map-flow use incompatible projections (fitSize vs scale/translate) plus opaque backgrounds, so the "layerable" flow/bubble overlays don't actually land on the base map's geography without merging at source.

vfx-iphone-device:

  • Registers its timeline inside an async onReady() (GLTF load + double rAF) → same 45s poll stall on every render.
  • Fails hyperframes lint as a root composition (requestanimationframe_in_composition), and can't be a <template> sub-comp (full HTML doc) — there is no consumption mode where lint passes and validate/inspect can exercise it without editing the block.
  • First ~0.7s of the render is black (scene not yet painted).
  • Ships hardcoded demo screen content with no injection point, though the catalog copy implies you can put "your UI" on the screen.

Caption components (all 15 caption-*):

  • Ship with an empty <video> (no src) → media_missing_src + media_in_subcomposition lint errors standalone; only lint-clean after being pasted into a host with real footage, which the catalog usage text doesn't mention.
  • caption-neon-glow's intentional dim resting state (rgba(0,255,240,0.14)) trips 16 WCAG warnings with no note that they're benign — agents "fix" them and break the identity.

Shared fix pattern

  1. Bake remote data offline (geo topojson → inline projected geometry; validated approach: d3-geo projection at authoring time, zero runtime network).
  2. Register the paused timeline synchronously; move async asset readiness behind the existing media-readiness gates instead of gating timeline registration.
  3. Keep composition backgrounds off the root element.
  4. For the maps: share one projection between base + overlay variants (or ship transparent, projection-matched overlays).
  5. Caption components: ship without the placeholder <video> (or with a documented, lint-exempt placeholder) and note the benign-contrast cases.

Repro evidence

Validation builds with full logs/renders exist for each case (us-map + us-map-flow merged-at-source build; vfx-iphone-device 15s render with 45s stall; caption-highlight/kinetic-slam/neon-glow re-authored builds). Happy to attach details per block.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions