--- phase: 16-tablo-detail verified: 2026-05-16T23:00:00Z status: human_needed score: 14/15 must-haves verified overrides_applied: 0 human_verification: - test: "Open the tablo detail page in a browser and walk through all 24 visual/interaction items listed in Plan 04's checkpoint task." expected: "Header shows colored avatar + editable title + action controls. Metadata row shows created date + badge + progress bar. Tab nav uses design token active states. Overview tab shows description. Tasks tab shows three kanban columns with etape-grouped task rows. Files tab shows table layout with upload/download/delete actions. Empty state renders when no files exist." why_human: "The Plan 04 browser checkpoint (blocking gate) was auto-approved under AUTO mode by the agent itself — it was not approved by a human. All 24 visual and interaction items require a human to load the running app in a browser to confirm layout, icon rendering, HTMX swap behavior, drag-and-drop continuity, and delete confirm flow." --- # Phase 16: Tablo Detail Verification Report **Phase Goal:** Restyle the tablo detail view — header, task kanban, etapes, and files — using design system components. **Verified:** 2026-05-16T23:00:00Z **Status:** human_needed **Re-verification:** No — initial verification ## Goal Achievement ### Observable Truths | # | Truth | Status | Evidence | |---|-------|--------|----------| | 1 | Tablo detail header uses project-card-top layout with title, avatar, and action controls | VERIFIED | `tablos.templ` line 245: `
` inside TabloDetailPage; color avatar with `tablo.Color.Valid` guard; `@TabloTitleDisplay` inside `project-card-title-row`; chat/invite/trash action controls on right | | 2 | Tab nav uses .tab-nav / .tab-nav-item / .tab-nav-item.is-active classes — no hardcoded hex | VERIFIED | `tablos.templ` lines 327/342/357/372/387: all 5 tabs use conditional `class="tab-nav-item is-active"` / `class="tab-nav-item"`; `grep -c "#804EEC" tablos.templ` returns 0 | | 3 | Metadata row uses .tablo-metadata-row with created date, Badge status pill, and progress track/bar | VERIFIED | `tablos.templ` line 304: `class="tablo-metadata-row"`; line 310: `@ui.Badge(BadgeVariantPrimary)` "In progress"; lines 311-312: `.project-progress-track` / `.project-progress-bar` | | 4 | Description zone renders inside TabloOverviewTabFragment (not in the persistent header) | VERIFIED | `tablos.templ` line 421: `@TabloDescDisplay(tablo, csrfToken)` inside `TabloOverviewTabFragment` body; no `TabloDescDisplay` call found above the tab nav | | 5 | EtapeStrip is not called from TasksTabFragment or tasks.templ | VERIFIED | `grep "EtapeStrip" tablos.templ` returns 0; `grep "EtapeStrip" tasks.templ` returns 0 | | 6 | Task kanban uses tasks-section design: section header with add button, task rows with checkbox and meta | VERIFIED | `tasks.templ` lines 174-205: `.kanban-column` > `.tasks-section` > `.tasks-section-header` with h3 + badge + `@AddTaskTrigger`; `.task-list sortable-column`; TaskCard uses `.task-row task-card` with `.task-check` + `.task-body` + trash IconButton | | 7 | KanbanBoard and KanbanColumn accept etapes []sqlc.Etape as 5th/6th parameter | VERIFIED | `tasks.templ` line 173: `templ KanbanColumn(tabloID, status, tasks, csrfToken, filter EtapeFilter, etapes []sqlc.Etape)`; KanbanBoard signature confirmed extended | | 8 | All three KanbanBoard call sites pass etapes as 5th argument | VERIFIED | `handlers_tasks.go` lines 594 and 645: `KanbanBoard(..., etapes)`; `tablos.templ` line 431: `@KanbanBoard(..., etapes)` | | 9 | groupTasksByEtape helper groups tasks by etape in declaration order with unassigned last | VERIFIED | `tasks.templ` line 30: `func groupTasksByEtape(tasks []sqlc.Task, etapes []sqlc.Etape) []EtapeGroup`; EtapeGroup type at line 21; EtapeGroupHeader at line 73; called in KanbanColumn at line 196 | | 10 | Files section uses @ui.Table with .overview-section-heading header | VERIFIED | `files.templ` line 13: `class="overview-section-heading"`; line 35: `@ui.Table(ui.TableProps{Head: fileTableHead(), Body: fileTableBody(...)})` | | 11 | FileListRow renders as tr.file-row-zone with Download and Delete IconButtons | VERIFIED | `files.templ` line 104: `` with download IconButton (Icon: "download") at line 119 and trash IconButton for delete | | 12 | FileDeleteConfirmFragment outer element is tr.file-row-zone with td colspan="4" | VERIFIED | `files.templ` line 145: ``; line 146: `` | | 13 | Empty state uses @ui.EmptyState when no files | VERIFIED | `files.templ` line 30: `@ui.EmptyState(ui.EmptyStateProps{Title: "No files yet", Description: "Upload your first file to get started."})` | | 14 | All CSS sections 19-25 in app.css use design tokens — no hardcoded hex | VERIFIED | `grep -c "#[0-9a-fA-F]{3,6}" app.css` returns 0; `.tasks-section`, `.tab-nav-item.is-active` (with `var(--color-brand-primary)`), `.kanban-column` (width: 18rem), `.etape-group-header` (background: `var(--color-surface-muted)`), `.task-list-empty` (font-style: italic) all confirmed | | 15 | All existing task, etape, and file handler tests pass unchanged | VERIFIED | `go test ./internal/web/... -count=1` exits 0; `go build ./... exits 0`; 2 test packages pass | **Score:** 15/15 truths technically verified ### Known Stubs (Intentional — per Plan 02 and UI-SPEC) These are documented stubs, not gaps. The plans explicitly authorized them as out of scope for Phase 16: | Stub | Location | Reason | |------|----------|--------| | `style="width: 0%;"` on `.project-progress-bar` | `tablos.templ` line 312 | Task completion percentage calculation is out of scope for v1 tablo detail header | | `Label: "In progress"` hardcoded in Badge | `tablos.templ` line 310 | Dynamic status from DB is out of scope for this plan | | Invite Member button has no action wired | `tablos.templ` | Member invitation feature is out of scope for v1 | | `EtapeGroup.EtapeColor` always `""` | `tasks.templ` | `sqlc.Etape` struct has no Color field in DB schema; color dot will render when field is added | ### Required Artifacts | Artifact | Expected | Status | Details | |----------|----------|--------|---------| | `backend/internal/web/ui/icon_button.templ` | download and chat icon cases in UIIcon switch | VERIFIED | Lines 71 and 77: `case "download":` and `case "chat":` | | `backend/internal/web/ui/app.css` | CSS Sections 19-25 (tasks-section through task-list-empty) | VERIFIED | All 7 sections confirmed; 0 hardcoded hex values | | `backend/templates/tablos.templ` | Restyled TabloDetailPage with project-card-top, tab-nav, metadata row | VERIFIED | Lines 245-412: all target patterns present; 0 `#804EEC` occurrences | | `backend/templates/tasks.templ` | groupTasksByEtape, EtapeGroupHeader, restyled KanbanBoard/Column/TaskCard | VERIFIED | All patterns present; 0 EtapeStrip calls | | `backend/internal/web/handlers_tasks.go` | Both KanbanBoard call sites pass etapes | VERIFIED | Lines 594 and 645 confirmed | | `backend/templates/files.templ` | @ui.Table, @ui.EmptyState, tr-based file rows | VERIFIED | All patterns present | ### Key Link Verification | From | To | Via | Status | Details | |------|----|-----|--------|---------| | `icon_button.templ` UIIcon switch | browser render | `case "download":` and `case "chat":` before default | VERIFIED | Both cases at lines 71, 77; `go build ./... exits 0` means generated file is current | | `app.css` | browser render | static asset embed | VERIFIED | All 7 new CSS sections present; no hex values | | `tablos.templ TabloDetailPage` | `app.css .project-card-top` | CSS class on div | VERIFIED | `class="project-card-top"` at line 245 | | `tablos.templ TabloOverviewTabFragment` | `TabloDescDisplay` | `@TabloDescDisplay(tablo, csrfToken)` call inside overview tab | VERIFIED | Line 421 inside `TabloOverviewTabFragment` | | `tablos.templ TasksTabFragment` | `tasks.templ KanbanBoard` | `@KanbanBoard(tablo.ID, csrfToken, tasks, filter, etapes)` | VERIFIED | Line 431 | | `tasks.templ groupTasksByEtape` | `tasks.templ KanbanColumn` | `groups := groupTasksByEtape(tasks, etapes)` | VERIFIED | Line 196 inside KanbanColumn body | | `handlers_tasks.go` | `tasks.templ KanbanBoard` | `KanbanBoard(..., etapes)` at both handler call sites | VERIFIED | Lines 594, 645 confirmed | | `files.templ FileListRow` | `files.templ FileDeleteConfirmFragment` | `hx-target="closest .file-row-zone"` / both are `` | VERIFIED | Both use `` — outerHTML swap is type-safe | | `files.templ FilesTabFragment` | `backend/internal/web/ui/table.templ @ui.Table` | `@ui.Table(ui.TableProps{Head: fileTableHead(), Body: fileTableBody(...)})` | VERIFIED | Line 35 | ### Requirements Coverage | Requirement | Source Plan | Description | Status | Evidence | |-------------|------------|-------------|--------|----------| | DETAIL-01 | 16-02 | Tablo detail header area matches the project-card-top design | SATISFIED | `project-card-top` layout, avatar, tab-nav with token classes, desc in overview tab — all verified in tablos.templ | | DETAIL-02 | 16-03 | Task kanban board uses the tasks-section design | SATISFIED | `.kanban-column` > `.tasks-section` > `.tasks-section-header` + `.task-list` + `.task-row task-card` in tasks.templ | | DETAIL-03 | 16-03 | Etapes section is visually consistent with the task section | SATISFIED | `groupTasksByEtape` helper + `EtapeGroupHeader` component in tasks.templ; EtapeStrip removed from all call sites; tasks grouped by etape in column | | DETAIL-04 | 16-04 | Files section uses the table component | SATISFIED | `@ui.Table` + `@ui.EmptyState` + `` rows with Download/Delete IconButtons in files.templ | ### Anti-Patterns Found | File | Line | Pattern | Severity | Impact | |------|------|---------|----------|--------| | `tasks.templ` | 458, 467 | `TODO: remove etapes and counts params after Phase 16 cleanup` | WARNING | Unreferenced TODO (no issue/PR number), but the retention was explicitly planned in 16-03 Plan Task 1 as a safe default to avoid handler signature changes. These params are kept intentionally. Not a functional blocker. | **Note on TODOs:** The two TODO markers in `tasks.templ` (lines 458, 467) are in `TaskCardGone` and `TaskCardOOB`. The plan explicitly instructed: "Add `// TODO: remove etapes and counts params after Phase 16 cleanup` comment." They indicate cleanup work deferred to after Phase 16, but lack a formal issue reference. Classified as WARNING (not blocker) because: (1) the retention is intentional and functionally correct — the parameters are kept to avoid breaking handler signatures; (2) the TODO references the current phase cleanup as context; (3) they do not prevent any goal truth from being true. ### Human Verification Required #### 1. Browser checkpoint for Phase 16 visual result **Test:** Start the dev server (`cd backend && just dev` or `air`). Navigate to a tablo detail page (e.g., `http://localhost:3000/tablos/{some-id}`). Walk through the 24 visual and interaction items from Plan 04's checkpoint task: - **Header (DETAIL-01):** Colored circle avatar with first letter of tablo title; inline-editable title; Discussion/Invite/Delete action controls; no visible hardcoded purple hex artifacts - **Metadata row:** Created date with calendar icon; "In progress" badge; progress bar track - **Tab nav:** 5 tabs in horizontal row; active tab has purple underline + bold; inactive tabs muted; clicking loads content via HTMX - **Overview tab:** Description zone appears inside the tab (not above tab nav); click-to-edit works - **Tasks tab (DETAIL-02 + DETAIL-03):** 3 kanban columns side by side; section header with status label + badge + "Add task" button; task rows with round checkbox + title + trash icon; if etapes defined, tasks grouped by etape with colored dot sub-heading; no EtapeStrip filter pills; drag-and-drop between columns works - **Files tab (DETAIL-04):** "Files" heading + "Upload file" button; clicking Upload reveals form inline; file rows in table (Filename / Size / Uploaded / Actions); download and trash icons per row; trash click → delete confirm replaces row; empty state "No files yet" when no files **Expected:** All 24 items pass. **Why human:** The Plan 04 blocking checkpoint was marked "auto-approved (AUTO mode active)" in the SUMMARY — it was not approved by an actual human. This is a `checkpoint:human-verify` gate task that the plan designated as `gate="blocking"`. Visual layout, icon rendering, HTMX swap behavior, drag-and-drop continuity, and the confirm/cancel flow cannot be verified programmatically. ### Gaps Summary No functional gaps found. All 15 must-have truths are verified in the codebase. The phase is blocked on human verification only — the browser checkpoint was auto-approved by the agent rather than reviewed by a human developer. --- _Verified: 2026-05-16T23:00:00Z_ _Verifier: Claude (gsd-verifier)_