fix(ios): unbreak the iOS build (pbxproj id collision) + gate it in CI#277
Merged
Conversation
ChatModelStore.swift and WorkbenchSheet.swift shared the same PBXFileReference (...0124) and PBXBuildFile (...0223) ids: they landed from two parallel branches (claude/channel-initial-load-perf and claude/ios-workbench-plugin-feasibility) that each hand-picked "the next" sequential id off the same base, and the merge kept both. Xcode dedupes by id, so ChatModelStore lost and was dropped from the compile list — even though the file was on disk with all four pbxproj entries present. The build failed at AppModel.swift:36 with `cannot find 'ChatModelStore' in scope`, and the only clue was a "Skipping duplicate build file" warning. Reassign ChatModelStore to unused ids (...0126 / ...0225). Verified: the duplicate warning is gone, BUILD SUCCEEDED, and the app installs and runs on device. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Nothing in CI compiled iOS, so the pbxproj id collision fixed in the previous commit broke develop unnoticed — the app stopped building and every gate stayed green. Three additions, all motivated by that miss: - ios-build (macos-14): builds the app for a generic simulator destination with CODE_SIGNING_ALLOWED=NO, so a real compile gates every apps/ios change without signing certs or a provisioning profile in CI. - scripts/check-pbxproj.py: runs first in that job. Catches duplicate object ids, Swift files on disk that are missing from Compile Sources, and references to files that no longer exist. xcodebuild would catch the same class of problem, but minutes later and pointing at whichever unrelated file used the dropped symbol; this names the two colliding files in a second. Verified against the broken pbxproj: it flags both ids and exits 1. - gateway-check now runs `cargo fmt --check`. The other Rust crates already gate on fmt and CLAUDE.md tells contributors to run it, but the gateway had no such step, so drift accumulated (7 hunks across 4 files, formatted here). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The first run of the new job failed on the runner's default Xcode 15.4 (Swift 5.10): `unknown attribute 'retroactive'` in ShellComponents.swift, plus "call to main actor-isolated initializer in a synchronous nonisolated context" in AppShellView/AgentsView. Both are Swift 6 features the sources already rely on — the code is fine, the CI toolchain was years behind what the project is developed against (Xcode 26.6 locally). Move to macos-15 and xcode-select the newest Xcode on the image rather than pinning a version, which would only need bumping again at the next image refresh. The chosen version is printed so the next toolchain drift is legible in the log instead of surfacing as mystery syntax errors. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
developdoes not build for iOS.xcodebuildfails with:...for a file that is on disk and has all four of its
project.pbxprojentries.ChatModelStore.swiftandWorkbenchSheet.swiftshare the same object ids(
…0124PBXFileReference,…0223PBXBuildFile). They arrived from two parallelbranches —
claude/channel-initial-load-perfandclaude/ios-workbench-plugin-feasibility— that each hand-picked "the next"sequential id off the same base, and the merge kept both. Xcode dedupes by id,
WorkbenchSheet won, and ChatModelStore was dropped from Compile Sources. The only
clue was an easily-missed
warning: Skipping duplicate build file.This is currently included in #276 (develop → main).
The fix
Reassign ChatModelStore to unused ids (
…0126/…0225). Four lines.Why CI missed it
Nothing in CI compiled iOS at all —
apps/ios/**was in no path filter and hadno job. The app stopped building and every gate stayed green.
ios-build(macos-14) — builds against a generic simulator destination withCODE_SIGNING_ALLOWED=NO, so a real compile gates everyapps/ioschange with nosigning certs or provisioning profile needed in CI.
scripts/check-pbxproj.py— runs first in that job. Flags duplicate objectids, Swift files on disk missing from Compile Sources, and dangling references.
xcodebuildcatches the same class of bug, but minutes later and pointing at anunrelated file; this names both colliding files in a second.
cargo fmt --check— the other Rust crates gate on fmt and CLAUDE.mdtells contributors to run it, but
gateway-checknever did. 7 hunks of driftacross 4 files, formatted here.
Verification
xcodebuild … build→ BUILD SUCCEEDED, duplicate warning gonecargo fmt --checkandcargo checkclean inserver/🤖 Generated with Claude Code