Files
Jarvis/project.yml
james.maesandClaude Opus 4.7 1557302e63 fix(build): force ProcessInfoPlistFile before pre-codesign
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>
2026-05-12 11:50:56 -05:00

671 lines
29 KiB
YAML

name: Jarvis
options:
createIntermediateGroups: true
generateEmptyDirectories: true
minimumXcodeGenVersion: "2.40.0"
deploymentTarget:
macOS: "14.0"
settings:
base:
SWIFT_VERSION: "6.0"
SWIFT_STRICT_CONCURRENCY: complete
ENABLE_HARDENED_RUNTIME: YES
CODE_SIGN_STYLE: Manual
CODE_SIGN_IDENTITY: "-"
OTHER_CODE_SIGN_FLAGS: "--options=runtime --timestamp"
LD_RUNPATH_SEARCH_PATHS: "@executable_path/../Frameworks"
MACOSX_DEPLOYMENT_TARGET: "14.0"
configs:
# DEVELOPMENT_TEAM intentionally unset for Debug.
# With ad-hoc signing (CODE_SIGN_IDENTITY="-") and DEVELOPMENT_TEAM set,
# Xcode generates incremental debug dylibs signed with the Team ID while
# the main executable remains adhoc — dyld refuses to load the mismatched
# dylib ("different Team IDs"), and xctest crashes during bootstrap.
Debug:
ONLY_ACTIVE_ARCH: YES
Release:
DEVELOPMENT_TEAM: 7UC2HETAN9
packages:
Keychain:
path: packages/Keychain
Config:
path: packages/Config
Logging:
path: packages/Logging
Shell:
path: packages/Shell
Bus:
path: packages/Bus
# Plan 05-05: App-level wiring consumes JarvisMCP (the confirmation
# broker / dispatcher / presenter chain), AgentCore (BoundedAsyncChannel
# for ME-04 closure + ToolUseRequest), and Replay (ReplayEvent type for
# the orch→replay channel + ReplayLog for the SEC-07 observer).
AgentCore:
path: packages/AgentCore
MCP:
path: packages/MCP
Replay:
path: packages/Replay
# Plan 06-05: App-level voice wiring (App/AppDelegate.installVoice + the
# Voice typealias in App/HUD/HudStateIntent.swift) consumes the Voice
# package's VoiceController, VoiceState, VoiceHudIntent, PushToTalk,
# MuteWakeWord, and AudioLevelEmitter surfaces.
Voice:
path: packages/Voice
# Plan 07-01: App-level memory wiring (future: AppDelegate.installMemory in
# Plan 07-06) consumes the Memory package's MemoryStore actor + schema.
# Plan 07-01 only stands up the package; the App→Memory edge is exercised
# via Bus events / DevOverlay rows in Plan 07-03 + 07-06.
Memory:
path: packages/Memory
# Plan 07-04: App-level vision wiring (future: AppDelegate.installVision in
# Plan 07-06) consumes the Vision package's CameraCapture, PresenceMonitor,
# PresenceSignalBus, and DisablePresence surfaces. Plan 07-04 only stands
# up the package and the VISION-03 grep gates; the App→Vision edge is
# wired in Plan 07-06.
Vision:
path: packages/Vision
# DevOverlay package — diagnostic floating panel showing live agent state,
# tool calls, token counts, and per-turn latency. Hidden by default; toggled
# from the menu bar (Show Dev Overlay item).
DevOverlay:
path: packages/DevOverlay
# Plan 08-01: Phase 8 evaluation harness — `Harness` library + `jarvis-eval`
# executable target. Consumed by tests / CI shipping-gate (`scripts/shipping-gate.sh`).
# The xcodegen entry exposes the local SPM package; the executable is
# invoked via `swift run --package-path packages/Harness jarvis-eval ...`.
Harness:
path: packages/Harness
# MCP Swift SDK — consumed by `mcp-time`, `mcp-clipboard` (Plan 05-02), and
# `mcp-applescript` (Plan 05-03) helper targets. Pinned at the same exact
# version as `packages/MCP/Package.swift` (Plan 05-01) to avoid
# dual-resolution drift.
swift-sdk:
url: https://github.com/modelcontextprotocol/swift-sdk
exactVersion: "0.12.0"
# Plan 05-05: swift-log is consumed transitively by `JarvisLogging`,
# `Replay`, `AgentOrchestrator`, and `JarvisMCP`. The Xcode framework
# linker needs an explicit App-target dependency once these are linked
# as separate frameworks (the App previously only saw Logging through
# JarvisLogging's exported symbols, which xcodegen surfaces as a
# "Logger.MetadataValue undefined" linker error).
swift-log:
url: https://github.com/apple/swift-log.git
from: "1.5.0"
targets:
Jarvis:
type: application
platform: macOS
sources:
- path: App
excludes:
- "Info.plist"
- "Jarvis.entitlements"
- "Jarvis.Debug.entitlements"
- "Jarvis.Release.entitlements"
- "Tests/**"
- "Resources/**"
# Blue-folder reference. The folder's NAME becomes the subdirectory
# inside Contents/Resources/ in the built bundle (xcodegen preserves
# the last path segment). Pointing this at `App/Resources/webview`
# makes the bundle path `Contents/Resources/webview/…`, matching
# `Bundle.main.url(forResource:withExtension:subdirectory:"webview")`.
- path: App/Resources/webview
type: folder
buildPhase: resources
settings:
base:
PRODUCT_BUNDLE_IDENTIFIER: com.koftwentytwo.jarvis
PRODUCT_NAME: Jarvis
INFOPLIST_FILE: App/Info.plist
GENERATE_INFOPLIST_FILE: NO
ENABLE_HARDENED_RUNTIME: YES
CODE_SIGN_STYLE: Manual
CODE_SIGN_IDENTITY: "-"
OTHER_CODE_SIGN_FLAGS: "--options=runtime --timestamp"
SWIFT_STRICT_CONCURRENCY: complete
SWIFT_VERSION: "6.0"
MACOSX_DEPLOYMENT_TARGET: "14.0"
LD_RUNPATH_SEARCH_PATHS: "@executable_path/../Frameworks"
configs:
Debug:
CODE_SIGNING_ALLOWED: NO
CODE_SIGNING_REQUIRED: NO
CODE_SIGN_ENTITLEMENTS: App/Jarvis.Debug.entitlements
# Hardened Runtime OFF for Debug — HR's strict "non-platform Team IDs
# must match" rule rejects Xcode 26's debug dylib incremental-link
# artifact (Jarvis.debug.dylib) against our ad-hoc signed main
# executable, producing the abrt-during-bootstrap crash on xctest
# launch. HR is only meaningful for Release/distribution anyway.
ENABLE_HARDENED_RUNTIME: NO
# OTHER_CODE_SIGN_FLAGS must not carry `--options=runtime` on Debug —
# that flag enables HR regardless of ENABLE_HARDENED_RUNTIME. Strip it.
OTHER_CODE_SIGN_FLAGS: ""
# Disable Swift 6 / Xcode 26 incremental-link `Jarvis.debug.dylib`
# artifact entirely on Debug. The dylib gets a Team-ID context
# (from how Xcode's compile cache signs it) that diverges from the
# ad-hoc outer bundle; dyld then aborts at __abort_with_payload
# when the app tries to load it. With NO, Swift links the binary
# statically and there's no separate dylib to load.
# Trade-off: ~5-15% slower incremental Debug compile, but the app
# actually launches from Xcode's Run scheme (⌘R).
SWIFT_ENABLE_DEBUG_DYLIB: NO
Release:
DEVELOPMENT_TEAM: 7UC2HETAN9
CODE_SIGNING_ALLOWED: NO
CODE_SIGNING_REQUIRED: NO
CODE_SIGN_ENTITLEMENTS: App/Jarvis.Release.entitlements
dependencies:
- package: Keychain
product: Keychain
- package: Config
product: Config
- package: Logging
product: JarvisLogging
- package: Shell
product: Shell
- package: Bus
product: Bus
# Plan 05-05: App-level MCP runtime wiring (App/MCP/MCPRuntimeWiring,
# App/MCP/ReplayingToolResultObserver) consumes these.
- package: AgentCore
product: AgentCore
- package: AgentCore
product: AgentOrchestrator
- package: MCP
product: JarvisMCP
- package: Replay
product: Replay
# Plan 05-05: AppDelegate and other App sources `import Logging`
# (swift-log's Logger). The App target previously got swift-log
# transitively through JarvisLogging; the Xcode framework linker is
# stricter once the App pulls in extra package frameworks (Replay,
# AgentCore, JarvisMCP) so the dep needs to be explicit.
- package: swift-log
product: Logging
# Plan 06-05: AppDelegate.installVoice + HudStateIntent.swift
# `import Voice` for the VoiceController + VoiceHudIntent typealias.
- package: Voice
product: Voice
# Plan 07-01: package wiring for downstream Phase 7 plans
# (AppDelegate.installMemory lands in 07-06). Declaring the dependency
# here so xcodegen picks it up at the same time as the Memory package
# path entry above.
- package: Memory
product: Memory
# Plan 07-04: package wiring for downstream Phase 7 plans
# (AppDelegate.installVision lands in 07-06). Declaring the dependency
# here so xcodegen picks it up at the same time as the Vision package
# path entry above. Product is `JarvisVision` (not `Vision`) to avoid
# colliding with Apple's Vision framework — see packages/Vision/Package.swift.
- package: Vision
product: JarvisVision
# DevOverlay diagnostic panel — toggled from the menu-bar 'Show Dev
# Overlay' item. AppDelegate.installDevOverlay() constructs the
# DevOverlayWindow on first toggle and routes the menu action to it.
- package: DevOverlay
product: DevOverlay
# Plan 05-02 / 05-03: build the helper apps before the Jarvis copyFiles
# phase consumes them. xcodegen orders target dependencies before copy
# phases.
- target: mcp-time
embed: false
link: false
- target: mcp-clipboard
embed: false
link: false
- target: mcp-applescript
embed: false
link: false
preBuildScripts:
# Three build-breaking pre-build phases — run BEFORE Compile Sources.
# Ordered fastest-failing first so common authoring errors surface
# before the slower lint walk of the Swift tree.
- name: Check bus-harness.html parity (canonical vs bundle)
script: |
"${SRCROOT}/scripts/check-bus-harness-parity.sh"
runOnlyWhenInstalling: false
basedOnDependencyAnalysis: false
inputFiles:
- $(SRCROOT)/webview/bus-harness.html
- $(SRCROOT)/App/Resources/webview/bus-harness.html
- name: Check bus protocol version (Swift/TS parity)
script: |
"${SRCROOT}/scripts/check-bus-protocol-version.sh"
runOnlyWhenInstalling: false
basedOnDependencyAnalysis: false
inputFiles:
- $(SRCROOT)/packages/Bus/Sources/Bus/Protocol.swift
- $(SRCROOT)/webview/packages/bus/src/protocol.ts
- name: Check no evaluateJavaScript calls (HUD-04)
script: |
"${SRCROOT}/scripts/check-no-evaluate-javascript.sh"
runOnlyWhenInstalling: false
basedOnDependencyAnalysis: false
- name: Check single-writer HUD state (HUD-08)
script: |
"${SRCROOT}/scripts/check-single-writer-hudstate.sh"
runOnlyWhenInstalling: false
basedOnDependencyAnalysis: false
# Plan 05-05 (MCP-04): reject runModal / beginModalSession / NSApp.run
# outside the two-file allowlist (TCCAlertService + ConfirmationPresenter).
# Module-wide lint — fails the build fast on regression.
- name: Check no modal presentation (MCP-04)
script: |
"${SRCROOT}/scripts/check-no-modal-presentation.sh"
runOnlyWhenInstalling: false
basedOnDependencyAnalysis: false
# Plan 07-06 (MEM-06): single emission site for ReplayEvent.memoryMutation.
- name: Check single memory.mutated emission site (MEM-06)
script: |
"${SRCROOT}/scripts/check-single-memory-mutated-emit.sh"
runOnlyWhenInstalling: false
basedOnDependencyAnalysis: false
# Plan 07-06 (D-05): single emission site for ReplayEvent.memoryRetrieval.
- name: Check single memory.used emission site (D-05)
script: |
"${SRCROOT}/scripts/check-single-memory-used-emit.sh"
runOnlyWhenInstalling: false
basedOnDependencyAnalysis: false
# Plan 07-06 (VISION-03): no PresenceSignalBus subscriber forwards into
# JarvisTTS or AgentOrchestrator submit / cancelAndSubmit / runTurn.
- name: Check presence-vision isolation (VISION-03)
script: |
"${SRCROOT}/scripts/check-presence-vision-isolation.sh"
runOnlyWhenInstalling: false
basedOnDependencyAnalysis: false
# Plan 07-06 (MEM-02): no literal 768 outside MemoryConstants.embeddingDim.
- name: Check embedding-dim literal (MEM-02)
script: |
"${SRCROOT}/scripts/check-embedding-dim-literal.sh"
runOnlyWhenInstalling: false
basedOnDependencyAnalysis: false
# Plan 09-01 (D-05/D-08, WARNING-2): orchestrator.events has exactly one
# production consumer — OrchestratorEventBroadcaster's drain Task.
- name: Check orchestrator.events single-consumer (Phase 9)
script: |
"${SRCROOT}/scripts/check-orchestrator-events-single-consumer.sh"
runOnlyWhenInstalling: false
basedOnDependencyAnalysis: false
- name: Build webview bundle
script: |
"${SRCROOT}/scripts/build-webview.sh"
runOnlyWhenInstalling: false
basedOnDependencyAnalysis: false
# Plan 05-02 (DEVIATION from plan): xcodegen's `copyFiles` phase doesn't
# resolve target products from BUILT_PRODUCTS_DIR — it expects file paths
# relative to SRCROOT. The plan's `files: [mcp-time.app, mcp-clipboard.app]`
# produced an empty Contents/Helpers/ at build time. Switched to a
# postBuildScript (`Copy MCP helpers into Contents/Helpers/`) that shells
# out to `cp -R` from BUILT_PRODUCTS_DIR — this matches the plan's
# deviation_rules clause #1 ("If xcodegen doesn't directly support nested
# .app bundles via Contents/Helpers/<Name>.app/, generate the helper
# bundles via separate xcodebuild targets and copy them in via a Build
# Phase script").
#
# Code Sign On Copy is NOT enabled anywhere — codesign.sh's deepest-first
# walker is the authoritative signer, preserving per-helper entitlements.
postBuildScripts:
- name: Copy voice models into Contents/Resources/Models/
# Plan 06-05 (Track B-1, 2026-05-03 audit fix): the voice subsystem
# reads ONNX models from `Contents/Resources/Models/` (capital M)
# in `AppDelegate.installVoice` (line 653). On disk, the canonical
# path is the repo-root `Resources/models/` (lowercase). project.yml
# had no copy phase wiring the two together, so the built .app
# bundle's `Contents/Resources/` had ZERO .onnx files and every
# cold launch logged `OpenWakeWordSession init failed (models
# absent?)`. This phase runs `scripts/copy-voice-models.sh` which
# does the canonical-path-to-runtime-path mapping (also corrects
# `openwakeword` → `openWakeWord` capitalization). The script
# gates on MANIFEST.json sha256 not being a `PLACEHOLDER_…` value
# so a forgotten `scripts/fetch-silero-models.sh` is a hard build
# error, not a silent runtime failure.
script: |
"${SRCROOT}/scripts/copy-voice-models.sh"
runOnlyWhenInstalling: false
basedOnDependencyAnalysis: false
- name: Create Contents/Helpers directory
script: |
mkdir -p "${TARGET_BUILD_DIR}/${WRAPPER_NAME}/Contents/Helpers"
runOnlyWhenInstalling: false
basedOnDependencyAnalysis: false
- name: Copy MCP helpers into Contents/Helpers/
script: |
# Replace any prior copies wholesale so stale files don't linger after
# a helper rename or removal. -R preserves the .app bundle structure.
set -euo pipefail
DEST="${TARGET_BUILD_DIR}/${WRAPPER_NAME}/Contents/Helpers"
for HELPER in mcp-time mcp-clipboard mcp-applescript; do
SRC="${BUILT_PRODUCTS_DIR}/${HELPER}.app"
if [ ! -d "$SRC" ]; then
echo "error: helper bundle missing at $SRC (was the ${HELPER} target built first?)" >&2
exit 1
fi
rm -rf "${DEST}/${HELPER}.app"
cp -R "$SRC" "${DEST}/${HELPER}.app"
done
runOnlyWhenInstalling: false
basedOnDependencyAnalysis: false
# Pre-codesign declares the bundle's Info.plist as an inputFile.
# Why: Xcode's built-in `ProcessInfoPlistFile` task (which copies
# App/Info.plist into Contents/Info.plist) has no implicit ordering vs.
# postBuildScripts. With the new build system on Xcode 26, an
# incremental build with no Swift compile work would schedule
# `ProcessInfoPlistFile` AFTER every PhaseScriptExecution — including
# codesign — silently clobbering the bundle Info.plist with the source
# one (which carries `<key>JarvisEntitlementsVerified</key><false/>` by
# design as the static-state default). The app then hard-blocks at boot
# via the AppDelegate marker check. Declaring the bundle plist as an
# inputFile forces Xcode to schedule `ProcessInfoPlistFile` before this
# phase. We also emit a stamp file as the outputFile so the new build
# system can build a clean dependency edge — declaring Info.plist as
# both input and output trips Xcode 26's "mutable output but no other
# virtual output node" check. The stamp file is the virtual output that
# downstream phases (codesign, post-codesign) chain off via their own
# inputFile, locking the rest of the postBuildScript chain behind us.
- name: Verify entitlements (pre-codesign)
script: |
"${SRCROOT}/scripts/verify-entitlements.sh" --pre-codesign
# Stamp file for build-graph ordering (see comment above). The
# script's real side effect is on Info.plist, but we expose this
# stamp as the virtual output so Xcode 26 can sequence later
# phases (codesign, post-codesign) behind us deterministically.
mkdir -p "${DERIVED_FILE_DIR}"
/usr/bin/touch "${DERIVED_FILE_DIR}/pre-codesign.stamp"
runOnlyWhenInstalling: false
basedOnDependencyAnalysis: false
inputFiles:
- $(TARGET_BUILD_DIR)/$(INFOPLIST_PATH)
outputFiles:
- $(DERIVED_FILE_DIR)/pre-codesign.stamp
- name: Codesign bundle (deepest-first)
script: |
# Fall back to CODE_SIGN_IDENTITY (then ad-hoc "-") when CODE_SIGNING_ALLOWED=NO,
# since Xcode does not set EXPANDED_CODE_SIGN_IDENTITY in that case.
export EXPANDED_CODE_SIGN_IDENTITY="${EXPANDED_CODE_SIGN_IDENTITY:-${CODE_SIGN_IDENTITY:--}}"
"${SRCROOT}/scripts/codesign.sh"
runOnlyWhenInstalling: false
basedOnDependencyAnalysis: false
inputFiles:
- $(DERIVED_FILE_DIR)/pre-codesign.stamp
- name: Verify entitlements (post-codesign)
script: |
"${SRCROOT}/scripts/verify-entitlements.sh" --post-codesign
runOnlyWhenInstalling: false
basedOnDependencyAnalysis: false
- name: Verify codesign settings (pbxproj lint)
script: |
"${SRCROOT}/scripts/verify-codesign-settings.sh"
runOnlyWhenInstalling: false
basedOnDependencyAnalysis: false
JarvisAppTests:
type: bundle.unit-test
platform: macOS
sources:
- path: App/Tests/AppTests
settings:
base:
PRODUCT_NAME: JarvisAppTests
PRODUCT_BUNDLE_IDENTIFIER: com.koftwentytwo.jarvis.AppTests
GENERATE_INFOPLIST_FILE: YES
SWIFT_STRICT_CONCURRENCY: complete
SWIFT_VERSION: "6.0"
MACOSX_DEPLOYMENT_TARGET: "14.0"
BUNDLE_LOADER: "$(TEST_HOST)"
TEST_HOST: "$(BUILT_PRODUCTS_DIR)/Jarvis.app/Contents/MacOS/Jarvis"
CODE_SIGN_IDENTITY: "-"
CODE_SIGN_STYLE: Manual
configs:
Debug:
CODE_SIGNING_ALLOWED: NO
CODE_SIGNING_REQUIRED: NO
dependencies:
- target: Jarvis
# Plan 05-05: MCPRuntimeWiringTests imports JarvisMCP, AgentCore, Replay
# for the structural wiring-graph assertions. Adding these new
# package deps to the AppTests target unfortunately disturbs the
# transitive resolution of Config/Keychain/Bus/Shell/Logging that the
# bundle was getting through `target: Jarvis`; declare them
# explicitly so the test bundle links cleanly.
- package: AgentCore
product: AgentCore
- package: AgentCore
product: AgentOrchestrator
- package: MCP
product: JarvisMCP
- package: Replay
product: Replay
- package: swift-log
product: Logging
- package: Config
product: Config
- package: Keychain
product: Keychain
- package: Bus
product: Bus
- package: Shell
product: Shell
- package: Logging
product: JarvisLogging
# Plan 06-05: VoiceWiringTests (App/Tests/AppTests/VoiceWiringTests.swift)
# asserts AppDelegate's voice wiring graph; needs the Voice product to
# @testable import the App target's voice integration code.
- package: Voice
product: Voice
# Track-D D-1: MemoryInstallWiringTests asserts AppDelegate.installMemory's
# post-D-1 wiring graph (extractor + coordinator construct even on vec
# failure; in-process tool registry gating). Requires Memory for the
# @testable import that lets the test reach internal types.
- package: Memory
product: Memory
JarvisEntitlementProbeTests:
type: bundle.unit-test
platform: macOS
sources:
- path: App/Tests/JarvisEntitlementProbeTests
excludes:
- "Info.plist"
settings:
base:
PRODUCT_NAME: JarvisEntitlementProbeTests
PRODUCT_BUNDLE_IDENTIFIER: com.koftwentytwo.jarvis.EntitlementProbeTests
INFOPLIST_FILE: App/Tests/JarvisEntitlementProbeTests/Info.plist
GENERATE_INFOPLIST_FILE: NO
SWIFT_STRICT_CONCURRENCY: complete
SWIFT_VERSION: "6.0"
MACOSX_DEPLOYMENT_TARGET: "14.0"
BUNDLE_LOADER: "$(TEST_HOST)"
TEST_HOST: "$(BUILT_PRODUCTS_DIR)/Jarvis.app/Contents/MacOS/Jarvis"
CODE_SIGN_IDENTITY: "-"
CODE_SIGN_STYLE: Manual
OTHER_SWIFT_FLAGS: "-DJARVIS_ENTITLEMENT_PROBE"
configs:
Debug:
CODE_SIGNING_ALLOWED: NO
CODE_SIGNING_REQUIRED: NO
dependencies:
- target: Jarvis
# =====================================================================
# MCP helper bundles (Plan 05-02)
# =====================================================================
# Each helper ships as a SEPARATELY codesigned nested .app under
# Jarvis.app/Contents/Helpers/<helper>.app/. Per-helper Info.plist +
# entitlements live under mcp-servers/<helper>/Support/. Codesigning is
# done by scripts/codesign.sh's deepest-first walker (NOT by xcodegen's
# "Code Sign On Copy" — that would strip per-helper entitlements). A
# postBuildScript on each target copies the source .entitlements into
# the bundle's Contents/Resources/<helper>.entitlements where codesign.sh
# expects to find it.
mcp-time:
type: application
platform: macOS
sources:
- path: mcp-servers/mcp-time/Sources/mcp-time
settings:
base:
PRODUCT_BUNDLE_IDENTIFIER: com.koftwentytwo.jarvis.mcp-time
PRODUCT_NAME: mcp-time
INFOPLIST_FILE: mcp-servers/mcp-time/Support/Info.plist
GENERATE_INFOPLIST_FILE: NO
CODE_SIGN_ENTITLEMENTS: mcp-servers/mcp-time/Support/mcp-time.entitlements
ENABLE_HARDENED_RUNTIME: YES
CODE_SIGN_STYLE: Manual
CODE_SIGN_IDENTITY: "-"
OTHER_CODE_SIGN_FLAGS: "--options=runtime --timestamp"
SWIFT_STRICT_CONCURRENCY: complete
SWIFT_VERSION: "6.0"
MACOSX_DEPLOYMENT_TARGET: "14.0"
configs:
Debug:
CODE_SIGNING_ALLOWED: NO
CODE_SIGNING_REQUIRED: NO
ENABLE_HARDENED_RUNTIME: NO
OTHER_CODE_SIGN_FLAGS: ""
Release:
DEVELOPMENT_TEAM: 7UC2HETAN9
CODE_SIGNING_ALLOWED: NO
CODE_SIGNING_REQUIRED: NO
dependencies:
- package: swift-sdk
product: MCP
postBuildScripts:
- name: Copy mcp-time.entitlements into bundle Resources
script: |
mkdir -p "${TARGET_BUILD_DIR}/${WRAPPER_NAME}/Contents/Resources"
cp "${SRCROOT}/mcp-servers/mcp-time/Support/mcp-time.entitlements" \
"${TARGET_BUILD_DIR}/${WRAPPER_NAME}/Contents/Resources/mcp-time.entitlements"
runOnlyWhenInstalling: false
basedOnDependencyAnalysis: false
mcp-clipboard:
type: application
platform: macOS
sources:
- path: mcp-servers/mcp-clipboard/Sources/mcp-clipboard
settings:
base:
PRODUCT_BUNDLE_IDENTIFIER: com.koftwentytwo.jarvis.mcp-clipboard
PRODUCT_NAME: mcp-clipboard
INFOPLIST_FILE: mcp-servers/mcp-clipboard/Support/Info.plist
GENERATE_INFOPLIST_FILE: NO
CODE_SIGN_ENTITLEMENTS: mcp-servers/mcp-clipboard/Support/mcp-clipboard.entitlements
ENABLE_HARDENED_RUNTIME: YES
CODE_SIGN_STYLE: Manual
CODE_SIGN_IDENTITY: "-"
OTHER_CODE_SIGN_FLAGS: "--options=runtime --timestamp"
SWIFT_STRICT_CONCURRENCY: complete
SWIFT_VERSION: "6.0"
MACOSX_DEPLOYMENT_TARGET: "14.0"
configs:
Debug:
CODE_SIGNING_ALLOWED: NO
CODE_SIGNING_REQUIRED: NO
ENABLE_HARDENED_RUNTIME: NO
OTHER_CODE_SIGN_FLAGS: ""
Release:
DEVELOPMENT_TEAM: 7UC2HETAN9
CODE_SIGNING_ALLOWED: NO
CODE_SIGNING_REQUIRED: NO
dependencies:
- package: swift-sdk
product: MCP
postBuildScripts:
- name: Copy mcp-clipboard.entitlements into bundle Resources
script: |
mkdir -p "${TARGET_BUILD_DIR}/${WRAPPER_NAME}/Contents/Resources"
cp "${SRCROOT}/mcp-servers/mcp-clipboard/Support/mcp-clipboard.entitlements" \
"${TARGET_BUILD_DIR}/${WRAPPER_NAME}/Contents/Resources/mcp-clipboard.entitlements"
runOnlyWhenInstalling: false
basedOnDependencyAnalysis: false
# ---------------------------------------------------------------------
# mcp-applescript helper (Plan 05-03 / MCP-04)
# ---------------------------------------------------------------------
# Identical xcodegen shape to mcp-time / mcp-clipboard, with ONE difference:
# CODE_SIGN_ENTITLEMENTS points at the per-helper entitlements file that
# carries `com.apple.security.automation.apple-events`. scripts/verify-
# entitlements.sh --post-codesign enforces bidirectionally that this
# helper MUST carry the key and no other helper may.
#
# Bundle ID `com.koftwentytwo.jarvis.mcp-applescript` MUST have the Apple
# Events capability registered at developer.apple.com for Release archive
# notarization to succeed (see .planning/phases/05-mcp/05-03-HUMAN-UAT.md).
# Debug ad-hoc signing works without the capability registration.
mcp-applescript:
type: application
platform: macOS
sources:
- path: mcp-servers/mcp-applescript/Sources/mcp-applescript
settings:
base:
PRODUCT_BUNDLE_IDENTIFIER: com.koftwentytwo.jarvis.mcp-applescript
PRODUCT_NAME: mcp-applescript
INFOPLIST_FILE: mcp-servers/mcp-applescript/Support/Info.plist
GENERATE_INFOPLIST_FILE: NO
CODE_SIGN_ENTITLEMENTS: mcp-servers/mcp-applescript/Support/mcp-applescript.entitlements
ENABLE_HARDENED_RUNTIME: YES
CODE_SIGN_STYLE: Manual
CODE_SIGN_IDENTITY: "-"
OTHER_CODE_SIGN_FLAGS: "--options=runtime --timestamp"
SWIFT_STRICT_CONCURRENCY: complete
SWIFT_VERSION: "6.0"
MACOSX_DEPLOYMENT_TARGET: "14.0"
configs:
Debug:
CODE_SIGNING_ALLOWED: NO
CODE_SIGNING_REQUIRED: NO
ENABLE_HARDENED_RUNTIME: NO
OTHER_CODE_SIGN_FLAGS: ""
Release:
DEVELOPMENT_TEAM: 7UC2HETAN9
CODE_SIGNING_ALLOWED: NO
CODE_SIGNING_REQUIRED: NO
dependencies:
- package: swift-sdk
product: MCP
postBuildScripts:
- name: Copy mcp-applescript.entitlements into bundle Resources
script: |
mkdir -p "${TARGET_BUILD_DIR}/${WRAPPER_NAME}/Contents/Resources"
cp "${SRCROOT}/mcp-servers/mcp-applescript/Support/mcp-applescript.entitlements" \
"${TARGET_BUILD_DIR}/${WRAPPER_NAME}/Contents/Resources/mcp-applescript.entitlements"
runOnlyWhenInstalling: false
basedOnDependencyAnalysis: false
schemes:
Jarvis:
build:
targets:
Jarvis: all
JarvisAppTests: [test]
test:
targets:
- JarvisAppTests
gatherCoverageData: false
run:
config: Debug
profile:
config: Release
analyze:
config: Debug
archive:
config: Release
EntitlementProbe:
build:
targets:
Jarvis: all
JarvisEntitlementProbeTests: [test]
test:
targets:
- JarvisEntitlementProbeTests
gatherCoverageData: false
run:
config: Release
profile:
config: Release
analyze:
config: Release
archive:
config: Release