docs(04): capture phase context
This commit is contained in:
parent
58c8231af9
commit
f31951ce1d
2 changed files with 250 additions and 0 deletions
121
.planning/phases/04-tasks-kanban/04-CONTEXT.md
Normal file
121
.planning/phases/04-tasks-kanban/04-CONTEXT.md
Normal file
|
|
@ -0,0 +1,121 @@
|
||||||
|
# Phase 4: Tasks (Kanban) - Context
|
||||||
|
|
||||||
|
**Gathered:** 2026-05-15
|
||||||
|
**Status:** Ready for planning
|
||||||
|
|
||||||
|
<domain>
|
||||||
|
## Phase Boundary
|
||||||
|
|
||||||
|
Inside a tablo, a user can run a kanban board with four fixed columns (todo / in progress / in review / done). Users can create tasks in a column, edit task title and description inline, move tasks between columns via drag-and-drop, reorder tasks within a column, and delete tasks. All mutations are HTMX-driven; ordering persists across refreshes.
|
||||||
|
|
||||||
|
Delivers TASK-01..07. **Not** in scope: configurable/user-defined columns (fixed for v1), rich-text task descriptions, task comments, task assignees, due dates, task tags/labels, file attachments on tasks (files attach to tablos in Phase 5), tab navigation on the tablo detail page (added only when Phase 5 files section is integrated).
|
||||||
|
|
||||||
|
</domain>
|
||||||
|
|
||||||
|
<decisions>
|
||||||
|
## Implementation Decisions
|
||||||
|
|
||||||
|
### Column Architecture
|
||||||
|
- **D-01:** Fixed 4 columns: `todo`, `in_progress`, `in_review`, `done` — hardcoded as Go constants, no `task_columns` table. No column CRUD routes in this phase. TASK-01's "configurable" option is deferred.
|
||||||
|
- **D-02:** Column stored on each task row as a Postgres `ENUM` type: `CREATE TYPE task_status AS ENUM ('todo','in_progress','in_review','done')`. Type-safe in the DB; sqlc generates a Go type; invalid values rejected at DB layer. Adding a future status requires `ALTER TYPE task_status ADD VALUE` (safe, non-blocking migration).
|
||||||
|
- **D-03:** Hard-delete only — no `deleted_at` column on tasks. Consistent with Phase 3 (D-01). All task delete handlers require inline confirmation before firing (reuse D-07 pattern from Phase 3).
|
||||||
|
|
||||||
|
### Task Ordering
|
||||||
|
- **D-04:** Task position stored as `position INTEGER NOT NULL` on the tasks row. First task in a column = 100, second = 200, gap of 100 between each. Inserting between two tasks uses the midpoint (e.g. 150). When gaps narrow below a threshold (e.g. adjacent positions differ by < 2), a rebalance pass reassigns multiples of 100 for that column. O(n) rebalance is acceptable at v1 task counts.
|
||||||
|
- **D-05:** Last-write-wins for concurrent edits — documented in code, acceptable for v1 (per TASK-07). No optimistic locking required.
|
||||||
|
|
||||||
|
### Move/Reorder Interaction
|
||||||
|
- **D-06:** Drag-and-drop via **Sortable.js** (standalone ~30KB utility, not a JS framework). Handles both within-column reorder (TASK-05) and cross-column move (TASK-04) via a single draggable surface per column.
|
||||||
|
- **D-07:** Sortable fires an `end` event on drop. A small inline `<script>` (~5 lines, no module system) reads the new task order from the DOM and fires an `hx-post` to `/tablos/{id}/tasks/reorder` with the new positions array. Server reorders the affected tasks, returns updated column fragment(s). Stays HTMX-first — the inline script is a thin event bridge, not application logic.
|
||||||
|
|
||||||
|
### Task Detail UX
|
||||||
|
- **D-08:** Task editing (TASK-03) uses **inline expand** in the kanban card. Clicking a task card swaps it via HTMX to an editable form showing title + description fields. On save (`POST /tablos/{tablo_id}/tasks/{task_id}`), the form swaps back to the display card with updated values. On cancel, restores the original card without a server round-trip. Same HTMX swap pattern as Phase 3's inline title/description edit (D-06).
|
||||||
|
- **D-09:** Task creation (TASK-02) uses an **inline form at the bottom of each column**. Clicking `+ Add task` in a column renders a small form (title only for quick capture) at the bottom of that column via HTMX swap. On submit, the new task card appends to the column and the form resets. On cancel, the form disappears. Consistent with Phase 3's inline create pattern (D-05).
|
||||||
|
- **D-10:** The kanban board is **embedded directly in the tablo detail page** (`GET /tablos/{id}`). No tab navigation yet. The page shows: tablo title/description (inline editable from Phase 3) → kanban board below. Phase 5 will add a files section further below. Tabs can be introduced later if the page becomes crowded.
|
||||||
|
|
||||||
|
### Claude's Discretion
|
||||||
|
- Exact Tailwind styling for task cards (compact vs spacious, shadow depth) — consistent with Phase 3's Card component aesthetic.
|
||||||
|
- Column header visual treatment (background color, count badge showing tasks per column).
|
||||||
|
- Whether the Sortable.js drag handle is the full card or a dedicated grip icon.
|
||||||
|
- HTTP verb for task create and edit: `POST /tablos/{id}/tasks` and `POST /tablos/{id}/tasks/{task_id}` (HTML form compatible).
|
||||||
|
- Whether position rebalancing happens synchronously in the same transaction as the reorder, or is deferred (sync is simplest for v1).
|
||||||
|
- Exact threshold for triggering rebalance (planner's call — e.g. when any adjacent gap < 2).
|
||||||
|
|
||||||
|
</decisions>
|
||||||
|
|
||||||
|
<canonical_refs>
|
||||||
|
## Canonical References
|
||||||
|
|
||||||
|
**Downstream agents MUST read these before planning or implementing.**
|
||||||
|
|
||||||
|
### Prior Phase Context (locked decisions that constrain this phase)
|
||||||
|
- `.planning/phases/03-tablos-crud/03-CONTEXT.md` — D-05 (inline create pattern), D-06 (inline edit pattern), D-07 (inline delete confirmation), D-01 (hard-delete), D-03 (sort by created_at) — all reused or extended in this phase
|
||||||
|
- `.planning/phases/02-authentication/02-CONTEXT.md` — D-23/D-24 (chi route groups, middleware order), RequireAuth middleware
|
||||||
|
- `.planning/phases/01-foundation/01-CONTEXT.md` — chi router + templ + sqlc + goose migration conventions
|
||||||
|
|
||||||
|
### Requirements
|
||||||
|
- `.planning/REQUIREMENTS.md` §TASK-01..07 — The 7 task requirements this phase delivers
|
||||||
|
- `.planning/PROJECT.md` — Core value statement and constraints (HTMX-first, no JS framework, single binary)
|
||||||
|
- `.planning/ROADMAP.md` §Phase 4 — Success criteria and user-in-loop note
|
||||||
|
|
||||||
|
### Codebase Patterns (Go backend)
|
||||||
|
- `backend/internal/web/router.go` — Router structure, protected group, route ordering convention (static before parametric)
|
||||||
|
- `backend/internal/web/handlers_tablos.go` — HTMX-aware handler pattern (HX-Request detection, fragment vs full-page response) — reuse verbatim
|
||||||
|
- `backend/internal/web/ui/` — Existing Card, Button, Badge, CSRFField components
|
||||||
|
- `backend/templates/` — Base layout, templ component patterns
|
||||||
|
- `backend/internal/db/queries/tablos.sql` — sqlc query style reference
|
||||||
|
- `backend/migrations/0003_tablos.sql` — Migration style reference (uuid PK, indexes, enum types)
|
||||||
|
- `backend/internal/tasks/doc.go` — Placeholder package; Phase 4 implementation lands here
|
||||||
|
|
||||||
|
</canonical_refs>
|
||||||
|
|
||||||
|
<code_context>
|
||||||
|
## Existing Code Insights
|
||||||
|
|
||||||
|
### Reusable Assets
|
||||||
|
- `ui.Card`, `ui.Button`, `ui.Badge`, `ui.CSRFField` — available in `backend/internal/web/ui/`. Task cards should use `ui.Card` variant.
|
||||||
|
- `auth.RequireAuth` middleware — already wraps the tablo route group; task routes nest inside the same group.
|
||||||
|
- `auth.Authed(ctx)` — extracts `*auth.User` from context for tablo ownership checks (tasks inherit tablo ownership).
|
||||||
|
- HTMX fragment pattern from Phase 2/3 (`HX-Request` header detection, 200+fragment vs 303+redirect) — reuse verbatim for all task mutations.
|
||||||
|
- `templates.Layout` — base layout; task views extend it via the tablo detail page.
|
||||||
|
|
||||||
|
### Established Patterns
|
||||||
|
- sqlc queries in `backend/internal/db/queries/<domain>.sql`, generated output in `backend/internal/db/sqlc/`. Phase 4 adds `tasks.sql`.
|
||||||
|
- Handler constructors return `http.HandlerFunc` with a `TasksDeps` struct (mirrors `TablosDeps` from Phase 3).
|
||||||
|
- Middleware order is locked (D-24): `RequestID → RealIP → SlogLogger → Recoverer → ResolveSession → csrf.Protect → [route groups]`. Task routes add to the existing `RequireAuth` group.
|
||||||
|
- goose migrations numbered sequentially: `0004_tasks.sql` is next.
|
||||||
|
- `templ generate` must run after any `.templ` file change to regenerate `*_templ.go`.
|
||||||
|
- Static route segments declared BEFORE parametric in chi (Pitfall 1) — e.g. `/tablos/{id}/tasks/new` before `/tablos/{id}/tasks/{task_id}`.
|
||||||
|
|
||||||
|
### Integration Points
|
||||||
|
- `backend/internal/web/router.go` — add task routes inside the existing `RequireAuth` group, nested under `/tablos/{id}/tasks*`.
|
||||||
|
- `backend/cmd/web/main.go` — pass `TasksDeps` (db pool) to `NewRouter` alongside existing `TablosDeps`.
|
||||||
|
- `backend/templates/tablos/detail.templ` (or equivalent) — embed the kanban board below the tablo title/description section.
|
||||||
|
- Sortable.js — loaded via CDN `<script>` tag in the base layout or tablo detail template (no npm required).
|
||||||
|
|
||||||
|
</code_context>
|
||||||
|
|
||||||
|
<specifics>
|
||||||
|
## Specific Ideas
|
||||||
|
|
||||||
|
- The `task_status` enum uses snake_case values: `todo`, `in_progress`, `in_review`, `done` — matching Go idiomatic constants.
|
||||||
|
- The reorder endpoint (`POST /tablos/{id}/tasks/reorder`) should accept a JSON body `{ "tasks": [{ "id": "uuid", "position": 150 }] }` or form-encoded array — planner decides encoding based on what HTMX + Sortable.js makes easiest.
|
||||||
|
- Column headers should show a task count badge (e.g. "In Progress (3)") — derived from the fetched task list, not a separate query.
|
||||||
|
- TASK-07 ("ordering persists across refreshes") is satisfied by writing `position` to the DB on every reorder — no client-side-only state.
|
||||||
|
|
||||||
|
</specifics>
|
||||||
|
|
||||||
|
<deferred>
|
||||||
|
## Deferred Ideas
|
||||||
|
|
||||||
|
- **Configurable columns** — user-defined column names and counts, `task_columns` table with CRUD. Deferred to v2 or a later phase. Schema is evolvable (add `task_columns` table, migrate `task_status` enum to FK reference).
|
||||||
|
- **Tabs on tablo detail (Overview / Tasks / Files)** — tab navigation deferred until Phase 5 adds the files section; revisit then if the page layout needs organization.
|
||||||
|
- **Task due dates, assignees, labels, comments** — out of v1 scope per PROJECT.md.
|
||||||
|
- **Rich-text task descriptions** — plain text only in v1; BlockNote/ProseMirror deferred.
|
||||||
|
|
||||||
|
</deferred>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Phase: 4-Tasks (Kanban)*
|
||||||
|
*Context gathered: 2026-05-15*
|
||||||
129
.planning/phases/04-tasks-kanban/04-DISCUSSION-LOG.md
Normal file
129
.planning/phases/04-tasks-kanban/04-DISCUSSION-LOG.md
Normal file
|
|
@ -0,0 +1,129 @@
|
||||||
|
# Phase 4: Tasks (Kanban) - Discussion Log
|
||||||
|
|
||||||
|
> **Audit trail only.** Do not use as input to planning, research, or execution agents.
|
||||||
|
> Decisions are captured in CONTEXT.md — this log preserves the alternatives considered.
|
||||||
|
|
||||||
|
**Date:** 2026-05-15
|
||||||
|
**Phase:** 4-tasks-kanban
|
||||||
|
**Areas discussed:** Column architecture, Move/reorder interaction, Task detail UX
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Column architecture
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Fixed columns (recommended) | 3 columns hardcoded, no task_columns table | |
|
||||||
|
| Configurable columns | task_columns table with user CRUD | |
|
||||||
|
| Fixed for now, schema-ready for later | 3 hardcoded names but schema-evolvable | |
|
||||||
|
|
||||||
|
**User's choice:** Fixed columns — but with 4 states: todo, in progress, in review, done (not the default 3-column set)
|
||||||
|
**Notes:** User specified the exact column names, overriding the default To do / Doing / Done suggestion.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Postgres enum type (recommended) | CREATE TYPE task_status AS ENUM | ✓ |
|
||||||
|
| TEXT with CHECK constraint | column TEXT NOT NULL CHECK (column IN ...) | |
|
||||||
|
| Small integer (0-3) | position SMALLINT, Go mapping layer | |
|
||||||
|
|
||||||
|
**User's choice:** Postgres enum type
|
||||||
|
**Notes:** No additional notes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Hard-delete (consistent with Phase 3) | No deleted_at, consistent with D-01 | ✓ |
|
||||||
|
| Soft-delete | deleted_at nullable, recoverable | |
|
||||||
|
|
||||||
|
**User's choice:** Hard-delete
|
||||||
|
**Notes:** Consistent with established Phase 3 pattern.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Move/reorder interaction
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Drag-and-drop with Sortable.js | ~30KB standalone utility, canonical kanban UX | ✓ |
|
||||||
|
| Button-driven move/reorder | Pure HTMX, ↑↓←→ buttons, no extra JS | |
|
||||||
|
| Select-based column move + buttons for reorder | Hybrid: select for column, buttons for order | |
|
||||||
|
|
||||||
|
**User's choice:** Drag-and-drop with Sortable.js
|
||||||
|
**Notes:** User accepted the JS dependency as a utility (not framework), staying within the "no JS framework" constraint.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| HTMX hx-trigger + Sortable 'end' event (recommended) | ~5 line inline script bridges Sortable to HTMX | ✓ |
|
||||||
|
| Vanilla fetch POST in Sortable callback | Bypasses HTMX for the drop interaction | |
|
||||||
|
| Let researcher/planner decide | Defer wiring pattern | |
|
||||||
|
|
||||||
|
**User's choice:** HTMX hx-trigger + Sortable 'end' event
|
||||||
|
**Notes:** Keeps the interaction HTMX-first with a minimal inline script bridge.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Integer gaps-of-100 (recommended) | position INTEGER, rebalance when gaps exhaust | ✓ |
|
||||||
|
| Fractional index string (lexorank-style) | TEXT, never rebalances, complex to generate | |
|
||||||
|
| Sequential integer (no gaps) | Renumber all rows on every reorder | |
|
||||||
|
|
||||||
|
**User's choice:** Integer gaps-of-100
|
||||||
|
**Notes:** Ordering strategy was not in the user's selected areas; asked inline since it's a schema gate.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Task detail UX
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Inline expand in the kanban card | HTMX swap, same pattern as Phase 3 inline edit | ✓ |
|
||||||
|
| Slide-over / modal panel | New panel component needed, no existing equivalent | |
|
||||||
|
| Dedicated task detail page | /tablos/{id}/tasks/{task_id}, interrupts board flow | |
|
||||||
|
|
||||||
|
**User's choice:** Inline expand in the kanban card
|
||||||
|
**Notes:** Consistent with Phase 3's inline edit pattern (D-06).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Inline form at bottom of column (recommended) | + Add task → form in column, consistent with Phase 3 | ✓ |
|
||||||
|
| A single shared create form above the board | Column selector, disconnects visually | |
|
||||||
|
| Click-to-edit: blank card appears immediately | More JS needed beyond Sortable | |
|
||||||
|
|
||||||
|
**User's choice:** Inline form at bottom of column
|
||||||
|
**Notes:** Consistent with Phase 3's inline create pattern (D-05).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Replaces the tablo detail body (board IS the detail page) | Title/desc + kanban on one page, no tabs | ✓ |
|
||||||
|
| Tabs: Overview \| Tasks \| Files | Tab nav added now, before Phase 5 files exist | |
|
||||||
|
|
||||||
|
**User's choice:** Board embedded directly in tablo detail page (no tabs)
|
||||||
|
**Notes:** Tabs deferred until Phase 5 when files section is added; revisit then if layout is crowded.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Claude's Discretion
|
||||||
|
|
||||||
|
- Exact Tailwind styling for task cards
|
||||||
|
- Column header visual treatment (background, count badge)
|
||||||
|
- Sortable.js drag handle (full card vs grip icon)
|
||||||
|
- HTTP verb for task create/edit endpoints
|
||||||
|
- Position rebalancing timing (sync vs deferred)
|
||||||
|
- Rebalance threshold (e.g. adjacent gap < 2)
|
||||||
|
|
||||||
|
## Deferred Ideas
|
||||||
|
|
||||||
|
- Configurable columns (user-defined names, task_columns table) — v2 or later phase
|
||||||
|
- Tab navigation on tablo detail (Overview / Tasks / Files) — revisit in Phase 5
|
||||||
|
- Task due dates, assignees, labels, comments — out of v1 scope
|
||||||
|
- Rich-text task descriptions — plain text only in v1
|
||||||
Loading…
Reference in a new issue