Skip to content

Latest commit

 

History

History
162 lines (130 loc) · 7.48 KB

File metadata and controls

162 lines (130 loc) · 7.48 KB

Xcode App Shell With SwiftPM Modules

Metadata

  • ID: ADR-q4h8s
  • Type: Architecture Decision Record
  • Owner: BeaconTrace maintainers and implementation agents
  • Reviewers: macOS architecture reviewer, build/release reviewer, TDL reviewer, QA reviewer
  • Status: Accepted
  • Date: 2026-05-29

Links

Context

BeaconTrace needs Xcode-native handling for app-product concerns while keeping the SwiftPM-first strengths that made the current implementation testable and agent-friendly. Opening Package.swift in Xcode is not equivalent to having a normal macOS app project: it does not make app icon, signing, capabilities, Archive, and release-oriented build settings first-class project concepts.

At the same time, moving all code into one Xcode app target would increase project-file churn and weaken swift test as the fast deterministic validation path.

Decision

BeaconTrace will migrate to an Xcode app shell plus SwiftPM modules.

The Xcode project will own the macOS app product:

  • BeaconTrace.app target.
  • AppIcon and asset catalog configuration.
  • Bundle identity and version settings.
  • Info.plist app metadata and privacy usage descriptions.
  • Entitlements and Signing & Capabilities.
  • Shared schemes and Archive/export integration.

SwiftPM will own reusable implementation and deterministic tests:

  • BeaconTraceCore remains a SwiftPM library target.
  • App feature code should be organized into SwiftPM library targets when doing so avoids source duplication and keeps tests independent of app packaging.
  • The Xcode app shell imports local package products and supplies the app entry point and product resources that belong to the app bundle.

XcodeBuildMCP project-scaffolding scaffold-macos may be used only as a reference template generated outside the repository. It must not be applied directly to the existing tree without an explicit migration plan.

Rationale

Xcode is the normal Apple-platform tool for app-product work: schemes, run destinations, debugger integration, Signing & Capabilities, asset catalogs, Archive, and distribution workflows all assume project targets. BeaconTrace is a normal macOS desktop app with Location Services, CoreWLAN behavior, charts, tables, export, and future distribution goals, so these project-level surfaces are useful rather than ornamental.

SwiftPM remains the better home for testable logic. Parser, security model, channel math, ordering, scheduler, settings, localization helpers, and export logic should remain testable without launching the app or editing the Xcode project file for every internal change.

This split also narrows future changes. Product settings change in the Xcode shell; logic changes remain in SwiftPM targets and tests.

Consequences

Positive:

  • Xcode can run, debug, inspect issues, manage schemes, configure capabilities, and archive the app through standard workflows.
  • SwiftPM tests remain available for deterministic logic validation.
  • App product metadata becomes explicit instead of script-generated only.
  • XcodeBuildMCP macOS project workflows become meaningful once defaults are configured.
  • Future release packaging has a clearer boundary.

Negative:

  • The repository will have two build surfaces during migration.
  • Project-file conflicts become possible.
  • Resources need a clear ownership model to avoid Bundle.module and Bundle.main drift.
  • The app entry point and test imports may need restructuring.

Implementation Rules

  1. Keep the Xcode app shell thin.
  2. Keep reusable logic out of the app shell unless it is truly product-only.
  3. Do not compile the same reusable source files both directly in the Xcode app target and through a SwiftPM product.
  4. Ensure there is exactly one @main entry point per app build graph.
  5. Keep resource ownership explicit:
    • App product resources such as AppIcon and app-level Info.plist settings belong to Xcode.
    • Xcode-owned asset catalogs must not be left inside SwiftPM executable target paths unless Package.swift deliberately excludes them and warning-free SwiftPM validation proves the compatibility path is clean.
    • Testable localization and feature resources may remain in SwiftPM targets only if both SwiftPM and Xcode app builds resolve them consistently.
  6. Move app feature code needed by tests into a SwiftPM library product before relying on the Xcode shell; tests should not depend on importing the SwiftPM executable target.
  7. Preserve script/build_and_run.sh until the Xcode workflow is validated, and treat it as launch-only/non-release unless it passes the same signing and resource checks as the Xcode-built bundle.
  8. Record any deliberate divergence between SwiftPM-staged bundles and Xcode bundles in the migration task plan.
  9. Do not claim release readiness from a Debug Xcode build.
  10. Do not introduce XcodeGen, Tuist, CocoaPods, or other project/dependency managers without a new ADR.
  11. Prefer XcodeBuildMCP project discovery and macOS workflows over ad hoc Xcode commands once a valid project exists, but verify the CLI/tool surface through help-first discovery before relying on it.

Alternatives Considered

Alternative Decision Reason
Keep SwiftPM-only Rejected for this migration Does not satisfy the goal of Xcode-native app configuration and debugging.
Hand-written minimal .xcodeproj only Rejected as the durable path Too easy to create fragile package/resource/project drift.
Direct in-repo scaffold Rejected XcodeBuildMCP scaffold is new-project-oriented and can collide with existing layout.
Xcode-only app Rejected for now Too disruptive and weakens existing SwiftPM testing workflow.
Tuist/XcodeGen Deferred Could reduce project-file churn, but adds a new tool and policy surface.
CodexBar-style script-owned app bundle Rejected for BeaconTrace Useful for script-heavy apps, but it keeps the main app product outside normal Xcode app-target management.

Validation

The migration is valid only when:

  1. Xcode project discovery finds the intended project/workspace and the project is readable, including project.pbxproj or an equivalent workspace-backed project.
  2. A shared BeaconTrace scheme is listed through XcodeBuildMCP macOS scheme listing.
  3. Xcode Debug build succeeds.
  4. SwiftPM tests still pass.
  5. The built Xcode app launches in fixture mode.
  6. The app bundle contains expected Info.plist, resources, and entitlements for the selected build configuration.
  7. Existing localization, privacy, scanning, parsing, channel, and export tests do not regress.
  8. The task plan records XcodeBuildMCP commands used and results.

External References

  • Apple Xcode Help: Build and run your app
  • Apple Xcode Help: About the debug area
  • Apple Xcode Help: Signing & Capabilities workflow
  • Apple Xcode Help: About Archives organizer
  • Apple Xcode Help: Configure schemes in Xcode
  • XcodeBuildMCP CLI tools, project-scaffolding scaffold-macos --help, macos build --help, and swift-package build --help