# Companion Targets — End-to-End Implementation Prompt > **Purpose:** Delegatable prompt for an AI coding agent to bring all 7 watchOS and macOS companion targets from 15-30% stubs to 100% production-ready. > **Date:** 2026-03-27 > **Scope:** 5 watchOS apps + 2 macOS apps across 5 product repos > **Estimated effort:** ~8-12 focused agent sessions --- ## Table of Contents 1. [Global Rules](#1-global-rules) 2. [Target Inventory & Current State](#2-target-inventory--current-state) 3. [ChronoMind watchOS — 25% → 100%](#3-chronomind-watchos) 4. [ChronoMind macOS — 30% → 100%](#4-chronomind-macos) 5. [JarvisJr watchOS — 25% → 100%](#5-jarvisjr-watchos) 6. [JarvisJr macOS — 30% → 100%](#6-jarvisjr-macos) 7. [PeakPulse watchOS — 20% → 100%](#7-peakpulse-watchos) 8. [NomGap watchOS — 35% → 100%](#8-nomgap-watchos) 9. [ByteLyst Auth watchOS — 15% → 100%](#9-bytelyst-auth-watchos) 10. [Cross-Cutting Tasks](#10-cross-cutting-tasks) 11. [Acceptance Criteria](#11-acceptance-criteria) 12. [Build Verification Commands](#12-build-verification-commands) --- ## 1. Global Rules ### Coding conventions (MUST follow for ALL targets) - All logging via `os.Logger` — never use `print()` - All colors from product theme files — never hardcode hex values in views - Use `#if canImport(WatchKit)` / `#if os(watchOS)` for platform-conditional code - watchOS minimum: watchOS 10+. macOS minimum: macOS 14+ - Shared code lives in the iOS app's `Shared/` directory — companion targets import from there - Data flow between iPhone ↔ Watch uses App Group (`UserDefaults(suiteName:)`) + `WCSession` (WatchConnectivity) - Data flow between iPhone ↔ Mac uses App Group shared `UserDefaults` - Commit messages: `feat(watch): description` or `feat(mac): description` - Never add emojis to code unless the existing codebase already uses them in that file - Every new file needs a one-line header comment describing its purpose ### Architecture pattern for ALL watchOS apps ``` ProductWatch/ ├── ProductWatchApp.swift # @main entry point ├── Views/ │ ├── WatchContentView.swift # Main navigation hub │ ├── Watch[Feature]View.swift # Feature-specific views │ └── Components/ # Reusable watch components ├── Store/ │ └── WatchStore.swift # ObservableObject reading from App Group ├── Complications/ │ └── WatchComplications.swift # WidgetKit complications (4 families) └── WatchSessionManager.swift # WCSession delegate (if bidirectional sync needed) ``` ### Architecture pattern for ALL macOS apps ``` ProductMac/ ├── ProductMacApp.swift # @main, MenuBarExtra scene ├── Views/ │ ├── MenuBarPopover.swift # Main popover content │ ├── MacSettingsView.swift # Settings window (TabView) │ └── Components/ # Reusable mac components ├── Store/ │ └── MacStore.swift # ObservableObject, App Group sync └── ProductMac.entitlements # App sandbox + App Group ``` ### Shared code reuse rules Each companion target should import types and engine logic from the iOS app's `Shared/` directory. The companion target should NEVER duplicate: - Model types (timer states, agent configs, session models) - Engine logic (timer calculations, stage computation) - Theme colors - App Group keys and data format The companion target SHOULD have its own: - Views (optimized for small/menu-bar screen) - Store (lightweight, reads from shared data) - Complications/Widgets (WidgetKit) --- ## 2. Target Inventory & Current State | # | Product | Target | Repo | Directory | Current % | Files | Key Gap | | --- | ---------- | ------- | ----------------------- | ------------------------ | --------- | ------------------------- | ------------------------------------------------------------------------------------------------- | | 1 | ChronoMind | watchOS | `learning_ai_clock` | `ios/ChronoMindWatch/` | 50% | 7 files | Missing: WCSession sync, snooze/dismiss actions, haptic cascade, notifications | | 2 | ChronoMind | macOS | `learning_ai_clock` | `ios/ChronoMindMac/` | 45% | 5 files | Missing: MenuBarPopover.swift, create-timer UI, live popover, keyboard shortcuts | | 3 | JarvisJr | watchOS | `learning_ai_jarvis_jr` | `ios/JarvisJrWatch/` | 25% | 3 files (+2 in Watch dir) | Missing: QuickSessionView, WCSession, complications, voice stub, haptics | | 4 | JarvisJr | macOS | `learning_ai_jarvis_jr` | `ios/JarvisJrMac/` | 40% | 5 files | Missing: MenuBarPopover.swift, text session UI, keyboard shortcut handler | | 5 | PeakPulse | watchOS | `learning_ai_peakpulse` | `ios/PeakPulseWatch/` | 30% | 3 files | Missing: real sensors (CLLocation, CMAltimeter), HealthKit workout, WCSession, complications | | 6 | NomGap | watchOS | `learning_ai_fastgap` | `watch/NomGapWatch/` | 55% | 9 files | Missing: StatsView body, WidgetKit migration, WCSession ↔ Expo bridge verification, notifications | | 7 | Auth | watchOS | `learning_ai_auth_app` | `ios/ByteLystAuthWatch/` | 40% | 3 files | Missing: push notification handling, haptic feedback, complication, offline state | --- ## 3. ChronoMind watchOS — 50% → 100% **Repo:** `learning_ai_clock` **Directory:** `ios/ChronoMindWatch/` **Shared code:** `ios/ChronoMind/Shared/` (TimerEngine, Store, Theme, AppGroup, Haptics, Notifications) ### What EXISTS (7 files, ~660 lines) | File | LOC | Status | | ---------------------------------------- | --- | ----------------------------------------------------------------------------------------------- | | `ChronoMindWatchApp.swift` | 16 | Complete | | `Views/WatchContentView.swift` | 177 | Good — timer list, next-up card, empty state | | `Views/WatchQuickTimerView.swift` | 56 | Good — 8 preset quick timers | | `Views/WatchTimerDetailView.swift` | 99 | Good — countdown, urgency badge, pomodoro, cascade progress, snooze info | | `WatchTimerStore.swift` | 125 | Good — reads from SharedTimerDataManager, quick timer creation, tick, haptic on fire | | `Complications/WatchComplications.swift` | 243 | Complete — 4 families (circular, rectangular, inline, corner), AppIntentConfiguration, timeline | | `ChronoMindWatch.entitlements` | — | Present | ### What's MISSING — implement these #### 3.1 WatchConnectivity (WCSession) for real-time sync **File:** `WatchSessionManager.swift` (~120 lines) ``` Purpose: Bidirectional WCSession so the iPhone app can push timer updates in real-time, and the Watch can send commands back (snooze, dismiss, pause, resume). Implementation: - WCSessionDelegate with activationDidCompleteWith, didReceiveMessage, didReceiveApplicationContext - On receive: decode [TimerSnapshot] and update WatchTimerStore - sendCommand(_ command: WatchTimerCommand) method for: snooze, dismiss, pause, resume, complete - WatchTimerCommand enum: snooze(id, minutes), dismiss(id), pause(id), resume(id), complete(id) - Reachability tracking with fallback to App Group polling - Wire into WatchTimerStore.init() — activate session ``` #### 3.2 Action buttons on WatchTimerDetailView **File:** Update `Views/WatchTimerDetailView.swift` ``` Add action buttons at bottom of ScrollView: - When state == .firing: "Snooze 5m" button + "Dismiss" button - When state == .active: "Pause" button - When state == .paused: "Resume" button - When state == .snoozed: "Snooze again" + "Dismiss" - All actions go through WatchSessionManager.sendCommand() - Haptic feedback (WKInterfaceDevice.current().play()) on each action ``` #### 3.3 Haptic cascade warnings **File:** Update `WatchTimerStore.swift` ``` In tick(), when a warning fires (nextWarningTime reached): - Play .notification haptic - If urgency == .critical: play 3x haptic sequence (notification + 0.3s delay + notification) - Update the timer's firedWarnings count - Schedule local notification via UNUserNotificationCenter ``` #### 3.4 Local notifications on Watch **File:** `WatchNotificationHandler.swift` (~50 lines) ``` - UNUserNotificationCenter.requestAuthorization on app launch - Schedule notification when timer is about to fire (from WatchTimerStore) - Custom notification categories with "Snooze" and "Dismiss" actions - UNNotificationCategoryIdentifier: "CHRONOMIND_TIMER_FIRED" ``` #### 3.5 Routines view (optional, stretch) **File:** `Views/WatchRoutineView.swift` (~80 lines) ``` - Read active routine from SharedTimerDataManager - Show current step name + progress - "Next Step" button to advance ``` ### Estimated new code: ~350 lines across 3 new files + 2 updated files --- ## 4. ChronoMind macOS — 45% → 100% **Repo:** `learning_ai_clock` **Directory:** `ios/ChronoMindMac/` **Shared code:** `ios/ChronoMind/Shared/` (same as iOS — TimerEngine functions are pure Swift) ### What EXISTS (5 files, ~520 lines) | File | LOC | Status | | ----------------------------- | --- | --------------------------------------------------------------------------------------------------- | | `ChronoMindMacApp.swift` | 40 | Complete — MenuBarExtra with timer label | | `MacTimerStore.swift` | 181 | Complete — CRUD, tick, notifications, App Group persistence. Uses Shared/ engine functions directly | | `Views/MacSettingsView.swift` | 101 | Complete — General/Data/About tabs | | `ChronoMindMac.entitlements` | — | Present | ### What's MISSING — implement these #### 4.1 MenuBarPopover.swift (~200 lines) **File:** `Views/MenuBarPopover.swift` ``` This is the main UI that appears when clicking the menu bar icon. Layout: - Header: "ChronoMind" + gear icon (opens Settings) - If no timers: empty state with "Create Timer" button - Next-up card: large countdown + urgency color + label + target time - Timer list: compact rows for remaining active timers - Quick actions row: preset buttons (5m, 10m, 25m Pomodoro, Custom) - "Custom Timer" button opens CreateTimerSheet Each timer row has: - Urgency dot + label + countdown - Right-click context menu: Pause, Resume, Snooze 5m, Dismiss, Delete Footer: - "x active timers" label + "Quit" button ``` #### 4.2 CreateTimerSheet.swift (~120 lines) **File:** `Views/CreateTimerSheet.swift` ``` Sheet presented from MenuBarPopover: - TextField for timer label - Picker: Countdown / Alarm / Pomodoro - If Countdown: duration picker (hours/minutes stepper) - If Alarm: DatePicker for target time - If Pomodoro: rounds stepper (default 4) + work/break duration - Urgency picker (5 levels) - Cascade preset picker - "Create" button → store.addCountdown/addAlarm ``` #### 4.3 Keyboard shortcut handler (~40 lines) **File:** Update `ChronoMindMacApp.swift` ``` Add .keyboardShortcut modifiers or NSEvent.addLocalMonitorForEvents: - ⌘N: Create new timer (open CreateTimerSheet) - ⌘,: Open Settings - Space: Pause/resume next firing timer - ⌘Q: Quit app Add .commands { } modifier to the App scene. ``` #### 4.4 MenuBarState.swift (~30 lines) **File:** `MenuBarState.swift` ``` @MainActor ObservableObject: - @Published var showCreateSheet = false - @Published var showTimerDetail: String? = nil // timer ID ``` #### 4.5 Launch at Login **File:** Update `Views/MacSettingsView.swift` ``` Wire the "Launch at Login" toggle to SMAppService.mainApp: - import ServiceManagement - SMAppService.mainApp.register() / unregister() ``` ### Estimated new code: ~390 lines across 3 new files + 2 updated files --- ## 5. JarvisJr watchOS — 25% → 100% **Repo:** `learning_ai_jarvis_jr` **Directory:** `ios/JarvisJrWatch/` **Shared code:** `ios/JarvisJr/Shared/` (Models, Store, Engine, Voice, Theme, AppGroup) ### What EXISTS (5 files, ~230 lines) | File | LOC | Status | | ---------------------------- | -------------------------- | --------------------------------------------------------------------------------- | | `JarvisJrWatchApp.swift` | 13 | Minimal — no store injection | | `WatchContentView.swift` | 85 | Basic — agent list from SharedAgentData, streak banner, links to QuickSessionView | | `QuickSessionView.swift` | exists (in JarvisJrWatch/) | Referenced but need to verify | | `ComplicationProvider.swift` | exists (in JarvisJrWatch/) | Referenced in AGENTS.md | | `WatchTimerStore.swift` | — | NOT present | ### What's MISSING — implement these #### 5.1 WatchAgentStore.swift (~80 lines) ``` @MainActor ObservableObject: - @Published var agents: [WatchAgent] — read from SharedAgentData (App Group) - @Published var streak: Int - @Published var activeSession: WatchSession? - struct WatchAgent: id, name, role, accentColor, sessionLength - struct WatchSession: agentId, startedAt, messages: [(role, text)] - loadFromSharedData() — decode from App Group UserDefaults - Inject into WatchApp via @StateObject ``` #### 5.2 QuickSessionView.swift (~150 lines) ``` If this file doesn't exist or is a stub, implement: - Agent name + role header - "Start Session" button (text-based on Watch, voice is stretch) - Once started: - Scrollable message list (alternating user/agent bubbles) - Text input via dictation (TextField with .watchDictation modifier or voice button) - "End Session" button - On end: summary card (duration, message count) - Send session data back to iPhone via WCSession ``` #### 5.3 WatchSessionManager.swift (~100 lines) ``` WCSessionDelegate: - Receive agent list updates from iPhone - Receive streak updates - Send session transcripts back to iPhone - Reachability handling ``` #### 5.4 Complications (~120 lines) **File:** `Complications/WatchComplications.swift` ``` WidgetKit complications (same pattern as ChronoMind): - AppIntentTimelineProvider reading from SharedAgentData - Circular: streak count or agent initial - Rectangular: "Coach — 5-day streak" or "JarvisJr — Ready" - Inline: "🔥 5 streak" or agent name - Corner: streak number with "JarvisJr" label - 4 supported families: accessoryCircular, accessoryRectangular, accessoryInline, accessoryCorner ``` #### 5.5 Update WatchApp entry point ``` Update JarvisJrWatchApp.swift: - @StateObject var agentStore = WatchAgentStore() - @StateObject var sessionManager = WatchSessionManager() - Inject both as environmentObjects - Activate WCSession in init() ``` ### Estimated new code: ~450 lines across 4 new files + 2 updated files --- ## 6. JarvisJr macOS — 40% → 100% **Repo:** `learning_ai_jarvis_jr` **Directory:** `ios/JarvisJrMac/` **Shared code:** `ios/JarvisJr/Shared/` ### What EXISTS (5 files, ~340 lines) | File | LOC | Status | | ----------------------------- | --- | ------------------------------------------------------------------ | | `JarvisJrMacApp.swift` | 39 | Complete — MenuBarExtra + Settings | | `MacAgentStore.swift` | 119 | Good — agent CRUD, persistence, notifications, 6 default templates | | `MacMenuBarState.swift` | 33 | Basic — isExpanded, showQuickSession, selectedAgentId | | `Views/MacSettingsView.swift` | 111 | Complete — General/Agents/About tabs | ### What's MISSING — implement these #### 6.1 MenuBarPopover.swift (~180 lines) ``` Main popover content (referenced in JarvisJrMacApp but not implemented): - Agent card grid (2 columns): avatar circle + name + role - Click agent → startQuickSession - Streak banner at top - "Talk to [Agent]" button for default agent - If activeSession: show session view (text chat) Agent card: - Colored circle with initial - Name (body bold) - Role (caption) - Total sessions badge (caption2) Session view (inline, replaces agent grid): - Agent name header - Message scroll view - TextField for text input - End session button ``` #### 6.2 MacTextSessionView.swift (~120 lines) ``` Text-based coaching session in the popover: - Agent name + role header - Scrollable message list (bubble style) - TextField + Send button at bottom - "End Session" button in toolbar - On end: increment totalSessions, save via MacAgentStore - Timer showing session duration ``` #### 6.3 Keyboard shortcut ``` Update JarvisJrMacApp.swift: - ⌥⇧J: Start session with default agent (already mentioned in settings) - Register as NSEvent.addGlobalMonitorForEvents - ⌘,: Settings ``` ### Estimated new code: ~300 lines across 2 new files + 1 updated file --- ## 7. PeakPulse watchOS — 30% → 100% **Repo:** `learning_ai_peakpulse` **Directory:** `ios/PeakPulseWatch/` **Shared code:** `ios/PeakPulse/` (Models, Services, Theme, Utils) ### What EXISTS (3 files, ~160 lines) | File | LOC | Status | | ----------------------------- | --- | ----------------------------------------------------------------------------------------------------------------------- | | `PeakPulseWatchApp.swift` | 11 | Minimal stub | | `WatchContentView.swift` | 145 | Functional — activity picker (hike/ski), tracking view with stats grid, start/stop. Uses local Timer (NOT real sensors) | | `PeakPulseWatch.entitlements` | — | Present | ### What's MISSING — implement these #### 7.1 Real sensor integration **File:** `WatchLocationService.swift` (~100 lines) ``` CLLocationManager on watchOS: - requestWhenInUseAuthorization() - Start updating location (desiredAccuracy: .bestForNavigation) - Publish: currentSpeed, currentElevation (altitude), totalDistance, elevationGain - Calculate distance between consecutive CLLocations - Track elevation gain (only count positive deltas) - Wire into WatchContentView replacing the mock values ``` #### 7.2 HealthKit workout session **File:** `WatchWorkoutManager.swift` (~120 lines) ``` HKWorkoutSession + HKLiveWorkoutBuilder: - Start workout session when tracking begins - Activity type: .hiking or .downhillSkiing based on selection - Collect: heart rate, active energy, distance - End workout and save to HealthKit when tracking stops - Request HealthKit authorization for: .heartRate, .activeEnergyBurned, .distanceWalkingRunning ``` #### 7.3 WatchConnectivity sync **File:** `WatchSessionManager.swift` (~80 lines) ``` - Send completed session data to iPhone via WCSession - Receive recent session summaries from iPhone for display - Transfer TrackPoint arrays via transferUserInfo (large data) ``` #### 7.4 WidgetKit complications **File:** `Complications/WatchComplications.swift` (~120 lines) ``` Same pattern as ChronoMind: - Circular: elevation or distance icon - Rectangular: "Last hike: 5.2km, +450m" or "Tracking: 45min" - Inline: "🥾 5.2km +450m" - Corner: distance with "PeakPulse" label - Read from App Group UserDefaults (last session summary) ``` #### 7.5 Session summary view **File:** `Views/WatchSessionSummaryView.swift` (~80 lines) ``` Shown after stopping a session: - Duration - Distance - Elevation gain/loss - Average speed - Max speed - Activity type icon - "Save" button (saves to HealthKit + syncs to iPhone) - "Discard" button ``` #### 7.6 Recent sessions list **File:** `Views/WatchSessionListView.swift` (~60 lines) ``` Tab or navigation destination: - List of recent sessions from App Group - Each row: date, activity type, distance, duration - Tap for detail view (read-only summary) ``` #### 7.7 Update WatchApp and ContentView ``` - Add @StateObject for WatchLocationService, WatchWorkoutManager - Add tab navigation: Tracking | Sessions | (complications handled separately) - Wire real sensor data into tracking stats grid - Add heart rate display if workout session active ``` ### Estimated new code: ~560 lines across 5 new files + 2 updated files --- ## 8. NomGap watchOS — 55% → 100% **Repo:** `learning_ai_fastgap` **Directory:** `watch/NomGapWatch/` **Shared code:** `watch/Shared/` (FastingState, ColorExtension) ### What EXISTS (9 files, ~770 lines) — MOST COMPLETE | File | LOC | Status | | ----------------------------- | ------ | -------------------------------------------------------------------------------------------------- | | `NomGapWatchApp.swift` | 20 | Complete | | `ContentView.swift` | 17 | Complete — TabView with 3 pages | | `FastingTimerView.swift` | 324 | Excellent — timer ring, stage badge, Digital Crown, haptic cascade, controls, next stage countdown | | `HydrationView.swift` | 71 | Complete — water tracking with progress bar | | `StatsView.swift` | exists | Need to verify content | | `WatchSessionManager.swift` | 134 | Good — WCSession delegate, command queue, offline queue | | `ComplicationProvider.swift` | 204 | Complete — CLKComplicationDataSource with 9 families | | `Shared/FastingState.swift` | exists | Shared model | | `Shared/ColorExtension.swift` | exists | Color init(hex:) | ### What's MISSING — implement these #### 8.1 StatsView implementation **File:** Update `StatsView.swift` (~80 lines) ``` Read from App Group (NomGapAppGroup): - Current streak (days) - Total fasts completed - Average fast duration - Longest fast - Total fasting hours Layout: - Streak flame at top - Stats in a 2-column grid (similar to PeakPulse) - "Last 7 days" mini bar chart (optional) ``` #### 8.2 Migrate complications from ClockKit → WidgetKit **File:** Update or replace `ComplicationProvider.swift` (~150 lines) ``` CLKComplicationDataSource is deprecated since watchOS 9. Migrate to WidgetKit: - AppIntentTimelineProvider (same pattern as ChronoMind) - 4 accessory families: circular, rectangular, inline, corner - Read from NomGapAppGroup.loadState() - Show: stage emoji, elapsed time, progress gauge - Keep backward compat: leave CLK version but add WidgetKit version ``` #### 8.3 Local notifications **File:** `WatchNotificationHandler.swift` (~50 lines) ``` - Stage transition notifications (entering ketosis, autophagy) - Hydration reminders (every 2 hours during active fast) - UNUserNotificationCenter on watchOS ``` #### 8.4 WCSession ↔ Expo React Native bridge verification ``` The WatchSessionManager sends/receives via WCSession, but the iPhone side is React Native (Expo). Verify that the Expo plugin (plugins/withWatchApp.js) properly: 1. Registers the WCSession delegate on the RN side 2. Handles incoming WatchCommand messages 3. Sends FastingState updates to the watch via updateApplicationContext If the bridge doesn't exist, create: - ios-extensions/NomGapWatchBridge/WatchBridge.swift — native module - Expo config plugin to register the bridge ``` #### 8.5 Fix print() usage ``` WatchSessionManager.swift line 43 uses print() — replace with os.Logger ``` ### Estimated new code: ~280 lines across 2 new files + 3 updated files --- ## 9. ByteLyst Auth watchOS — 40% → 100% **Repo:** `learning_ai_auth_app` **Directory:** `ios/ByteLystAuthWatch/` ### What EXISTS (3 files, ~215 lines) — surprisingly functional | File | LOC | Status | | ---------------------------- | --- | ---------------------------------------------------------------------------------------------------- | | `ByteLystAuthWatchApp.swift` | 17 | Complete — uses os.Logger | | `WatchContentView.swift` | 196 | Good — polls `/auth/mfa/push/pending`, approve/deny UI, loading/error/empty states, 10s auto-refresh | | `Info.plist` | — | Present | ### What's MISSING — implement these #### 9.1 Push notification handling **File:** `WatchNotificationHandler.swift` (~60 lines) ``` UNUserNotificationCenter for push MFA: - Register for remote notifications in WatchApp init - Handle incoming push with approval request data - Create actionable notification with "Approve" and "Deny" buttons - UNNotificationCategory: "MFA_APPROVAL" - On action: call respond(to:approved:) API ``` #### 9.2 Haptic feedback **File:** Update `WatchContentView.swift` ``` Add haptics for: - New approval received: .notification - Approve action: .success - Deny action: .failure - Error state: .retry ``` #### 9.3 WidgetKit complication **File:** `Complications/AuthComplication.swift` (~100 lines) ``` AppIntentTimelineProvider: - Circular: shield icon (green if no pending, orange if pending) - Rectangular: "ByteLyst Auth — 2 pending" or "All clear" - Inline: "🛡️ 2 pending" or "🛡️ All clear" - Corner: pending count with shield label - Read pending count from App Group (set by main app or watch polling) - Timeline refresh: every 5 minutes, or .after(nextPoll) ``` #### 9.4 Offline/no-auth state improvement **File:** Update `WatchContentView.swift` ``` When no token is available: - Show QR code prompt: "Scan from iPhone to pair" - Or: instruction to open ByteLyst Auth on iPhone - Add a "Refresh" button that re-checks App Group keychain When offline: - Show last-known pending count from App Group cache - Badge: "Last updated: X minutes ago" ``` #### 9.5 WCSession for token sync **File:** `WatchSessionManager.swift` (~60 lines) ``` The main app should push the access token to the Watch via WCSession. On the Watch side: - Receive token via didReceiveApplicationContext - Store in shared Keychain (App Group) - Trigger approval refresh ``` ### Estimated new code: ~220 lines across 3 new files + 1 updated file --- ## 10. Cross-Cutting Tasks ### 10.1 XcodeGen project.yml updates For repos that use XcodeGen (`project.yml`), ensure the companion targets are properly declared: - **ChronoMind:** `ios/project.yml` — verify ChronoMindWatch and ChronoMindMac targets include all new files - **JarvisJr:** `ios/project.yml` — verify JarvisJrWatch and JarvisJrMac targets - **PeakPulse:** `ios/project.yml` — verify PeakPulseWatch target Each watchOS target needs: ```yaml targets: ProductWatch: type: application platform: watchOS deploymentTarget: '10.0' sources: - path: ProductWatch - path: Product/Shared # shared code from iOS app settings: INFOPLIST_FILE: ProductWatch/Info.plist PRODUCT_BUNDLE_IDENTIFIER: com.saravana.product.watchkitapp WATCHOS_DEPLOYMENT_TARGET: '10.0' dependencies: - target: ProductWidgets # if WidgetKit complications ``` ### 10.2 App Group entitlements Verify every companion target has the correct App Group in its entitlements: | Product | App Group | | ---------- | ------------------------------------------------- | | ChronoMind | `group.com.chronomind.shared` | | JarvisJr | `group.com.saravana.jarvisjr` | | PeakPulse | `group.com.saravana.peakpulse` | | NomGap | (defined in Expo app.json or withWatchApp plugin) | | Auth | `group.com.bytelyst.auth` | ### 10.3 Shared helper: `formatTime()` global function Several watch views reference a `formatTime(_:)` free function. Ensure it exists in a shared utility file accessible to the watchOS target: ```swift func formatTime(_ date: Date) -> String { let formatter = DateFormatter() formatter.timeStyle = .short return formatter.string(from: date) } ``` ### 10.4 Theme color access from companion targets Each companion target needs access to the product's theme colors. Options: 1. Add the theme file (e.g., `ChronoMindTheme.swift`) to the Watch target's sources in project.yml 2. Or create a lightweight `WatchTheme.swift` with just the needed colors --- ## 11. Acceptance Criteria For EACH companion target, the implementation is 100% when: ### watchOS targets - [ ] App launches in watchOS Simulator without crashes - [ ] Main content view shows real data from App Group - [ ] At least one bidirectional action works (Watch → iPhone command) - [ ] WCSession activates and receives data - [ ] WidgetKit complications render in all 4 accessory families - [ ] Haptic feedback fires on key actions - [ ] Local notifications schedule correctly - [ ] No `print()` statements — all `os.Logger` - [ ] All colors from theme — no hardcoded hex in views - [ ] Builds clean with `xcodebuild -scheme ProductWatch -destination 'platform=watchOS Simulator,name=Apple Watch Series 10 (46mm)' build` ### macOS targets - [ ] App launches as menu bar app - [ ] Menu bar icon shows relevant live data (countdown / agent name) - [ ] Popover opens with correct content - [ ] Create/interact actions work (create timer / start session) - [ ] Settings window opens with ⌘, - [ ] Launch at Login toggle works via SMAppService - [ ] App Group syncs data from iOS app - [ ] Notifications fire correctly - [ ] No `print()` statements - [ ] Builds clean with `xcodebuild -scheme ProductMac -destination 'platform=macOS' CODE_SIGNING_ALLOWED=NO build` --- ## 12. Build Verification Commands Run after implementing each target: ```bash # ── ChronoMind ───────────────────────────────────── cd /path/to/learning_ai_clock/ios # watchOS xcodebuild -scheme ChronoMindWatch \ -destination 'platform=watchOS Simulator,name=Apple Watch Series 10 (46mm)' \ build # macOS xcodebuild -scheme ChronoMindMac \ -destination 'platform=macOS' \ CODE_SIGNING_ALLOWED=NO build # ── JarvisJr ────────────────────────────────────── cd /path/to/learning_ai_jarvis_jr/ios xcodebuild -scheme JarvisJrWatch \ -destination 'platform=watchOS Simulator,name=Apple Watch Series 10 (46mm)' \ build xcodebuild -scheme JarvisJrMac \ -destination 'platform=macOS' \ CODE_SIGNING_ALLOWED=NO build # ── PeakPulse ───────────────────────────────────── cd /path/to/learning_ai_peakpulse/ios xcodebuild -scheme PeakPulseWatch \ -destination 'platform=watchOS Simulator,name=Apple Watch Series 10 (46mm)' \ build # ── NomGap ──────────────────────────────────────── # NomGap watchOS requires an Xcode project (may need manual setup # since the main app is React Native/Expo) cd /path/to/learning_ai_fastgap # Verify via Expo custom dev client or standalone Xcode project # ── ByteLyst Auth ───────────────────────────────── cd /path/to/learning_ai_auth_app/ios xcodebuild -scheme ByteLystAuthWatch \ -destination 'platform=watchOS Simulator,name=Apple Watch Series 10 (46mm)' \ build ``` --- ## Summary: Total New Code Estimate | Target | New Files | New LOC | Updated Files | | ------------------ | --------- | ---------- | ------------- | | ChronoMind watchOS | 3 | ~350 | 2 | | ChronoMind macOS | 3 | ~390 | 2 | | JarvisJr watchOS | 4 | ~450 | 2 | | JarvisJr macOS | 2 | ~300 | 1 | | PeakPulse watchOS | 5 | ~560 | 2 | | NomGap watchOS | 2 | ~280 | 3 | | Auth watchOS | 3 | ~220 | 1 | | **TOTAL** | **22** | **~2,550** | **13** | **Recommended execution order:** ChronoMind (watch + mac) → PeakPulse (watch) → JarvisJr (watch + mac) → NomGap (watch) → Auth (watch) This order prioritizes the most feature-complete iOS apps first, ensuring the Shared/ code they depend on is already proven.