Symptom: app hard-blocks at boot with "JarvisEntitlementsVerified
missing/false" after every incremental build, even though the build
log shows pre-codesign writing YES into the bundle Info.plist.
Root cause: Xcode 26's new build system schedules the built-in
ProcessInfoPlistFile task (which copies App/Info.plist into
Contents/Info.plist) independently from postBuildScripts. On
incremental builds with no Swift compile work, ProcessInfoPlistFile
ran AFTER pre-codesign, codesign, post-codesign, AND
verify-codesign-settings — silently clobbering the bundle Info.plist
with the source one. Source App/Info.plist carries
<key>JarvisEntitlementsVerified</key><false/> by design as the
static-state default; pre-codesign is supposed to flip it to <true/>
inside the bundle. With the new ordering, the bundle ended every
build at <false/> (and the signature was also stale relative to
that plist, though codesign --verify happened to still pass).
Fix: declare $(TARGET_BUILD_DIR)/$(INFOPLIST_PATH) as an inputFile
of the pre-codesign phase, plus a per-build stamp file as its
outputFile. This forces Xcode to make ProcessInfoPlistFile a
prerequisite of pre-codesign, and chains codesign (also gaining
the stamp as inputFile) deterministically behind it. Xcode 26's
"mutable output but no other virtual output node" check rejects
naming the plist as both input and output of the same phase, so
the separate stamp file is required.
Verified: clean and incremental builds both produce a bundle
with JarvisEntitlementsVerified=true and a valid signature.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>