mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-05 17:30:50 +00:00
00af29c169da025a708a94499d4c1c4e281e718e
8
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
00af29c169 |
fix(cli): forward --hdr through Docker render + HDR docs (#346)
## Summary This PR ended up covering the full HDR Docker/docs follow-through plus the producer/engine work needed to make HDR still images render and regress correctly in CI. The branch now does four things: - forwards `--hdr` through the Docker render path in the CLI - adds and expands HDR documentation across the docs site - adds first-class HDR still-image support to the engine/producer pipeline - adds targeted HDR regression coverage, including a CI-safe fallback for PNG HDR metadata detection when `ffprobe` does not expose PNG color tags ## What changed ### CLI and docs - `hyperframes render --docker --hdr` now preserves `--hdr` when invoking the in-container CLI - added a dedicated HDR guide and linked it from CLI, producer, engine, rendering, and common-mistakes docs - documented HDR constraints and verification flow: HDR source requirements, MP4/H.265 Main10 output, PQ/HLG handling, Docker usage, and common SDR fallback causes ### Engine and producer HDR image support - added `ImageElement` support to the engine composition model and parsing path - threaded image elements through producer compilation and orchestration - probed image sources for HDR color spaces so image-only compositions can trigger HDR output without requiring an HDR video source - included HDR image start times in stacking queries so the layered compositor can place images correctly in z-order - integrated HDR image compositing into the layered HDR render loop alongside native HDR video layers and SDR DOM overlays - forced screenshot mode for HDR layered compositing where required to keep DOM/HDR layer composition deterministic - skipped readiness waiting for natively extracted HDR videos in the engine path where it was unnecessary and could block layered HDR flows ### HDR metadata robustness - added a fallback in `extractVideoMetadata()` to read PNG `cICP` metadata directly when `ffprobe` omits color-space fields for PNGs - this specifically fixes CI/Docker detection for the `hdr-image-only` fixture, where the render was falling back to SDR because the PNG was not being recognized as BT.2020 PQ ### Regression coverage and fixture cleanup - added `hdr-image-only`, a regression fixture that validates HDR still-image rendering end to end - added `hdr-pq`, a focused HDR PQ regression fixture for the video path - updated regression CI to run an `hdr` shard with `--sequential hdr-pq hdr-image-only` - removed the older larger `hdr-regression/*` fixture set in favor of the smaller targeted regressions used by CI - added the necessary fixture generation/readme material and checked-in golden outputs for the new HDR tests ## Why The original PR description only covered the CLI flag forwarding and docs work. Since then, the branch also picked up the missing runtime support needed for HDR still images and the regression coverage to keep that path from breaking. The practical issue this closes is: - local host runs could pass while CI failed `hdr-image-only` - the failure was a full-frame visual mismatch caused by SDR fallback, not unstable rendering - root cause was PNG HDR metadata not being surfaced by `ffprobe` in the CI Docker environment - parsing the PNG `cICP` chunk directly makes HDR detection deterministic across environments ## Test plan ### Local targeted checks ```bash bunx oxlint packages/engine/src/utils/ffprobe.ts packages/engine/src/utils/ffprobe.test.ts bunx oxfmt packages/engine/src/utils/ffprobe.ts packages/engine/src/utils/ffprobe.test.ts bun --cwd packages/engine test src/utils/ffprobe.test.ts src/utils/hdr.test.ts ``` ### Producer regression runs on host ```bash bun run --cwd packages/core build:hyperframes-runtime:modular bun --cwd packages/producer test -- --sequential --exclude-tags slow,render-compat,hdr bun --cwd packages/producer test -- --sequential hdr-pq hdr-image-only ``` Observed result: - `fast` shard: 7 passed, 0 failed - `hdr` shard: 2 passed, 0 failed ### CI-equivalent Docker verification ```bash docker build -f Dockerfile.test -t hyperframes-producer:test . docker run --rm \ --security-opt seccomp=unconfined \ --shm-size=4g \ -v "$PWD/packages/producer/tests:/app/packages/producer/tests" \ hyperframes-producer:test \ --sequential hdr-pq hdr-image-only ``` Observed result: - `hdr-image-only`: passed - `hdr-pq`: passed - shard summary: 2 passed, 0 failed ### Specific regression fixed Before the PNG `cICP` fallback, the Docker/CI run failed `hdr-image-only` with: - missing `"[Render] HDR source detected — output: PQ ..."` log line - full-frame visual mismatch across all 100 checkpoints - PSNR ~17 on every frame, indicating a consistent SDR-vs-HDR pipeline mismatch After the fallback, the same Docker path recognizes the PNG as HDR and the shard passes. |
||
|
|
99a903be2f |
feat(hdr): layered HDR compositing, shader transitions, and HDR image support (#268)
* feat(hdr): shader transitions, --hdr flag, and SDR rendering fixes - 15 GLSL→TypeScript shader transitions on rgb48le buffers - Dual-scene compositing with scene detection via window.__hf.transitions - --hdr flag gates ffprobe probing (zero overhead on SDR compositions) - Cross-transfer conversion (PQ↔HLG) via OOTF-corrected composite LUT - Buffer.from() copy in writeFrame() fixes streaming encoder race condition - SDR rendering fixes (three stacked bugs) - Object.assign fix for window.__hf preservation Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: tighten shader smoke thresholds + assert .scene contract - Tighten the all-transitions smoke test thresholds: at progress=0 we now require the center pixel R-channel > 35000 (was > 25000) and at progress=1 < 15000 (was < 25000). The old midpoint of 25000 sat exactly halfway between the test from-pixel (40000) and to-pixel (10000), so a half-blended transition would silently pass. - Add a runtime assertion in HyperShader.init() that every scene id resolves to a DOM element with the .scene class. Without this, missing ids silently no-op when textures + querySelectorAll(.scene) run later. Addresses deferred review feedback from PR #268. * fix(hdr): restore VIRTUAL_TIME_SHIM and applyRenderModeHints in renderOrchestrator Commit c6b4619c ("feat(hdr): shader transitions, --hdr flag, and SDR rendering fixes") accidentally removed two pieces of the deterministic rendering pipeline: 1. The `VIRTUAL_TIME_SHIM` injected via `createFileServer.preHeadScripts`, which freezes `Date.now()` and `requestAnimationFrame` so RAF-driven animations advance only when `window.__hf.seek(t)` is called. 2. The `applyRenderModeHints` function and its post-`compileForRender` call site, which auto-forces screenshot capture mode for compositions the compiler flagged as needing it (RAF, iframes, etc.). Without (1), RAF animations advanced by wall-clock between the main-loop seek and the per-DOM-layer seek inside `compositeToBuffer`, producing the sawtooth PSNR pattern on `raf-ball-render-compat` (high PSNR at integer seconds, ~24 dB everywhere else). Without (2), `iframe-render-compat` lost its automatic fallback to screenshot mode and the child-document motion stopped being captured. Both helpers are still produced by `htmlCompiler` and exercised by `renderOrchestrator.test.ts` — the orchestrator just stopped calling them. Restored: - Re-import `VIRTUAL_TIME_SHIM` from `./fileServer.js` - Pass `preHeadScripts: [VIRTUAL_TIME_SHIM]` to both `createFileServer` call sites (probe + main render) - Re-add `applyRenderModeHints` (matching the test expectations) and call it immediately after `compileForRender` - Persist `renderModeHints` in `summary.json` and the "Compiled composition metadata" log line Fixes the `iframe-render-compat` and `raf-ball-render-compat` regression failures on `feat/hdr-layered-compositing`. Made-with: Cursor * test(engine): expand sampleRgb48le coverage + audit Uint16Array alignment Adds: - 8 new sampleRgb48le bilinear-interpolation tests covering boundary pixels, sub-pixel weights, edge clamping, and odd-byte-offset Buffers. - uint16-alignment-audit.test.ts documenting the alignment requirement for Uint16Array views over Buffer slices vs. readUInt16LE/writeUInt16LE. Background: ~105 hot-loop sites in shader transitions still use readUInt16LE/writeUInt16LE. Switching to Uint16Array views would cut overhead but requires guaranteed even byteOffsets — these tests document the contract before any future refactor lands. * fix(engine,producer): mask DOM layers during HDR layered compositing The HDR layered compositor blits z-ordered layers over a shared canvas. DOM layers used a full-page screenshot from `captureAlphaPng`, which captures *every* painted pixel on the page — root background, sibling-scene content, overlay UI elements that aren't part of the current layer. Those opaque pixels were then blitted over the canvas, overwriting any HDR content composited beneath in earlier layers. The previous workaround toggled `display:none` on hide ids via `hideVideoElements`/`showVideoElements`. That correctly hid native videos but did nothing about the root composition's background or about overlay elements that the layer grouping considered part of a different layer. This commit replaces the workaround with a precise CSS mask installed before each DOM screenshot: 1. `applyDomLayerMask` injects a stylesheet that hides every `body *` and re-shows the layer's elements (and their descendants and their injected `__render_frame_*` siblings) with `visibility: visible !important`. CSS visibility is *not* multiplicative through descendants — a child with `visibility: visible` overrides an ancestor's `visibility: hidden`, so deeply nested layer content still paints even though every intermediate ancestor is hidden by the mass-hide rule. 2. Non-layer data-start ids are inline-hidden with `visibility: hidden !important`. Inline `!important` beats stylesheet `!important`, so this overrides the show rule for elements that fall under a show selector but should NOT paint — most importantly HDR videos and other-layer SDR videos that live as descendants of `#root`. 3. `removeDomLayerMask` tears the stylesheet down and clears the inline `visibility`/`opacity` properties so subsequent video frame injection gets a clean slate. Crucially the mask only sets `visibility`, never `opacity`. CSS opacity *is* multiplicative — `opacity: 0` on `#root` would zero out every descendant including layer videos, even with `visibility: visible`. We also extend `initTransparentBackground` to force the composition root (`[data-composition-id]`) transparent in addition to `html`/`body`, because compositions almost always set `#root { background: ... }` and that background paints across the whole viewport otherwise. Both compositing paths use the new helpers: - The per-layer DOM branch (`compositeToBuffer`) for normal frames. - The transition path (single DOM screenshot per scene) so transition frames also get a clean per-scene capture. Adds extensive `KEEP_TEMP=1`-gated diagnostics to `compositeToBuffer`: per-layer pixel-add accounting, dumps of every captured DOM PNG, and a periodic raw `rgb48le` snapshot of the composite buffer. These were essential to diagnosing the root-overwrite bug and stay zero-cost in normal renders. Also stops the workDir / per-video frame-dir cleanup when `KEEP_TEMP=1` so the dumps survive past frame N. Made-with: Cursor * fix(engine): preserve GSAP-applied opacity across DOM-layer captures SDR clips inside an HDR composition were rendering at full opacity even when the user had animated their wrapper opacity (e.g. fade-in or yoyo). Two bugs in the per-layer screenshot path conspired to drop the GSAP-applied opacity on the floor: 1. removeDomLayerMask was unconditionally calling `el.style.removeProperty("opacity")` on every wrapper after each layer capture. applyDomLayerMask only ever sets `visibility`, so the only inline opacity present is the value GSAP wrote. Stripping it between layer captures means that on the next capture (at the same timestamp), GSAP's `totalTime(t, false)` no-ops because the timeline is already at that time — the opacity is never restored, and the wrapper renders fully opaque. 2. injectVideoFramesBatch was reading the source <video>'s computed opacity via `parseFloat(computedStyle.opacity) || 1` and copying it onto the injected <img>. Because syncVideoFrameVisibility forces the <video> to `opacity: 0 !important` to hide it during capture, the computed value is always 0, which `|| 1` then silently flips to full opacity. The <img> is a sibling of the <video> inside the same wrapper, so it should inherit opacity from the wrapper directly instead of having a value hard-set on it. Fix both: drop the opacity removal in removeDomLayerMask, skip opacity when copying visual properties from <video> to <img>, and explicitly clear any stale inline opacity on the <img> so it inherits from the wrapper that GSAP is animating. Made-with: Cursor * fix(producer): correct hdrLayerStartTimes typo to hdrVideoStartTimes The diagnostic logging block in executeRenderJob's HDR layer composite path referenced an undeclared `hdrLayerStartTimes` map. The correct variable, declared and populated earlier in the same function, is `hdrVideoStartTimes`. The typo was introduced alongside the DOM-layer masking work and broke the producer build/typecheck on CI. Made-with: Cursor * fix(engine): restore video opacity copy to injected frame img Commit 188ebcca removed the opacity copy from `injectVideoFramesBatch` on the assumption that the <img> sibling would inherit GSAP's opacity from a shared wrapper. That breaks any composition where GSAP animates opacity directly on the <video> element itself: the <img> has no animated ancestor and renders at full opacity throughout any fade, even when the user's intent is partial or zero opacity. The CI `style-7-prod` and `style-8-prod` regressions caught this: the <video id="aroll"> fade-in from 3.0-3.5s rendered as a hard cut because the <img> inherited opacity 1 regardless of GSAP's tween. Restore the old explicit copy from `computedStyle.opacity` to the <img>'s inline opacity, with the `|| 1` fallback intentionally preserved. The fallback is load-bearing: GSAP's seek does not re-apply tweens that have already completed, so post-fade frames read opacity 0 from the stale `opacity: 0 !important` we apply to hide the native <video>. The `|| 1` recovers the tween's end-state opacity 1 for those frames, matching the final on-screen intent and the existing baseline renders. Handles both DOM shapes: - GSAP on wrapper: video's own computed opacity is 1, img set to 1, wrapper's opacity applies via stacking as before. - GSAP on <video>: video's computed opacity is the tween value, copied to img directly since they are siblings. Fixes: - style-7-prod: 0 failed frames (was 2 @ t=3.17, 3.33) - style-8-prod: 0 failed frames (was 2 @ t=3.05, 3.24) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
0cc79a35b0 |
feat(hdr): z-ordered multi-layer compositing with PQ support (#289)
* feat(hdr): add z-ordered multi-layer compositing with PQ support Per-frame z-order analysis groups elements into DOM and HDR layers, composited bottom-to-top. Adjacent DOM elements merge into single screenshots. PQ (HDR10/smpte2084) support via sRGB-to-PQ LUT with 203-nit SDR reference white. queryElementStacking walks DOM for effective z-index, groupIntoLayers splits on HDR/DOM boundaries. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(hdr): address review feedback across stack - Document groupIntoLayers tie-break (V8 stable sort → DOM order). - Expand layerCompositor docstring: merge rationale, visibility inclusion. - Add tests: empty input, negative z-index, stable tie-break at equal z. - Document getEffectiveZIndex CSS stacking-context limitations. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
a21a62b574 |
feat(engine): add HDR two-pass compositing — DOM layer + native HLG video (#288)
## Summary Compositions with HDR video AND DOM overlays (text, graphics, SDR video) couldn't render both correctly — either HDR data was lost (Chrome captures sRGB only) or DOM overlays were missing (FFmpeg pass-through skips Chrome). This PR adds in-memory alpha compositing that combines both. ## What it does **Per-frame two-pass capture:** 1. **DOM pass** — Chrome screenshots the page with a transparent background (CDP alpha). HDR videos are hidden, leaving transparent holes where they go. 2. **HDR pass** — Pre-extracted native HLG/PQ frames (16-bit PNG from FFmpeg) are read from disk. 3. **Composite** — DOM pixels (sRGB RGBA8) are alpha-composited over HDR pixels (rgb48le) in Node.js memory, with sRGB→HLG/PQ conversion via a 256-entry lookup table. **Key components:** - `decodePng()` / `decodePngToRgb48le()` — Pure Node.js PNG decoders (no native dependencies). Support all 5 PNG filter types. - `blitRgba8OverRgb48le()` — Alpha composite with per-pixel sRGB→HDR LUT conversion. Fast paths for alpha=0 (skip) and alpha=255 (overwrite). - `initTransparentBackground()` + `captureAlphaPng()` — Split CDP transparent background setup (once) from per-frame screenshot capture (eliminates 2 CDP round-trips per frame). - Single-pass FFmpeg extraction — All HDR frames extracted in one sequential FFmpeg run (avoids duplicate frames from per-frame `-ss` fast seek). ## Key design decisions | Decision | Why | |----------|-----| | In-memory compositing (not FFmpeg overlay) | Eliminates ~2400 process spawns + temp files per render. Pure pixel math is 10x faster. | | 16-bit PNG intermediate | Raw `-f rawvideo` loses color metadata, causing moiré artifacts. PNG is self-describing. | | sRGB→HLG LUT (256 entries) | DOM content is sRGB. Without conversion, it appears orange-shifted in HLG stream. | | Native HDR detection before extraction | `extractAllVideoFrames` converts SDR→HDR. Pre-extraction probe identifies original HDR sources so only truly-HDR videos get native extraction. | ## Files changed | File | What changed | |------|-------------| | `packages/engine/src/utils/alphaBlit.ts` | **NEW** — PNG decode, sRGB→HDR LUT, alpha compositing (14 tests) | | `packages/engine/src/services/screenshotService.ts` | Transparent background CDP, `captureAlphaPng()` | | `packages/engine/src/services/videoFrameInjector.ts` | `hideVideoElements()` / `showVideoElements()` | | `packages/engine/src/services/streamingEncoder.ts` | Input color space tags for rgb48le | | `packages/producer/src/services/renderOrchestrator.ts` | Two-pass HDR capture loop, native HDR detection | ## How to test Render a composition with an HDR video background and text overlays. Both should be visible — HDR video at full quality, text crisp with correct colors (not orange-shifted). ## Stack position **3 of 6** — Stacked on #265 (HDR output pipeline). This is the foundation for all layered compositing that follows. 🤖 Generated with [Claude Code](https://claude.com/claude-code) |
||
|
|
5a3fde19d4 |
feat(engine): add HDR video output pipeline (#265)
## Summary Adds the ability to render HDR video output (H.265 10-bit, BT.2020) from HyperFrames compositions. When the renderer detects HDR source video, it automatically switches to the HDR output pipeline — no flags needed. ## What it does - **Auto-detection** — Probes each video source with `ffprobe`. If any has bt2020/PQ/HLG color metadata, the output switches to H.265 10-bit with correct color tags. SDR-only compositions are unaffected (H.264, bt709). - **HLG pass-through** — Native HLG pixels from FFmpeg extraction are piped directly to the encoder without conversion. This avoids brightness loss from HLG→linear→PQ conversion (which requires an OOTF system gamma we can't reliably apply). - **Encoder HDR support** — Both chunk and streaming encoders accept HDR presets: `libx265`, `yuv420p10le`, BT.2020 color primaries, `hvc1` codec tag (required for Apple playback). - **WebGPU HDR capture (gated)** — A complete WebGPU float16 readback pipeline is implemented and tested but gated behind headed Chrome (headless doesn't expose WebGPU). Ready for future use with WebGPU canvas content. - **HDR utilities** — `detectTransfer()` (PQ vs HLG), `getHdrEncoderColorParams()`, `analyzeCompositionHdr()`. 15 unit tests. ## Key design decisions | Decision | Why | |----------|-----| | No `--hdr` flag | SDR content encoded as HDR causes orange shift in browsers. Auto-detect eliminates this. | | HLG pass-through (not HLG→PQ) | Conversion loses brightness without OOTF. Pass-through matches source exactly. | | `hvc1` codec tag | Apple QuickTime requires `hvc1` (not `hev1`) for HEVC playback. | | 1-hour streaming timeout | HDR capture at ~6fps needs more time than the default 10-minute FFmpeg timeout. | ## Files changed | File | What changed | |------|-------------| | `packages/engine/src/utils/hdr.ts` | **NEW** — HDR detection, transfer types, encoder params (15 tests) | | `packages/engine/src/services/hdrCapture.ts` | **NEW** — WebGPU readback, HLG conversion, PQ encode | | `packages/engine/src/services/streamingEncoder.ts` | HDR presets, raw rgb48le input, color tags | | `packages/engine/src/services/chunkEncoder.ts` | HDR presets, conditional color tags | | `packages/producer/src/services/renderOrchestrator.ts` | Auto-detection loop, HDR pass-through capture path | ## How to test Render a composition with an HDR video source. The output should be H.265 10-bit with HDR metadata visible in `ffprobe` (bt2020, arib-std-b67 or smpte2084). Plays correctly in QuickTime and on HDR displays. ## Stack position **2 of 6** — Stacked on #258 (SDR/HDR normalization). Provides the encoder infrastructure that phases 1-5 build on. 🤖 Generated with [Claude Code](https://claude.com/claude-code) |
||
|
|
229538c622 |
fix: add media rendering guardrails to prevent silent failures (#112)
## Summary - **Lint rules** catch media elements missing `id` (renderer silently skips them), missing `src`, `preload="none"` (blocks renderer), and video nested in timed divs (freezes playback). Upgraded `video_nested_in_timed_element` from warning to error. - **Compiler** strips `preload="none"` from media during compilation. Runs parallel, cached keyframe interval analysis via ffprobe — warns on sparse keyframes (>2s) that cause seek failures and audio/video desync. Suggested ffmpeg command preserves audio (`-c:a copy`). - **Pre-render lint** lints `index.html` + all `compositions/*.html` sub-compositions before render via shared `lintProject()` helper. Warns by default; `--strict` blocks on errors, `--strict-all` blocks on errors + warnings. - **Render orchestrator** logs a hint to retry with `--workers 1` when parallel capture times out on video-heavy compositions. - **Refactor**: extracted `runFfprobe()` + `parseProbeJson()` helpers to deduplicate ~80 lines of spawn boilerplate across 3 ffprobe functions. Extracted `shouldBlockRender()` so strict flag tests exercise production code. Shared `lintProject()` used by both `lint` and `render` commands. ## Context Discovered during a real composition build session where: 1. `<audio>` without `id` rendered silently (preview worked fine because runtime queries `[data-start]`, but renderer queries `[id][src]`) 2. `<video>` inside timed `<div>` froze on first frame 3. `preload="none"` caused 45s renderer timeout 4. YouTube clips with sparse keyframes from `yt-dlp --download-sections` caused audio/video desync 5. Parallel workers timed out on video-heavy compositions ## Test plan - [x] Core: 365/365 tests passing (5 new lint tests) - [x] Engine: 24/24 tests passing - [x] CLI: 14/14 tests passing (7 lintProject + 7 shouldBlockRender) - [x] Lint + format hooks pass - [ ] Manual: create a composition with `<audio data-start="0" src="test.wav">` (no id) — verify `npx hyperframes lint` catches it - [ ] Manual: run `npx hyperframes render --strict` with lint errors — verify it blocks - [ ] Manual: run `npx hyperframes render --strict-all` with lint warnings — verify it blocks |
||
|
|
20be2ea1c2 |
style: apply oxfmt baseline formatting across all source files (#25)
## Summary - Run `oxfmt .` across the entire codebase to establish formatted baseline - 299 files changed — mechanical formatting only, no logic changes - Double quotes, semicolons, 2-space indent, trailing commas, 100 print width Part 3/4 of [VA-851](https://linear.app/heygen/issue/VA-851/pre-migration-configure-eslint-prettier-and-conventional-commits) ## Test plan - [x] `pnpm format:check` — all 426 files pass - [x] `pnpm -r typecheck` — all packages pass - [x] `pnpm build` — all packages build - [x] All 348 tests pass |
||
|
|
9f8e5ba5a1 |
initial code (#2)
* feat: initial code port from hyperframes-internal Port all OSS-ready packages from the internal monorepo: - @hyperframes/core — shared types, HTML generation, GSAP utilities, runtime - @hyperframes/cli — CLI for creating, previewing, and rendering compositions - @hyperframes/engine — framework-agnostic rendering engine (BeginFrame + FFmpeg) - @hyperframes/producer — video rendering pipeline (Puppeteer + FFmpeg) - @hyperframes/ui-player — browser-based video player component - @hyperframes/studio — composition editor (React frontend + Hono backend) Includes regression test suite with Docker-based test harness. All HeyGen-internal references, deployment infrastructure, and proprietary assets have been removed. Package names migrated from @app/* to @hyperframes/*. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: scrub internal codenames and stale references from OSS port - Replace static.heygen.ai runtime URLs in test fixtures - Remove internal CDN publish script (publish-hyperframe-runtime.ts) - Replace sandbox-studio, sandbox-interceptor, __magicEditRuntime with neutral names (studio, hyperframe-runtime, __hyperframeRuntime) - Fix stale Vault API / localhost references in docs - Remove broken deprecated_studio link Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: remove remaining internal codenames and stale references - Delete stale producer README.md and PIPELINE.md (referenced nonexistent files) - Replace "Cerberus" codename with "HyperFrames" in test design reviews - Replace magic-edit postMessage identifiers with hf-preview/hf-parent - Rename debug-magic-edit-timeline.ts to debug-timeline.ts - Replace "Motion Cut" with "HyperFrames" in Timeline comments - Fix studio/CLI references to nonexistent archive package (use local data/projects/ dir, stub render proxy) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |