personal memory agent

push: ship Wave 3 push server (root /api/push/*, APNs dispatch) master

Root Flask blueprint at /api/push/* with register/unregister/status/test endpoints, backed by a dedicated push runtime that subscribes to cortex finish events for Daily Briefing and runs a 60s periodic check for Pre-Meeting Prep. Three categories ship: SOLSTONE_DAILY_BRIEFING, SOLSTONE_PRE_MEETING_PREP, SOLSTONE_AGENT_ALERT. Commitment Nudge is deferred to Wave 3.1 (LedgerItem has no machine-readable due date); the constant + payload shape are defined server-side for iOS forward-compat. APNs transport is httpx + PyJWT with ES256 bearer JWTs cached for 55 minutes. BadDeviceToken / Unregistered responses auto-prune the device. Device tokens are never logged beyond the last 4 chars; JWTs and .p8 contents never logged at all. PII fallback is hardcoded in payload builders — lock-screen bodies are generic; detail lives in `data`. Write ownership: think/push/devices.py owns push_devices.json, think/push/triggers.py owns nudge_log.jsonl. Layer hygiene stays clean without allowlist entries. Live APNs validation is deferred pending Apple Developer enrollment; the post-enrollment checklist lives in docs/design/push.md §10. Design: docs/design/push.md Spec sections: cpo/specs/in-flight/mobile-ux-native-ios-android.md §§3, 3.2, 3.3, 3.4, 8.3 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>