fix(cli): accept portrait aspects for --resolution alias flag

The aspect-agnostic resolution aliases (`--resolution 1080p` / `hd` / `4k` / `uhd`) previously all normalized to a landscape preset, which rejected portrait 1080x1920 compositions with 'Output resolution incompatible'. Users had to specify the orientation-bearing alias (`1080p-portrait`) or render at native.

This threads two new fields (`outputResolutionAspectAgnostic` + `outputResolutionRaw`) through the render pipeline. At the CLI layer we detect whether the user's flag was an aspect-agnostic alias; at the compile stage we re-map the preset to the composition's orientation via the existing `suggestMatchingPreset` sibling-lookup (formerly private). Explicit orientation-bearing aliases and canonical presets stay strict.

Field signal: ts=1784176662 (darwin/arm64, CLI 0.7.59, `--resolution 1080p` on a 1080x1920 portrait comp).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

— Via
This commit is contained in:
Via
2026-07-16 06:23:14 +00:00
co-authored by Claude
parent 9ed255c0ef
commit 46e9ecf3f2
13 changed files with 460 additions and 15 deletions
+24
View File
@@ -39,6 +39,30 @@ describe("@hyperframes/core public API exports", () => {
expect(core.normalizeResolutionFlag(undefined)).toBeUndefined();
});
it("exports isAspectAgnosticResolutionAlias for tier-only aliases", () => {
// Tier-only aliases → true (orientation follows the composition).
expect(core.isAspectAgnosticResolutionAlias("1080p")).toBe(true);
expect(core.isAspectAgnosticResolutionAlias("hd")).toBe(true);
expect(core.isAspectAgnosticResolutionAlias("4k")).toBe(true);
expect(core.isAspectAgnosticResolutionAlias("uhd")).toBe(true);
// Case-insensitive.
expect(core.isAspectAgnosticResolutionAlias("1080P")).toBe(true);
expect(core.isAspectAgnosticResolutionAlias("UHD")).toBe(true);
// Orientation-suffixed aliases → false (user picked an orientation).
expect(core.isAspectAgnosticResolutionAlias("1080p-portrait")).toBe(false);
expect(core.isAspectAgnosticResolutionAlias("portrait-1080p")).toBe(false);
expect(core.isAspectAgnosticResolutionAlias("4k-square")).toBe(false);
expect(core.isAspectAgnosticResolutionAlias("1080p-square")).toBe(false);
// Canonical presets → false.
expect(core.isAspectAgnosticResolutionAlias("landscape")).toBe(false);
expect(core.isAspectAgnosticResolutionAlias("portrait")).toBe(false);
expect(core.isAspectAgnosticResolutionAlias("landscape-4k")).toBe(false);
// Unknown / empty / undefined → false.
expect(core.isAspectAgnosticResolutionAlias("8k")).toBe(false);
expect(core.isAspectAgnosticResolutionAlias("")).toBe(false);
expect(core.isAspectAgnosticResolutionAlias(undefined)).toBe(false);
});
it("exports TIMELINE_COLORS", () => {
expect(core.TIMELINE_COLORS).toBeDefined();
expect(core.TIMELINE_COLORS.video).toBeDefined();