Task Breakdown: Task tracking
Feature ID: task-tracking
Plan: ./plan.md
Status: Draft
Last updated: 2026-05-25
How to use
Phases mirror plan.md §10. Tasks sequential unless (parallel).
Phase 1 — Data + read/write API + list page
- T1. Create entity files under
packages/agent/src/entities/:task.entity.ts,task-assignee.entity.ts,task-reviewer.entity.ts,task-approver.entity.ts,task-block.entity.ts,task-relation.entity.ts,task-chat-message.entity.ts,task-attachment.entity.ts(per plan.md §3.1).(parallel) - T2. Register entities in
apps/api/src/typeorm.config.ts. - T3. Migration
CreateTasksTables.ts. Inspect generated SQL. - T4. Migration
AddTaskIdToPluginUsageEvents.ts(additive column + index). - T5. Repositories:
TaskRepository(withfindByScope,findChildren,findBlockers,findActiveBlockers,findCycle(parentId, candidateId)),TaskAssigneeRepository, etc. - T6. State-machine class
TaskTransitionService.assertCanTransition(task, target, ctx)enforcing spec.md §3.2. - T7. Cycle-detection helper
assertNoParentCycle(parentId, candidateChildId)andassertNoBlockCycle(...). - T8. DTOs under
apps/api/src/tasks/dto/: create, update, transition, filter, response. - T9.
TasksController+TasksServicewith CRUD + assignees/reviewers/approvers/blockers/relations endpoints (chat in Phase 2). Tests: unit + e2e. - T10. Wire
TasksModuleintoapp.module.ts. - T11. Slug generator:
T-<incrementing>per user; uses an atomic counter in DB. - T12. Activity log events:
TASK_CREATED,TASK_UPDATED,TASK_ASSIGNED,TASK_COMPLETEDwired throughActivityLogService. - T13. i18n keys under
tasks.*and sidebar key (already reserved inagents/spec.md §5.1). - T14. Patch
DashboardSidebar.tsxto surface the "Tasks" item (Phase 1 of agents wires the placeholder; this one wires the route). - T15.
/taskslist page (server component) with Cards + Table views. Filter chips for status; quick-filter dropdowns for scope/assignee/label/priority. - T16.
/tasks/newcreate form. - T17.
apps/web/src/lib/api/tasks.tsclient wrappers.
Phase 2 — Detail page + chat
- T18.
/tasks/[id]page renders the full detail layout (header, sidebar, description editor, sub-tasks, attachments, activity, related, chat). Inline title editor. - T19. Sub-task badge logic (
n/mdone). - T20. Chat endpoints
GET/POST/PATCH /tasks/:id/chatand/task-chat-messages/:id. 5-minute edit window enforced server-side. - T21. Chat UI panel using the same Tiptap mention + wikilink extensions as
KbEditor.tsx. - T22. Mention parser (server-side) extracts
@<slug>and validates against the user's Agents/users; storesmentionsjsonb. - T23. Attachment upload flow: re-use existing KB upload endpoint, then attach via
/tasks/:id/attachments. - T24. Activity feed: extend
ActivityFeedClient.tsxfilter to accepttaskId; render new event icons. - T25. Secret-scan applied to description + chat body saves.
Phase 3 — Kanban + per-target tabs
- T26. Build
TasksKanbanView.tsxadapted fromWorksKanbanView.tsx. Columns per status. - T27. Drag-drop status transitions: optimistic update, debounced 250 ms patch.
- T28. View-mode persistence:
localStoragekeytasks-view-mode. - T29. Patch
WorkTabs.tsxto add "Tasks" tab between Items and KB (per Q1 default). - T30. Add "Tasks" tab to Mission detail page.
- T31. Add "Tasks" tab to Idea detail page.
- T32. Tab listings reuse the global
/taskslist component with prefilled scope filter.
Phase 4 — Agent integration
Depends on agents Phase 3 (heartbeat runtime + AgentRunService).
- T33.
packages/tasks/src/tasks/trigger/agent-task-execute.task.ts(maxDuration 60m). - T34.
packages/tasks/src/tasks/trigger/agent-chat-reply.task.ts(maxDuration 5m). - T35. Dispatch hook in
TaskTransitionService: when target=in_progressand any assignee is an Agent, dispatch one run per Agent. Dedup by(taskId, agentId, generation). - T36. Dispatch hook in
TaskChatService.post: when message body matches@<agent-slug>and that agent is on the task, dispatch reply run. - T37. AgentRunService extended with
kind: 'task'andkind: 'chat'paths (Agents Phase 5 task T51-T52 reference this). - T38. Add
taskIdtoPluginUsageEventwrites from insideagent-task-execute/agent-chat-reply. - T39.
GET /tasks/:id/spendendpoint returning per-task token + USD totals fromplugin_usage_events. - T40. UI: "Spend on this task" small block in the Task detail sidebar.
- T41. Playwright e2e: create Task → assign Agent → move to in_progress → Agent posts a chat message within 30 s.
Phase 5 — Dashboard surfaces
- T42.
apps/web/src/components/dashboard/TasksInProgressTile.tsx. - T43. "Recent Tasks" block component + integration into the dashboard page.
- T44. "View all (N)" link →
/tasks.
Phase 6 — Reserved plugin interface
- T45. Create
packages/plugin/src/contracts/capabilities/task-tracker.interface.ts(interface only, no plugin implements). - T46. Add a section in
docs/specs/architecture/plugin-sdk.mddocumenting the reserved capability with examples of what a future plugin (Linear, GitHub Issues) would look like. - T47. Add a no-op contract test in
packages/plugin/src/contracts/__tests__/task-tracker.spec.tsasserting type-shape only.
Phase 7 — Account-transfer (Export / Import / GitHub Sync) extension
Per ADR-008. Tasks export is opt-in in the UI (high-volume, high-mutation; many users won't want them backed up). When opted in, all tenant-owned tasks (incl. their chat, attachments-metadata, blockers, relations, watchers) export.
- T51. Extend
account-transfer/types.tswithExportedTask+ExportedTaskChatMessage+ supporting types (assignees, reviewers, approvers, blockers, relations). - T52. Inject
TaskRepository+ all the task-aux repositories intoAccountExportService. - T53. Implement
AccountExportService.exportTasks(userId, options)returningExportedTask[]. Default off; enabled byExportOptions.includeTasks = true. - T54. Add
tasks?: ExportedTask[]toAccountExportPayload(optional field). Bumpversion. - T55. Implement
AccountImportService.importTasks(payload, options)— create-or-update by(userId, slug). Recreate join-table rows (assignees, blockers, etc.) post-task-create. - T56. Update
GitHubSyncServicesynced layout: write tasks totasks/<slug>.json(JSON is friendlier than YAML for the chat list). - T57. Add UI toggle on
/settings/import-export: "Include Tasks in export (advanced)" (default OFF — high volume warning). - T58. Activity events
TASK_EXPORTED,TASK_IMPORTED,TASK_SYNCED. - T59. Round-trip Playwright test with a Work containing 50 tasks and 200 chat messages.
- T60. Confirm with the operator: should chat messages including authored-by-Agent rows export? (They reference Agents that may or may not have round-tripped.) Default: yes — export with
authorType='agent'andauthorId; on import, if the Agent exists in the target tenant, link; otherwise render as "(unknown agent)".
Phase 8 — Default-on rollout
- T48. Feature flag
FEATURE_TASK_TRACKINGdefaulting to off. - T49. Internal beta on staging; gather "Kanban scrollbar / drag-drop weirdness" bugs.
- T50. Flip flag default to on.
Phase 8 — Recurring tasks [operator override F5: must ship in v1]
Promoted from v2-out-of-scope to v1 per operator instruction. Pattern mirrors existing
mission-tickTrigger.dev cron task.
- T61. Add columns to
taskstable (in the originalCreateTasksTables.tsmigration if not yet landed, else a follow-up migrationAddRecurringTaskColumns.ts):isRecurring,recurrenceRule,recurrenceTimezone,nextOccurrenceAt,recurrenceEndsAt,recurrenceMaxOccurrences,recurrenceOccurredCount,parentRecurringTaskId. Index(isRecurring, nextOccurrenceAt)for dispatcher hot path. - T62. Add
rrulenpm package (pnpm add rrule -F @ever-works/agent). ValidaterecurrenceRuleon every write viaRRule.fromString()— reject malformed. - T63. Compute
nextOccurrenceAton every recurrence-related write (create / update / after-fire). HelpercomputeNextOccurrence(rule, timezone, from)lives inpackages/agent/src/tasks/recurrence.ts. HonorsrecurrenceEndsAtandrecurrenceMaxOccurrences. - T64. Repository method
TaskRepository.casClaimRecurrence(taskId, expectedNextOccurrenceAt)— atomicUPDATE tasks SET nextOccurrenceAt = <newNext>, recurrenceOccurredCount = recurrenceOccurredCount + 1 WHERE id = ? AND nextOccurrenceAt = ?. Returns affected rows; > 0 means we claimed it. - T65. Service method
TaskRecurrenceDispatcherService.dispatchDue(batchSize = 200)— queries due templates, iterates, CAS-claims, clones into a fresh task row viacloneRecurringTaskAsInstance(template). EmitsTASK_RECURRENCE_FIREDactivity row. - T66. Helper
cloneRecurringTaskAsInstance(template)— copies title/description/priority/labels/assignees/reviewers/approvers/scope, drops chat/attachments/watchers, setsparentRecurringTaskId = template.id,isRecurring = false, statustodo, recomputes slug counter. - T67. New Trigger.dev cron task
packages/tasks/src/tasks/trigger/task-recurrence-dispatcher.task.ts. Cadence* * * * *UTC. Bootstraps Nest, calls service. Test: race two concurrent calls, assert exactly one clones the instance. - T68. UI: "Make this recurring" toggle on the New-Task dialog. When ON, surface (Daily / Weekly / Monthly / Custom RRULE) frequency picker + day-of-week / time-of-day pickers contextual to the frequency + optional end date + optional max count. Show RRULE preview text ("Every Monday at 9am UTC, until Dec 31").
- T69. UI: "Recurring" badge on template task cards; "Instance N of N" badge on cloned instances; "View template" link on instances; "X future occurrences" sidebar widget on templates.
- T70. UI: edit-template confirmation modal — "Apply to future instances only" (the only v1 path; no retroactive edits).
- T71. New activity event type
TASK_RECURRENCE_FIREDadded toActivityActionTypeenum. - T72. Playwright e2e: create recurring task with
FREQ=DAILY, advance clock by 25 hours, observe instance cloned + parent'srecurrenceOccurredCountincremented.
(Renumbered: account-transfer extension was Phase 7 T51-T60; recurring tasks is Phase 8 T61-T72; what was Phase 8 default-on rollout shifts to Phase 9.)
Phase 9 — Default-on rollout (was Phase 7 / 8)
(No content change; just shifted in the ordering.)
Definition of Done
- All boxes ticked.
-
pnpm test+pnpm lint+pnpm type-checkgreen. - No regression in existing Works Kanban (still loads, drag-drop free of the new code).
- Architecture doc references updated.
- PR review-loop clean.