From 7e58d050f8923d1f50e2da7fb1f77a65963715a0 Mon Sep 17 00:00:00 2001 From: Via Date: Thu, 16 Jul 2026 06:52:11 +0000 Subject: [PATCH] fix(fallow): resolve audit findings for portrait --resolution PR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three findings, all resolved: - packages/producer/src/server.ts `render` (CRAP 31.6, cyclo 10 — minor): pre-existing complexity; the PR only threads `outputResolutionAspectAgnostic` through parseRenderOverrides / RenderInput and does not touch `render`. Line-shift fingerprint — exempted via health.ignore with justification comment. - packages/producer/src/services/distributed/plan.ts `plan` (CRAP 36.7, cyclo 33 — major): pre-existing complexity; the PR only adds one optional field spread inside `plan` and does not add branches. Line-shift fingerprint — exempted via health.ignore with justification. - packages/producer/src/services/render/stages/compileStage.ts `runCompileStage` (cyclo 23, cognitive 19 — minor): this one is a real complexity bump from the two-branch aspect-agnostic re-target block added in the fix. Extracted the block into a local helper `adaptAspectAgnosticResolution` so `runCompileStage` stays under both the cyclomatic (20) and cognitive (15) thresholds. Verified locally with `fallow audit --base origin/main --fail-on-issues` (exit 0, "No GitHub PR/MR findings") and `tsc --noEmit` on the producer package. Co-Authored-By: Claude — Via --- .fallowrc.jsonc | 12 ++++ .../services/render/stages/compileStage.ts | 69 ++++++++++++------- 2 files changed, 55 insertions(+), 26 deletions(-) diff --git a/.fallowrc.jsonc b/.fallowrc.jsonc index d0ccbb4ab..14efceac6 100644 --- a/.fallowrc.jsonc +++ b/.fallowrc.jsonc @@ -743,6 +743,18 @@ // work on this same branch (commits 444639d75, b57b31beb, 6f2e9848c, // eba8a0fa2), unrelated to the Grade group (Plan 5) currently landing. "packages/studio/src/components/editor/propertyPanelSections.tsx", + // Portrait --resolution alias fix (via/resolution-portrait-fix): + // server.ts `render` (cyclo 10 / CRAP 31.6) and distributed/plan.ts + // `plan` (cyclo 33 / CRAP 36.7) are both pre-existing complexity — + // the PR only threads `outputResolutionAspectAgnostic` through the + // parseRenderOverrides/RenderInput/DistributedRenderConfig shape and + // adds one field spread inside `plan`. Neither function body gained + // branches, but the line-shift fingerprint re-flags the inherited + // complexity. The new re-target logic itself is extracted into + // `adaptAspectAgnosticResolution` in compileStage.ts to keep that + // stage's runCompileStage under the cyclo/cognitive thresholds. + "packages/producer/src/server.ts", + "packages/producer/src/services/distributed/plan.ts", ], }, } diff --git a/packages/producer/src/services/render/stages/compileStage.ts b/packages/producer/src/services/render/stages/compileStage.ts index 5b21886a3..cf3f13995 100644 --- a/packages/producer/src/services/render/stages/compileStage.ts +++ b/packages/producer/src/services/render/stages/compileStage.ts @@ -37,7 +37,7 @@ import { join } from "node:path"; import type { EngineConfig } from "@hyperframes/engine"; -import { suggestMatchingPreset } from "@hyperframes/core"; +import { suggestMatchingPreset, type CanvasResolution } from "@hyperframes/core"; import type { CompiledComposition } from "../../htmlCompiler.js"; import { compileForRender } from "../../htmlCompiler.js"; import type { ProducerLogger } from "../../../logger.js"; @@ -110,6 +110,41 @@ export interface CompileStageResult { deCompileGate?: string; } +/** + * Aspect-agnostic aliases (`--resolution 1080p` / `hd` / `4k` / `uhd`) all + * normalize to a landscape preset up-front (see `normalizeResolutionFlag`), + * which was historically fine because 16:9 was the only shipped orientation. + * Once portrait + square presets landed, that early normalization started + * rejecting portrait/square compositions with a cryptic "aspect ratio does + * not match" from `resolveDeviceScaleFactor` — a common enough hit that a + * field report (CLI 0.7.59) surfaced it. When the flag was aspect-agnostic, + * re-target the preset to the sibling that matches the composition's + * orientation while preserving the tier (HD vs 4K). Explicit + * orientation-bearing presets stay strict — a `--resolution portrait` on a + * landscape composition still errors, honoring the user's stated intent. + * + * Extracted so `runCompileStage` keeps its complexity envelope tight; the + * two-branch shape lives here. + */ +function adaptAspectAgnosticResolution( + requested: CanvasResolution | undefined, + aspectAgnostic: boolean | undefined, + width: number, + height: number, + log: ProducerLogger, +): CanvasResolution | undefined { + if (!requested || !aspectAgnostic) return requested; + const flipped = suggestMatchingPreset(width, height, requested); + if (!flipped || flipped === requested) return requested; + log.info("Adapted aspect-agnostic --resolution to composition orientation", { + compositionWidth: width, + compositionHeight: height, + requestedResolution: requested, + effectiveResolution: flipped, + }); + return flipped; +} + export async function runCompileStage(input: CompileStageInput): Promise { const { projectDir, @@ -274,31 +309,13 @@ export async function runCompileStage(input: CompileStageInput): Promise