Repository navigation
fix(suiteui): export-pack finish pass, refused sizes block Export and the CLI says why - #5968
Draft
prakashUXtech wants to merge 52 commits into
Draft
prakashUXtech wants to merge 52 commits into
prakashUXtech wants to merge 52 commits into
Conversation
A bad --json export option came back as exit 70 "failed" with the schema's
JSON pointer ("/size/pixels/0: expected at least 1"), and a shape refusal
told CLI users to unlock a ratio lock they don't have. The options schema
now refuses in a sentence, the fake rethrows the refusal as is, and the CLI
maps ExportOptionRefusal to data (65) with the stretch hint.
DesignHeadless.export read no options, so {"size":{"pixels":...}} wrote 1x
SVG and said ok. It now parses the suite options and refuses any size but
1x in words.
The sheet kept Export enabled under a refused size readout. ExportSheetRows gains startBlock, the reason Export can't start, which the button uses for disabled, help and its accessibility reason. The export-pack snapshot states also check goldens under Golden/inspector, which CI records.
XP-7 shipped the live StillMetadata and the gps-phone.jpg sample, so the three file tests no longer wait on it.
7 of 9 tasks
…-20261028-092121 # Conflicts: # Sources/DesignModel/DesignHeadless.swift # Sources/SuiteUI/ExportSheet.swift
This was referenced Oct 31, 2026
…olicy A Linux-safe JPEGMetadata carrier in SuiteImaging copies the source's Exif APP1 onto the still and edits it in place: dropped entries are removed and their bytes zeroed, orientation is set to 1, and the thumbnail and source pixel size always go. PhotoHeadless runs JPEG exports from a JPEG through it, so the CLI no longer needs the ImageIO carrier in SuiteShell. Refs #5834
…-20261028-092121 # Conflicts: # Bundle/Samples/Sunset.png # UITests/Fixtures/suite/Sunset.png
…-20261028-092121 # Conflicts: # Sources/DesignModel/DesignHeadless.swift
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.
Mac finish pass for the export-pack quality gate. Refs #5834
Covers #3477 and #4523 (export-pack, SuiteUI).
What changed
ExportSheetRows.startBlockgives the reason Export can't start: either the run is past editing, or the Size row's readout is a refusal. The button now uses that reason for.disabled,.helpand its control reason. Before, it only checkededitable, so a refused size still left Export enabled.ExportOptionRefusaltodata(exit 65), notfailed(exit 70)."stretch": true. It no longer says to unlock a ratio lock the CLI doesn't have.PhotoWindow.writenow passes an export's encoded still throughPhotoWindow.carryingMetadata, which uses the liveStillMetadata. Photo's sheet has no metadata row, so the policy is the suite default.all. The orientation is dropped, because the decode already turned the pixels upright. Test:PhotoExportMetadataTests(gps-phone.jpg opened and exported throughImageIOCodec; GPS, Make, Model, DateTimeOriginal and Copyright kept, orientation dropped, no source copies nothing). Mutation plan:PhotoApp.PhotoWindow+Export.PhotoHeadless.exportused to turn the resampled buffer into 8-bit RGBA and then back into a linear buffer for core's encoder. NowexportBufferhands the buffer toCoreRasterImageCodec.encode(buffer:)as is. At 48 MP that saves about 0.4 s. PNG bytes are unchanged (theAgentsJSONOptionsGiveTheSheetsPixelsdecodes the headless PNG and compares it toexportPixels).JPEGMetadatain SuiteImaging is a Linux-safeMetadataCarryingfor JPEG. It copies the source's Exif APP1 onto the encoded still and edits the TIFF structure in place, with bounds checks. It removes each dropped tag (GPS IFD, serial numbers, maker notes and so on), sets a dropped Orientation to 1, and always clears the source's thumbnail and pixel-size tags. XMP and IPTC go along only when the policy drops nothing but the orientation.PhotoHeadlessremembers an opened JPEG's bytes, and a JPEG export now runs through it withExportRules.dropped(metadata)plus Orientation, since the decode already turned the pixels upright. No Package.swift change was needed: PhotoModel already links SuiteImaging, and ImageIO stays inside SuiteImageIO. PNG export carries no metadata yet, because core's PNG writer has no eXIf chunk.Golden/inspector/export-pack-<state>-<light|dark>.png. Golden/README.md says goldens must come from the macOS CI job, so no baselines are committed here. A missing baseline is recorded as a known issue, and CI records it.Tests
ExportPackRowsTests.aRefusedSizeBlocksExportAndSaysWhyandSuiteExportPackSnapshots.eachStateReadsItsSize: Export is blocked only in the refused state.CLIExportRefusalTests: the refusal kind isdatawith exit 65, there are no schema paths, and the shape refusal names stretch.DesignHeadlessExportOptionsTests: SVG refuses pixels, scale 2, long edge and unknown keys, and accepts none,{}and scale 1.FakeCanvasExportTests,LibraryExportMetadataWriteTests(re-enabled).PhotoHeadlessMetadataTests:allkeeps GPS, camera, copyright, date and serial, with the orientation at 1.noLocationdrops GPS and the serial (its bytes too) and keeps the rest.nonekeeps nothing identifying. A PNG export still writes, and an unreadable source copies nothing.AfterGlowCLICore.Output,DesignModel.DesignHeadless,SuiteKernel.ExportOptions,SuiteKernel.FakeCanvasDocument,SuiteImaging.JPEGMetadata(3/3 caught), andPhotoModel.PhotoHeadless(addsmetadataSkipped, caught). Two older entries in that plan,pngRoundTripExactandmergedNotKept, escape on this head. This branch didn't add them, andpngRoundTripExacttargets thewritePNGfallback that only runs when core throws unsupported.Proof
swift test --filter '...|SuiteExportPackSnapshots|ExportPackRowsTests': "✔ Suite ExportPackRowsTests passed", "Suite SuiteExportPackSnapshots passed after 5.997 seconds with 12 known issues" (the 12 are the unrecorded goldens).build/debug/afterglow design export d.design --format svg --json '{"size":{"pixels":[1080,1350]}}'on a 1440x1024 document |kind: data, exit 65, "SVG writes each frame at its own size, so it takes no size. Leave size out."; with no options it writeswidth="1440" height="1024"and ok | CLI output; DesignHeadlessExportOptionsTests.build/debug/afterglow photo export p.ora --format png --json '{"size":{"pixels":[1080,1350]}}'on a 1600x1200 image |kind: data, exit 65, "1080 × 1350 doesn't keep the artwork's 4:3 shape. Pass "stretch": true with pixels to stretch." | CLI output; CLIExportRefusalTestsafterglow photo export p.ora --json '{"size":{"pixels":[0,0]}}'and'{"size":{"scale":0}}'| "Each side in pixels has to be at least 1." and "A scale has to be more than 0.", bothkind: data, exit 65, no/size/...path | CLI output; CLIExportRefusalTests, FakeCanvasExportTestsPhotoJourneyTests/PhotoExportMetadataJourneyTests/testExportKeepsTheSourcesMetadata(11-02, through the journey wrapper, head ee56f92): Photo.app opens gps-phone.jpg, Export, JPEG, Export | the status bar reads "Exported gps-phone.jpg", and the written file read back with ImageIO keeps {GPS}, {TIFF}.Make, Model and Copyright and {Exif}.DateTimeOriginal, with Orientation 1. All six metadata assertions passed | photo-export-metadata-opened.png, -sheet.png, -exported.png. The run is marked failed by one app-audit contrast reading onphoto.adjust.header(1.42:1) in the two shots without a sheet. That header is unchanged here, and dev's hosted journeys (full run 41307844351) show no such fault. On this Mac, macOS's Documents-folder privacy prompt for the freshly signed runner was on screen in those shots..build/debug/afterglow photo export gps-phone.jpg --format jpeg --out out-<m>.jpg --json '{"metadata":"<m>"}'for all, noLocation and none, each output read back with ImageIO | source: GPS 48.858055,2.294445, Make Generic, Model Phone One, Copyright (c) 2026 Test Owner, DateTimeOriginal 2026:10:01 12:34:56, serial SN-0042-BODY, Orientation 6.all: every one kept, Orientation 1, ok, exit 0.noLocation: no GPS and no serial, the rest kept, Orientation 1.none: none of them. With"pixels":[16,16]the 16x16 output keeps them too | CLI output; "✔ Suite PhotoHeadlessMetadataTests passed after 0.210 seconds" (5 tests)Not fixed in this pass
PNG.write: 7.8 s for its single-threaded Deflate at level 1, against 2.4 s for the Lanczos resample, on a loaded Mac. A Photo Model can't call Darwin's zlib, because Models stay Linux-safe, and a deflate written in the app would copy engine work. So this case waits on perf(png): level-6 DEFLATE encode of 12 MP within its 2.5 s release budget creative-core#728 and a core bump.PhotoBudgetTests/realSizeExport(gated in release; the scale-2 PNG case has a 6 s budget) fails until then (13.1 s at release). The JPEG cases pass in release: 6000x4000 at 1x 1887 ms (3 s budget), long edge 2048 914 ms, 4:5 crop 526 ms, 4032x3024 at 1080x810 570 ms (1.5 s each). The audit's 6.87 s and 2.4 s were debug-build numbers. The 6000x4000 scale-2 case (53 s) shares the Deflate cost. Profile and details are on Photo export of a 24 MP image takes 5 to 53 s (scale 2 worst) #5976.## After betasection. Photo's sheet already lists only the formats it writes (PhotoExportSheetAdapter.formats).Snapshots
suiteui-export-pack-refused-light.pngandsuiteui-export-pack-refused-dark.png: Export is now disabled, next to the refused readout. The other export-pack states are unchanged.Notes
.disabledand.helpare already used on this button.RenderBudgetExportPackTests): not re-timed in this pass, because the gate had no slot. This change adds one readout per render, the same work the Size row already does.PhotoBudgetTests/realSizeExportruns in a scratch release worktree (swift test -c release). The JPEG cases pass. The scale-2 PNG case fails at 13.1 s against 6 s, waiting on core (above).scripts/ci --changedpassed every lint, the build and every suite this branch owns. Each printedCI: FAILonly on known flakes outside this branch: test(library): metadataPickInTwoBodies reads a nil LibraryShell.read in heavy runs #6123, FlareLayersFilesBudgetTests p95 fails under the parallel FlareModel run #6078, SegmentedTabsTests fade-length check fails under parallel load #6145, andHaloMovieWriterTestsand Photo place decodes hitting their limits under load.JPEGMetadata(above), so Photo export drops all source metadata (GPS, Make, DateTimeOriginal) #5975's Package.swift change isn't needed for JPEG. Dev was merged in at 28e3c9a.scripts/ci --changedon 4756f0f (run 12, 11-01): every lint, the C4 ownership check, the mutation anchors, the build and every changed-scope suite passed (AfterGlowCLI, Design, Flare, Halo, Library, Photo, SuiteImaging, SuiteKernel, SuiteUI and the snapshots, 480 s). It printedCI: FAILon one heavy test outside this branch: test(library): metadataPickInTwoBodies reads a nil LibraryShell.read in heavy runs #6123'sRenderBudgetLibraryExportPackTests/metadataPickInTwoBodies("LibraryShell.read?()"), the same order-dependent flake as runs 4, 7 and 8. There's still no literalCI: PASS, so the PR stays a draft.scripts/ci --changedrun 13 (11-01, same head 4756f0f, dev unchanged): every lint, the build and every changed-scope suite passed again. OnlyRenderBudgetLibraryExportPackTests/metadataPickInTwoBodies(test(library): metadataPickInTwoBodies reads a nil LibraryShell.read in heavy runs #6123, "LibraryShell.read?()") failed in the heavy batch (226 tests, 2577 s). That makes three runs in a row that fail only on this flake. Still no literalCI: PASS, so the PR stays a draft.scripts/ci --changedrun 14 (11-01, same head 4756f0f, dev unchanged at 5864f15): every lint, the build and every changed-scope suite passed. The heavy batch (226 tests, 3329 s) failed on two tests outside this branch:HaloMovieWriterTests/keyedRendersAsATwoSecondMovieMatchingFrameZerohit its 600 s limit (850 s under load), andRenderBudgetLibraryExportPackTests/metadataPickInTwoBodiesfailed (test(library): metadataPickInTwoBodies reads a nil LibraryShell.read in heavy runs #6123). Rerun alone through the gate, both pass (242 s and 6 s). creative-core#728 is still open, so the two slow-export boxes stay unticked. Still no literalCI: PASS, so the PR stays a draft.scripts/ci --changedrun 15 (11-01, same head 4756f0f, dev unchanged at 5864f15, core#728 still open): every lint, the build and the changed-scope suites passed. In the heavy batch, two tests outside this branch hit their 600 s limit under load from the other lanes:HaloMovieWriterTests/keyedRendersAsATwoSecondMovieMatchingFrameZero(800 s) andGestureContractTests/photo(_:)with.remove(1652 s for the 18 cases). Once the result was a certainCI: FAIL, I stopped the run to free the shared gate. Still no literalCI: PASS, so the PR stays a draft.scripts/ci --changedrun 16 (11-01, same head 4756f0f, dev unchanged at 5864f15, core#728 still open): every lint, the build and every changed-scope suite passed. The heavy batch (226 tests, 3528 s) failed on the same two tests outside this branch as run 14:HaloMovieWriterTests/keyedRendersAsATwoSecondMovieMatchingFrameZerohit its 600 s limit (910 s under load), andRenderBudgetLibraryExportPackTests/metadataPickInTwoBodiesfailed (test(library): metadataPickInTwoBodies reads a nil LibraryShell.read in heavy runs #6123, "LibraryShell.read?()"). Still no literalCI: PASS, so the PR stays a draft.scripts/ci --changedrun 17 (11-01, head 9d6c9f8, dev 7346d79 merged in, core#728 still open): every lint, the build and every changed-scope suite passed. The heavy batch (3254 s) failed on one test outside this branch,RenderBudgetLibraryExportPackTests/metadataPickInTwoBodies(test(library): metadataPickInTwoBodies reads a nil LibraryShell.read in heavy runs #6123, "LibraryShell.read?()"). test(library): metadataPickInTwoBodies reads a nil LibraryShell.read in heavy runs #6123 also fails on a Photo branch, and the re-enabled Library metadata tests here open no window, so this branch doesn't cause it. Still no literalCI: PASS, so the PR stays a draft.scripts/ci --changedrun 18 (11-01, head ee56f92, dev 2302a8e merged in, core#728 still open): dev's fix(suite): mac finish pass, the welcome tour ships real-size samples and a default Continue #5973 remadeSunset.pngat 1600 x 1067, and that clashed with this branch's level-1 copy. I resolved it by rebuilding both copies withMAKE_SAMPLES=1 swift test --filter SampleMakerTestson the merged tree (committedSamplesMatchTheirMakeFilespasses). Every lint, the build and every changed-scope suite passed. The heavy batch (225 tests, 2780 s) failed on one test outside this branch,RenderBudgetLibraryExportPackTests/metadataPickInTwoBodies(test(library): metadataPickInTwoBodies reads a nil LibraryShell.read in heavy runs #6123, "LibraryShell.read?()"). Still no literalCI: PASS, so the PR stays a draft.