Skip to content

Technical: Notifications

ccpk1 edited this page Mar 10, 2026 · 5 revisions

This document provides technical details about the ChoreOps notification system architecture for developers and advanced users.

Terminology: This document uses terms like "chore ID", "assignee ID", and "entity ID". For precise definitions of Item vs Entity, Internal ID, and Domain Item terminology, see ARCHITECTURE.md - Lexicon Standards.


Notification Replacement System (Smart Tags)

Notifications use a smart tagging system to prevent notification spam. When a new notification is sent with the same tag, it replaces the previous notification instead of stacking.

How Tags Work

Each notification is tagged with a unique identifier combining the config entry ID, entity type, entity ID, and assignee ID:

Multi-Instance Support: The config entry ID is included as the first identifier to ensure notifications from different ChoreOps integrations don't interfere with each other. Each identifier is truncated to 8 characters to stay within mobile notification tag limits.

Notification Type Tag Pattern Example
Chore Approval choreops-status-{entry_id}-{chore_id}-{assignee_id} choreops-status-abc12345-def67890-ghi01234
Reward Approval choreops-rewards-{entry_id}-{reward_id}-{assignee_id} choreops-rewards-abc12345-xyz78901-ghi01234
Assignee Due State Family choreops-status-{entry_id}-{chore_id}-{assignee_id} choreops-status-abc12345-def67890-ghi01234
System Alerts choreops-system-{entry_id}-{assignee_id} choreops-system-abc12345-ghi01234

The assignee due-state family covers:

  • due window
  • due reminder
  • overdue

Those three states now share one canonical mobile identity per chore and assignee. The transport behavior is intentional:

  • Replace: a newer due-state notification is sent on the same canonical tag so it replaces the older one
  • Clear: when the due-state prompt is no longer valid, that canonical tag is explicitly cleared
  • Compatibility clear: legacy due_window and overdue tags are also cleared to remove stale notifications created by older builds

Example: Multiple Chore Notifications

When Zoë claims multiple chores, each notification remains independent:

  1. Zoë claims "Make Bed" (chore1) → Tag: choreops-status-entry123-chore1ab-zoe12345
  2. Zoë claims "Feed Dog" (chore2) → Tag: choreops-status-entry123-chore2cd-zoe12345

Result: Approvers see both notifications because each chore has a unique tag.

Reminder Notifications

When approvers press "Remind in 30 min":

  • A new notification is scheduled with the same tag as the original chore
  • After 30 minutes, the reminder replaces only that specific chore's notification
  • Other chore notifications remain untouched

For assignee due timing, this means a reminder replaces the earlier due-window prompt rather than stacking with it.

Automatic Notification Clearing

The integration automatically clears certain notifications from mobile devices to prevent stale action buttons and notification spam.

Approval/Disapproval Clearing (Multi-Approver Support):

  • When any approver approves or disapproves a chore/reward (via notification button OR dashboard), the integration sends a clear_notification message to all approver devices
  • This removes the original "Chore/Reward Claimed" notification with action buttons from all approvers
  • Example: Assignee claims chore → Both approvers notified → Approver 1 approves via notification button → Notification cleared from both approver devices
  • Why: Prevents other approvers from seeing stale action buttons for already-processed claims

Claim/Approval Path (Assignee transient due-state notifications):

  • When an assignee claims a due-window, reminder, or overdue notification, the assignee transient notification family is cleared from their device
  • When a chore is approved, the assignee transient family is cleared and the approver claim workflow notification is cleared from approver devices

Which Notifications Are Auto-Cleared:

  • Chore Claimed - Cleared when any approver approves/disapproves (any path)
  • Reward Claimed - Cleared when any approver approves/disapproves (any path)
  • Chore Due Window (Assignee) - Replaced by reminder or overdue; cleared when invalidated
  • Chore Reminder (Assignee) - Replaced by overdue; cleared when invalidated
  • Chore Overdue (Assignee) - Replaces earlier due-state prompts; cleared when invalidated
  • Chore/Reward Reminder (30 min) - Cleared when any approver approves/disapproves
  • Chore Disapproved - Auto-clears original approver claim notifications
  • All other notifications - Remain until dismissed by user

Enhanced auto-clearing for assignees

The notification system now provides comprehensive auto-clearing for assignee notifications:

Chore State Transitions:

  • When an assignee claims a chore → The canonical due-state family is cleared from their device
  • When an approver approves any chore → The canonical due-state family is cleared from the assignee's device
  • When an approver disapproves a chore → Assignee receives disapproval notification, approver claim notifications are cleared
  • When a chore is reset or deleted → Invalidated transient prompts are cleared from devices

Why This Matters: Assignees no longer see stale due-window, reminder, or overdue action prompts after the chore state changes. This prevents confusion and duplicate claims.

Approval Aggregation (Chores Only)

When an assignee has multiple pending chores waiting for approval, the integration uses smart aggregation to reduce notification clutter for approvers:

How It Works:

  1. Assignee claims multiple chores → Each claim generates individual notifications to approvers
  2. Approver approves one chore → Old notification is cleared and replaced with an updated aggregated notification:
  • Shows: "[Assignee] has N pending chores. Latest: [Chore Name] (X points)"
  • Includes: Action buttons for the most recent pending chore
  1. Approver continues approving → Notification updates with new count and latest chore details
  2. Last chore approved → No replacement notification sent (all approvals complete)

Rewards: Do not use aggregation. Each reward approval sends independent notifications and clears the original claim notification.

Why This Matters: Approvers with multiple assignees/chores see consolidated status updates instead of a growing list of individual notifications.

Overdue routing contract (rotation + allow steal)

Overdue notification routing is payload-driven to keep manager boundaries clean and avoid duplicate attempts.

Emit contract (ChoreManager):

  • Emits one overdue event per assignee target
  • Includes user_id as the single notification target
  • Includes overdue_message_type with values:
    • default
    • steal_available

Consume contract (NotificationManager):

  • Sends overdue notifications only to payload user_id (no rotation fan-out)
  • Selects assignee overdue message key strictly from overdue_message_type
  • Falls back to the default overdue assignee message when the field is missing or unknown
  • Keeps approver overdue message/action behavior unchanged

Mode behavior:

  • Rotation + allow-steal may emit steal_available for non-turn assignees
  • Independent / Shared (All) / Shared (First) continue using default

Translation System

Notifications are translated per-user using the integration's custom translation architecture:

  • 14 languages supported via Crowdin (English, Spanish, Dutch, French, German, Italian, and more)
  • Per-user preferences - Users can use different languages
  • Automatic fallback to English for missing translations
  • Translation files: translations_custom/{lang}_notifications.json
  • Translation key pattern: {notification_type}_{audience} (e.g., chore_approved_kid, badge_earned_parent)
    • These key suffixes are legacy translation identifiers and remain unchanged.

Notification Translation Flow

  1. Integration determines recipient's language preference
  2. Loads appropriate translation file (en_notifications.json, es_notifications.json, etc.)
  3. Formats notification with dynamic placeholders ({kid_name}, {chore_name}, {points}, etc.)
  4. Sends translated notification to user's mobile device

Key Features:

  • Titles, messages, and action button labels all translated
  • Emojis preserved across all languages
  • Placeholder replacement happens after translation

For complete translation architecture details (sensor entities, translation constants, Crowdin workflow), see ARCHITECTURE.md - Translation Architecture.


Implementation Reference

Notification-Specific Code

  • Notification Manager: managers/notification_manager.py - Core notification logic, smart tagging, auto-clearing, aggregation
  • Action Handler: notification_action_handler.py - Processes action button presses from mobile notifications
  • Translation Files: translations_custom/{lang}_notifications.json - Notification text for 14 languages

Notification Constants

All notification constants follow the TRANS_KEY_NOTIF_* pattern in const.py:

  • TRANS_KEY_NOTIF_TITLE_* - Translation keys for notification titles
  • TRANS_KEY_NOTIF_MESSAGE_* - Translation keys for notification messages
  • TRANS_KEY_NOTIF_ACTION_* - Translation keys for action button labels

Example Pattern:

TRANS_KEY_NOTIF_TITLE_CHORE_APPROVED_KID = "chore_approved_kid"
TRANS_KEY_NOTIF_MESSAGE_CHORE_APPROVED_KID = "chore_approved_kid"

For complete constant naming conventions and patterns, see DEVELOPMENT_STANDARDS.md - Constant Naming Standards.


See Also

Architecture & Design:

Development Standards:


Last Updated: March 2026 (payload-driven overdue steal routing)

Clone this wiki locally