Skip to content

fix(lint): video and audio take their length from the file, only an img needs data-duration - #4154

Merged
miguel-heygen merged 1 commit into
mainfrom
fix/lint-media-duration-img-only
Sep 19, 2026
Merged

miguel-heygen merged 1 commit into
mainfrom
fix/lint-media-duration-img-only

Conversation

@miguel-heygen

@miguel-heygen miguel-heygen commented Sep 19, 2026

Copy link
Copy Markdown
Collaborator

What changes

media_missing_duration no longer fires for video and audio. Their length comes from the media file when data-duration is absent, so data-start alone is enough. The rule still reports an img that carries data-start or data-track-index and has no data-duration or data-end: an image has no length of its own, and the runtime gives an unresolved image an open end (packages/core/src/runtime/init.ts around line 833; only video and audio are auto-resolved in packages/core/src/compiler/htmlCompiler.ts). A bare img with no timing attributes stays a static layer and is not flagged. The message now says "image".

timeline_element_missing_timing for non-media elements is unchanged.

Verification

  • packages/lint: structure.test.ts and structure.catalog.test.ts pass on a Linux box (15 tests; the catalog test still reports nothing for every registry item and skill example).
  • Fixtures: a timed img without a duration is flagged and passes with one; video and audio with data-start and data-track-index and no duration produce no structure finding; a bare img is not flagged.
  • Deliberate mutations: removing the video/audio exclusion turns 1 test red, removing the img-only gate turns 2 red, removing the img branch turns 1 red.
  • Grepped the repo: the rule id and message are read only by structure.ts and its tests; the Studio lint panel renders findings generically.

Before / After

No visible change: a lint-rule tweak inside packages/lint, with no Studio component, style or markup touched, so there is nothing to capture.

Pre-review

An independent reviewer confirmed the runtime claim at file:line, ran hostile fixtures (uppercase tags, media as a sub-composition host, data-end only, bare, div control) and the three mutations above. No blocking or should-fix findings.

Audited Trusting Not exercised
Runtime resolution of img vs video/audio; other readers of the rule id and docs wording; hostile fixtures; 3 mutations; catalog zero-false-positive sweep Author's Linux-box test runs Studio's image drop default of 3 s (not opened); CLI/Studio end to end

@somanshreddy somanshreddy 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.

Reviewed at 2975f712. The deletion is right for two of the three media tags; for img the premise is only half-verified, so one question before I stamp.

What the rule caught (from the removed tests): a media element that IS a timeline clip (has data-start/data-track-index) but lacks data-durationmedia_missing_duration — while a static <img> with no timing attrs was already exempt. So this is specifically about timeline-clip media with no length.

Right to remove for video/audio. They resolve to their intrinsic file length at render when data-duration is absent, and the lint is static so it can't know that length anyway — flagging them was a false positive. No concern.

img is where the premise doesn't fully hold, as far as I can confirm. The comment cites a "dropped-image default for img," but the only default I can find — DEFAULT_TIMELINE_ASSET_DURATION — lives in packages/studio/src/utils/studioHelpers.ts, i.e. it's applied when Studio adds a clip (it writes data-duration), not by core at render. I couldn't locate a core/render default that gives a bare, hand-or-agent-authored <img data-start="0"> (no data-duration) a length. If there isn't one, then removing the rule drops the guard for exactly the case it was built for: an agent adds an image clip (start set), forgets the duration, and there's no nudge — the image then renders with whatever core's no-duration fallback is (historically "stays to the end of the composition").

Question before stamp: does core/render give a timeline-clip <img> (data-start, no data-duration) a default length, or is that Studio-add-only?

  • If core defaults it → premise holds, delete away, I'll approve.
  • If it's Studio-only → consider scoping the removal to video/audio and keeping media_missing_duration for img, since that's the one type with no render default and the one an agent is most likely to under-specify.

(I searched rather than assume, but didn't exhaustively trace core's timing resolver — if you can point at the render-side img default I'll happily flip.)

Codex disabled per workspace cap — manual pass only.

@miguel-heygen
miguel-heygen force-pushed the fix/lint-media-duration-img-only branch from 2975f71 to 03818e8 Compare September 19, 2026 08:15
@miguel-heygen miguel-heygen changed the title fix(lint): delete media_missing_duration, media gets a default length fix(lint): video and audio take their length from the file, only an img needs data-duration Sep 19, 2026

@somanshreddy somanshreddy 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.

Re-reviewed at 03818e86. The narrowing is exactly right — thanks for scoping it. Holding only for the current CI run to settle (the reds shown are superseded, not real).

Narrowing verified — my earlier finding is fully addressed:

  • FILE_LENGTH_TAGS = new Set(["video", "audio"]) — those are excluded from the missing-duration check (their length comes from the file / the compiler probes it), so media_missing_duration no longer fires on video/audio.
  • img keeps the rule: isImage = row.tag === "img" still emits media_missing_duration with the sharpened message "an image on the timeline without data-duration, and an image has no length of its own," and the static-layer exemption is now img-specific. So a bare-authored image clip is still nudged toward an explicit duration until the runtime gives it the dropped-image default — which is the sequencing #4144's note calls out.

CI is settling, and the reds aren't real: the Test/Producer/Tests on windows-latest fails are 0-duration — superseded/cancelled by the newer run (the exact misleading-cancelled-red that #4149 is built to hide). The current run's Test/studio-core/Typecheck/Producer: unit tests are pending. For a lint PR the Test job (runs structure.test.ts) is the content-validating check, so I'll flip to approve once it lands green on the current run rather than stamp over a pending run whose 0s predecessors were cancelled.

Code-wise this is an approve. Re-ping me or I'll flip when the current Test is green.

Codex disabled per workspace cap — manual pass only.

@somanshreddy somanshreddy 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.

Flipping to APPROVE at 03818e86 — the current run's Test is green and the narrowing is exactly right.

  • Narrowing (my earlier finding, implemented): FILE_LENGTH_TAGS = {video, audio} are excluded (length from the file / the compiler probes it); img keeps media_missing_duration ("an image has no length of its own") until the runtime gives images the dropped-image default. Correct scoping.
  • Test is green on the current run (35431494108, 5m56s full pass — it runs structure.test.ts, the content-validating check for this lint change), plus Test: runtime contract green.
  • The two remaining red rows (Tests on windows-latest: matrix, Producer: matrix) are 0-duration matrix-parents from the older, superseded runs (35431494007 / 35431493958) that were cancelled when the current run started — the misleading-cancelled-red #4149 is built to hide. Not real failures at this head.

merge is BLOCKED only on REVIEW_REQUIRED. Approving.

Codex disabled per workspace cap — manual pass only.

@miguel-heygen
miguel-heygen merged commit 17b0c26 into main Sep 19, 2026
49 of 81 checks passed
@miguel-heygen
miguel-heygen deleted the fix/lint-media-duration-img-only branch September 19, 2026 08:47
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