URL: https://mkdocs.justinsforge.com/memory/general/reference_creatortrack_task_primitives/
CreatorTrack Generic Task Primitives (Workstream A)¶
Status: DEPLOYED to prod 2026-07-11 (merged to main b34d8e4, plain code merge, no migration; ensureTasksApp seeds props on tasks-app access, ws 90 seeded, other workspaces on-access). Built on branch feat/task-dev-primitives off main b67e7ca. Plan: creatortrack-task-dev-primitives-2026-07-11. Running report: forge/comms/results/creatortrack-task-dev-primitives.md.
Turns CreatorTrack's task layer into a real project/dev tracker WITHOUT ever looking like one. North Star: every primitive reads as sensible for a content creator too (a dev types bug/feature, a creator types Reel/Sponsored; same code, same UI, configured by the user). NEVER a "dev mode", "software" label, or dev-only preset.
What shipped (per commit, on the branch)¶
| Task | Commit | What |
|---|---|---|
| 1. Board group-by any field | 52850a6 |
Kanban board groups by Status (default), Priority, or ANY custom SELECT field. Group-by picker in the board header; drag writes the grouped field's value; "No |
| 2. Type + Milestone selects | 27eaa9f |
Two idempotent default select props (Type, Milestone), empty-optioned, seeded via ensureTasksApp (lib/system-apps.ts). Not in CORE_TASK_PROPS, so they surface as ordinary editable selects and auto-appear as board/timeline group-by options. |
| 3. External-URL field kind | 0d7fc6e |
The url prop kind now renders as a clickable external link (new tab, rel="noopener noreferrer nofollow", bare-domain coerced to https). components/workspace/database/Cell.tsx UrlCell. Dev links a PR, creator links a published video. |
| 4. Task -> page relation | 8548b91 |
Un-hardwires collection_relations targets to allow standalone PAGE nodes (target_kind:"page" on PropConfig). Seeds a "Related pages" relation prop. Forward direction here; the reverse-direction UI landed in follow-up B. |
| 5. Bulk paste -> tasks | 66acfe2 |
The shared Composer splits a multi-line title into one task per non-empty line (shares the composer chips). Dev pastes a bug list, creator a content-idea dump. |
| 6. Timeline view | 9058b6f |
New shared TimelineView (components/apps/shared/TimelineView.tsx + timeline.css): dated bars on a day axis from start+due/dueEnd, dependency links from the blockedBy relation, optional row grouping by any select-or-status field (reuses Task 1's taskValue/columnKeys/BoardGroupField, exported from ProjectBoardView.tsx). Registered as a tasks view surface (timeline SurfaceViewType) alongside list/calendar/matrix/database/search. Called Timeline, never "gantt", in every user-visible string. Read-only bars in this commit; drag-to-reschedule = follow-up A. |
| A. Timeline drag-to-reschedule | a8527fa |
Drag a bar body to move both dates, drag an edge handle to resize; single PATCH on mouse-up via the same updateTask write path the board's onMove uses (Start = bar left, Due = bar right). |
| B. Reverse-relations UI | cfbcf78 |
Closes the Task 4 gap: a page/doc node shows a "Linked tasks" strip of the tasks whose "Related pages" relation points at it. listRelationBacklinks (lib/node-actions.ts) queries collection_relations by toRow; the existing /api/node/[id]/backlinks route now returns { pages, tasks }; LinkedTasksStrip in PageBody.tsx renders it on page/doc nodes. |
Key files¶
- New:
components/apps/shared/TimelineView.tsx,components/apps/shared/timeline.css,app/api/collection/pages/route.ts. - Registration:
lib/tasks.ts(SurfaceViewTypeaddstimeline; exportedSURFACE_VIEW_TYPESas the single source of truth),components/apps/tasks/ViewTabsBar.tsx,components/apps/tasks/TasksClient.tsx,components/apps/tasks/tasks.css. - Prop/relation plumbing:
lib/system-apps.ts(prop seeds),lib/collection.ts,lib/prop-types.ts,lib/data.ts,app/api/collection/relation/route.ts,components/workspace/database/Cell.tsx,components/apps/tasks/Peek.tsx(PeekPatch widened withstart/dueEnd). - Root-cause fix folded into commit
9058b6f: the settings PATCH route (app/api/tasks/settings/route.ts) was validating surface view types against its own stale inline list that omitted evendatabase, silently coercingdatabase+timelinetoliston save. Now uses the exportedSURFACE_VIEW_TYPES.
Merge-day notes¶
- No SQL migration. Despite the plan's assumption, the build added NO
db/migrationsfile and did NOT touchdb/schema.ts. All new props/relations (Type,Milestone,Related pages, thetarget_kindrelation config) seed idempotently at runtime viaensureTasksApp/ensureProjectsProps(lib/system-apps.ts), the same lazy-backfill path Status/Priority/Tags use. On merge they backfill on next tasks-app touch; nothing manual to run. - Merge is a plain code merge to main; the standard CT deploy (which does NOT run migrations) is sufficient.
Dev verification¶
Verified on a worktree dev server (next dev --webpack, WORKSPACE_DEV_AUTH=1, DB clone ct_feat_task_dev_primitives). Timeline: two ws74 tasks given dates + a blockedBy link render as bars with the dependency arrow drawn between them; group-by Priority splits into HIGH/LOW/NO PRIORITY headers with the cross-group dependency line staying aligned. Drag (follow-up A): a real mouse drag of a bar body persisted the shifted start+due, a right-edge drag persisted a +2-day resize, both via PATCH /api/tasks/{id}. Reverse-relations (follow-up B): linking two tasks to a page shows a "2 linked tasks" strip below the page title with clickable chips.
Gotchas seen (worth reusing): (1) the original :3062 slot server had died and another worktree grabbed the port; confirm the process serving a slot's port actually has that worktree's cwd (readlink /proc/<pid>/cwd) before trusting a runtime check. (2) A page's client fetch (a useEffect strip) can stall on the Next dev server when the page fires many concurrent load-time polls (notifications, etc.) that saturate the browser's 6-per-host connection pool; blocking the noisy polls in the test made it deterministic. It is a dev on-demand-compile artifact, not a bug: a warm prod build resolves the fetch immediately.
Follow-on: work hierarchy Board surface (branch feat/work-hierarchy-dashboard, 2026-07-12)¶
The task primitives above (board group-by, Type/Milestone selects, Timeline) are extended by the work hierarchy build (NOT yet merged): the Tasks app now has its own Board surface (reusing ProjectBoardView) whose columns are the workspace's real Status prop options exposed as a new taskStatuses field on the /api/tasks aggregate (lib/tasks.ts listTasks) -- the pipeline is data, never hardcoded. The filter bar gains Status + any-custom-field axes (persisted in the tasks_app prefs blob), and the Composer gains a Status quick-add chip. Dragging a board card writes {status} ONLY (the /api/tasks/[id] PATCH done fast-path drops a co-sent status; the server derives done from status). Milestone (a select prop here) now also drives per-project milestone rollups + roadmap markers in the Projects app.