feat(studio): motion assets — video intro, tightened pack gate, ning-hongye - #9
Merged
Conversation
Wangnov
marked this pull request as ready for review
July 18, 2026 12:50
…gate - theme.json gains an additive motionAssets map (mp4/webm); videos skip CSS variables and ride a dedicated __CTS_MOTION_JSON__ slot into a runtime-mounted muted <video> with static-intro fallback, honoring prefers-reduced-motion and playback-failure recovery. - pack gate now enforces the delivery contract end to end: canonical semver, description/author/license, WebP-only previews and assets within Codex App Manager budgets (1.4MB each / 24MB combined), native codexTheme validation with codex-theme-v1 round-trip when present, runtime-consumed motion keys only, intro-video requiring a static intro, and the 50MB archive cap checked post-zip. - start gains --appearance (dark|light|system) to override the native appearanceTheme; codex-theme-schema.mjs ports the canonical validator.
Recompress all 28 PNG assets to WebP (19.8MB -> 6.1MB, every file under the 1.4MB manager budget), lift delivery metadata out of the legacy nested metadata block to the top level, and bump to 1.2.1 so existing installs pick up the recompressed package. REGISTRY now tracks the real manifest version.
宁红夜 — 赤练无明: dual-appearance Naraka skin and the first user of motionAssets, shipping a 7.1MB intro video with a static intro fallback for non-motion hosts. Verified on Codex 26.715.21425.
- ning-hongye chrome.html mounted cts-spirit-orbit while every layout, badge and dark-shell rule targets .cts-serpent-orbit — unify on the latter so the orbit ring and crest render; the late crimson border override is renamed with it and still wins in order. - motion.test.mjs resolves the runtime template via fileURLToPath so the suite survives checkouts under paths containing spaces.
…ailure - a stamp change now tears down a still-playing intro so theme switches never leave the old video running or block the new theme's intro; same-stamp re-ensures still leave it untouched. - every video failure path (error event, play rejection, play throw) remounts the intro from scratch so the static fallback restarts its animation timeline instead of landing in an expired forwards state. - the loader rejects motion keys that shadow a static asset — the merged data-URL namespace would otherwise silently drop the CSS variable.
- fallbackToStatic now runs at most once and only while it still owns the live #cts-intro and the runtime is not disabled — a hot switch or off rejects the pending play() with AbortError, and the stale closure must not tear down (or resurrect over) the next theme's intro. - assertInside rejects absolute manifest paths outright: they can resolve inside the dev checkout and pack fine, but the manifest ships verbatim and the package would fail to load anywhere else.
- applyNativeTheme now inserts appearanceTheme before the first TOML table when the key is absent (previously the merge silently no-opped on configs that never set it), and restoreNativeTheme deletes the key when the pristine baseline had none — apply/restore stay symmetric. - validateCodexTheme accepts an omitted fonts.code/ui as 'keep the Codex default' (same as null), and the share string normalizes the omission to an explicit null so both spellings serialize identically. loadTheme() calling the validator no longer rejects such themes.
Codex reads appearanceTheme from the [desktop] table; the old top-level regex kept editing a stale root-level copy on real configs. Backup, apply and restore now all operate on the [desktop]-scoped key: replace in place, insert into (or create) the table when absent, and delete on restore when the pristine baseline had none — stray root-level copies stay untouched. Null/omitted fonts are skipped by the TOML writer instead of being written as the literal string "null".
Wangnov
force-pushed
the
feat/studio-motion-intro
branch
from
July 18, 2026 12:54
73aab30 to
748b3e6
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 73aab30840
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three stacked pieces that land the video intro capability end to end:
feat(studio)—motionAssetssupport ported from the design workbench onto the post-fix(studio): adapt Composer across Codex 26.715 builds #6 composer architecture (SPEC 1.1, §2a):__CTS_MOTION_JSON__slot into a runtime-mounted muted<video>; staticintroart stays as the fallback;prefers-reduced-motionskips entirely; playback failure recovers to static.codexThemewithcodex-theme-v1round-trip, runtime-consumed motion keys only,intro-video⇒ staticintrorequired, and the 50MB archive cap post-zip.start --appearance dark|light|system;codex-theme-schema.mjscanonical validator; +6 motion tests (34 total).fix(skins)—rem-rezeromodernized for the tightened gate: 28 PNGs → WebP (19.8MB → 6.1MB, all under the 1.4MB budget), delivery metadata lifted out of legacymetadata, bumped to 1.2.1 so existing installs fetch the recompressed pack.feat(skins)— 宁红夜 — 赤练无明 (ning-hongye-crimson-night, games): first video-intro skin, 7.1MB opening video + full static fallback, verified on Codex 26.715.21425.Compatibility
motionAssetsis additive: current Codex App Manager imports the pack fine and keeps the full static experience (manifest extraction is lenient; the mp4 is simply unused). Manager-side playback lands separately.Verification
npm run check+npm test: 34/34codex reviewrounds; all findings fixed (incl. a pre-existingserpent-orbitclass break in the skin and a space-safe test path)Note
Merging to main auto-publishes to the R2 catalog. If #8 (second-wave skins) merges first, this branch needs a trivial REGISTRY rebase (adjacent-line additions).