The upgrade scenario retargets a copy of the candidate's .xctestrun at the
previous release's app but kept the candidate's DYLD_FRAMEWORK_PATH and
DYLD_LIBRARY_PATH, so the old app loaded the candidate's BookPlayerKit.
Once #1653 removed TimeParser.getTimerOption(from:), 5.22.2 stopped at
launch with a missing symbol, the check fell back to building 5.22.1, and
6.0.0 couldn't get an upgrade result. The copy now drops every DYLD_* entry
of the app's environment; the test runner's own variables stay.
The 6.0.0 release check couldn't get an upgrade result: the previous release (5.22.2) crashed at launch on both iOS 26.5 and 27.0 before seeding its data.
Cause
retarget()makes a copy of the candidate's.xctestrunthat installs the previous release's app, but it kept the candidate'sUITargetAppEnvironmentVariables. Those carryDYLD_FRAMEWORK_PATH/DYLD_LIBRARY_PATHpointing at the candidate's build products, so the old app loaded the candidate'sBookPlayerKit.frameworkinstead of the one it embeds. The crash reports say so:#1653 removed
TimeParser.getTimerOption(from:), so 5.22.2 couldn't start. The cached 5.22.2 app embeds its ownBookPlayerKitwith that symbol, so App Store users upgrading from 5.22.2 aren't affected; only the check was. The script then fell back to building 5.22.1, which ran the Mac out of disk. Before #1653, the candidate's framework happened to be a superset, so earlier upgrade checks ran the old app on the new framework without anyone noticing.Fix
The copy drops every
DYLD_*key fromUITargetAppEnvironmentVariables, so the previous release runs on the frameworks it ships with. The test runner's own environment (TestingEnvironmentVariables) is untouched. CLAUDE.md's release-check paragraph says so.Testing
A full run of the check from this branch (develop e7ecc8f + this fix), Xcode 27.1, previous release 5.22.2 from the cache, passed in 14.9 min:
The same build without the fix: upgrade crashed on both (the missing symbol above), then the 5.22.1 fallback build ran out of disk.