1. config/schema.sql — Added timezone_name VARCHAR(100) to user_preferences table + an ALTER TABLE migration at the bottom for existing DBs.
2. core/tz.py — Rewrote with dual-path timezone support:
- Request context: _get_request_tz() now checks X-Timezone-Name header (IANA) first, falls back to X-Timezone-Offset
- Background jobs: New tz_for_user(user_uuid) and user_now_for(user_uuid) read stored timezone_name from prefs, fall back to numeric offset, then UTC
- All existing function signatures (user_now(), user_today()) preserved for backward compat
3. scheduler/daemon.py — Fixed 3 bugs:
- _user_now_for() now delegates to tz.user_now_for() which uses IANA timezone names (DST-safe)
- check_nagging() — replaced datetime.utcnow() with _user_now_for(user_uuid) so nags evaluate in user's timezone
- poll_callback() — replaced single UTC midnight check with _check_per_user_midnight_schedules() that iterates users and creates daily schedules at their local midnight
4. api/routes/preferences.py — Added "timezone_name" to allowed PUT fields.
5. synculous-client/src/lib/api.ts — Added X-Timezone-Name header to every request + added timezone_name to preferences update type.
6. synculous-client/src/app/dashboard/layout.tsx — Now syncs both timezone_offset and timezone_name (via Intl.DateTimeFormat().resolvedOptions().timeZone) on session start.
Add a visual status indicator showing:
- Online/offline status with colored dot indicator
- Last seen timestamp
- Typical wake time (if available)
The indicator now displays whenever Discord notifications are enabled,
not just when presence tracking is active.
The API requires adaptive_mode when adaptive_timing_enabled is true,
but the frontend was only sending the enabled flag. This caused 400
errors when users tried to toggle adaptive timing on.
Now the toggle sends both fields when enabling, satisfying the API
validation requirements.
- #11: Add validation to prevent simultaneous scheduling of routines and medications
- Added _check_schedule_conflicts() in routines.py
- Added _check_med_schedule_conflicts() in medications.py
- Returns HTTP 409 with descriptive error on conflict
- #10: Fix medication reminders not being sent
- Added call to check_adaptive_medication_reminders() in daemon poll loop
- #9: Fix can't enable adaptive timing
- Added proper error handling and logging in update_adaptive_settings()
- Returns meaningful error message on database failures
- #8: Fix nagging not working
- Added debug logging for missing settings
- Auto-create medication schedules if they don't exist
- Improved error logging (warning -> error)
- Create knowledge.py handler with dynamic book selection
- Support list/select/query actions for multiple books
- Implement vector search with cosine similarity
- Add knowledge detection to AI parser config
- Cache embeddings per-book for performance
- Add numpy dependency for vector operations
- Create knowledge.py handler with dynamic book selection
- Support list/select/query actions for multiple books
- Implement vector search with cosine similarity
- Add knowledge detection to AI parser config
- Cache embeddings per-book for performance
- Changed timer button to red/tomato themed pill button
- Added red background, border, and hover effects
- Shows remaining time when running
- Green pulsing indicator when active
- Made TomatoIcon slightly larger (22px) for visibility