# Development Changelog **Purpose:** Development changelog tracking work-in-progress changes, refactors, and improvements (not the release CHANGELOG.md). **Owner:** Development Team **Last Updated:** 2025-12-22 (P2.3 complete) **Status:** active For release notes, see [CHANGELOG.md](../../CHANGELOG.md). --- ## 2025-12-22 ### Changed - **2025-12-22 — P2.6 COMPLETE**: Type safety cleanup — eliminated all `any` usages except documented TypeScript mixin limitation - **Batch 1**: Replaced `any` return types in `src/vite-plugin.ts` with concrete types (`UserConfig`, `{ code: string; map: null }`) - **Audit Result**: Codebase already follows type safety best practices; all external boundaries use `unknown`, all data payloads use `Record` - **Remaining Exception**: `src/utils/PlatformServiceMixin.ts:258` — `any[]` required for TypeScript mixin pattern (documented with inline comment) - **Verification**: `rg '\bany\b' src/` returns zero matches except documented exception; TypeScript compilation passes - **CI Status**: All checks pass (`./ci/run.sh`); P2.6 closed out in progress docs - **2025-12-22 — P2.7 COMPLETE**: Created `docs/SYSTEM_INVARIANTS.md` — single authoritative document naming and explaining all enforced invariants - **2025-12-22 — P2.1 COMPLETE**: Schema versioning strategy — iOS explicit version tracking in CoreData metadata - **Implementation**: Added `SCHEMA_VERSION` constant and `checkSchemaVersion()` method in `PersistenceController` - **Approach**: Version stored in `NSPersistentStore` metadata (non-intrusive, observability contract) - **Behavior**: Version logged on store load; mismatches logged as warnings (not blocked) - **Documentation**: Added schema versioning strategy section to `ios/Plugin/README.md` with migration contract - **Parity**: iOS now has explicit version tracking matching Android's Room versioning approach - **Verification**: CI passes; version logging verified; parity matrix updated - **2025-12-22 — P2.2 COMPLETE**: Combined edge case tests — added 3 resilience test scenarios - **Scenario A**: DST boundary + duplicate delivery + cold start (must-have) - Tests recovery idempotency under DST transitions - Verifies only one logical delivery recorded after dedupe - Validates next notification time is DST-consistent - **Scenario B**: Rollover + duplicate delivery + cold start (must-have) - Tests rollover idempotency under re-entry - Verifies duplicate delivery doesn't double-apply state transitions - Validates cold start reconciliation produces correct state - **Scenario C**: Schema version metadata + cold start recovery (nice-to-have) - Confirms P2.1 schema version metadata is present and logged - Verifies version check doesn't interfere with recovery - **Implementation**: Added to `ios/Tests/DailyNotificationRecoveryTests.swift` - **Test Labels**: All tests labeled with `@resilience @combined-scenarios` comments - **Verification**: Tests runnable via xcodebuild on macOS; skipped on Linux CI (expected) - **2025-12-22 — P2.3 COMPLETE**: Android combined edge case tests — achieved parity with iOS P2.2 - **P2.3.1**: Enabled Android test infrastructure - Added AndroidX test dependencies (JUnit, Robolectric, Room testing, coroutines-test) - Enabled unit tests in `android/build.gradle` (removed disabled test configuration) - Created test directory structure: `android/src/test/java/com/timesafari/dailynotification/` - **P2.3.2**: Created test infrastructure helpers - Created `TestDBFactory.kt` with in-memory Room database factory - Added data injection helpers: invalid schedules, duplicate schedules, DST boundary, past schedules - Similar to iOS `TestDBFactory.swift` but uses Room in-memory databases - **P2.3.3**: Implemented 3 combined test scenarios - **Scenario A**: `test_combined_dst_boundary_duplicate_delivery_cold_start()` - DST + duplicate + cold start - **Scenario B**: `test_combined_rollover_duplicate_delivery_cold_start()` - Rollover + duplicate + cold start - **Scenario C**: `test_combined_schema_version_cold_start_recovery()` - Schema version + cold start - **Parity**: Android now has automated combined edge case tests matching iOS P2.2 intent - **Implementation**: Added to `android/src/test/java/com/timesafari/dailynotification/DailyNotificationRecoveryTests.kt` - **Test Labels**: All tests labeled with `@resilience @combined-scenarios` comments - **Verification**: Tests runnable via `./gradlew test` on Android environment - **2025-12-22 — P1.5b COMPLETE**: Moved iOS/App test harness out of published tree - **Action**: Moved `ios/App/` to `test-apps/ios-app-legacy/` (legacy test harness) - **Rationale**: Test harness should not be in published package tree - **Active Test App**: `test-apps/ios-test-app/` remains the active test app - **Verification**: Confirmed `ios/App` no longer appears in `npm pack --dry-run` output - **Impact**: Cleaner package structure, test harness clearly separated from library code - **P1.5 COMPLETE**: Documentation consolidation phase finished - **Step 1**: Updated `docs/00-INDEX.md` to elevate contracts and progress docs as authoritative - **Step 2**: Added drift guards (Purpose, Owner, Last Updated, Status) to all progress docs - **Step 3**: Archived consolidation artifacts to `docs/_archive/2025-12-16-consolidation/` - **Step 4**: Archived legacy iOS checklist; added cross-references to testing, integration, and deployment docs - **Step 5**: Documented CI contracts as policy-as-code in `ci/README.md`; standardized archive directory to `docs/_archive/` - Fixed `exports["./web"]` paths in package.json (now points to actual built files: `dist/esm/web.{js,d.ts}`) - Tightened `package.json` "files" field to exclude `ios/App/` and Xcode user state files - Enhanced `verify.sh` forbidden files check to include `ios/App/` pattern and additional editor/macOS junk files - Moved GitHub Actions workflow to `docs/_reference/` (reference only, not used) - Established local CI as single source of truth (`./ci/run.sh`) - **P1.4**: Created shared core types module (`src/core/`) - Migrated `observability.ts` to use `core/events` (EVENT_CODES, EventLog) - Migrated `definitions.ts` to re-export core contracts/enums instead of duplicating - Migrated `web.ts` to use canonical types from core - **P1.4**: Enhanced `verify.sh` with core module purity enforcement - Platform import blocking: comprehensive regex detects Node builtins + Capacitor/React - Export validation: Node-based check for `package.json.exports['./core']` - Split checks: source validation (pre-build) + artifact validation (post-build) ### Added - `ci/run.sh` - Local CI entrypoint (wraps `./scripts/verify.sh`) - `ci/README.md` - Local CI documentation - `githooks/pre-push` - Git hook to run CI before push - `Makefile` - Convenience targets (`make ci` runs local CI) - **P1.4**: `src/core/errors.ts` - ErrorCode enum, DailyNotificationError class - **P1.4**: `src/core/enums.ts` - PermissionState, ScheduleKind, HistoryKind, etc. - **P1.4**: `src/core/contracts.ts` - Schedule, ContentCache, Config, Callback, History interfaces - **P1.4**: `src/core/events.ts` - EventLog with schemaVersion, EVENT_CODES constants - **P1.4**: `src/core/guards.ts` - Runtime validators - **P1.4**: `src/core/index.ts` - Curated public exports - **P1.4**: `package.json.exports["./core"]` - Core module export path - **P2.3**: `android/src/test/java/com/timesafari/dailynotification/TestDBFactory.kt` - Test database factory with in-memory Room databases - **P2.3**: `android/src/test/java/com/timesafari/dailynotification/DailyNotificationRecoveryTests.kt` - Combined edge case tests (3 scenarios) ### Fixed - **P0.5**: Packaging now excludes `xcuserdata/`, `*.xcuserstate`, `DerivedData/`, and `ios/App/` from npm package - **P0.6**: Fixed broken `exports["./web"]` paths that would have caused import failures - **P1.4**: Eliminated duplicate type definitions (EVENT_CODES, EventLog, Schedule, Config, etc.) ### Notes - Package is now publish-safe with correct exports and no forbidden files - `verify.sh` now hard-fails if forbidden files are detected in `npm pack --dry-run` - **P0 Phase Complete**: All publish safety and CI hardening work finished - Packaging correctness (whitelist-based, forbidden files check) - Export correctness (`exports["./web"]` paths fixed) - CI correctness (local CI as single source of truth) - CI debuggability (failure output preserved) - Documentation alignment (all progress docs match reality) - **P1.4 Phase Complete**: Shared core types module implemented - Core module is single source of truth for shared types - Consumers migrated (observability, definitions, web) - Core purity enforced via verify.sh (platform import blocking, export validation) - No behavior changes - only type consolidation --- ## 2025-12-16 ### Changed - Documentation structure consolidated (139 files organized) - Created progress tracking system (`docs/progress/`) - Removed native Java code from `src/android/` (21 files removed) - Fixed podspec reference in `package.json` (`DailyNotificationPlugin.podspec` → `CapacitorDailyNotification.podspec`) - Fixed markdown lint script paths (`doc/*.md` → `docs/**/*.md`) - Updated parity matrix to reflect actual iOS persistence (CoreData + SQLite) - Updated `.npmignore` to be more defensive (added iOS-specific exclusions, *.tgz, etc.) - Updated `verify.sh` to run iOS tests when xcodebuild is available ### Added - `docs/progress/` directory with tracking documents - `docs/00-INDEX.md` - Documentation index - `docs/CONSOLIDATION_SOURCE_MAP.md` - File mapping audit trail - `docs/CONSOLIDATION_COMPLETE.md` - Consolidation summary - `scripts/verify.sh` - Single verification entrypoint (with build + pack checks + iOS tests) - `ci/run.sh` - Local CI entrypoint (wraps verify.sh) - `ci/README.md` - Local CI documentation - `src/web.ts` - Web platform implementation (throws "not supported" errors) - `.npmignore` - Belt-and-suspenders safety net for npm packaging - `ios/Tests/TestDBFactory.swift` - Test helper for creating test databases and injecting invalid data - `ios/Tests/DailyNotificationRecoveryTests.swift` - iOS recovery tests (equivalent to Android TEST 4) - Invalid records handling - Duplicate delivery deduplication - Rollover idempotency - Cold start recovery - Migration safety ### Removed - `src/android/*.java` - 21 Java files (duplicates of code in `android/src/main/java/`) - These were old copies not used in the build process - Actual native code remains in `android/src/main/java/` ### Notes - **PHASE 1 (Repo Hygiene)** ✅ Complete - **PHASE 3 (Verification Entrypoint)** ✅ Complete - **P0 Build/Publish Safety** ✅ Complete - Build now succeeds (`npm run build` works) - Package includes correct podspec (`npm pack --dry-run` verified) - Verify script includes build and pack checks - Added `.npmignore` as belt-and-suspenders safety net - **Parity Matrix Correction** ✅ Complete - iOS rollover is actually implemented (NotificationCenter pattern) - iOS persistence confirmed (CoreData + SQLite) - **iOS Recovery Testing** ✅ Complete - Added automated recovery tests equivalent to Android TEST 4 - Tests cover invalid data, duplicate delivery, rollover idempotency, cold start, migration safety - Tests require macOS with Xcode to run (skipped on Linux CI) - TypeScript config files (`timesafari-android-config.ts`, `timesafari-ios-config.ts`) kept as they are legitimate TS files - `verify.sh` script includes checks for native code in `src/` directories, build, pack validation, and iOS tests --- ## Template for Future Entries ### YYYY-MM-DD **Changed:** - **Added:** - **Removed:** - **Notes:** - **Related Commits/PRs:** - --- **Last Updated:** 2025-12-22