Skip to content

feat(core): grade groups grade a whole lane from one hf-color-group - #6678

Merged
vanceingalls merged 1 commit into
mainfrom
feat/color-groups
Oct 28, 2026
Merged

vanceingalls merged 1 commit into
mainfrom
feat/color-groups

Conversation

@vanceingalls

Copy link
Copy Markdown
Collaborator

What

A grade group: one inert <hf-color-group id data-color-grading> that any number of video/img/canvas elements join with data-color-group="<id>". It is the picture's twin of audio groups (<hf-audio-group> + data-audio-group): membership lives on the member, the group element is inert (display:contents, injected next to the audio-group style).

Why: a podcast camera is cut into hundreds of clips. Grading the camera means editing one attribute, not hundreds, and the preview follows at once.

How

  • packages/core/src/colorGroups.ts: lookup and the effective grade. A member's own data-color-grading wins over its group's (v1).
  • Runtime (colorGrading.ts): members are found by [data-color-group] as well as [data-color-grading], and every read goes through effectiveColorGrading. The existing observer also watches data-color-group, and treats adding or removing an hf-color-group as a change. A group edit is one refresh(), and WebGL draws only the members on screen.
  • Lint: color_grading_non_media accepts the group element and still validates its JSON.
  • Engine: a group member keeps full-size frames in render, the same as a directly graded video.
  • Docs: a "Grade a whole lane" section in docs/reference/color-grading.mdx, plus the lint rule text.

Tests

  • core: 5535 passed in full, including 11 new module tests and 6 new runtime ones. Each new test was checked to fail when its code is broken on purpose.
  • CLI Chromium test: all 50 <img> members repaint after one edit of the group's grading.
  • lint 1227, parsers 1371, engine shown-boxes browser test and injector unit tests all pass. Typecheck passes in core, parsers, lint, engine and cli.

Limits

  • The watcher is on body, so a group placed in <head> is not watched.
  • Studio's property panel still reads only a clip's own attribute.
  • media-treatment cannot write a group's grade yet.

🤖 Generated with Claude Code

@mintlify

mintlify Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
hyperframes 🟢 Ready View Preview Oct 28, 2026, 4:02 PM

💡 Tip: Enable Automations to automatically generate PRs for you.

@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Edit accuracy: accurate 271 (base branch 271), smooth 143 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)

@heygengenesis heygengenesis Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Verdict: APPROVE · 0 blocker · 2 important · 0 nits · head a93c183

Required checks are green. The red Comments check isn't required: the comment ratchet flags the new colorGroups.ts at 23% against the package's 12.7%, plus +2 comment lines in runtime/colorGrading.ts and colorGradingContract.ts.

  • important studio-server/src/helpers/freezeFrame.ts:141: COPIED_PICTURE_ATTRS copies data-color-grading but not data-color-group. A freeze frame of a lane clip comes out ungraded inside a graded lane. Add data-color-group to the list.
Scope

Read in full: colorGroups.ts, the runtime selector/observer/read path, the engine shown-boxes change, the lint rule and the new tests. I grepped every data-color-grading reader (bundler LUT rebase/inline, producer scans, plan, freezeFrame, Studio) for group awareness. The Studio property panel and media-treatment gaps are listed in the PR's Limits.

— Claude (Genesis)

* element sharing the id is never read as a lane's grade.
*/
export function resolveColorGroupElement(root: GroupLookupRoot, groupId: string): Element | null {
const el = root?.getElementById(groupId) ?? null;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

important: this resolves the group with a document-wide getElementById. That brings back the collision compiler/mediaRenderIds.ts already fixed for audio groups (AUDIO_GROUP_RENDER_ID_ATTR / busForMember). Ids are only unique per composition file. If two scene files each declare <hf-color-group id="cam-a"> with different grades, every member in the second scene gets the first scene's grade, in preview and in render. measureVideoShownBoxes resolves the same way. Pairing the member with the group in its own [data-composition-id] subtree first (falling back to the first match) would match what audio groups do. The Desktop podcast pages declare one group per camera in one composition, so they aren't affected today.

@vanceingalls
vanceingalls added this pull request to the merge queue Oct 28, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Oct 28, 2026
@vanceingalls
vanceingalls added this pull request to the merge queue Oct 28, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Oct 28, 2026
An inert <hf-color-group> holds a lane's data-color-grading; <video>, <img>
and <canvas> join with data-color-group. A member's own grading overrides
its group's. The runtime discovers members, regrades them when the group's
grading or a member's data-color-group changes, and ungrades them when the
group element or its grading goes, drawing only members on screen.

Render keeps group-graded video at full size like directly graded video,
and lint accepts (and still validates) grading on hf-color-group.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@vanceingalls
vanceingalls merged commit 09b1290 into main Oct 28, 2026
21 of 22 checks passed
@vanceingalls
vanceingalls deleted the feat/color-groups branch October 28, 2026 17:10

This branch was successfully deployed

1 active deployment
staging - docs — 4117d916 Deployed Oct 28, 2026 by mintlify[bot]
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.

1 participant