Skip to content

feat(check): add data-layout-allow-caption-zone waiver - #2853

Merged
xuanruli merged 4 commits into
mainfrom
xuanru/caption-zone-allow-waiver
Jul 28, 2026
Merged

xuanruli merged 4 commits into
mainfrom
xuanru/caption-zone-allow-waiver

Conversation

@xuanruli

Copy link
Copy Markdown
Contributor

Summary

  • Add data-layout-allow-caption-zone so intentional lower-third text can opt out of --caption-zone / caption_zone_collision (element or ancestor via closest).
  • Mirror the skip in geometry candidate collection and in captionFinding (for mocked candidates).
  • One-line docs in CLI reference + data-attributes skill.

Test plan

  • bun run test -- src/commands/check.test.ts -t 'allow-caption|caption band|caption zone'
  • bun run test -- src/commands/layout-audit.browser.test.ts -t 'allow-caption|caption layers'
  • Manual: hyperframes check --caption-zone=... on a fixture with/without the attr

Made with Cursor

Opt intentional lower-third copy out of caption_zone_collision.

Co-authored-by: Cursor <[email protected]>
@mintlify

mintlify Bot commented Jul 28, 2026

Copy link
Copy Markdown

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

Project Status Preview Updated (UTC)
hyperframes 🟢 Ready View Preview Jul 28, 2026, 7:43 PM

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

@james-russo-rames-d-jusso james-russo-rames-d-jusso left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Reviewed at 37c5ea8.

Small, sharp addition — data-layout-allow-caption-zone slots cleanly next to the existing three waivers and both defense layers (browser candidate filter + pipeline captionFinding skip) are wired up. Tests cover own-element (pipeline) + ancestor (browser) placement. No blockers.

Three lens-level concerns / nits on the inline comments below, plus one question:

Question — presence semantics. .closest("[data-layout-allow-caption-zone]") and "data-layout-allow-caption-zone" in candidate.dataAttributes both treat data-layout-allow-caption-zone="false" as still-suppressing. Consistent with the other three data-layout-allow-* waivers, so probably intended — flagging only in case you'd prefer explicit falsy values to un-suppress.

What I didn't verify:

  • Any downstream layout skill / template file that lists the four current waivers by name would need this new entry appended too. Grepped the CLI repo — only the two doc files above reference these attrs. If the parent HeyGen mono has any consumer of this skill's attribute vocabulary, worth a follow-up sweep.

— Review by Rames D Jusso

cx <= zone.x1 * canvas.width &&
cy >= zone.y0 * canvas.height &&
cy <= zone.y1 * canvas.height;
if ("data-layout-allow-caption-zone" in candidate.dataAttributes) return null;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Concern — pipeline guard is redundant in prod, and asymmetric with the browser filter.

Under real runtime, all geometry candidates arrive from __hyperframesGeometryCandidates in the browser, which already excludes elements matching element.closest("[data-layout-allow-caption-zone]") from the text-candidate stream (browser.js:1402). By the time a candidate reaches captionFinding, a real-DOM waiver has already been stripped, so this guard is a no-op in prod — the only path that exercises it is the direct-mock test at check.test.ts:451 (which passes dataAttributes bypassing the browser filter entirely).

Also note the asymmetry: the browser filter uses .closest() (element OR any ancestor), while this check inspects only the candidate's own dataAttributes. That's fine while the browser is the sole candidate producer, but if a future non-DOM candidate source (fixture loader, cached-golden replay, batched cross-frame path) ever feeds the pipeline, ancestor-scoped waivers won't propagate through here.

Suggestion: a one-line comment above this guard noting it's defense-in-depth for test mocks / non-browser candidate sources would help the next reader understand why both layers exist. No code change required.

— Rames D Jusso

if (
includeText &&
hasOwnTextCandidate(element, true) &&
!element.closest("[data-layout-allow-caption-zone]")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Nit — inline .closest() diverges from the helper convention used by sibling waivers.

The three sibling waivers all sit behind small named predicates:

  • data-layout-ignore → line ~101 (isElementIgnored-shape helper)
  • data-layout-allow-overflow → line 105
  • data-layout-allow-overlap → line 544
  • data-layout-allow-occlusion → line 867

The new attribute inlines !element.closest("[data-layout-allow-caption-zone]") at the call site. One usage is fine as-is, so this is a soft nit — but if you're anticipating more usages (e.g. gating other geometry findings on the same waiver, or adding a symmetric browser-side hasOwnMediaCaptionZone branch later), a isCaptionZoneExempt(element) helper next to the other three keeps the pattern uniform and makes future additions cheap.

— Rames D Jusso

- In a multi-scene `group_wN.html` (continue runs), every scene-local element stays in the DOM during the other scenes' time windows; the layout-box union almost always overflows the canvas during morph seams. Mark the root and every scene-local primary/supporting element with this attribute **at construction**, not after `check` flags it.
- **Blast radius — it silences more than the overflow audit.** The attribute is inherited down the subtree (the perception probe walks ancestors), so it also suppresses the rendered-perception checks `text-clipping`, `content-cramped-container`, and `foreground-over-panel` for every descendant. Putting it on a persistent panel that also hosts real foreground content disables collision checks on that content for the panel's whole lifetime. Prefer the narrowest opt-out: scope it to the smallest decorative wrapper, or use per-element `data-layout-bleed="true"` for one intentional primary-text crop. The two canvas/edge checks `primary-offscreen` and `foreground-over-panel` deliberately run **even under** allow-overflow, so it cannot hide a wordmark sliced by the frame or text bleeding onto a panel edge.
- `data-layout-ignore` — exclude this element from layout audits entirely.
- `data-layout-allow-caption-zone` — opt out of `--caption-zone` / `caption_zone_collision` for intentional lower-third copy (element or ancestor).

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Concern — one-liner is missing the blast-radius framing that the other waivers have.

Compare against the data-layout-allow-overflow entry a few lines up (line 58) which walks through inheritance semantics + what's silenced vs what deliberately still fires. The new attribute:

  • Inherits down the subtree via element.closest("[data-layout-allow-caption-zone]"), so placing it on a wrapper <div> silences caption-zone checks for every descendant.
  • Silences only caption_zone_collision — the other layout audits (data-layout-* overflow / overlap / occlusion / clipping / bleed / etc.) all still run on marked elements.

Both of those are the intended contract, but a user reading this line wouldn't know either. A two-clause sentence would fix it — e.g. "…for intentional lower-third copy (applies to the element and every descendant via closest; does not suppress overflow, overlap, or occlusion checks — pair with those attributes if you need to silence multiple audits)."

— Rames D Jusso

@miguel-heygen miguel-heygen 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.

Reviewed at exact head 37c5ea84a76e87a06064800aae8451bab80bd577.

The runtime implementation is narrow and correct: the browser guard removes only caption-zone text candidates, media/frame candidates still flow, and the pipeline backstop returns only from captionFinding, leaving overlap, occlusion, overflow, and contrast untouched. Direct, ancestor, unmarked, and mocked-candidate paths are meaningful; the two focused suites pass 127/127. Typecheck, oxlint, formatting, and manifest validation also pass locally, and exact-head CI is fully green.

One important agent-contract gap remains:

skills/hyperframes-cli/references/lint-validate-inspect.md:55-69 is the mandatory reference for agents running hyperframes check, but it still lists only the existing overflow/overlap/occlusion/ignore escape hatches and documents --caption-zone without the new waiver. A validation/diagnosis request routes directly to /hyperframes-cli; that agent is not required to load the updated hyperframes-core/references/data-attributes.md, so it cannot discover data-layout-allow-caption-zone and may move intentional lower-thirds instead of applying the sanctioned waiver.

Please add the new escape hatch to that CLI reference, including element/ancestor inheritance and narrowest-wrapper blast-radius guidance, then regenerate skills-manifest.json so the hyperframes-cli hash advances as well. The current manifest is mechanically in sync; the missing source reference is the issue.

No other blockers found.

@xuanruli

Copy link
Copy Markdown
Contributor Author

Addressed the three inline notes:

  1. One-line comment on the pipeline dataAttributes guard (mock/backstop; browser uses closest, pipeline only sees own attrs).
  2. Browser filter now goes through hasAllowCaptionZoneFlag next to the sibling waiver helpers.
  3. data-attributes.md now covers ancestor blast radius and that this attr only silences caption_zone_collision.

@xuanruli

Copy link
Copy Markdown
Contributor Author

Added data-layout-allow-caption-zone to skills/hyperframes-cli/references/lint-validate-inspect.md (escape hatch + --caption-zone paragraph) with element/ancestor + narrowest-wrapper guidance, and regenerated skills-manifest.json so the CLI skill hash advances.

@miguel-heygen miguel-heygen 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.

Re-reviewed at exact head b57eec30954093c76a32477ec0c474aad1ccfcc5.

The original blocker is closed: the mandatory /hyperframes-cli check reference now documents the waiver, ancestor inheritance, narrowest-wrapper guidance, and single-audit blast radius; both hyperframes-cli and hyperframes-core manifest hashes advance and the manifest validates. The helper extraction and pipeline-backstop comment also resolve the earlier nits.

Runtime and tests remain clean. The focused browser + pipeline suites pass 127/127; CLI typecheck, oxlint, oxfmt, manifest validation, and exact-head CI are green.

One fresh P2 docs-contract issue surfaced in the R2 pass:

docs/packages/cli.mdx:615 adds data-layout-allow-caption-zone inside the deprecated inspect section, but the waiver belongs to the opt-in check --caption-zone gate documented at lines 548-551. inspect has no --caption-zone flag, so a reader following the new sentence from that section cannot exercise the feature it describes, while the active check section never tells them the waiver exists.

Please move the new caption-zone sentence into the check section immediately after the --caption-zone flag/table guidance (or duplicate it there and make the deprecated section explicitly point to check). State the same element/ancestor and caption-only blast-radius contract used in the CLI skill. The existing overflow/overlap/occlusion sentences can remain under inspect; only the new caption-zone guidance is misplaced.

No runtime blockers found.

@xuanruli

Copy link
Copy Markdown
Contributor Author

Moved data-layout-allow-caption-zone out of deprecated inspect into the active check section (element/ancestor via closest, caption-only scope, narrowest-wrapper). Inspect now points at check for that attr.

New head: f3f33aab5964c84e38a0b11a35739f230e8bb679 — ready for re-review.

@miguel-heygen miguel-heygen 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.

Re-reviewed at exact head f3f33aab5964c84e38a0b11a35739f230e8bb679.

The R2 docs blocker is closed. The active check section now owns the waiver contract immediately beside --caption-zone: element-or-ancestor inheritance via closest, suppression limited to caption_zone_collision, explicit non-suppression of overflow/overlap/occlusion/contrast, and narrowest-wrapper guidance. The deprecated inspect section now points readers back to check instead of presenting the feature as an inspect capability.

The delta from the prior reviewed head is docs-only. The runtime/browser/pipeline implementation and focused 127-test evidence remain unchanged. On this exact head, the schema mirror is in sync, mint validate passes, and mint broken-links reports no broken links. Fresh CI is still running, so merge remains correctly gated by the required checks.

No blockers remain. Approved.

@xuanruli
xuanruli merged commit 3a7950f into main Jul 28, 2026
47 checks passed
@xuanruli
xuanruli deleted the xuanru/caption-zone-allow-waiver branch July 28, 2026 22:56
dahans-msft2 pushed a commit to dahans-msft2/hyperframes that referenced this pull request Aug 6, 2026
* feat(check): add data-layout-allow-caption-zone waiver

Opt intentional lower-third copy out of caption_zone_collision.

Co-authored-by: Cursor <[email protected]>

* fix(check): address caption-zone waiver review nits

Co-authored-by: Cursor <[email protected]>

* docs(skills): document caption-zone waiver on CLI agent path

Co-authored-by: Cursor <[email protected]>

* docs(cli): document caption-zone waiver under check, not inspect

Co-authored-by: Cursor <[email protected]>

---------

Co-authored-by: Cursor <[email protected]>

This branch was successfully deployed

1 active deployment
staging - docs — f3f33aab Deployed Jul 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.

3 participants