chore: normalize project.pbxproj ordering - #1705
Conversation
Canonical sort applied by the xcodeproj tool, so later commits in this stack show only their own file additions. No project changes. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Multimodal adversarial review (interrogate)
Intent
Canonicalize
iOS_SDK/OneSignalSDK/OneSignal.xcodeproj/project.pbxprojto the Rubyxcodeprojgem’s save order so later stacked PRs aren’t buried in ~126 lines of pre-existing reorder noise. Scoped as reorder-only: no source/behavior/build-setting value changes.
Reviewers
- Reviewer A:
claude-fable-5-thinking-xhigh, 2 findings - Reviewer B:
gpt-5.6-sol-xhigh, 0 findings - Reviewer C:
cursor-grok-4.5-high-fast, 0 findings - Reviewer D:
claude-opus-5-thinking-high, 4 findings
All four independently confirmed the pure-reorder claim (identical 9814-line multiset; gem 1.28.1 round-trip of base → head is byte-identical; head save is a no-op).
Act On
None against this diff. The change is a verified content-preserving reorder of dictionary keys / object-map entries and achieves the stated, file-scoped intent.
Consider
- Landing race with open PR #1703 (D) —
#1703(fadi/sdk-4977) inserts4977…objects next to the exact3C14E3A9…AEblock this PR relocates, at non-canonical UUID positions. If #1703 merges from currentmainwithout rebasing onto this baseline, the next gem save regenerates the same class of noise this PR exists to eliminate, and the overlapping hunks are merge-hostile. Agree merge order: land this first, then rebase #1703 (or normalize its inserts). - Pin / record the
xcodeprojgem version (D) — repo has noGemfile. Head is a fixed point on 1.26–1.28; older gems (e.g. 1.25) still rewriteHEADER_SEARCH_PATHSquoting. Without a pin, “canonical” is not reproducible across machines. - No enforcement that the baseline stays clean (A, D) — the disorder being fixed was introduced by parent
#1702. A tiny CI check (Xcodeproj::Project.open(...).save+git diff --exit-codeonOneSignal.xcodeproj) would protect the motivation. Scope carefully:examples/demo/App.xcodeprojis XcodeGen-generated and should not be gem-normalized. - Sibling project drift outside this PR’s scope (A) —
OneSignalExample.xcodeprojis not a no-op under gem save (contentful empty-array deletions observed). Fine to leave out of this chore given the explicit single-file scope; worth a follow-up if stacked work will touch the dev app via the gem. - Branch / stack hygiene (D) — this reorder-only chore lives on
nan/jwt-pr1-path-encoding, and #1706 is already based on it. Prefer a dedicatedchore/pbxproj-normalize→mainif the branch tip may later gain path-encoding commits after review.
Noted
- Pre-existing 23-hex-character object IDs from
#1702(A, D): gem preserves them; not introduced by this reorder. Optional follow-up to regenerate to 24-char form while the file is quiet.
Dismissed
- Normalize
examples/demo/App.xcodeprojin this PR (A) — demo project is generated byxcodegen(seeexamples/demo/build.md/.github/actions/setup-demo). Gem-normalizing it fights the generator. - Any correctness / build-setting-value regressions in this diff (implicit adversary scan) — line multiset identity + gem round-trip disprove content drift; ordered arrays (
children,files,targets, etc.) were not reordered.
Agreement Map
- Strong consensus (4/4): pure reorder, intent achieved for
OneSignal.xcodeproj. - Divergence: A/D pushed process/sustainability findings (sibling projects, CI, gem pin, #1703 race, branch naming); B/C returned empty reviews after verifying the multiset. Pattern fits a mechanical chore — quality risk is recurrence after merge, not the patch itself.
Verdict: Safe to merge as a no-behavior baseline, with explicit landing coordination vs #1703 and a follow-up for gem pin / CI guard if the gem will keep writing this file.
Sent by Cursor Automation: Untitled
| 3C14E3A92FAE54C006ED053 /* IOSLogger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IOSLogger.swift; sourceTree = "<group>"; }; | ||
| 3C14E3AA2FAE54C006ED053 /* OneSignalLogHttpSender.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OneSignalLogHttpSender.swift; sourceTree = "<group>"; }; | ||
| 3C14E3AB2FAE54C006ED053 /* FileLogStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileLogStore.swift; sourceTree = "<group>"; }; | ||
| 3C14E3AC2FAE54C006ED053 /* OSLoggerPlatformProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OSLoggerPlatformProvider.swift; sourceTree = "<group>"; }; | ||
| 3C14E3AD2FAE54C006ED053 /* KotlinByteArray+Data.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "KotlinByteArray+Data.swift"; sourceTree = "<group>"; }; | ||
| 3C14E3AE2FAE54C006ED053 /* OSLoggerAdaptersTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OSLoggerAdaptersTests.swift; sourceTree = "<group>"; }; |
There was a problem hiding this comment.
Consider (Reviewer D; lead agrees): This relocated 3C14E3A9…AE PBXFileReference cluster is the same neighborhood open PR #1703 (fadi/sdk-4977) inserts into with non-canonical 4977… IDs.
The reorder here is verified content-preserving. The risk is landing order: if #1703 merges from current main without rebasing onto this baseline, the next xcodeproj gem save regenerates the reorder noise this PR exists to eliminate (and the overlapping hunks are merge-hostile).
Please agree merge sequence with #1703 — land this first, then rebase #1703 (or have #1703 emit gem-canonical inserts).
There was a problem hiding this comment.
Agreed — land this PR first, then rebase #1703 onto the normalized baseline (or have it emit gem-canonical inserts) so the next xcodeproj save doesn’t regenerate reorder noise.
| "FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]" = ( | ||
| "$(inherited)", | ||
| "$(SRCROOT)/../../OneSignal-KMP-SDK/kmp/build/XCFrameworks/release/OneSignalKMP.xcframework/ios-arm64", | ||
| ); | ||
| "FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]" = ( | ||
| "$(inherited)", | ||
| "$(SRCROOT)/../../OneSignal-KMP-SDK/kmp/build/XCFrameworks/release/OneSignalKMP.xcframework/ios-arm64_x86_64-simulator", | ||
| ); |
There was a problem hiding this comment.
Consider (Reviewers A/D): These FRAMEWORK_SEARCH_PATHS keys only moved within buildSettings (order-insensitive) — values are unchanged, and gem 1.28.1 round-trips head as a no-op.
Two sustainability gaps remain outside this hunk:
- No
Gemfilepin — olderxcodeproj(e.g. 1.25) still rewritesHEADER_SEARCH_PATHSquoting, so “canonical” isn’t reproducible. - No CI guard that
Project.open(...).saveis a no-op onOneSignal.xcodeproj(the disorder came from parent feat: [SDK-4976] add Swift adapters for KMP logger #1702).
Worth a small follow-up if the gem will keep editing this file; do not gem-normalize examples/demo/App.xcodeproj (XcodeGen-owned).
There was a problem hiding this comment.
Addressed in this PR:
- Root
Gemfile/Gemfile.lockpinsxcodeprojto1.28.1. - New
pbxproj-canonicalworkflow opens/savesOneSignal.xcodeprojand fails on any diff.
examples/demo/App.xcodeproj is intentionally left alone (XcodeGen-owned).
Keep the reorder baseline reproducible and stop the next gem save from quietly reintroducing disorder. Co-authored-by: Cursor <cursoragent@cursor.com>


Description
One Line Summary
One-time canonical sort of
project.pbxprojobject sections so later stacked PRs show only their own file additions, plus a pinnedxcodeprojgem and CI guard to keep that baseline clean.Details
Motivation
The
xcodeprojgem re-sorts the project file into UUID order on save.mainalready has ~126 lines of pre-existing disorder relative to that order, so the first PR that uses the gem would otherwise bury real changes in reorder noise. Landing the normalization alone keeps follow-up PRs readable.Scope
iOS_SDK/OneSignalSDK/OneSignal.xcodeproj/project.pbxprojreorder only (no source or behavior changes)Gemfile/Gemfile.lockpinningxcodeproj1.28.1OneSignal.xcodeprojis a no-opexamples/demo/App.xcodeproj(XcodeGen-owned)Merge note
Land this before #1703, then rebase #1703 onto the normalized baseline.
Testing
Unit testing
Not needed for the reorder — no compile inputs change.
Manual testing
Opened the project with the pinned
xcodeprojgem and confirmed a no-op save after this commit is empty of further churn.CI
pbxproj-canonicalrunsProject.open(...).save+git diff --exit-codeonOneSignal.xcodeproj.Affected code checklist
Checklist
Overview
Testing
Final pass
Made with Cursor