feat: native macOS Phase 2 — SwiftPM Spike setup - #153
Conversation
Set up the 3-target SwiftPM layout (executable App + library Core + testTarget CoreTests) per spec/native-macos-requirements.md's no-.xcodeproj decision: the executable stays a thin @main entry point while Core holds the actual logic/views, which is what lets #Preview work without ENABLE_DEBUG_DYLIB (only settable via .xcodeproj). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Confirms library-target separation lets #Preview render without ENABLE_DEBUG_DYLIB (Package.swift-only setup, no .xcodeproj). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Confirms swift test discovers and runs the CoreTests target via Swift Testing (@Test/#expect), matching the framework Phase 3's security.rs migration (spec/phase-tasks.md 3-11) will use. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
nicklockwood/SwiftFormat only ships a command plugin (no build-tool plugin exists upstream), so this is invoked explicitly via `swift package --allow-writing-to-package-directory swiftformat` rather than running automatically on every build. Verified both lint (--lint) and write modes locally against the current source tree; fixed the one real violation swiftformat found in CoreTests.swift. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Attach SwiftLintBuildToolPlugin to App/Core/CoreTests so `swift build`
and `swift test` enforce .swiftlint.yml (strict: true) automatically,
in contrast to SwiftFormat's manual command-plugin invocation.
Also disables SwiftFormat's swiftTestingTestCaseNames rule: it rewrites
`@Test("description") func name()` into a backtick-quoted function
name, which then fails SwiftLint's identifier_name
(validates_start_with_lowercase) check. Keeping the descriptive-string
+ camelCase form avoids the two tools fighting each other.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Mirrors the existing fmt-rust/lint-format-ts pre-commit jobs: runs swiftformat + swiftlint --fix over apps/native-macos on commit, and no-ops with a message (rather than failing) when swift isn't on PATH locally, since CI is the enforcement backstop either way. Verified end-to-end via `lefthook run pre-commit --command lint-format-swift --force --all-files`, which also caught and fixed a real trailing-comma violation in Package.swift. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
ubuntu-latest job running swiftformat --lint and swiftlint --strict via the SPM plugins added in the previous two commits, gated on paths: ['apps/native-macos/**'] so it doesn't fire for unrelated changes. Uses swift-actions/setup-swift@v2 pinned to 6.2 to match Package.swift's swift-tools-version. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Runs swift build + swift test on the macos-26 runner image (Xcode 26.x, matching this repo's local dev environment and the platforms: [.macOS(.v26)] requirement). Verified -skipPackagePluginValidation, which spec/phase-tasks.md flagged as possibly needed: it is not a recognized flag on Swift 6.2.4 (absent from swift build/test/package --help), and swift build/test already run cleanly without a TTY locally with the SwiftLint/SwiftFormat plugins attached, so it's omitted. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
New apps/native-macos/README.md documents swift build/test, the SwiftFormat/SwiftLint plugin invocations, and the lefthook/CI enforcement split. Root CLAUDE.md gets a one-line pointer to it. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
Warning Review limit reached
Next review available in: 21 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (13)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
Adds the Phase 2 SwiftPM “spike” scaffold for the independent native macOS reimplementation under apps/native-macos/, along with local hooks and CI to enforce Swift formatting/linting and run basic build/test.
Changes:
- Introduces a new SwiftPM package (
Native) withApp(executable),Core(library), andCoreTests(Swift Testing) targets plus minimal placeholder implementation. - Adds SwiftFormat + SwiftLint configuration and wiring (SwiftLint build-tool plugin + SwiftFormat command plugin), plus a
lefthookpre-commit job for Swift files. - Adds a dedicated GitHub Actions workflow (
native.yml) to lint, build, and test the native macOS package.
Reviewed changes
Copilot reviewed 12 out of 13 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
lefthook.yml |
Adds a lint-format-swift pre-commit command for Swift formatting/linting. |
CLAUDE.md |
Documents where the SwiftPM native macOS package lives and points to its README for commands. |
apps/native-macos/Package.swift |
Defines the SwiftPM package, targets, dependencies, and SwiftLint plugin usage. |
apps/native-macos/Package.resolved |
Pins SwiftPM dependency resolution for the new native macOS package. |
apps/native-macos/.swiftlint.yml |
Adds SwiftLint configuration (strict mode, opt-in rules, exclusions). |
apps/native-macos/.swiftformat |
Adds SwiftFormat configuration and disables the Swift Testing test case name rule. |
apps/native-macos/README.md |
Documents build/test/lint/format commands and the no-.xcodeproj approach. |
apps/native-macos/Sources/App/Main.swift |
Adds the executable entry point for the App target. |
apps/native-macos/Sources/Core/Core.swift |
Adds a minimal Core API surface (Core.version). |
apps/native-macos/Sources/Core/RootView.swift |
Adds a placeholder SwiftUI RootView and #Preview. |
apps/native-macos/Tests/CoreTests/CoreTests.swift |
Adds a baseline Swift Testing test for Core.version. |
.gitignore |
Ignores SwiftPM build artifacts and generated Xcode project files under apps/native-macos/. |
.github/workflows/native.yml |
Adds CI workflow for native macOS linting and build/test. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if ! command -v swift >/dev/null 2>&1; then | ||
| echo "swift not found locally, skipping Swift format/lint (still enforced in CI)" | ||
| exit 0 | ||
| fi |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Summary
Implements
spec/phase-tasks.mdPhase 2 (tasks 2-1 through 2-9): the SwiftPM scaffold for the independent native macOS reimplementation (apps/native-macos/), plus lint/format tooling and CI.apps/native-macos/Package.swift: 3-target layout (Appexecutable,Corelibrary,CoreTests), no.xcodeprojperspec/native-macos-requirements.md's brew-browser-style decision.swift-tools-version:6.2,platforms: [.macOS(.v26)].RootView+#PreviewinCore, confirming the library-target split lets previews work withoutENABLE_DEBUG_DYLIB.CoreTestsbaseline using Swift Testing (@Test/#expect), matching the framework Phase 3'ssecurity.rsmigration will use.strict: true), both verified to build/lint/format cleanly.lefthook.yml: newlint-format-swiftjob (mirrorsfmt-rust/lint-format-ts), no-ops whenswiftisn't onPATHlocally..github/workflows/native.yml:lintjob (ubuntu-latest,swift-actions/setup-swift@v2@ 6.2) +build-and-testjob (macos-26, matches the platform's actual macOS 26 requirement rather thanmacos-latest).apps/native-macos/README.md+ a CLAUDE.md pointer documenting the build/lint commands.Naming note
Deviated from
spec/phase-tasks.md's literalMCVectorNative/MCVectorNativeKitnaming — per user feedback mid-implementation, dropped the redundantMCVectorprefix (the repo is alreadymc-vector). Targets areApp/Core/CoreTests, package nameNative.Verified deviations from the task table
-skipPackagePluginValidation(task 2-8's open question) does not exist as a flag on Swift 6.2.4 — omitted.native.yml's build/test job runs onmacos-26rather thanmacos-latest, sincemacos-latestdoesn't move to macos-26 until later and this project specifically targets macOS 26 Tahoe.Test plan
swift buildclean locally (Xcode 26.3 / Swift 6.2.4)swift test— 1/1 passingswift package swiftformat --lint— 0 files require formattingswift package swiftlint --strict(via build-tool plugin duringswift build) — cleanlefthook run pre-commit --command lint-format-swift --force --all-files— verified end-to-end, caught and fixed a real trailing-comma violation