Skip to content

feat: argo × hyperframes integration — 16 shaders, argo add, block pre-render, showcase - #30

Merged
shreyaskarnik merged 43 commits into
mainfrom
feat/hyperframes-integration-pr
Sep 15, 2026
Merged

shreyaskarnik merged 43 commits into
mainfrom
feat/hyperframes-integration-pr

Conversation

@shreyaskarnik

Copy link
Copy Markdown
Owner

What

Full integration with HyperFrames (Apache-2.0), in four tracks:

1 · Shader transitions (5 → 16)

  • 11 fragment shaders ported from hyperframes' shader library into src/transitions/shaders/ (attribution headers; uniform names mapped to argo's harness at port time)
  • New export.transition.accent: '#hex' tints accent-aware shaders (domain-warp, ridged-burn, thermal-distortion, sdf-iris, ripple-waves); accent participates in the shader cache key
  • Boundary-frame extraction now clamps marks past the assembled video's end (jpeg-stitch mark drift previously crashed export with ENOENT)

2 · argo add + registry compatibility

  • argo add <name> | --list | --json | --registry <url> installs blocks/components from the hyperframes registry into blocksDir (default blocks/, git-tracked) — items stored as native HTML, verbatim, adapted at use time
  • Path-traversal guards on item names AND remote-declared file paths before any path.join()
  • Component adapter: { type: 'hf-component' } overlay cue + applyComponent()/removeComponent() script API — full-frame injection, CSS-custom-property params validated against injection
  • ARGO_BLOCKS_DIR env bridge at all three record() call sites; argo validate checks installs + accent hex

3 · Block pre-render adapter

  • { type: 'hf-block' } overlay cue: recording-time pacing no-op → export-time headless-chromium pre-render (drives window.__timelines via seek(t, false) — GSAP's default suppresses the onUpdate/.call() callbacks compositions use for label text) → alpha PNG sequence → ffmpeg overlay + enable=between() cutaway (never shifts placements/chapters/subtitles)
  • Content-addressed cache salted with RENDERER_VERSION; wired at all four export paths (pipeline ×2, CLI export, preview)
  • Known v1 limitation (documented): incompatible with export.speedRamp

4 · Showcase demo

demos/hyperframes-showcase.* — a 13-scene, 3:24 full-tour recorded by argo itself: multi-voice TTS, every overlay template, camera suite, a data-chart block cutaway, live vignette/shimmer grade, confetti + freeze-frame hold, whip-pan shader cuts, rebranded logo-outro end card.

🎬 The video artifact is distributed outside git (a 181MB intermediate cut is what keeps videos/ out of this branch — GitHub's 100MB history cap). Will attach the final MP4 to this PR after opening.

Verification

  • 720+ tests green (66 → 74 test files); every track's GLSL/registry/renderer code landed with TDD
  • Live-registry smokes: argo add vignette end-to-end; logo-outro pre-rendered 60 alpha frames from the real catalog
  • Specs and implementation plans in docs/superpowers/; per-task + whole-branch reviews ran on each track
  • Squashed from 35 local commits (full history preserved on the local working branch)

https://claude.ai/code/session_017pvzMoFKE6PbEmbaLT4q4K

Shader transition port, argo add + registry compat, block pre-render
adapter, and the 'better together' showcase demo. Approved 2026-07-06.
… chromatic-split, flash-through-white shaders
…paths

Adds resolveHfBlockCues (maps hf-block overlay cues onto scene placement
windows, allowing durationMs to extend past the scene into the following
gap) and renderHfBlocks (per-cue cache-hit-cheap PNG sequence rendering
sharing a single lazily-launched chromium instance) to src/hf/block-render.ts.

Wires all four export call sites that must stay in sync per the repo's
four-path invariant: pipeline.ts primary + variants, cli.ts export command,
and preview.ts export (threading blocksDir through PreviewExportConfig from
both cli.ts preview/dashboard call sites, mirroring how shaderTransition
config already reaches that code).
Dogfoods all three integration tracks: domain-warp shader (accent-tinted)
at every boundary, vignette + grain-overlay applied live during recording,
rebranded logo-outro block composited as the end card. Story page +
live-catalog hybrid recording per the Track 4 spec.
13 scenes covering every major feature of both systems: multi-voice TTS,
all overlay templates + x-post block, camera suite, post-export zoom,
data-chart hf-block cutaway, live vignette/grain/shimmer components,
confetti + freeze-frame hold, 16-shader grid, rebranded logo-outro.

Recording hardening learned the hard way: pages with autoplaying <video>
saturate the jpeg-stitch frame writer (10-min stalls) — the catalog scene
rides the static catalog page + one bounded preview at q88 instead.
…under jpeg-stitch)

Wall-clock marks can outrun the assembled video when frames drop during
capture; an out-of-range boundary made ffmpeg extract nothing -> ENOENT.
Clamp to the probed duration with a warning. Plus: choreography-thesis VO
rewrite, grain removed, outro tail buffer, grain-overlay opacity var.
…cache salt

GSAP's seek() default suppresses callbacks, freezing composition label
text written in onUpdate/.call() (data-chart percentages stuck at 0.0%).
RENDERER_VERSION now salts the block cache hash so behavior changes
invalidate stale frames automatically. Demo: whip-pan transitions (VO,
grid highlight, and config now agree), 15-min test budget + retries for
slow-machine screencast runs.
@shreyaskarnik
shreyaskarnik marked this pull request as ready for review July 9, 2026 01:17
@salir-admin

Copy link
Copy Markdown

when you plan to release this?

…ate block cues

Three fixes found reviewing this branch against current main.

1. hf-* overlays crashed two code paths. `renderTemplate` deliberately throws
   for `hf-component` (injected live) and `hf-block` (composited at export),
   but the preview and the imported-video PNG pre-pass passed every manifest
   overlay to it. So `argo preview` returned 500 for any demo using the
   catalog, this branch's showcase included, and saving overlay edits failed
   too. Every export of an imported video with such a cue also failed before
   ffmpeg ran. `isZoneTemplateCue()` in templates.ts is now the one check
   both paths use. The recording-side `showOverlay`/`withOverlay` already
   branched on these types.

2. hf-block cues were used unvalidated outside `argo validate`. `name` was
   passed straight to `path.join(blocksDir, name)`, which breaks the
   repo's validate-before-join invariant, and a malformed `fit` became
   `scale=NaN:NaN`, rejected by ffmpeg only after TTS and recording had run.
   `resolveHfBlockCues` now skips such cues with a warning, matching its
   documented best-effort contract, and `renderHfBlocks` refuses a bad name
   before touching the filesystem. The name rule is shared with `argo add`
   via `isValidItemName`, so installing and referencing accept the same names.

3. New browser and ffmpeg tests skipped silently. The Chromium suites had no
   guard, and shader-render used `it.runIf`, which skips silently in CI.
   Both now use the capability helpers: skip locally, fail in CI.
   `itWithCapability` is new, for suites that mix guarded and unguarded
   tests. `apply-component`'s browser lifecycle moves into the describe that
   needs it, so `resolveBlocksDir`'s pure tests stop depending on Chromium.

Each fix has a test that fails without it; the guards were checked by forcing
the capability false under CI=1. 866 tests pass, all 16 shaders ship.

Not addressed: `fit: 'cover'` stretches rather than cover-crops
(block-filter.ts), e.g. a 16:9 block in a 9:16 variant renders squashed.
…s fix, cover-crop blocks

Found by checking this branch against the live hyperframes registry (399
installable items) and upstream main since the July port.

`argo add` corrupted binary assets. Item files were fetched with
`res.text()` and written as UTF-8, which replaces every invalid byte with
U+FFFD: a real 74,455-byte registry PNG was written as 135,320 bytes, with
the install reporting success. 13 items were affected, all present at port
time. `fetchItemFile` now reads `arrayBuffer` and the bytes are written
unchanged.

`argo add` refused nested asset paths. The flat-name rule rejected any `/`,
and 64 items keep assets under `assets/…`, 17 of them already in July. Each
`/`-separated segment is now checked against the same rule, which still
rejects `..`, `.`, empty segments (absolute paths, `a//b`, trailing `/`),
dotfiles and backslashes; a resolved-path check backs it up. Blocks load
their HTML over file://, so their relative assets resolve at render time.

`gravitational-lens` started darkened. Its horizon mask applied at full
strength from progress 0, turning the frame centre black on the first frame
of every boundary. Ported upstream dd06b321 (#3660). A new test checks that
all 16 shaders start on the outgoing frame and end on the incoming one, since
every future port can break that and nothing else would catch it.

`fit: 'cover'` stretched. It scaled blocks straight to the output size, so a
16:9 block in a 9:16 variant rendered squashed. It now fills keeping the
aspect ratio and centre-crops; a no-op when aspects already match. Checked
with a real ffmpeg render, not only the filter string.

`argo validate` now also rejects a non-finite fit or a scale <= 0, matching
the render-path check added earlier, so validate cannot pass a cue that export
would skip.

Known limitation, not fixed: components inject their HTML into the recorded
page, so a component's relative asset URLs (e.g. the hw-* handwriting fonts)
resolve against the demo app, not blocksDir. Those 8 components install
correctly but render with fallback fonts/assets.
Upstream moved large binary assets off the git registry: 396 files across
25 items now declare `url` (static.heygen.ai) and nothing exists at the
registry path, so `argo add carousel-circle-1` failed with a 404 on its
first image.

A file's source is now its `url` when present, otherwise the registry path.
Following the hyperframes CLI, only an absolute `https://` url is honoured,
since the manifest is third-party input, and each file is capped at 128 MB.
Every source is validated before the first request, so a bad manifest fails
before anything is written.

Verified against the live registry:
- 6 real items installed, including CDN-hosted carousel images, nested
  fonts and audio, and top-level PNGs. All 26 files byte-identical to
  upstream.
- all 399 installable manifests pass installItem's path and url checks
  (previously 64 rejected and 13 corrupted).
@shreyaskarnik
shreyaskarnik merged commit 4f21bee into main Sep 15, 2026
6 checks passed
@shreyaskarnik
shreyaskarnik deleted the feat/hyperframes-integration-pr branch September 15, 2026 18:15
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