Skip to content

Prefactor: Source Media becomes a discriminated union (source-media issue 01) - #11

Merged
lenxism merged 2 commits into
mainfrom
source-media/01-source-media-union
Jul 13, 2026
Merged

Prefactor: Source Media becomes a discriminated union (source-media issue 01)#11
lenxism merged 2 commits into
mainfrom
source-media/01-source-media-union

Conversation

@lenxism

@lenxism lenxism commented Jul 13, 2026

Copy link
Copy Markdown
Owner

Summary

  • The store's ephemeral media record becomes a SourceMedia discriminated union on kind (image | video) per ADR-0026; the video variant carries the intrinsic duration and the canDecode decodability verdict later video tickets consume, though nothing constructs it yet.
  • All existing image paths flow through the union unchanged: drop/paste/picker loaders tag kind: 'image', the texture hook accepts the union (resolving only the image kind), aspect math and object-URL revocation are kind-agnostic. Store actions renamed to setSourceMedia / clearSourceMedia.
  • Adds the ADR-0026 vocabulary docs (Source Media supersedes ADR-0014's image-only phrasing) and a store-seam lifecycle test (src/state/source-media.test.ts, red→green).

Test plan

  • New source-media.test.ts covers binding each kind and URL revocation on replace / clear / start-over
  • Existing serialization stripping tests still pass (Source Media never serialized)
  • typecheck, lint, build, and the full Vitest suite green locally

Note

Low Risk
Mostly types, renames, and docs; image upload and rendering behavior unchanged, with new store tests covering URL lifecycle for both kinds.

Overview
Introduces Source Media as the umbrella for ephemeral screen input (still Source Image or future Source Video), documented in ADR-0026 (superseding ADR-0014) and CONTEXT.md / architecture invariants. The render contract is phrased as f(SceneDocument, SourceMedia); pixels stay out of the document while mapping (Fit, crop) remains document.

The editor store’s media field becomes a kind-discriminated union: images add kind: 'image'; the video variant adds duration and canDecode for later tickets (no user-facing video import yet). Actions are renamed to setSourceMedia / clearSourceMedia; object-URL revocation on replace, clear, and Start over is kind-agnostic. Image loaders, dropzone, demo boot, and useSourceImageTexture accept the union but still resolve only kind === 'image' (video shows the placeholder until preview lands).

Adds src/state/source-media.test.ts for binding and lifecycle; serialization test smuggled payload now includes kind: 'image'.

Reviewed by Cursor Bugbot for commit d65081d. Bugbot is set up for automated code reviews on this repo. Configure here.

…ssue 01)

The store's ephemeral media record is now a SourceMedia union on `kind`
(image | video) per ADR-0026 — the video variant carries the intrinsic
duration and decodability verdict the video tickets need, though nothing
constructs it yet. Import paths, the texture hook, aspect math, and
object-URL revocation all flow through the union; zero behavior change.
Includes the ADR-0026 vocabulary docs the union is named after.
@vercel

vercel Bot commented Jul 13, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
mockstudio Ready Ready Preview, Comment Jul 13, 2026 6:47pm

@cursor cursor Bot 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.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 7bee833. Configure here.


useEffect(() => {
if (!media) {
if (media?.kind !== 'image') {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Video aspect uses placeholder

Medium Severity

When bound SourceMedia is kind: 'video', useSourceImageTexture falls back to the placeholder aspect for buildSceneSpec, while useArtboardAspect in Viewport still derives aspect from media.naturalWidth / naturalHeight. Once video is bound, "auto" frame sizing and artboard letterboxing can disagree.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 7bee833. Configure here.

The two crop round-trip tests reference `image.crop`, which lands with
issue 02's Scene Document v5 — committing them here without the schema
half broke typecheck in CI. They return with the crop schema change.
@lenxism
lenxism merged commit c86084d into main Jul 13, 2026
4 checks passed
@lenxism
lenxism deleted the source-media/01-source-media-union branch July 13, 2026 19:01
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