Skip to content

refactor(core): one owner for the distributed fps set - #5756

Merged
miguel-heygen merged 1 commit into
mainfrom
cloudrender/fps-owner
Oct 17, 2026
Merged

miguel-heygen merged 1 commit into
mainfrom
cloudrender/fps-owner

Conversation

@miguel-heygen

Copy link
Copy Markdown
Collaborator

What changed

The integer frame rates the distributed renderer (Lambda, Cloud Run) accepts were written out by hand in about 25 places: type unions, runtime checks, error messages, CLI help, harness gates and a test's own copy. Adding 25 in #5423 had to touch 28 files and still missed a few. They now come from one owner in @hyperframes/core, next to Fps:

export const DISTRIBUTED_FPS = [24, 25, 30, 60] as const;
export type DistributedFps = (typeof DISTRIBUTED_FPS)[number];
export function isDistributedFps(value: unknown): value is DistributedFps;
  • producer: config validation, the plan v2 manifest reader, render request mapping, plan types and the parity and regression harnesses use the owner. Error messages are built from the constant.
  • aws-lambda / gcp-cloud-run: the plan result Fps field derives from SerializableDistributedRenderConfig["fps"].
  • cli: lambda and cloudrun checks, --fps help text and the data-fps default read the owner. readAllowedCompositionFpsFromDir no longer takes an allowed list. Its test passed [24, 30, 60], a stale copy without 25.
  • engine: EngineConfig.fps and the snapshot validator still said 24 | 30 | 60, so a distributed render that passed an engine config snapshot with fps 25 was refused. They now use the owner.

Core is the owner because it already owns Fps, and the CLI bundles it, as do engine and producer. The adapters see it through producer's types. No new dependency edges.

Error wording changes from "must be 24, 25, 30, or 60" to "must be one of 24, 25, 30, 60".

What I measured

Ran each changed or covering test file on its own, with exit codes:

File Result
core parseFps.test.ts (new isDistributedFps cases) exit 0
engine config.test.ts (new snapshot fps cases) exit 0
cli compositionFps.test.ts (new 25 fps case) exit 0
producer plan-parity-harness, planV2, regression-harness-distributed, renderRequest, regression-shard-plan exit 0, 6 / 62 / 18 / 20 / 21 pass, 0 fail
aws-lambda validateConfig, renderToLambda exit 0, 36 / 11 pass
gcp-cloud-run validateConfig, renderToCloudRun exit 0, 18 / 8 pass

tsc --noEmit is clean in core, engine, producer, cli, aws-lambda and gcp-cloud-run.

Mutations:

  • Owner changed to [24, 30, 60, 50]: all 13 files above fail, which shows every consumer reads the owner.
  • Engine enum put back to the literal [24, 30, 60]: only "accepts every distributed fps, including 25" fails.

What I did NOT exercise

  • No cloud render. This is a type and validation refactor; the render path is unchanged.
  • Studio's local render settings still offer 24 / 30 / 60. That is the in-process renderer, not the distributed set, so it stays out of this PR.
  • The CLI still falls back to 30 without a warning when data-fps is outside the set (for example 50 or 30000/1001). That is a behaviour change and gets its own PR.

The integer rates Lambda and Cloud Run accept were written out by hand in
about 25 places across core, engine, producer, the adapters and the CLI.
They now come from DISTRIBUTED_FPS / DistributedFps / isDistributedFps in
@hyperframes/core. Engine config snapshots accept 25 like the rest.
@github-actions

Copy link
Copy Markdown
Contributor

Edit accuracy: accurate 271 (base branch 271), smooth 166 of those

The gate passes.
Smoothness is reported in the artifact, not gated. A case fails only if it fails 2 of 3 runs.

Quarantined, measured but not gated (0)

Unstable (1)

  • crop-none-px-r0-nested-z100: tracking 0.04, pressJump 0, drop 40.07, reload 40.07, render 40.03, renderKey -, undo true, teleport true / tracking 0.04, pressJump 0, drop 0.08, reload 0.08, render 0.03, renderKey -, undo true, teleport true / tracking 0.04, pressJump 0, drop 0.08, reload 0.08, render 0.03, renderKey -, undo true, teleport true

@jrusso1020 jrusso1020 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving at e93b6d78.

One owner for the set. Core's DISTRIBUTED_FPS = [24, 25, 30, 60] and isDistributedFps now back every distributed check:

  • the producer's config validation (its own ALLOWED_FPS copy is gone), planV2, renderRequest and the harnesses
  • the CLI's lambda (render and render-batch), cloudrun and compositionFps
  • the engine's config enum
  • the Lambda and Cloud Run event types, through SerializableDistributedRenderConfig["fps"]

A repo-wide search turns up no other hard-coded distributed fps list in producer, engine, cli, aws-lambda or gcp-cloud-run.

The only behaviour change is the intended engine fix. Before, ENUM_ENGINE_CONFIG_FIELDS.fps was [24, 30, 60], and validateEngineConfigSnapshot runs on every serialized request, so a 25 fps snapshot was refused even though the rest of the distributed path accepted 25. Every other check was already {24, 25, 30, 60}. includes is a strict comparison, so "30", NaN and 29.97 are rejected exactly as the old === chains rejected them. Widening EngineConfig.fps is safe because capture, encode and chunk math all read the rational job.config.fps, never EngineConfig.fps. The engine test loops over all four rates and fails against the old enum.

Non-blocking

  • skills/hyperframes-cli/references/cloudrun.md:25 and lambda.md:87 still list 24/30/60 for the distributed commands, so an agent following the skill would tell a user that 25 isn't supported. The docs pages already say 24, 25, 30, 60.
  • The error text changed from "must be 24, 25, 30, or 60" to "must be one of 24, 25, 30, 60". That only matters to anything outside the repo matching on it.

CI is green. No live run.

— Rames

@miguel-heygen
miguel-heygen added this pull request to the merge queue Oct 17, 2026
Merged via the queue into main with commit d5162be Oct 17, 2026
81 checks passed
@miguel-heygen
miguel-heygen deleted the cloudrender/fps-owner branch October 17, 2026 09:04
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