Field signal ts=1784039841 (win32/x64, CLI 0.7.57): shifted-DOM-image-
layer bug at frame 120 reproduces with BOTH PRODUCER_FORCE_SCREENSHOT=true
AND HF_DE_PARALLEL_ROUTER=false set. First case where both known escape
hatches fail simultaneously. Standalone 1920x1080 GSAP paused timeline,
absolute PNG layers, 4 independent scenes.
Ships a skipped regression fixture to codify the shape. NOT a fix — no
root cause identified. The composition is preserved so a future
diagnostic pass has a real, checked-in repro and a proposed fix can be
validated against the same shape the field reported.
Skip mechanism (belt-and-suspenders):
1. meta.json tagged `field-signal-reproducer` and `known-broken`;
producer/package.json test:regression* scripts add the tag to
--exclude-tags alongside the existing `transparency` skip.
2. Not registered in any .github/workflows/regression.yml shard's
args, so the CI regression sweep won't pick it up either.
Un-skip when a fix lands: drop the tags from meta.json AND add the
fixture id to a shard's args in the workflow. See src/README.md for
the field-signal envelope and diagnostic starting points.
Stack: PR #8 of 9 (base via/gpu-parity-gate).
Signed-off-by: Via
escape-hatch-fatal-fallback — field-signal reproducer
This is a REPRODUCER, not a FIX. No root cause has been identified. The fixture exists so a future diagnostic pass has a real, checked-in composition that reliably surfaces the shift, and so a proposed fix can be validated against the same shape the field reported.
Field signal envelope
ts=1784039841- Platform:
win32/x64 - CLI version:
0.7.57 - Reported in
#hyperframes-cli-feedback
Failure mode
At frame 120 of a 30fps render (i.e. t=4.0s), a DOM <img> layer positioned
absolutely inside the composition shifts by a small but visually obvious offset
from its baseline position. The shift is not an animation frame — it is a
compositor artifact that appears in the encoded output and is absent from the
authored timeline.
Why this fixture matters — both escape hatches fail
The two known escape hatches for shifted-layer / compositor-race classes of bug are:
PRODUCER_FORCE_SCREENSHOT=true— forces the "screenshot" capture path inpackages/producer/src/services/renderOrchestrator.tsandpackages/engine/src/config.ts. This is also the default; setting it explicitly is idempotent with the default state, but the field report set it explicitly to rule out env-inference bugs.HF_DE_PARALLEL_ROUTER=false— forces the distributed-encoder parallel router OFF inpackages/producer/src/services/renderOrchestrator.ts(default is off; the router is opt-in viaHF_DE_PARALLEL_ROUTER=true).
Prior escape-hatch cases (e.g. the RAM-pressure Runtime.callFunctionOn
cluster tracked around #1087 / #2504) had at least one working fallback: either
the screenshot path or the single-worker path would produce a clean render even
when the other was regressing.
This case has none. Applying both escape hatches leaves the shift intact. That's the anomaly worth codifying — every prior triage playbook for this class of bug assumed at least one lever worked.
Composition shape (verbatim from field envelope)
- Standalone 1920x1080 render (no host composition; no picture-in-picture)
- GSAP
paused: truetimeline, driven from outside viatl.progress()/tl.seek()(matchesparallel-capture-regressionand every other GSAP-driven HF regression fixture) - Absolute PNG layers —
<img>tags positioned viaposition: absolutewith explicittop/left/width/height - 4 independent scenes — no cross-fades that overlap the shift frame; the middle 1.1s of scene 2 (which contains frame 120) is a clean opacity=1 window with no compositional cross-traffic
src/index.html implements exactly this shape. PNG bytes are inlined as tiny
data URIs (1x1 solid colors that the layout scales to layer size) — this
preserves the layout shape without shipping binary assets. If diagnostic work
reveals the shift is sensitive to real image decode paths (e.g. sRGB gamma,
non-square intrinsic dimensions, animated PNG chunks), swap the inline URIs
for byte-identical copies of the field asset and re-run.
How this fixture is skipped
The fixture is tagged field-signal-reproducer and known-broken in
meta.json. Two mechanisms combine to keep CI green:
- Local
pnpm test/bun run test— the producer package'stestscript (packages/producer/package.json) exclude thefield-signal-reproducertag via--exclude-tags, alongside the pre-existingtransparencyexclusion. - CI regression sweep —
.github/workflows/regression.ymlruns shards with explicit fixture-name arg lists. This fixture's name is not in any shard, so it won't be picked up.
Both belt-and-suspenders are intentional. If a future dev drops the tag without updating the workflow (or vice versa), the fixture stays skipped.
When a fix lands
- Verify the fix eliminates the shift by running the fixture manually:
The
PRODUCER_FORCE_SCREENSHOT=true HF_DE_PARALLEL_ROUTER=false \ bun run --cwd packages/producer test escape-hatch-fatal-fallback--exclude-tagsfilter is bypassed when an explicit fixture name is passed — the tag exclusion only fires when the harness is enumerating. - Drop the
field-signal-reproducerandknown-brokentags frommeta.json(keepregressionandrender-compat). - Add
escape-hatch-fatal-fallbackto the currently-lightest shard'sargsin.github/workflows/regression.yml(see the LPT-heuristic comment there for balancing guidance). - If baselines don't exist yet, run
bun run --cwd packages/producer test:update escape-hatch-fatal-fallbackto freeze them, then commit theoutput/directory contents that the harness writes.
Diagnostic starting points
For whoever picks this up — a few threads worth pulling before treating the composition shape as the root cause:
- Does the shift move to a different frame if the fixture duration changes? If frame 120 tracks with 4s wall-clock, it's a timing-side effect. If it tracks with the third-scene boundary regardless of duration, it's a scene-transition effect.
- Does the shift survive a single-worker in-process render? The
in-process path lives in
packages/producer/src/regression-harness.tsand bypasses both the screenshot toggle and the DE parallel router. If the shift disappears in-process, the fatal-fallback surface is inside the Docker/lambda capture harness, not the composition renderer. - Does the shift survive on Linux/darwin as well as win32/x64? The field report is win32-only. Cross-platform reproduction would rule out a win32-specific input pipeline (Chromium's Windows compositor thread has a history of shipping DOM shifts under memory pressure).
- Compare against the
parallel-capture-regressionfixture — same GSAP-paused shape, no reported shift. What's the delta? Likely candidates: absolute-positioned<img>decode timing, per-scene opacity gating, or the layer's y/x tween during the shift window.