summaryrefslogtreecommitdiff
path: root/docs/superpowers/specs/2026-07-15-task-labels-and-projects-design.md
diff options
context:
space:
mode:
authorPeter Stone <thepeterstone@gmail.com>2026-07-15 10:15:56 +0000
committerPeter Stone <thepeterstone@gmail.com>2026-07-16 02:54:17 +0000
commit56cd7195060e7ac304cba946087d5f56d5a5f187 (patch)
tree5ed98edd83c500cf0db1c8b343e80d3b2d3e3cb4 /docs/superpowers/specs/2026-07-15-task-labels-and-projects-design.md
parentf48eae22ec7510e662e0ad6a3fa02781e951af4d (diff)
Add design docs for four backlog task-scheduling ideas
Labels/projects, budgets/availability, recurring maintenance buckets, and linear task chains -- refined via a 24-question interview (2026-07-15) into concrete data models, mechanisms, and API shapes. None approved for implementation yet; each spec notes its dependencies on the others (labels/projects is foundational to two of the other three). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VTUSAEKfsPc6WGDq45yPHD
Diffstat (limited to 'docs/superpowers/specs/2026-07-15-task-labels-and-projects-design.md')
-rw-r--r--docs/superpowers/specs/2026-07-15-task-labels-and-projects-design.md69
1 files changed, 69 insertions, 0 deletions
diff --git a/docs/superpowers/specs/2026-07-15-task-labels-and-projects-design.md b/docs/superpowers/specs/2026-07-15-task-labels-and-projects-design.md
new file mode 100644
index 0000000..4144d5b
--- /dev/null
+++ b/docs/superpowers/specs/2026-07-15-task-labels-and-projects-design.md
@@ -0,0 +1,69 @@
+# Task Labels and Projects — Design
+
+**Status:** Backlog idea, refined via interview 2026-07-15. Not yet approved for implementation.
+
+## Context
+
+doot-native tasks have had a `Labels []string` field on `models.Task` (`internal/models/types.go`) since early in the project — it's fully wired at the store layer (persisted as a JSON column, scanned back out by `scanNativeTasks`) but never surfaced in any UI, web or widget. There's no editing, no display, no filtering.
+
+There's also no real "project" concept for doot-native tasks today. `Task.ProjectID`/`ProjectName` exist on the struct and `ProjectName` is a real column in `native_tasks`, but a repo-wide search turns up **zero** places that ever set `ProjectName` to a non-empty value when constructing a native task — it's vestigial, always empty in practice. This is likely a leftover from the Todoist-sync era (Todoist tasks did have real project names; the field just never got repurposed after native tasks replaced Todoist in commit `945c345`). So this feature isn't "finish wiring up projects" — it's building projects from scratch, alongside finally wiring up labels.
+
+This is a foundational feature: [[doot-future-task-scheduling-ideas]] items 1 (budgets/availability) and 4 (task chains) both reference "projects" as a dependency. Building this first unblocks both.
+
+## Scope
+
+doot-native tasks only, matching every other feature built this session. Trello/Google Tasks cards keep whatever labeling concept they already have server-side (Trello lists, etc.) — this feature does not touch them.
+
+## Data Model
+
+**Labels** — reuse the existing field, no schema change needed:
+- `Task.Labels []string`, already a JSON column on `native_tasks`.
+- Free-form text tags, many-to-many with tasks (a task can have any number of labels).
+- User-assignable color per label. Since labels are currently just strings with no identity beyond their text, color needs a home: a new small `labels` table (`name TEXT PRIMARY KEY, color TEXT`) mapping label text → color hex. A label typed on a task that doesn't yet exist in this table gets a default color (or prompts for one) the first time it's colored.
+
+**Projects** — new, lightweight:
+```sql
+CREATE TABLE projects (
+ id TEXT PRIMARY KEY,
+ name TEXT NOT NULL,
+ color TEXT NOT NULL,
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+ archived BOOLEAN DEFAULT 0
+);
+```
+- `native_tasks` gets a new `project_id TEXT DEFAULT ''` column (a real FK-shaped reference, not the vestigial `project_name` string column — that column stays as dead weight for now since dropping SQLite columns needs a table-rebuild migration, out of scope for this feature; it just stops being read).
+- Exactly one project per task (`project_id` is a single string, empty = unassigned), per the interview answer. Labels handle the cross-cutting many-to-many need instead.
+- A project is not itself an atom/task — it's pure metadata (name + color) that a task points to.
+
+## Recurrence Interaction
+
+Both `project_id` and `Labels` are **series-level metadata**: `CreateNextIteration` (in `internal/store/native_tasks.go`) already copies `content`, `description`, `project_name`, `priority`, and `labels` onto every new occurrence — `project_id` joins that same copy-forward list, no new mechanism needed. This matches the interview's "inherit automatically" answer exactly.
+
+## API
+
+New endpoints, doot-only, matching the existing `/api/widget/task/*` pattern:
+- `GET /api/widget/projects` — list all non-archived projects (id, name, color), for populating a picker.
+- `POST /api/widget/projects` — create a project (name, color).
+- `POST /api/widget/task/project` — `{id, project_id}`, sets or clears a task's project.
+- `POST /api/widget/task/labels` — `{id, labels: []string}`, replaces a task's label set (matches `UpdateNativeTask`'s replace-whole-value style rather than an add/remove-single-label API).
+- Labels don't need their own CRUD endpoint in the same way projects do — a label is just a string until someone assigns it a color, so `POST /api/widget/task/labels` implicitly "creates" any new label text. A separate `POST /api/widget/labels/color` — `{name, color}` — sets a label's color.
+
+## UI
+
+**Widget (Android):** per the interview, minimal — a small color mark on the time-grid row (project color takes priority for the row's accent; if labels need visual representation too, a second smaller dot, but start with just project color to avoid clutter). No filtering UI on the widget itself.
+
+**Task detail popup (`TaskDetailActivity`):** full display and editing — a project picker (chip showing current project, tap to open a picker/create-new dialog) and a label editor (chip-entry, similar in spirit to the recurrence weekday chips but free-text with autocomplete against existing label names), both using the color-coding.
+
+**Web:** out of scope for this spec's UI section — the interview didn't ask about web display specifically; assume parity with the widget's popup-level editing is desirable but not designed here.
+
+## Testing
+
+Standard TDD per this project's convention: store-layer tests for `CreateProject`, `GetProjects`, `SetTaskProject`, `SetTaskLabels`, `SetLabelColor`; handler tests for the new endpoints (mirroring `widget_test.go`'s style); a `CreateNextIteration` test confirming `project_id` and `Labels` both carry forward to the next occurrence.
+
+## Out of Scope
+
+- Project hierarchies (sub-projects, nesting) — flat list only.
+- Multi-project tasks — exactly one project per task, per the interview.
+- Archived-project handling in the UI beyond hiding them from the picker (no dedicated archive-management screen designed here).
+- Web UI specifics (noted above).
+- Migrating/backfilling the vestigial `project_name` column — it's simply superseded, not cleaned up, in this spec.