This document tracks significant architectural decisions and patterns in the Super Productivity codebase. When making changes that affect these patterns, reference this document and update it if needed.
Status: ✅ Active (since commit 400ca8c1, 2026-01-29)
Decision: The task.dueDay and task.dueWithTime fields are mutually exclusive in new data. When setting dueWithTime, dueDay must be cleared (set to undefined). When reading, dueWithTime takes priority over dueDay.
Rationale:
- Prevents state inconsistency bugs where both fields had conflicting values
- Single source of truth for task scheduling
- Simpler state management
Implementation:
- Writing: Clear
dueDaywhen settingdueWithTime(in meta-reducers) - Reading: Check
dueWithTimefirst; only checkdueDayifdueWithTimeis not set (in selectors) - Legacy Data: Old data with both fields works via priority pattern (no migration needed)
Key Files:
task.model.ts- Field definitions with JSDoctask-shared-scheduling.reducer.ts- Write implementationwork-context.selectors.ts- Read patternplanner.selectors.ts- Read patterntask.selectors.ts- Read pattern
When to Update This Pattern:
- Adding new date/time scheduling fields
- Modifying task scheduling logic
- Working with task selectors that check due dates
Status: ✅ Active (established pattern)
Decision: TODAY_TAG (ID: 'TODAY') is a virtual tag whose membership is determined by task.dueWithTime or task.dueDay, not by task.tagIds. The tag's taskIds field stores only the ordering of tasks, not membership.
Key Invariant: TODAY_TAG.id must NEVER be added to task.tagIds
Rationale:
- Uniform move operations across all tags (virtual and regular)
- Single source of truth for "today" membership (date fields, not tagIds)
- Self-healing ordering (stale entries automatically filtered)
- Natural integration with planner (which uses date fields)
Related: Uses the dueDay/dueWithTime mutual exclusivity pattern (Decision #1)
Key Files:
tag.const.ts- TODAY_TAG definitionwork-context.selectors.ts- Membership computationtask-shared-helpers.ts- Invariant enforcement
When to Update This Pattern:
- Adding new virtual tags
- Modifying tag membership logic
- Working with today's task list
- Before implementing: Check if your change affects any active pattern
- During implementation: Follow the documented patterns
- After implementation: Update this document if you've:
- Changed an existing pattern
- Added a new architectural pattern
- Made a decision that affects future development
Add a new decision record when:
- The decision affects multiple files/modules
- Future developers need to understand "why" not just "what"
- The pattern needs to be followed consistently across the codebase
- The decision prevents a specific class of bugs
### N. [Pattern/Decision Name]
**Status**: ✅ Active | 🚧 Draft | ⚠️ Deprecated | ❌ Superseded
**Decision**: [One-sentence summary of the decision]
**Rationale**:
- [Why was this decision made?]
- [What problems does it solve?]
**Implementation**:
- [How is it implemented?]
- [Key techniques or patterns used]
**Documentation**: [Link to detailed docs]
**Key Files**: [List of primary files implementing this pattern]
**When to Update This Pattern**: [Scenarios when someone should review/update this]docs/sync-and-op-log/- Operation log architecturedocs/long-term-plans/- Future architectural plans
When committing changes related to these patterns, reference this document and the specific decision:
feat(tasks): implement feature X
Uses dueDay/dueWithTime mutual exclusivity pattern (ARCHITECTURE-DECISIONS.md #1)