Workflow: Capture a Task¶
Realizes: spec_v3.md §1.1 Active Task Capture,
§5.5.1 Natural Language Task Parsing.
Scenario¶
Nick sends a Discord DM to Donna:
"Remind me to review the quarterly plan tomorrow at 10am, high priority."
Donna parses the message, classifies priority, deduplicates against existing tasks, persists the row, schedules reminders, and replies.
Path Through the Code¶
- Inbound.
donna.integrations.discord_botreceiveson_messageand forwards(text, user_id, channel_id)to the orchestrator. - Orchestrator intent routing.
donna.orchestratoridentifies this as a task-capture intent and invokes theparse_taskskill. - Skill execution.
donna.skills.executor.SkillExecutorruns the YAML-definedparse_taskskill step-by-step. - Model call.
donna.models.router.ModelRouter.completeroutes to the configured model fortask_parse(seeconfig/donna_models.yaml) and logs an invocation row viadonna.logging.invocation_logger. - Schema validation. The structured output is validated against
schemas/task_parse_output.json. The parser emits a structuredtime_intent(the when of the task); if the model omits it, an LLM-free fallback re-extracts common date phrasings. See Task System → Time Intent. - Dedup.
donna.tasks.dedupruns deduplication (spec_v3.md §5.3— fuzzy title match + LLM semantic comparison). - Persist.
donna.tasks.databasewrites the row (includingtime_intent_json, from whichdeadline/deadline_typeare derived);donna.integrations.supabase_syncmirrors it. - Route. The
routing gate inspects the
time_intent. Because this task is time-bound (exact, "tomorrow at 10am"), it goes to the Scheduler immediately — it is not deferred for the Challenger. An undated task would instead stay inbacklog; a recurring one goes to the automation pipeline. - Schedule.
donna.schedulingplaces the task and enqueues reminder cadence (T-24h, T-1h, T). If no slot exists before the deadline, the task transitions toneeds_scheduling(perconfig/task_states.yaml) instead of stranding in backlog. - Reply. The Discord bot confirms back with slot-aware,
persona-voice copy generated by
donna.integrations.confirmation_copy— e.g. the confirmed time for a scheduled task, a "couldn't find a slot" message when unplaceable, or a backlog note for undated tasks. (This replaces the old static "Scheduled: pending." reply.)
Sequence¶
sequenceDiagram
participant U as User
participant D as discord_bot
participant O as orchestrator
participant S as SkillExecutor
participant R as ModelRouter
participant V as schema validator
participant DB as tasks.database
participant SC as scheduling
U->>D: DM text
D->>O: route(text, user_id)
O->>S: run(parse_task, text)
S->>R: complete(prompt, "task_parse", user_id)
R-->>S: structured JSON
S->>V: validate(task_parse_output)
V-->>S: ok
S->>S: run(dedup_check, parsed)
S-->>O: Task (with time_intent)
O->>DB: INSERT tasks WHERE user_id=?
O->>SC: routing_gate.route(time_intent, priority)
SC->>SC: time-bound → schedule now (skip Challenger)
SC->>SC: enqueue reminders
O-->>D: persona-voice confirmation (slot-aware)
D-->>U: reply
Observability¶
Every hop emits a structured log line with correlation_id, user_id,
task_id. See Domain → Observability.