- Target macOS 26 or later on Apple Silicon with Swift 6.3 strict concurrency.
- Treat
ScanPhotoEditor.xcodeprojas the primary build, test, signing, and release format. - Regenerate the project from
project.ymlwith XcodeGen 2.45.4 after project-setting changes. - Change app versions through
MARKETING_VERSIONandCURRENT_PROJECT_VERSIONinproject.yml; keepInfo.plistversion keys bound to those build settings. - Open the generated project in Xcode and use the Xcode integration for diagnostics after Swift or project edits.
xcodebuildis the run-script fallback. - Keep image processing geometry-only: orientation normalization, perspective correction, explicit quarter-turn rotation, explicit flips, and encoder-required color-profile handling.
- Never add automatic adjustment, white balance, exposure, contrast, saturation, sharpening, denoising, restoration, OCR, face analysis, or cloud upload code.
- Never modify imported originals. Copy them into the
.scanphotopackage and render exports from the copied bytes. - Use normalized top-left-origin coordinates ordered top-left, top-right, bottom-right, bottom-left.
- Preserve undoability for user-visible geometry, creation, deletion, and ordering changes.
- When reordering source images, update both
SourceAsset.importOrderfor sidebar presentation andProjectManifest.regionOrderfor export/PDF ordering; preserve the current region order within each source. - Use preview-sized images while editing and decode full resolution only for export.
- Keep imported originals file-backed in
ProjectFileStorage; do not reintroduce a document-wide in-memory original-data dictionary. - Keep PDF export page-streamed so full-resolution corrected images are not accumulated across pages.
- Keep successful export completion distinct from cancellation; only present the completion view for a finished, non-cancelled export report.
- Do not isolate
PhotoProjectDocumentor itsReferenceFileDocumentconformance toMainActor; SwiftUI creates, opens, and snapshots reference documents on non-main queues. - Before encoding JPEG thumbnails or exports with ImageIO, render opaque images as RGBX so the encoder does not receive an unnecessary alpha channel.
- Mark UI tests that use
XCUIApplicationorXCUIElementAPIs as@MainActorunder Swift strict concurrency. - SwiftUI views that render values from
PhotoProjectDocument.manifestmust observe the document directly; observing onlyProjectEditingStoredoes not propagate the document's Combine updates. - In
GeometryCanvasView, derive the rendered image rectangle and scrollable content size from the same zoomed canvas dimensions so the image never extends beyond the scroll bounds. - Keep
EditorWorkspaceViewin a stable top-and-bottom layout with the source editor above the corrected preview; do not use content-measurement-driven layout switching such asViewThatFits. - Define main-window toolbar content only in
ProjectRootView; do not add competing toolbar declarations to split-view child views. Group related controls withControlGroupso sidebar and inspector width changes do not independently overflow actions. - Keep source-wide actions in the Source Actions menu, region creation/deletion in their own
ControlGroup, and transforms in the geometry group; do not expose source removal and region deletion as adjacent, indistinguishable trash buttons.