Core — Task Reconciliation
source field ownership tracking (user/system), PUT /meetings/:id/tasks/system reconciliation semantics, and TaskEvent broadcast during the live session.
Core — Task Reconciliation
Owner: Core Engineer Domain: core Complexity: M Prerequisite: Milestone 04 merged
When this slice is complete, every task tracks whether its fields are source: system (generated, unedited) or source: user (user-created, or a system task the user has edited or completed). During an active recording, task create/update/complete/delete fan out as com.wordloop.task.v1 events. PUT /meetings/{id}/tasks/system reconciles the final generated candidate set against live drafts and user edits: unedited system tasks absent from the new set are removed, user-owned tasks and edits are preserved by identity (not duplicated), and a task the user deleted is reported back as an explicit conflict rather than silently resurrected.
Required Capabilities
-
POST /tasks { content, meeting_id, source }creates a task with the givensource(userorsystem, service auth required forsystem). -
PATCH /tasks/{id}on any field — including marking a taskcompleted— promotes asource: systemtask tosource: user. -
DELETE /tasks/{id}removes the task. -
GET /tasks?meeting_id={id}&filter=alllists all tasks for the meeting. - Every create/update/delete on a meeting-bound task broadcasts
com.wordloop.task.v1 { meeting_id, task, action }to the meeting's live session. -
PUT /meetings/{id}/tasks/system { tasks: [...] }reconciles the final candidate set: a candidate matching an existing live draft by content keeps that draft's identity instead of delete+insert; unmatched drafts are replaced; user-created and user-edited tasks are preserved and not duplicated even when a final candidate matches their content. - A final candidate matching a task the user deleted is not silently recreated — it is reported in the response's
conflicts[]withreason: "deleted_by_user". -
PUT /meetings/{id}/tasks/systemresponds{reconciled: int, conflicts: [{content, reason}]}and is idempotent — re-running it with the same candidate set does not change the task set again.
Dependencies
- Milestone 04 (
live-transcript-to-final-rebuild) must be merged — the live recording WebSocket session used to exercise task events during an active session.
Domain Notes
Reconciliation is identity-preserving, not delete-and-recreate: a final candidate whose content matches an existing task (live draft, or user-owned) keeps that task's row and id. This is what lets a user-owned edit or completion survive finalization even though the final generated set never mentions the edited content verbatim in the same words the user typed.
Test Cases
Test cases map to tests/bets/meeting-recording/test_milestone_08_live_tasks_and_reconciliation.py. Run via ./dev test bet meeting-recording.
| Test | Location | Assertion |
|---|---|---|
test_draft_tasks_appear_during_live_transcript | test_milestone_08 | A source: system task created via the service write-back during an active recording fans out as com.wordloop.task.v1 { action: created } and is listed with source: system. |
test_user_can_create_edit_complete_and_delete_tasks | test_milestone_08 | User task create, content edit, completion, and delete each succeed and are reflected in GET /tasks/{id}; the live session sees the CRUD sequence as ["created", "updated", "updated", "deleted"] task.v1 events. |
test_user_owned_task_fields_are_tracked | test_milestone_08 | Editing a source: system task's content promotes it to source: user; completing a source: system task also promotes it; an untouched generated task stays source: system. |
test_final_rebuild_reconciles_generated_task_candidates | test_milestone_08 | A final candidate set is reconciled against live drafts: a matching candidate keeps the existing task's id (case/whitespace-insensitive match), an unmatched draft is replaced, a brand-new candidate is added as source: system; re-running reconciliation with the same candidates is idempotent. |
test_user_created_tasks_survive_final_reconciliation | test_milestone_08 | User-created tasks (including one whose content matches a final candidate) remain after reconciliation with source: user, are not duplicated, and only the genuinely new candidate counts toward reconciled. |
test_user_edits_are_not_overwritten_by_final_generation | test_milestone_08 | A user-edited task's content and a user-completed task's status both survive reconciliation unchanged, without being duplicated by a matching final candidate. |
test_deleted_user_owned_tasks_do_not_reappear_silently | test_milestone_08 | A user-deleted task (whether originally user- or system-owned) does not reappear after reconciliation; the response's conflicts[] reports each as reason: "deleted_by_user" rather than dropping them silently. |
Completion Checklist
- Code merged and deployed
- Bet progress tests pass (
./dev test bet meeting-recording) - Permanent service tests implemented per testing strategy
- Code review completed
- API review completed (
PUT /meetings/{id}/tasks/systemreconciliation contract) - Testing review completed
- System documentation updated (as applicable)
App — Live Task UI
Live task list in the recording view via the M02 shared components, reconciliation result visible on finalization, and wiring the M02 library to the live session.
ML — Live Task Extraction
TaskProducedEvent emission from the same batched insight pipeline as talking points, and final task candidates in the PUT /meetings/:id/tasks/system write-back.