- 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
- Analysis: AN-x2p7k
- Requirements: FR-m6v9d, FR-5nsmh
- Related ADRs: ADR-ifyc8
- Tasks: T-r2b7x
- Issue: N/A - No issue linked
- PR: N/A - Not yet submitted
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.
BeaconTrace will migrate to an Xcode app shell plus SwiftPM modules.
The Xcode project will own the macOS app product:
BeaconTrace.apptarget.- AppIcon and asset catalog configuration.
- Bundle identity and version settings.
Info.plistapp metadata and privacy usage descriptions.- Entitlements and Signing & Capabilities.
- Shared schemes and Archive/export integration.
SwiftPM will own reusable implementation and deterministic tests:
BeaconTraceCoreremains 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.
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.
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.moduleandBundle.maindrift. - The app entry point and test imports may need restructuring.
- Keep the Xcode app shell thin.
- Keep reusable logic out of the app shell unless it is truly product-only.
- Do not compile the same reusable source files both directly in the Xcode app target and through a SwiftPM product.
- Ensure there is exactly one
@mainentry point per app build graph. - Keep resource ownership explicit:
- App product resources such as AppIcon and app-level
Info.plistsettings belong to Xcode. - Xcode-owned asset catalogs must not be left inside SwiftPM executable
target paths unless
Package.swiftdeliberately 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.
- App product resources such as AppIcon and app-level
- 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.
- Preserve
script/build_and_run.shuntil 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. - Record any deliberate divergence between SwiftPM-staged bundles and Xcode bundles in the migration task plan.
- Do not claim release readiness from a Debug Xcode build.
- Do not introduce XcodeGen, Tuist, CocoaPods, or other project/dependency managers without a new ADR.
- 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.
| 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. |
The migration is valid only when:
- Xcode project discovery finds the intended project/workspace and the project
is readable, including
project.pbxprojor an equivalent workspace-backed project. - A shared
BeaconTracescheme is listed through XcodeBuildMCP macOS scheme listing. - Xcode Debug build succeeds.
- SwiftPM tests still pass.
- The built Xcode app launches in fixture mode.
- The app bundle contains expected
Info.plist, resources, and entitlements for the selected build configuration. - Existing localization, privacy, scanning, parsing, channel, and export tests do not regress.
- The task plan records XcodeBuildMCP commands used and results.
- 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, andswift-package build --help