Created detailed, file-by-file, function-by-function execution plan for P3.
Includes:
- Exact files to modify
- Exact functions to instrument
- Exact event codes to add
- Exact JSDoc patterns
- Exact commands to run
- Batch-by-batch execution plan
Ready for Cursor execution after approval.
Created P3-DESIGN.md with scope for:
- P3.1: Performance optimization & metrics
- P3.2: Enhanced observability
- P3.3: Developer experience improvements
- P3.4: Documentation polish
Updated baseline tag reference to v1.0.11-p2.3-p1.5b-complete
P3 focuses on polish, performance, and developer experience while maintaining all established invariants.
Moved legacy iOS test harness from ios/App/ to test-apps/ios-app-legacy/
Rationale:
- Test harness should not be in published package tree
- Active test app remains at test-apps/ios-test-app/
- Legacy test harness preserved for reference
Verification:
- Confirmed ios/App no longer appears in npm pack --dry-run
- Build passes successfully
- Package structure cleaner
Progress Docs:
- Updated 00-STATUS.md: marked P1.5b complete
- Updated 01-CHANGELOG-WORK.md: added P1.5b completion entry
Updated 03-TEST-RUNS.md with actual test execution results:
- All 3 combined edge case tests passing (100% success rate)
- Test execution command documented
- Robolectric configuration fix noted
P2.1: iOS Schema Versioning Strategy
- Added SCHEMA_VERSION constant and checkSchemaVersion() method in PersistenceController
- Version stored in NSPersistentStore metadata (observability contract, not migration gate)
- CoreData auto-migration remains authoritative; version mismatches logged, not blocked
- Documentation added to ios/Plugin/README.md with migration contract
P2.2: Combined Edge Case Tests
- Added 3 resilience test scenarios to DailyNotificationRecoveryTests.swift:
- test_combined_dst_boundary_duplicate_delivery_cold_start()
- test_combined_rollover_duplicate_delivery_cold_start()
- test_combined_schema_version_cold_start_recovery()
- All tests labeled with @resilience @combined-scenarios comments
- Tests verify idempotency and correctness under combined stressors
P2.3: Android Combined Tests Design
- Created P2.3-DESIGN.md with scope, invariants, and acceptance criteria
- Created P2.3-IMPLEMENTATION-CHECKLIST.md with step-by-step execution plan
- Design ready for implementation to achieve parity with iOS P2.2
Documentation Updates
- Fixed parity matrix: iOS invalid data handling now correctly shows "✅ Recovery tested" with test references
- Updated progress docs (00-STATUS.md, 01-CHANGELOG-WORK.md, 03-TEST-RUNS.md, 04-PARITY-MATRIX.md)
- Updated P2-DESIGN.md to reflect P2.3 scope (Android combined tests)
- Updated SYSTEM_INVARIANTS.md baseline tag references
Baseline Tag
- Created and pushed v1.0.11-p2-complete tag
- Tag represents P2.x completion (schema versioning + combined resilience tests)
All invariants preserved. CI passes. Tests runnable via xcodebuild on macOS.
- Fix getNextNotificationTime() to find earliest scheduled notification
instead of using first request (pendingNotificationRequests doesn't
guarantee order)
- Add comprehensive logging for rollover tracking with DNP-ROLLOVER
prefix for Xcode console filtering
- Reset all notifications and rollover state when scheduling new
notification via scheduleDailyNotification() to ensure clean test
state
- Fix userInfo scope error in handleNotificationDelivery error handler
- Update test app UI to refresh status every 5-10 seconds and
immediately after notification delivery to reflect rollover changes
- Add console logging in UI to debug getNotificationStatus() results
This ensures the UI correctly displays the next notification time after
rollover completes, and test notifications start with a clean slate.
Implement comprehensive data access layer for Core Data entities:
- Add NotificationContentDAO, NotificationDeliveryDAO, and NotificationConfigDAO
with full CRUD operations and query helpers
- Add DailyNotificationDataConversions utility for type conversions
(Date ↔ Int64, Int ↔ Int32, JSON, optional strings)
- Update PersistenceController with entity verification and migration policies
- Add comprehensive unit tests for all DAO classes and data conversions
- Update Core Data model with NotificationContent, NotificationDelivery,
and NotificationConfig entities (relationships and indexes)
- Integrate ReactivationManager into DailyNotificationPlugin.load()
DAO Features:
- Create/Insert methods with dictionary support
- Read/Query methods with predicates (by timesafariDid, notificationType,
scheduledTime range, deliveryStatus, etc.)
- Update methods (touch, updateDeliveryStatus, recordUserInteraction)
- Delete methods (by ID, by key, delete all)
- Relationship management (NotificationContent ↔ NotificationDelivery)
- Cascade delete support
Test Coverage:
- 328 lines: DailyNotificationDataConversionsTests (time, numeric, string, JSON)
- 490 lines: NotificationContentDAOTests (CRUD, queries, updates)
- 415 lines: NotificationDeliveryDAOTests (CRUD, relationships, cascade delete)
- 412 lines: NotificationConfigDAOTests (CRUD, queries, active filtering)
All tests use in-memory Core Data stack for isolation and speed.
Completes sections 4.4, 4.5, and 6.0 of iOS implementation checklist.
Adds complete iOS documentation suite to support iOS implementation
parity with Android features. Includes implementation directives,
recovery scenario mappings, database migration guide, troubleshooting
guide, and test scripts.
New Documentation:
- iOS Implementation Directive: Phase-based implementation guide
mirroring Android structure with iOS-specific considerations
- iOS Recovery Scenario Mapping: Maps Android recovery scenarios
to iOS equivalents with detection logic comparisons
- iOS Core Data Migration Guide: Complete Room → Core Data entity
mappings with implementation checklist for missing entities
- iOS Troubleshooting Guide: Common issues, debugging techniques,
and error code reference
Enhanced Documentation:
- API.md: Added iOS-only methods (permissions, background tasks,
pending notifications), platform differences table, and iOS-specific
error types. Updated version to 2.3.0.
Test Infrastructure:
- iOS test scripts for Phase 1 (cold start), Phase 2 (termination),
and Phase 3 (boot recovery) testing scenarios
All documentation addresses gaps identified in iOS Implementation
Documentation Review and provides foundation for iOS recovery feature
implementation (currently pending).
Note: iOS recovery features (ReactivationManager, scenario detection)
are NOT yet implemented. Documentation is ready to guide implementation.
Adds documentation and test harness for Phase 2 (Force Stop Detection & Recovery).
Changes:
- Add PHASE2-EMULATOR-TESTING.md with detailed test procedures
- Add PHASE2-VERIFICATION.md with test matrix and verification template
- Add test-phase2.sh automated test harness
Test harness features:
- 3 test cases: force stop with cleared alarms, intact alarms, empty DB
- Automatic force stop simulation via adb
- Log parsing for scenario detection and recovery results
- UI prompts for plugin configuration and scheduling
Related:
- Directive: android-implementation-directive-phase2.md
- Requirements: docs/alarms/03-plugin-requirements.md §3.1.4
- Testing: docs/alarms/PHASE2-EMULATOR-TESTING.md
- Verification: docs/alarms/PHASE2-VERIFICATION.md
Remove duplicate status matrix from Section 3.3 and consolidate to Section 11
as single source of truth. Fix all section number references throughout
documentation.
Changes:
- Remove duplicate status matrix table from Section 3.3
- Update all references from "Section 3.3" and "Section 10" to "Section 11"
- Fix phase directive paths to use consistent ../ prefix format
- Fix P1 path typo (missing "directive" in filename)
- Update Doc C status in matrix to reflect completion
- Remove duplicate text in Doc B baseline scenarios
- Remove self-referencing links in Doc B
All status matrix references now point to Section 11, eliminating confusion
about which matrix is authoritative.
Create unified alarm documentation system with strict role separation:
- Doc A: Platform capability reference (canonical OS facts)
- Doc B: Plugin behavior exploration (executable test harness)
- Doc C: Plugin requirements (guarantees, JS/TS contract, traceability)
Changes:
- Add canonical rule to Doc A preventing platform fact duplication
- Convert Doc B to pure executable test spec with scenario tables
- Complete Doc C with guarantees matrix, JS/TS API contract, recovery
contract, unsupported behaviors, and traceability matrix
- Remove implementation details from unified directive
- Add compliance milestone tracking and iOS parity gates
- Add deprecation banners to legacy platform docs
All documents now enforce strict role separation with cross-references
to prevent duplication and ensure single source of truth.
- Fix TestNativeFetcher to read from same SharedPreferences as plugin
- Changed PREFS_NAME from 'DailyNotificationPrefs' to 'daily_notification_timesafari'
- Changed KEY_STARRED_PLAN_IDS from 'starred_plan_ids' to 'starredPlanIds'
- Updated getStarredPlanIds() to read from plugin's SharedPreferences location
- Added diagnostic logging for plan ID loading
- Add updateStarredPlans() call in App.vue mounted() hook
- Ensures starred plan IDs are persisted to native storage on app startup
- Allows native fetcher to read plan IDs from SharedPreferences
- Added diagnostic logging for configuration flow
- Document cross-platform storage pattern
- Created docs/CROSS_PLATFORM_STORAGE_PATTERN.md with architecture flow
- Documented TypeScript → Capacitor bridge → Plugin → Native storage → Native fetcher flow
- Added iOS implementation checklist with code examples
- Clarified why native storage is needed (background workers can't use bridge)
- Add JWT generation logging to test-user-zero.ts
- Log JWT algorithm (ES256K) and DID when token is generated
- Helps diagnose JWT verification issues
Fixes:
- Empty planIds array in native fetcher requests
- SharedPreferences key mismatch between plugin and native fetcher
- Missing documentation for iOS implementation
All changes maintain backward compatibility.
Add configureNativeFetcher() plugin method to enable TypeScript configuration
of native fetchers with API credentials. This provides a cross-platform
mechanism for passing configuration from JavaScript to native code without
relying on platform-specific storage.
- Add configure() method to NativeNotificationContentFetcher interface
(optional, defaults to no-op for fetchers that don't need config)
- Add configureNativeFetcher plugin method in DailyNotificationPlugin
- Add TypeScript definitions and comprehensive JSDoc
- Create NATIVE_FETCHER_CONFIGURATION.md documentation
- Update TestNativeFetcher to use real API endpoint (10.0.2.2:3000)
- Update DemoNativeFetcher Javadoc explaining configure() is optional
- Add configureNativeFetcher() call to demo app's configurePlugin()
Enables host apps to configure native fetchers from TypeScript, keeping
the interface consistent across Android, iOS, and web platforms.
Add INTEGRATION_REFACTOR_CONTEXT.md that maps current codebase to the
Integration Point Refactor plan, including:
- Current state analysis and what needs to be created/modified
- Dependency mapping and implementation checklists
- Testing strategy and open questions
Also update AndroidManifest.xml files to register Application classes.
Add comprehensive documentation and implementation artifacts for refactoring
the plugin to use app-provided content fetchers instead of hardcoded TimeSafari
integration.
Changes:
- Add integration-point-refactor-analysis.md with complete ADR, interfaces,
migration plan, and 7-PR breakdown
- Add INTEGRATION_REFACTOR_QUICK_START.md for quick reference on new machines
- Add src/types/content-fetcher.ts with TypeScript SPI interfaces
- Add examples/native-fetcher-android.kt with Kotlin implementation skeleton
- Add examples/js-fetcher-typescript.ts with TypeScript implementation skeleton
- Add tests/fixtures/test-contract.json for golden contract testing
Architecture Decisions:
- Dual-path SPI: Native Fetcher (background) + JS Fetcher (foreground only)
- Background reliability: Native SPI only, no JS bridging in workers
- Reversibility: Legacy code behind feature flag for one minor release
- Test contract: Single JSON fixture for both fetcher paths
This provides complete specification for implementing the refactor in 7 PRs,
starting with SPI shell and progressing through background workers, deduplication,
failure policies, and finally legacy code removal.
All documentation is self-contained and ready for implementation on any machine.
Add comprehensive implementation guide for creating PlanAction claims
via hydratePlan() function pattern, following established hydrateGive()
and hydrateOffer() patterns.
Changes:
- Add hydrate-plan-implementation-guide.md with complete implementation
details, usage examples, and testing recommendations
- Link implementation guide from getting-valid-plan-ids.md Method 6
- Link implementation guide from localhost-testing-guide.md Option B
The guide provides:
- Complete hydratePlan() function implementation
- PlanActionClaim interface structure
- Helper functions (createAndSubmitPlan, editAndSubmitPlan)
- Usage examples and edge cases
- Testing recommendations and security considerations
This complements plan creation documentation by showing how to
programmatically construct valid PlanAction JWTs for POST /api/v2/claim.
Plans are created by importing JWT claims with @type: PlanAction via
POST /api/v2/claim, not through a dedicated plan creation endpoint.
Changes:
- Document POST /api/v2/claim route in localhost-testing-guide.md
- Add Method 6 (PlanAction JWT import) to getting-valid-plan-ids.md
- Update seed-test-projects.js with warnings about PlanAction JWT requirements
- Clarify that seed script cannot create plans (requires DID signing)
This reflects the actual TimeSafari API architecture where plans are
created as a side effect of importing PlanAction claims.
- Update plan handle ID format to match TimeSafari specification
- Default format: https://endorser.ch/entity/{26-char-ULID}
- ULID: 26 characters, Crockford base32 encoded
- Validates RFC 3986 URI format
- Add ULID generation functions
- generateULID() creates 26-character Crockford base32 strings
- generateValidPlanHandleId() creates full URI format IDs
- Auto-generates valid IDs for testing
- Update DEFAULT_TEST_PROJECT_IDS
- Now generates valid URI format IDs automatically
- Removes placeholder warnings (IDs are now valid format)
- Add URI validation to seed scripts
- Validates plan IDs match RFC 3986 URI format
- Error messages with format examples
- Blocks seeding with invalid formats
- Update test-user-zero.ts config
- Auto-generates valid URI format plan IDs
- Clear documentation of required format
- Note that real IDs from database should replace test IDs
- Update documentation
- Document default URI format specification
- Explain ULID structure and encoding
- Show examples of valid formats
This ensures all test project IDs match the actual TimeSafari plan
handle ID format, preventing validation errors during prefetch testing.
- Replace placeholder plan IDs with explicit warnings
- Change from test_project_X to PLACEHOLDER_ID_X
- Add validation to prevent seeding with placeholders
- Add helpful error messages with usage examples
- Add comprehensive guide for getting valid plan IDs
- Methods: Create projects, query database, check account settings
- Format examples: UUID, hash, custom formats
- Step-by-step instructions for each method
- Troubleshooting common issues
- Update test-user-zero.ts with placeholder warnings
- Clear instructions on how to get real plan IDs
- Links to documentation
- Notes about plan ID format variations
- Improve test server startup
- Warn when using placeholder IDs
- Allow plan IDs via command line argument
- Provide guidance on updating config
The previous test_project_X IDs were not valid for real TimeSafari
databases. Users must now provide actual plan handle IDs from their
TimeSafari setup, making testing more realistic and avoiding silent
failures with invalid IDs.
- Add seed-test-projects.js utility script
- Generates test project data matching API schema
- Creates projects with handleIds, jwtIds, planSummary, previousClaim
- Supports export, seed, and generate commands
- Can seed projects to localhost API server
- Add test-api-server-with-seed.js
- Standalone Express server for localhost testing
- Auto-seeds test projects on startup
- Implements /api/v2/report/plansLastUpdatedBetween endpoint
- Includes debugging endpoints (/api/test/projects, /api/test/health)
- Ready to use immediately without database setup
- Update localhost testing guide
- Add seeding instructions and examples
- Document test API server usage
- Explain how to integrate with existing API servers
This enables testing prefetch functionality even when your localhost
API has no project data. The test server can be started immediately
and provides 5 seeded test projects ready for prefetch queries.
- Add serverMode configuration to test-user-zero config
- Supports: localhost, staging, production, mock, custom
- Auto-detects platform (Android/iOS/Web) for localhost URLs
- Android emulator uses 10.0.2.2 for host machine localhost
- Add getApiServerUrl() helper function
- Returns correct URL based on serverMode and platform
- Handles Android emulator special case (10.0.2.2)
- Update TestUserZeroAPI to respect serverMode
- Checks mock mode before making network calls
- Uses getApiServerUrl() for base URL resolution
- Allows runtime URL switching via setBaseUrl()
- Add localhost testing configuration
- Configurable port and HTTPS settings
- Development mode headers support
- Create localhost testing guide
- Step-by-step setup instructions
- Platform-specific localhost addresses explained
- Quick test API server example
- Troubleshooting common issues
- Monitoring prefetch execution commands
- Update Capacitor config to use getApiServerUrl()
- Fixes breaking change from api.server removal
This enables testing prefetch functionality with a local development
API server running on localhost, perfect for development and debugging
of the 5-minute prefetch scheduling feature.
- Add null safety check to permission callback to prevent NPE
- Fix fetch time calculation bug that caused double subtraction
- scheduleFetch() now accepts pre-calculated fetchTime directly
- Calculate scheduledTime back from fetchTime for worker data
- Add structured logging (DN|FETCH_SCHEDULING) for better traceability
The permission callback was crashing with NullPointerException when
Capacitor passed a null call parameter. The prefetch scheduling had a
logic error where fetchTime was calculated twice - once in the plugin
and once in the fetcher, causing 10-minute delays instead of 5-minute.
Both issues are now fixed and verified working:
- Permission callback handles null gracefully
- Prefetch schedules correctly 5 minutes before notification
- WorkManager job fires at the correct time
- All structured logs appear in logcat
Closes prefetch scheduling investigation.
- Add comprehensive logging to scheduleBackgroundFetch method
- Log scheduledTime and currentTime for comparison
- Log calculated fetch time and delay in ms, hours, and minutes
- Log detailed timing information for future vs past fetch times
- Add fallback path logging for immediate fetch scenarios
- Add logging to scheduleDailyNotification callback
- Log scheduled notification result with content details
- Log when scheduleBackgroundFetch is called
- Add error logging when notification scheduling fails
- Add WorkManager status logging in DailyNotificationFetcher
- Log work ID when work is enqueued
- Log detailed timing information (delay_ms, delay_hours)
- Add past time detection with duration logging
- Improve immediate fetch fallback logging
- Add prefetch scheduling trace documentation
- Document complete code flow from notification to prefetch
- Include debugging checklist and log search patterns
- Add ADB commands for troubleshooting
These changes enable better debugging of prefetch scheduling issues
by providing detailed timing and execution information at every
decision point in the prefetch scheduling flow.
- Add comprehensive User Zero configuration based on TimeSafari crowd-master
- Implement stars querying API client with JWT authentication
- Create UserZeroView testing interface with mock mode toggle
- Add 5-minute fetch timing configuration for notification scheduling
- Include comprehensive documentation and TypeScript type safety
- Fix readonly array and property access issues
- Add proper ESLint suppressions for console statements
Files added:
- docs/user-zero-stars-implementation.md: Complete technical documentation
- src/config/test-user-zero.ts: User Zero configuration and API client
- src/views/UserZeroView.vue: Testing interface for stars querying
Files modified:
- capacitor.config.ts: Added TimeSafari integration configuration
- src/components/layout/AppHeader.vue: Added User Zero navigation tab
- src/router/index.ts: Added User Zero route
- src/lib/error-handling.ts: Updated type safety
Features:
- Stars querying with TimeSafari API integration
- JWT-based authentication matching crowd-master patterns
- Mock testing system for offline development
- 5-minute fetch timing before notification delivery
- Comprehensive testing interface with results display
- Type-safe implementation with proper error handling
Mark off items that are already implemented in the current codebase:
Phase 1 (Foundation):
- Status Matrix Module: Modular architecture already implemented
- Exact-Alarm Gate: DailyNotificationExactAlarmManager exists
- BootReceiver Idempotent: DailyNotificationRebootRecoveryManager exists
Phase 2 (Testing & Reliability):
- Error handling improvements: DailyNotificationErrorHandler exists
- Structured logging: Event IDs already implemented
Phase 3 (Security & Performance):
- Security hardening: PermissionManager, HTTPS enforcement exist
- Performance optimizations: Multiple optimizers exist
- Diagnostics system: Comprehensive error handling and metrics exist
Acceptance Criteria:
- Error Handling: Most items resolved via error handler
- Reliability: All items resolved via existing managers
- Security: All items resolved via existing security measures
This shows the codebase is much more advanced than the plan suggested - most architectural work is already complete!
Implementation plan hardening:
- Document force-stop limitation: system cancels alarms until next explicit launch
- Add force-stop test case: no delivery until launch, then rescheduler restores schedules
- Make Doze degradation unmistakable: fixed string badge 'Degraded (Doze)' with EVT_DOZE_FALLBACK_TAKEN
- Freeze PendingIntent flags rule as Security AC: FLAG_IMMUTABLE unless mutation required
Analysis doc clarification:
- Add closed vs force-stopped distinction: closing/swiping doesn't affect alarms, force-stopping cancels them
These edits harden edge-cases around force-stop behavior and make Doze degradation UI requirements crystal clear for QA testing.
Implementation plan upgrades:
- Add timezone & manual clock change resilience: TimeChangeReceiver with TIME_SET/TIMEZONE_CHANGED
- Codify PendingIntent flags security: FLAG_IMMUTABLE vs FLAG_MUTABLE with examples
- Add notification posting invariants: channel validation and small icon requirements
- Clarify battery optimization UX limits: no ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS prompt
- Move MAX_RESPONSE_SIZE to config: Config.NETWORK_MAX_RESPONSE_SIZE with diagnostics inclusion
- Make Room migrations testable: fallbackToDestructiveMigration(false) test requirement
- Enforce event IDs in PR checklist: CI lint script validation for Log. calls
- Make degraded mode UI unmissable: visual badge + one-tap link to exact-alarm settings
- Add channelId snapshot to diagnostics: include channelId, importance, areNotificationsEnabled()
- Add manual clock skew test case: +10m clock move without timezone change
Analysis doc correctness polish:
- Add safe Application class example: show minimal <application> without android:name
- Show minimal BOOT_COMPLETED example: remove android:priority attribute
- Tighten WAKE_LOCK guidance: revisit only if introducing foreground services
- Mirror Cordova guard in Build Config: already present (no change needed)
- Add error surfaces to Mermaid flow: annotate @PluginMethod and Use Case Handler with → Canonical Error
All changes maintain existing structure with surgical precision edits for correctness, resilience, and reviewer clarity.
Implementation plan improvements:
- Fix event name consistency: DOZE_FALLBACK → EVT_DOZE_FALLBACK_TAKEN in Test Matrix
- Lock receiver export policy as AC: only BootReceiver exported
- Handle unknown Content-Length: add streaming guard for -1 responses
- Ensure single joined error mirrors AC: validation failures return one joined message
- Add webDir echo and device idle hint to diagnostics: include webDir path and isDeviceIdleMode
- Make degradation visible in UI AC: matrix shows 'Degraded timing (Doze)' when fallback active
- Add Room migrations guard: no-op migration and fallbackToDestructiveMigration(false) test
Analysis doc improvements:
- Trim WAKE_LOCK guidance: not required unless explicitly acquiring/releasing wakelocks
- Add Boot receiver priority note: android:priority has no effect for BOOT_COMPLETED
- Fix application android:name accuracy: only set if custom Application class exists
- Mirror Cordova compat note in Build section: include only when using Cordova plugins
- Annotate Mermaid flow with canonical errors: show where canonical errors are produced
- Link Truth Table to test UI buttons: integrate with Open Channel/Exact Alarm Settings buttons
All changes maintain existing structure with surgical precision edits.
Analysis doc improvements:
- Unify runtime naming: fix tree diagram cordova.js → capacitor.js
- Make manifest receivers explicit: add exported attributes and intent filters
- Surface exact-alarm user rule: add decision rule for QA/ops reasoning
- Guard Cordova dependency: add note about Cordova shims requirement
- Add error surfacing to runtime flow: show validation and use-case error paths
- Add auto-generated note to capacitor.plugins.json section
Implementation plan improvements:
- Add diagnostics button to Phase 1 DoD
- Add Doze/Idle case to Test Matrix for false negative prevention
- Make unknown field rejection explicit acceptance criterion
- Link receivers export policy to Manifest Hygiene checklist
- Add event ID requirement to PR checklist for grep-able logs
All changes maintain existing structure with surgical precision edits.