OpenAI Film Fieldnotes

Candidate construction guide · native Resolve not tested

Grow a document range and return the camera

An original SVG/code Remotion treatment with a complete manual DaVinci Resolve / Fusion construction guide. Two meaningful content variants share one framegraph. No source artwork, raster/video adaptation input or native Resolve project is shipped. Builder tests are not a rendered-quality approval.

Public kit: install and verify

The kit root contains core-publication-v08.zip, active-assets.zip, handoff.py, guide.json, this README, controls.csv, fusion-controls.csv, overlay-manifest.json, provenance.json and test_kit.py. The distributor supplies the pinned core and handoff helper; neither a private worker nor a repository checkout is required. No generator or prebuilt inputs helper is needed: both payloads are embedded in the recipe.

Both ZIPs start with project/. From the kit root, unpack core first, then the active overlay into the same kit root, not into project/ again:

python3 -m zipfile -e core-publication-v08.zip .
python3 -m zipfile -e active-assets.zip .
python3 handoff.py verify --guide guide.json --project project
python3 handoff.py frames --guide guide.json --project project > controls-regenerated.csv
cmp controls.csv controls-regenerated.csv
PYTHONDONTWRITEBYTECODE=1 python3 test_kit.py --project project --core core-publication-v08.zip

Integrity contracts (SHA-256):

Artifact SHA-256
Core ZIP 307fb6b927e35e6d73779652873d994f5c3e36cb7deba65f22fa64748057a0de
Active ZIP a670419b922bcf908f1d3f7edd30c1f10218e39dc4b3383c7960e9615be9e930
Recipe 0fb01c8278624841873044311fd8fcbfad622d368d78e09e6a856ff30e8d7276
Guide be26d71cfe62d38eb74345026774f1b3761ab59dfadb9e92769fcade65715713
Handoff helper dedfeaefb89a3158c060f092d9393fe208a52f88b51e21e8bd06c8b272a25721

overlay-manifest.json binds every active recipe/SVG ZIP member and every guide/control/provenance artifact. The active ZIP has only this recipe and its 2 original SVGs, no core, dependencies or legacy art. source.localMedia is research metadata, not a requested input path.

Remotion: preflight, then authorized rendering

Read project/README.md and project/AGENT_GUIDE.md. Use Node >=22.18, Python 3.11+, FFmpeg/FFprobe and an explicitly installed supported Chromium. Preserve project/public/fonts/Geist.ttf and its OFL.txt; do not replace the font or silently shrink text. The core browser text-fit gate remains authoritative. Set REMOTION_BROWSER_EXECUTABLE if your installed browser is not discovered. No automatic browser download is required by these instructions.

From project/, the actual archived CLI is:

cd project
npm ci
node --experimental-strip-types --input-type=module -e '
import {prepareInput} from "./scripts/lib.mjs";
for (const variant of ["default", "adaptation"]) {
  const prepared = await prepareInput({projectRoot: process.cwd(), recipeId: "canvas-range-camera-return", variant});
  console.log(variant, prepared.expected);
}
'
node --experimental-strip-types scripts/render.mjs --recipe canvas-range-camera-return --variant default --out out/canvas-range-camera-return-default.mp4
node --experimental-strip-types scripts/render.mjs --recipe canvas-range-camera-return --variant adaptation --out out/canvas-range-camera-return-adaptation.mp4
node --experimental-strip-types scripts/verify.mjs out/canvas-range-camera-return-default.mp4
node --experimental-strip-types scripts/verify.mjs out/canvas-range-camera-return-adaptation.mp4

Expected: 1920×1080, 24/1 fps, 144 frames, 6 seconds (6.000000000), zero audio streams. The renderer refuses an existing MP4 or its sibling manifest; choose a new basename instead of overwriting. Keep each generated .manifest.json with its output. These commands are for the authorized renderer: this builder did not encode or review candidate output.

Content substitutions

Default: editable weekly studio sessions. Adaptation: editable weekly garden tasks. Both contain original code-like text, a distinct brief, context and SVG document mark. The code is displayed text, not an executed app or an assertion of product functionality.

Every slot, both literal payloads, consuming layers and field contracts appear under guide.json.editableSubstitutions. Keep the same number of rows/items, literal line breaks, aspect ratios and range/camera parenting. Character limits are not a font-fit guarantee. For custom SVGs use original permitted geometry, no <image>, raster data URI, external resource, script, embedded font or source frame. Inspect both content and framing after every edit.

From project/, create a complete Content object, not a partial override:

python3 - <<'PY'
import json
from pathlib import Path
recipe = json.loads(Path("recipes/canvas-range-camera-return.json").read_text())
content = dict(recipe["defaults"])
content["attachment"] = "Planning brief"
Path("custom.json").write_text(json.dumps(content, indent=2) + "\n")
PY
node --experimental-strip-types --input-type=module -e '
import {prepareInput} from "./scripts/lib.mjs";
console.log((await prepareInput({projectRoot: process.cwd(), recipeId: "canvas-range-camera-return", contentPath: "custom.json"})).expected);
'
node --experimental-strip-types scripts/render.mjs --recipe canvas-range-camera-return --content custom.json --out out/canvas-range-camera-return-custom.mp4

--content and --variant are mutually exclusive. Relative content paths are resolved against the process working directory; the example deliberately runs inside project/. The frozen guide verifies the embedded variants. A changed recipe or SVG requires a revised hash contract; do not relabel it as this freeze.

Source clock, observation and adaptation

Film: Prototyping with canvas in ChatGPT. Retained official-player publication: 2025-04-08, timestamp 2025-04-08T12:25:22-07:00. This is pinned local metadata, not a new live web verification. Selection window: September 5, 2024 through September 5, 2026 at 17:13:40.602033 UTC; no later publication is used.

Source interval [1608, 1752) at 24/1, with exact nominal source seconds [67, 73). Local frame zero = source 1608; last local frame 143 = source 1751. Excerpt offset is zero. Source-relative PTS and durations are retained verbatim in guide.json.sourceClock; every excerpt PTS was separately compared as a rational time. Absolute master PTS and coded-tail duration were not recovered. Do not round this clock or stretch it to another timeline rate.

Research excerpt SHA-256: 8c0edacf13856e57e0e98c8395876c545ee812edce70d61fa245295bb400e208. The source master SHA is inherited, not freshly rehashed. The source/timing unit and related implementation file hashes are in provenance.json. Related Edit/SelectionContext and its partial Resolve guide supplied parenting/masking concepts, not a complete adapter.

Inspection: all 144 excerpt frames viewed statically as consecutively decoded 480×270 thumbnails, plus 6 selected 1920×1080 native-size stills. Contact sheets are not moving review or all-frame full-resolution inspection. No whole-film/new-coverage claim, native Resolve execution, exact source-quality approval or measured OpenAI props is made.

Authored choreography

  1. 0–3: wide browser workspace. 3–12: the common camera reaches 1.92 scale, translated by (−616.4,−409.4) design pixels. This is an authored focus mapping, not recovered camera calibration.
  2. Selection row starts are 13/15/17/20/23/26/29/32/35. Each highlight grows for two frames. The last endpoint reaches its full width at 37. Text, line numbers, range masks, pointer and contextual action all remain inside the same document/workspace/camera hierarchy.
  3. 48–124: contextual action remains attached below the range. Camera holds close through 97, returns via scale 1.30 at 108 and 1.025 at 120, then reaches 1 at 134.
  4. The range ends at 121, after the main return while a small settling displacement remains. The contextual action ends at 125. The original text remains unchanged through 143; no request entry, send or rewritten result is invented.

Visible-state brackets are source observations/estimates; all numeric tracks are chosen adaptation values. guide.json.observationPolicy keeps those categories separate. The following samples are checkpoints to inspect, not assertions that a rendered output already passed:

Local frame Source frame Nominal source seconds Expected authored state
0 1608 67.000000 Wide workspace, original document.
3 1611 67.125000 Last wide hold frame.
12 1620 67.500000 Close camera; no range yet.
13 1621 67.541667 First range row begins growing.
16 1624 67.666667 Second range row completing.
24 1632 68.000000 Middle of selection growth.
35 1643 68.458333 Final range row begins.
37 1645 68.541667 Full nine-row selection.
48 1656 69.000000 Context action disclosed below range.
97 1705 71.041667 Last close hold before return.
100 1708 71.166667 Camera returning; range remains parented.
108 1716 71.500000 Intermediate wide return.
120 1728 72.000000 Range still present, camera near wide.
121 1729 72.041667 Range clears; contextual action still present.
125 1733 72.208333 Contextual action removed.
134 1742 72.583333 Camera reaches original overview.
143 1751 72.958333 Unchanged document at cutoff, no sent request.

Resolve / Fusion construction

  1. Create a 1920×1080, square-pixel composition at 24/1, local frames 0–143 inclusive. Set the actual rational cadence, not a rounded integer substitute. Do not add a final hold. Keep audio empty.
  2. Work on transparent 4096×4096 domains, with design pixel (0,0) placed at work pixel (1024,1024). Parent/child domains stay identical. Build the opaque RootPaper Background and nodes listed below in order; later siblings are foreground. guide.json.rootPipeline supplies its color/domain, final crop coordinates and MediaOut connection. nativePalette supplies normalized RGB values for editable colors in both variants; use opacity separately.
  3. For each layer build Construct → LocalMask → AnchorShift → ScaleRotate → Position → Gated → Merge.Foreground; the previous sibling feeds Merge.Background. For a group, Construct is its ordered child merges over a transparent background. Apply group alpha once after assembly.
  4. guide.json.fusionNodes names every tool, connection, parent, raw/static control, content binding and gate. svgSubgraphs enumerates every original SVG Rectangle/Ellipse/Polygon, color, alpha and merge order for both variants. Build those natively; do not rasterize SVGs or use source footage as Loaders.
  5. Bake the numeric rows in fusion-controls.csv at each integer local frame. Its AnchorShift/Position/ScaleRotate/Gated columns are derived below. controls.csv contains every raw property sample, including independent width/radius tracks. Neither CSV is a magically importable .setting file: transfer columns to the named native controls using frame-based keys.
  6. Install the licensed bundled Geist. Use Text+ for text, the explicit weight, pixel box, line advance, tracking and alignment in each node. Text+ Size fontSize/4096 is only an uncalibrated starting estimate, not a verified CSS conversion. Compare glyph footprint, baseline and fit natively before delivery. Retain literal line breaks and stepped character reveals. Never scale type down just to hide overflow.
  7. After the last root merge, crop exactly work pixels x=[1024,2944), y=[1024,2104) to 1920×1080; do not resize. Send to MediaOut. Keep anything outside the final crop until this final operation, except declared local masks.

Coordinates and interpolation

Treatment-specific hierarchy

Build document text and all nine range masks in document space before the common camera transform. Do not place highlights in output/screen space. Keep the document aperture at its own parent, so it transforms with the workspace. Row mask widths are independent numeric controls: a changed line requires a deliberate endpoint check, not a screen-space compensating key.

RootPaper -> ordered root merges -> FinalCrop -> MediaOut
backdrop [rect] -> backdrop_Merge
camera [group] -> camera_Merge
  workspace [group] -> workspace_Merge
    window-paper [rect] -> window-paper_Merge
    tab-strip [rect] -> tab-strip_Merge
    active-tab [rect] -> active-tab_Merge
    tab-title [text] -> tab-title_Merge
    address-bar [rect] -> address-bar_Merge
    address [text] -> address_Merge
    side-paper [rect] -> side-paper_Merge
    brand [text] -> brand_Merge
    brief-box [rect] -> brief-box_Merge
    brief-icon [image] -> brief-icon_Merge
    attachment [text] -> attachment_Merge
    request-box [rect] -> request-box_Merge
    request [text] -> request_Merge
    draft-status [text] -> draft-status_Merge
    document-link [rect] -> document-link_Merge
    document-link-label [text] -> document-link-label_Merge
    response [text] -> response_Merge
    ask-box [rect] -> ask-box_Merge
    ask-placeholder [text] -> ask-placeholder_Merge
    ask-plus [path] -> ask-plus_Merge
    voice-disc [ellipse] -> voice-disc_Merge
    document-heading [text] -> document-heading_Merge
    preview-button [rect] -> preview-button_Merge
    preview-label [text] -> preview-label_Merge
    document [group] -> document_Merge
      document-paper [rect] -> document-paper_Merge
      code [group] -> code_Merge
        pre-number-0 [text] -> pre-number-0_Merge
        pre-line-0 [text] -> pre-line-0_Merge
        pre-number-1 [text] -> pre-number-1_Merge
        pre-line-1 [text] -> pre-line-1_Merge
        pre-number-2 [text] -> pre-number-2_Merge
        pre-line-2 [text] -> pre-line-2_Merge
        pre-number-3 [text] -> pre-number-3_Merge
        pre-line-3 [text] -> pre-line-3_Merge
        pre-number-4 [text] -> pre-number-4_Merge
        pre-line-4 [text] -> pre-line-4_Merge
        pre-number-5 [text] -> pre-number-5_Merge
        pre-line-5 [text] -> pre-line-5_Merge
        pre-number-6 [text] -> pre-number-6_Merge
        pre-line-6 [text] -> pre-line-6_Merge
        pre-number-7 [text] -> pre-number-7_Merge
        pre-line-7 [text] -> pre-line-7_Merge
        range-row-1 [rect] -> range-row-1_Merge
        range-row-2 [rect] -> range-row-2_Merge
        range-row-3 [rect] -> range-row-3_Merge
        range-row-4 [rect] -> range-row-4_Merge
        range-row-5 [rect] -> range-row-5_Merge
        range-row-6 [rect] -> range-row-6_Merge
        range-row-7 [rect] -> range-row-7_Merge
        range-row-8 [rect] -> range-row-8_Merge
        range-row-9 [rect] -> range-row-9_Merge
        row-number-1 [text] -> row-number-1_Merge
        row-text-1 [text] -> row-text-1_Merge
        row-number-2 [text] -> row-number-2_Merge
        row-text-2 [text] -> row-text-2_Merge
        row-number-3 [text] -> row-number-3_Merge
        row-text-3 [text] -> row-text-3_Merge
        row-number-4 [text] -> row-number-4_Merge
        row-text-4 [text] -> row-text-4_Merge
        row-number-5 [text] -> row-number-5_Merge
        row-text-5 [text] -> row-text-5_Merge
        row-number-6 [text] -> row-number-6_Merge
        row-text-6 [text] -> row-text-6_Merge
        row-number-7 [text] -> row-number-7_Merge
        row-text-7 [text] -> row-text-7_Merge
        row-number-8 [text] -> row-number-8_Merge
        row-text-8 [text] -> row-text-8_Merge
        row-number-9 [text] -> row-number-9_Merge
        row-text-9 [text] -> row-text-9_Merge
        post-number-0 [text] -> post-number-0_Merge
        post-line-0 [text] -> post-line-0_Merge
        post-number-1 [text] -> post-number-1_Merge
        post-line-1 [text] -> post-line-1_Merge
        post-number-2 [text] -> post-number-2_Merge
        post-line-2 [text] -> post-line-2_Merge
        post-number-3 [text] -> post-number-3_Merge
        post-line-3 [text] -> post-line-3_Merge
        post-number-4 [text] -> post-number-4_Merge
        post-line-4 [text] -> post-line-4_Merge
        post-number-5 [text] -> post-number-5_Merge
        post-line-5 [text] -> post-line-5_Merge
        post-number-6 [text] -> post-number-6_Merge
        post-line-6 [text] -> post-line-6_Merge
        post-number-7 [text] -> post-number-7_Merge
        post-line-7 [text] -> post-line-7_Merge
        post-number-8 [text] -> post-number-8_Merge
        post-line-8 [text] -> post-line-8_Merge
        post-number-9 [text] -> post-number-9_Merge
        post-line-9 [text] -> post-line-9_Merge
        post-number-10 [text] -> post-number-10_Merge
        post-line-10 [text] -> post-line-10_Merge
        post-number-11 [text] -> post-number-11_Merge
        post-line-11 [text] -> post-line-11_Merge
        post-number-12 [text] -> post-number-12_Merge
        post-line-12 [text] -> post-line-12_Merge
        post-number-13 [text] -> post-number-13_Merge
        post-line-13 [text] -> post-line-13_Merge
      range-action [group] -> range-action_Merge
        action-shadow [rect] -> action-shadow_Merge
        action-paper [rect] -> action-paper_Merge
        action-plus [path] -> action-plus_Merge
        action-label [text] -> action-label_Merge
      selection-pointer [path] -> selection-pointer_Merge
    chrome-dot-0 [ellipse] -> chrome-dot-0_Merge
    chrome-dot-1 [ellipse] -> chrome-dot-1_Merge
    chrome-dot-2 [ellipse] -> chrome-dot-2_Merge

Animated controls

Every static numeric/text/shape control remains in guide.json.fusionNodes; this short table lists animated controls only. The complete raw key arrays and per-frame values are in the guide and CSVs.

Layer.property Keys Numeric minimum → maximum
camera.x 8 -616.4 → 0
camera.y 8 -409.4 → 0
camera.scale 8 1 → 1.92
range-row-1.width 2 0.01 → 170
range-row-2.width 2 0.01 → 432
range-row-3.width 2 0.01 → 432
range-row-4.width 2 0.01 → 432
range-row-5.width 2 0.01 → 432
range-row-6.width 2 0.01 → 432
range-row-7.width 2 0.01 → 432
range-row-8.width 2 0.01 → 432
range-row-9.width 2 0.01 → 24
selection-pointer.x 11 84 → 709
selection-pointer.y 11 270 → 516

Differences and acceptance limits

The source syntax coloring and monospaced font are replaced by live proportional Geist and simplified row coloring. Highlight widths, pointer coordinates and camera/easing values are authored. The source has changing glyph-level endpoints; this kit uses nine editable row masks with chosen endpoints. Native text shaping and apparent camera blur remain unvalidated.

The builder has not executed Resolve or reviewed moving candidate output. Archive hashes, schema checks, sampled controls and custom-content preflights cannot validate native antialiasing, Text+ layout, browser shaping, occlusion readability or motion quality. Parent rendering and independent comparison are separate acceptance gates. Source quality remains false until that process explicitly establishes otherwise. No corpus or publication count is changed.

Optional provenance audits may resolve the repo: and accepted-stage: bindings in provenance.json against the retained research archive. Those historical sources are not needed to install, preflight, render or manually construct this public kit, and may never become adaptation inputs.