diff --git a/docs/superpowers/specs/2026-04-08-knowledge-task-consolidation.md b/docs/superpowers/specs/2026-04-08-knowledge-task-consolidation.md new file mode 100644 index 0000000..d0d40a8 --- /dev/null +++ b/docs/superpowers/specs/2026-04-08-knowledge-task-consolidation.md @@ -0,0 +1,144 @@ +# Knowledge View Task Consolidation — Design Spec + +## Goal + +Consolidate tasks into the Knowledge view as a card type, deprecate the standalone `/notes` and `/tasks` list views, and simplify navigation. The Knowledge view becomes the single hub for all content types: notes, tasks, people, places, and lists. + +## Architecture + +The Knowledge view already renders notes, people, places, and lists as typed cards in a filterable grid with a sidebar. Tasks are added as a fifth card type using the same two-tier pagination system (ID pre-fetch → content batch). The backend knowledge endpoints (`/api/knowledge/ids`, `/api/knowledge/batch`, `/api/knowledge/counts`) are extended to include tasks. No changes to the note/task CRUD API. + +## Task Cards + +Task cards follow the same layout as other knowledge cards: + +- **Left accent strip**: distinct color for tasks (e.g. `#a78bfa` purple to differentiate from note indigo) +- **Type badge**: "Task" in top-right corner +- **Card body**: + - Title (2-line clamp) + - Status badge: `todo` / `in_progress` / `done` / `cancelled` — styled with existing status colors from theme (`--color-status-*`) + - Priority indicator: shown only when priority is not `none` — uses existing priority colors (`--color-priority-*`) + - Due date: shown when set, with overdue styling (`--color-overdue`) when past and status is not `done`/`cancelled` +- **Card footer**: tags (up to 3) + last-modified date — identical to other card types + +Clicking a task card navigates to `/tasks/:id/edit` (same as today). + +## Filter Sidebar Changes + +The type filter section gains a "Tasks" button: + +``` +Type +────────── +[All] 127 +[Notes] 84 +[Tasks] 22 +[People] 8 +[Places] 5 +[Lists] 8 +``` + +The filter value for tasks is `type=task`. The backend already stores tasks as notes with `is_task=True`; the knowledge endpoints need to map the `type=task` filter to `is_task=True`. + +## New Note Button Interaction + +Current: click "New note" to create a note; chevron expands a dropdown with Note/Person/Place/List. + +New behavior: + +1. **Click "New note"** (when collapsed) → expands to reveal type options: Task, Person, Place, List. The main button label does not change. +2. **Click "New note"** again (when expanded) → navigates to `/notes/new` (generic note). +3. **Click any type option** → navigates to `/notes/new?type=` (for task: `/notes/new?type=task`, which is equivalent to `/tasks/new`). +4. **Click outside** → collapses the dropdown. + +This replaces the current chevron split-button pattern with a simpler toggle. The dropdown items are: Task, Person, Place, List (no "Note" item in the dropdown — clicking the button itself creates a note). + +## Route Changes + +### Redirects + +| Old route | New behavior | +|-----------|-------------| +| `/notes` | 302 redirect → `/` (Knowledge view) | +| `/tasks` | 302 redirect → `/` (Knowledge view) | + +### Preserved routes (no change) + +| Route | Purpose | +|-------|---------| +| `/notes/:id` | Note viewer | +| `/notes/:id/edit` | Note editor | +| `/notes/new` | New note (with optional `?type=` param) | +| `/tasks/:id/edit` | Task editor | +| `/tasks/new` | New task | + +### Router implementation + +Add redirect entries in the router config: + +```ts +{ path: '/notes', redirect: '/' }, +{ path: '/tasks', redirect: '/' }, +``` + +### Navigation + +Remove from `AppHeader.vue`: +- "Tasks" nav link (``) +- The `/tasks` entry in both desktop nav-center and mobile menu + +Remove from `AppHeader.vue` (already done — `/notes` was removed in a prior change, but verify). + +### Deleted files + +- `frontend/src/views/NotesListView.vue` +- `frontend/src/views/TasksListView.vue` +- `frontend/src/stores/notes.ts` (if only used by NotesListView) +- `frontend/src/stores/tasks.ts` (if only used by TasksListView) + +Verify no other components import from these before deleting. The note/task viewer and editor screens import from `api/client.ts` directly, not from the list stores. + +## Backend Changes + +### `/api/knowledge/ids` + +Accept `type=task` as a valid filter. When `type=task`, query `notes` table with `is_task = True`. When `type` is not set (all), include tasks in results alongside notes/people/places/lists. + +### `/api/knowledge/batch` + +Return task-specific fields for items where `is_task = True`: +- `status`: todo / in_progress / done / cancelled +- `priority`: none / low / normal / high +- `due_date`: ISO date string or null + +These are already columns on the `Note` model — just include them in the batch response when the item is a task. + +### `/api/knowledge/counts` + +Add `task` to the counts response: + +```json +{ "note": 84, "task": 22, "person": 8, "place": 5, "list": 8, "total": 127 } +``` + +### `/api/knowledge/tags` + +No change — tasks already have tags on the same `Note` model. + +## Keyboard Shortcuts + +Remove from `App.vue` `onGlobalKeydown`: +- `case "t": router.push("/tasks/new")` — keep this, it still works +- `case "g"` sequence `case "t": router.push("/tasks")` — change to `router.push("/")` (direct navigation, don't rely on redirect) + +Update shortcuts overlay panel text if it references "Tasks list". + +## No API Endpoint Changes + +All existing REST endpoints remain: +- `GET/POST /api/notes` — notes CRUD +- `GET/POST /api/tasks` — tasks CRUD +- `PATCH /api/notes/:id`, `PATCH /api/tasks/:id` +- `DELETE /api/notes/:id`, `DELETE /api/tasks/:id` + +MCP tools (`fable_create_task`, `fable_list_tasks`, etc.) are unaffected.