feat(planner): bridge todos with dueDate into the candidate pool (#472) #473

Merged
pm-bot merged 1 commit from feat/todo-candidate-writer into main 2026-06-13 22:11:15 +02:00
Collaborator

Summary

  • Todos mit dueDate werden synchron als source='todo'-Candidates geschrieben — /heute plant sie jetzt automatisch.
  • Schließt die UX-Lücke aus rc21: Empty-State-CTA „Manuelle Aufgabe erstellen → /todo" war eine Sackgasse, weil Todos und Candidates getrennt waren.
  • Sync-Source-Pattern (Option a aus arch-Diskussion in #472): jedes addItem/updateItem/removeItem läuft jetzt in db.transaction und ruft den TodoCandidateWriter im selben Tx auf.

Implementation

  • Migration 0021: candidate_source += 'todo' (additiv, forward-only)
  • TodoCandidateWriterService.upsertFromTodo(tx, ownerSub, listItemId, data):
    • dueDate=null → bestehenden Candidate löschen (Insel-Schutz)
    • dueDate gesetzt → upsert mit title, priority, latestAt=endOfDay(dueDate), lifecycleState=done?'done':'pending'
    • ON CONFLICT (ownerSub, source, sourceRef) DO UPDATE
  • removeForTodo(tx, ownerSub, listItemId) löscht via sourceRef

Test plan

  • Unit: todo-candidate-writer.service.spec.ts (7 tests) — mapping, trigger condition, idempotency
  • Unit: lists.service.spec.ts an neuen Constructor angepasst
  • Integration: todo-candidate-flow.int-spec.ts (7 E2E-Tests):
    • create todo (dueDate=heute) → erscheint in /planner/today
    • todo ohne dueDate → KEIN candidate
    • update auf dueDate=heute → nachträglich auf /heute
    • update auf dueDate=null → candidate weg
    • done=true → lifecycleState=done
    • delete item → candidate weg
    • shopping-item legt KEINEN candidate an
  • Alle 459 unit tests + 91 integration tests grün
  • lint + typecheck clean

Closes #472

🤖 Generated with Claude Code

## Summary - Todos mit `dueDate` werden synchron als `source='todo'`-Candidates geschrieben — `/heute` plant sie jetzt automatisch. - Schließt die UX-Lücke aus rc21: Empty-State-CTA „Manuelle Aufgabe erstellen → /todo" war eine Sackgasse, weil Todos und Candidates getrennt waren. - Sync-Source-Pattern (Option a aus arch-Diskussion in #472): jedes `addItem`/`updateItem`/`removeItem` läuft jetzt in `db.transaction` und ruft den TodoCandidateWriter im selben Tx auf. ## Implementation - Migration 0021: `candidate_source += 'todo'` (additiv, forward-only) - `TodoCandidateWriterService.upsertFromTodo(tx, ownerSub, listItemId, data)`: - dueDate=null → bestehenden Candidate löschen (Insel-Schutz) - dueDate gesetzt → upsert mit title, priority, latestAt=endOfDay(dueDate), lifecycleState=done?'done':'pending' - ON CONFLICT (ownerSub, source, sourceRef) DO UPDATE - `removeForTodo(tx, ownerSub, listItemId)` löscht via sourceRef ## Test plan - [x] Unit: todo-candidate-writer.service.spec.ts (7 tests) — mapping, trigger condition, idempotency - [x] Unit: lists.service.spec.ts an neuen Constructor angepasst - [x] Integration: todo-candidate-flow.int-spec.ts (7 E2E-Tests): - create todo (dueDate=heute) → erscheint in /planner/today - todo ohne dueDate → KEIN candidate - update auf dueDate=heute → nachträglich auf /heute - update auf dueDate=null → candidate weg - done=true → lifecycleState=done - delete item → candidate weg - shopping-item legt KEINEN candidate an - [x] Alle 459 unit tests + 91 integration tests grün - [x] lint + typecheck clean Closes #472 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(planner): bridge todos with dueDate into the candidate pool (#472)
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
afffe5abea
Todos mit dueDate werden synchron als source='todo'-Candidates geschrieben,
sodass /heute sie planen kann. Schließt die UX-Lücke aus rc21 (Empty-State-CTA
„Manuelle Aufgabe erstellen → /todo" führte ins Leere).

- Drizzle migration 0021: candidate_source += 'todo' (additiv)
- TodoCandidateWriterService.upsertFromTodo / removeForTodo (Sync-Source-Pattern)
- ListsService.addItem/updateItem/removeItem wrappen jetzt in db.transaction
  und rufen den Writer im selben Tx auf
- E2E-Integration: create todo (dueDate=heute) → POST /planner/run → erscheint
  in /planner/today

Refs #472

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
pm-bot merged commit beac10a6a2 into main 2026-06-13 22:11:15 +02:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
admin-mrrm/mrrmlabapp!473
No description provided.