feat: Add enriched classification output and Todoist dedupe sync #4

Merged
daniel merged 4 commits from feature/todoist-dedupe-enrichment into main 2026-04-09 19:01:53 +00:00
Collaborator

Summary

Adds richer structured classification output (details) and a full Todoist upsert/dedupe sync flow owned by this API.

What changed

  • Richer output: details object with summary, suggested_title, suggested_notes, deadline, people, organizations, attachments_referenced, next_steps, key_points, source_signals
  • Optional request metadata: message_id, thread_id, from_address, received_at for deduplication
  • Todoist upsert: SQLite-backed dedupe store; create/update Todoist tasks without duplicates
  • Backward compatible: top-level /classify response fields unchanged

New modules

  • app/dedupe_store.py
  • app/sync.py
  • app/todoist.py

Dedupe precedence

  1. message_id exact match
  2. thread_id match
  3. normalized content fingerprint fallback

Todoist behavior

  • needs_action=false: no task created
  • TODOIST_API_KEY unset: safe no-op (status=disabled)
  • existing task with same classification: unchanged
  • existing task with new context: update in-place
  • material context change: comment added to Todoist task

New env vars

  • TODOIST_API_KEY (required for sync)
  • TODOIST_PROJECT_ID (optional)
  • EMAIL_CLASSIFIER_DB_PATH (optional, defaults to .data/email_classifier.db)

Target version

v0.2.0

## Summary Adds richer structured classification output (`details`) and a full Todoist upsert/dedupe sync flow owned by this API. ### What changed - **Richer output**: `details` object with summary, suggested_title, suggested_notes, deadline, people, organizations, attachments_referenced, next_steps, key_points, source_signals - **Optional request metadata**: `message_id`, `thread_id`, `from_address`, `received_at` for deduplication - **Todoist upsert**: SQLite-backed dedupe store; create/update Todoist tasks without duplicates - **Backward compatible**: top-level `/classify` response fields unchanged ### New modules - `app/dedupe_store.py` - `app/sync.py` - `app/todoist.py` ### Dedupe precedence 1. `message_id` exact match 2. `thread_id` match 3. normalized content fingerprint fallback ### Todoist behavior - `needs_action=false`: no task created - `TODOIST_API_KEY` unset: safe no-op (status=`disabled`) - existing task with same classification: unchanged - existing task with new context: update in-place - material context change: comment added to Todoist task ### New env vars - `TODOIST_API_KEY` (required for sync) - `TODOIST_PROJECT_ID` (optional) - `EMAIL_CLASSIFIER_DB_PATH` (optional, defaults to `.data/email_classifier.db`) ### Target version `v0.2.0`
steve-w added 1 commit 2026-04-09 18:15:12 +00:00
steve-w added 1 commit 2026-04-09 18:18:40 +00:00
steve-w added 1 commit 2026-04-09 18:26:39 +00:00
steve-w added 1 commit 2026-04-09 18:32:36 +00:00
daniel merged commit 17191fc489 into main 2026-04-09 19:01:53 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: daniel/email-classifier#4