OpenAI Film Fieldnotes

Candidate construction guide · native Resolve not tested

Held-workspace modal relay

Resolve/Fusion construction guidance for codex-modal-relay, paired with the retained editable Remotion recipe. This is guidance awaiting separate critique, not an imported Fusion composition, a new render, or a source-fidelity verdict. resolveApplicationVerified remains false.

Binding and inspection

Every exact geometry, opacity, blur and exposure number below is retained implementation data, not a new measurement of the film. The independent review remains changes-required: three minor findings are still open.

Local clock and coordinate setup

Create a 122-frame, 1920 × 1080 composition. Verify the actual project/export timebase is 24000/1001; a rounded UI label is not authority. Do not use 24 fps. If the editor cannot preserve this timebase, report the incompatibility instead of retiming. With a Fusion composition whose first frame is not zero, add its start frame to every local key and gate. Source ordinal = 1390 + local frame.

Every layer's start is inclusive and end exclusive. A Fusion gate for [4,26) therefore has its first visible frame at 4 and last at 25. Child keys stay on the same local clock, not time since the parent appeared. Child visibility is intersected with every ancestor. The many children declared [0,122) must not leak outside their modal's gate.

Use local transparent domains for each dialog; keep their artwork at its declared pixel dimensions. For an unscaled local box, the target center is (x + width/2, y + height/2) in its parent's pixel coordinates. Convert to normalized coordinates only at the appropriate parent boundary; invert Y for a bottom-up Fusion coordinate system. This is a placement target, not a claim that raw x is a Fusion Center value. Do not add the parent position twice. Preserve shadow pixels outside a dialog: these groups do not declare clipping.

Fusion hierarchy

Use a white Background_Canvas, then a back-to-front chain of Merges:

desktop (1920×1080 SVG)
workspace-before-relay / workspace-after-relay (1720×1080 SVGs)
toolbar-dropdown-hover
toolbar-main-hover
first-scrim
create-copy-dialog
one-frame-progress
copy-confirmation
second-scrim
save-dialog
relay-cursor
disclosure-back
disclosure
MediaOut1

The JSON expands all 85 recipe layers, including every modal child. Its parentLayerId, mergeIndex, backgroundInput, output, recipePointer and effective activity interval define the hierarchy. These are construction labels, not a .setting file. Processed_<id> means that layer's content, any local mask, placement, blur and alpha before its final Merge. A group begins with a transparent Background, merges its children in order, and applies its outer transform/opacity to the assembled result. Do not fade each child separately in place of fading the group.

SVG plates contain original outlined interface artwork. Import/rebuild their vectors without flattening the full treatment. Vector-import support is not tested here; if the target Resolve cannot preserve an asset's geometry, report that limitation. Do not substitute the source movie or a rendered modal clip. Use Background + Rectangle/Ellipse masks for primitives and editable paths for glyphs. CSS radii are pixel values, not values to paste into a normalized Fusion corner-radius control. Blur and shadow kernels need visual matching.

State relay and overlap

Local interval Construction
[0,4) WorkspaceBefore and cursor; no scrim or modal yet
[4,26) First scrim plus first dialog
[26,27) Exactly one compact-progress frame, over the same scrim
[27,47) Confirmation over the same scrim
[47,87) WorkspaceAfter, no scrim or modal; undimmed breathing interval
[80,82) Dropdown hover at (1417,19), 34 × 33, alpha 0.098
[82,87) Main toolbar hover at (1313,19), 104 × 33, alpha 0.098
[87,122) Second scrim and taller save dialog

Both scrims cover 1720 × 1080, not the full 1920-pixel width. The exposed desktop strip on the right must not dim. First scrim uses #101010, alpha 0.135. Second scrim starts at 0.06 at frame 87 and reaches 0.135 at 88.

The first dialog has y=454/451.8/451 at frames 4/5/6; opacity 0.88/0.97/0.985/1 at 4/5/6/7; spatial blur 0.32/0.12/0 at 4/5/6. The save dialog is 533 × 636 at x=525; y=338/335/334 at 87/88/89; opacity 0.525/0.94/0.975/1 at 87/88/89/90; blur 0.45/0.2/0 at 87/88/89. These settle curves are not source-approved: background text persists one frame too long at 6 and 89 in the retained outputs.

Within the second form, the second-option hover is active [98,104), and the third-option hover [103,121). At 103 both are at alpha 0.6 on different rows. First-option-check ends at 110; third-option-check starts at 110. Keep that hard substitution. Save-button-hover starts at 120, while third hover is 0.5; the latter disappears at 121. There is no final submission in this window.

Cursor, easing and exposure

Keep the cursor above the dialogs but below the disclosure. Its six children are three halo paths followed by three foreground paths. Arrow is active [0,97), hand [97,119), then arrow [119,122). The hand sits at local (-8,-2), 37 × 46 in a 40 × 48 cursor group, with origin (4,1); do not crop that negative offset. Both scale axes go from 1 at 106 to 0.88 at 108, hold through 110 and return to 1 at 114. Foreground and halo have separate opacity/blur tracks.

All motion is sampled using src/timing.ts: exact right-key values win; otherwise use the left key's easing. linear is linear; smooth is progress² × (3 − 2 × progress); hold keeps the left value until the right frame. Clamp beyond the key range. Preserve the supplied dense linear keys. Do not apply automatic spline smoothing or generic ease-in/out.

relay-cursor uses 41 parent-transform samples when its shutter is positive. For sample index 0–40:

sampleFrame = frame + (sampleIndex/40 - 0.5) * shutterFrames
sampleOpacity = 1 / (sampleIndex + 1)

Compose the cursor children once at the integer frame, including their shape, press, opacity and blur state. Branch that result to 41 independently sampled parent placements; Merge these branches in ascending sample order using the stated alpha. Evaluate parent x/y at the fractional times; do not time-shift the child group or change arrow/hand gates within the exposure. At zero shutter, use only one branch. At frame 79 the retained shutter is 0.6 native frames; it is not a 0.6-degree shutter angle. Fusion motion blur, Echo or a uniform opacity trail is not proven equivalent. No macro implements this stack here.

The large sample count does not make the cursor fit correct. The inherited review still sees dark leading arrows/hands at fast flights (16–22, 56–64, 97–104). Keep this as the biggest remaining gap, not a repaired result.

Remotion and shared handoff

Use an already authorized, assembled toolkit with the core and selected SVG pack. The retained web project/ alone may omit asset files; its presence is not proof of an assembled runtime. No asset/dependency installation or render was done for this guide. From that toolkit's project/:

npm --silent run catalog -- show codex-modal-relay --contract
npm run render -- --help
npm run render -- --recipe codex-modal-relay --variant default --out out/codex-modal-relay-original.mp4
npm run render -- --recipe codex-modal-relay --variant adaptation --out out/codex-modal-relay-adaptation.mp4
npm run verify -- out/codex-modal-relay-original.mp4
npm run verify -- out/codex-modal-relay-adaptation.mp4

The package scripts, help and option parsers were checked against the archive; read-only catalog/help commands were exercised. The render/verify-output commands above were not executed. They require existing pinned dependencies, FFmpeg/FFprobe and supported Chromium. Render never overwrites an existing MP4 or manifest. Keep each sibling .manifest.json. For new content start with examples/codex-modal-relay/default.json, save the full Content object under inputs/, then use --content inputs/codex-modal-relay.json instead of --variant. Do not treat design inputs as partial Content overrides.

From dual-toolkit-200/, replacing PATH/project with the assembled toolkit:

python3 handoff.py verify --guide guides/layered/codex-modal-relay/guide.json --project PATH/project
python3 handoff.py frames --guide guides/layered/codex-modal-relay/guide.json --project PATH/project > controls.csv

Write CSV only to authorized storage. It reports raw local implementation values, ancestor-gated activity and nominal source seconds. It does not export world-space transforms, text shaping, masks, SVG geometry, fractional exposure images, measured PTS or native Resolve nodes. The parent owns this runtime.

Inspection gate

Use every checkpoint in guide.json; compare actual source and both outputs, not a browser seek presented as an exact frame. The inherited open findings are CM-R03-01 (cursor exposure), CM-R03-02 (wrong early control feedback) and CM-R03-03 (late settling). Preserve the fixed first-button gray fit as data; do not call it the observed source feedback. Text metrics, scrim alpha and blur remain fitted. Manually couple full/truncated identifiers and toolbar art. No Poe functionality, new moving-source review, source completion, or native Resolve verification follows from these instructions or a control-file pass.

Read-only helper tests

From this guide directory, run FIELDNOTES_LIBRARY=PATH/library python3 -B test_guide.py, replacing the path with the retained library root. The six tests check recipe/source/archive pins, all layer and numeric-control mappings, SVG-only asset members, inherited findings and modal-specific boundaries. They read assets directly from their ZIPs and use the parent-owned handoff helpers; they do not assemble a runtime, write evidence, render, or test Resolve. Without the environment variable the suite reports a skip, which is not a validation pass.

Per-SVG binding repair · September 13, 2026

guide.json.svgAssets now pins all 6 distinct SVG paths referenced by image layers across defaults and adaptation, with no extra pack members. Keys are relative to project/public/; values are SHA-256 hashes of the uncompressed project/public/<path> ZIP member bytes. The accepted asset archive's own hash was verified before deriving these pins. Shared paths are listed once.

The helper test requires the exact referenced path set and checks every member's bytes against its pin; missing, extra or changed assets fail. The regression failed for the missing map before this repair. Recipe bytes, numeric controls, source bounds, Fusion geometry and prior evidence remain unchanged. This adds asset verification, not new media, motion review or native Resolve validation.