HarloPulse App Intents: Siri sync, status snippet, honest type toggles (WWDC26 P0)#13
Conversation
…Pulse (WWDC26 P0) Applies the buildable subset of "Explore advanced App Intents features for Siri and Apple Intelligence" to HarloPulse. All compiler-verified against the iOS 26.5 SDK: zero errors, zero warnings, and appintentsmetadataprocessor EXTRACTS the metadata (was silently skipping until AppIntents.framework became an explicit dependency — without that, Siri/Shortcuts never discover the intents). Session patterns implemented: - IntentDialog(full:supporting:) on every intent — voice-first vs glance responses (SyncPulseIntent: "Synced 3 data types... Mac said accepted=12" / "Synced") - $param.requestValue() clarification — TogglePulseTypeIntent asks "Which data type?" instead of failing when unspecified - ForegroundContinuableIntent — first-time enable of a type routes through needsToContinueInForegroundError so the HealthKit consent sheet happens honestly in the foreground app, never silently skipped - Enhanced DisplayRepresentation — PulseStatusEntity with title/subtitle/sf-symbol - ShowsSnippetView — PulseStatusSnippetView renders pairing state, enabled-type count, last push/result inside Siri results - IntentDonationManager — successful manual syncs are donated (payload-free: the intent carries nothing biometric) so Siri learns the user's sync cadence - AppShortcutsProvider — "Sync HarloPulse" / "HarloPulse status" Architecture: PulseModel became a shared singleton (intents run outside the view hierarchy; a second HealthReader would have double-registered HKObserverQuery callbacks), gained persisted lastPush/lastResult mirrors (cold background launches can report honestly) and an awaitable syncNow() that resolves when every enabled type's fetch+push cycle completes (DispatchGroup over the existing anchor-commit-on-success path — unchanged semantics). xcodegen footgun fixed: an `info:` block makes xcodegen REGENERATE the named plist on every generate — it silently destroyed the HealthKit usage strings once. The block is gone; INFOPLIST_FILE points at the checked-in plist, which now genuinely is the source of truth (comment in project.yml so nobody re-adds it). Not in this PR by design (privacy gates per the adoption plan): no CSSearchableIndex of anything, no IntentValueQuery over Harlo memories, no assistant-schema domains (none exists for coaching; plain AppIntents get Siri/Shortcuts/Spotlight regardless). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
|
Warning Review limit reached
More reviews will be available in 16 minutes and 24 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…st path, stale-result guard Independent pre-merge review found one real blocker: Siri re-enabling an already-on type (or the foreground-continuation racing the @AppStorage onChange) overwrote the activeQueries dict entry, orphaning a still-executing HKObserverQuery that store.stop() could never reach — duplicate pushes, and after a later toggle-off the orphan kept firing with a deleted anchor, re-pushing FULL history for a disabled type (D65 violation). installObserver now stops any existing query before replacing (fixes every caller path), and the toggle intent gains an "already on/off" fast path. Also: syncNow no longer reports yesterday's Mac ack when an empty-delta run pushed nothing ("no new samples since last push"). Verified: zero diagnostics, BUILD SUCCEEDED, metadata extraction runs. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
…lary, privacy gates, P0-P3 Decision surface for the WWDC26 App Intents session: per-pattern verdicts (ADOPT-NOW / ADOPT-NEXT / GATED / REJECT with rationale — notably: NO CSSearchableIndex of traces, IntentValueQuery over memories gated behind architect+counsel, OwnershipProvidingEntity rejected by design since cognitive state is never shared), the shared intent vocabulary across Pulse/HarloGlance/OTTO, the py2app-can't-host- App-Intents constraint and the HarloGlance menu-bar answer, binding privacy gates, and the phased P0-P3 roadmap. P0 ships in PR #13. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
…lary, privacy gates, P0-P3 Decision surface for the WWDC26 App Intents session: per-pattern verdicts (ADOPT-NOW / ADOPT-NEXT / GATED / REJECT with rationale — notably: NO CSSearchableIndex of traces, IntentValueQuery over memories gated behind architect+counsel, OwnershipProvidingEntity rejected by design since cognitive state is never shared), the shared intent vocabulary across Pulse/HarloGlance/OTTO, the py2app-can't-host- App-Intents constraint and the HarloGlance menu-bar answer, binding privacy gates, and the phased P0-P3 roadmap. P0 ships in PR #13. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
What
The buildable-today subset of the WWDC26 advanced App Intents session, applied to HarloPulse — three intents + entity + shortcuts, compiler-verified end-to-end on the iOS 26.5 SDK (zero errors/warnings, App Intents metadata extraction confirmed running).
SyncPulseIntent— "Sync HarloPulse"IntentDialog(full:supporting:)· payload-free donation viaIntentDonationManager(Siri learns sync cadence; nothing biometric in the donation)PulseStatusIntentShowsSnippetView(SwiftUI status card in Siri results) ·ReturnsValue<PulseStatusEntity>· enhancedDisplayRepresentationTogglePulseTypeIntent$dataType.requestValue("Which data type?")clarification ·ForegroundContinuableIntentso first-time enables run the HealthKit sheet honestly in-foregroundTwo real catches while building
appintentsmetadataprocessorneeds the explicit framework dependency or Siri/Shortcuts never see the intents. Fixed inproject.yml.info:block regenerates (overwrites) the named plist — it destroyed the HealthKit usage strings once. Removed; the checked-inInfo.plist+INFOPLIST_FILEis now genuinely the source of truth (with a warning comment).Architecture note
PulseModel→ shared singleton (intents run outside the view tree; a secondHealthReaderwould double-register observers), with persisted status mirrors + an awaitablesyncNow()over the existing anchor-commit-on-success path. Push semantics unchanged.Deliberately absent (privacy gates)
No
CSSearchableIndex, noIntentValueQueryover memories, no donation payloads. Rationale + the full 12-pattern matrix: companion PRdocs/frontier/app-intents-adoption-plan.md.Test on device
Build & run, then: "Hey Siri, Sync HarloPulse" · "Hey Siri, HarloPulse status" · Shortcuts app → HarloPulse actions.
🤖 Generated with Claude Code