# Task UI Issues Analysis ## Problem Statement Tasks displayed in the WHOOSH UI show "undefined" fields and placeholder text like "Help Promises: (Not implemented)" and "Retry Budgets: (Not implemented)". ## Root Cause Analysis ### 1. UI Displaying Non-Existent Fields **Location**: `ui/script.js` lines ~290-310 (loadTaskDetail function) **Current Code**: ```javascript async function loadTaskDetail(taskId) { const task = await apiFetch(`/v1/tasks/${taskId}`); taskContent.innerHTML = `

${task.title}

Task Details

Status: ${task.status}

Priority: ${task.priority}

Help Promises: (Not implemented)

Retry Budgets: (Not implemented)


Description:

${task.description}

`; } ``` **Issue**: "Help Promises" and "Retry Budgets" are hard-coded placeholder text, not actual fields from the Task model. ### 2. Missing Task Fields in UI **Task Model** (`internal/tasks/models.go`): ```go type Task struct { ID uuid.UUID ExternalID string ExternalURL string SourceType SourceType Title string Description string Status TaskStatus Priority TaskPriority AssignedTeamID *uuid.UUID AssignedAgentID *uuid.UUID Repository string ProjectID string Labels []string TechStack []string Requirements []string EstimatedHours int ComplexityScore float64 ClaimedAt *time.Time StartedAt *time.Time CompletedAt *time.Time CreatedAt time.Time UpdatedAt time.Time } ``` **Fields NOT displayed in UI**: - ❌ Repository - ❌ ProjectID - ❌ Labels - ❌ TechStack - ❌ Requirements - ❌ EstimatedHours - ❌ ComplexityScore - ❌ ExternalURL (link to GITEA issue) - ❌ AssignedTeamID/AssignedAgentID - ❌ Timestamps (claimed_at, started_at, completed_at) ### 3. API Endpoint Issues **Expected Endpoint**: `/api/v1/tasks` **Actual Status**: Returns 404 **Possible Causes**: 1. **Route Registration**: The route exists in code but may not be in the deployed image 2. **Image Version**: Running image `anthonyrawlins/whoosh:council-team-fix` may pre-date the `/v1/tasks` endpoint 3. **Alternative Access Pattern**: Tasks may need to be accessed via `/api/v1/projects/{projectID}/tasks` **Evidence from code**: - `internal/server/server.go` shows both endpoints exist: - `/api/v1/tasks` (standalone tasks endpoint) - `/api/v1/projects/{projectID}/tasks` (project-scoped tasks) ### 4. Undefined Field Values When the UI attempts to display task fields that don't exist in the API response, JavaScript will show `undefined`. **Example Scenario**: ```javascript // If API returns task without 'estimated_hours'

Estimated Hours: ${task.estimated_hours}

// Renders as: "Estimated Hours: undefined" ``` ## Impact Assessment ### Current State 1. ✅ Task model in database has all necessary fields 2. ✅ Task service can query and return complete task data 3. ❌ UI only displays: title, status, priority, description 4. ❌ UI shows placeholder text for non-existent fields 5. ❌ Many useful task fields are not displayed 6. ❓ `/v1/tasks` API endpoint returns 404 (needs verification) ### User Impact - **Low Information Density**: Users can't see repository, labels, tech stack, requirements - **No Assignment Visibility**: Can't see which team/agent claimed the task - **No Time Tracking**: Can't see when task was claimed/started/completed - **Confusing Placeholders**: "(Not implemented)" text suggests incomplete features - **No External Links**: Can't click through to GITEA issue ## Recommended Fixes ### Phase 1: Fix UI Display (HIGH PRIORITY) **1.1 Remove Placeholder Text** ```javascript // REMOVE these lines from loadTaskDetail():

Help Promises: (Not implemented)

Retry Budgets: (Not implemented)

``` **1.2 Add Missing Fields** ```javascript async function loadTaskDetail(taskId) { const task = await apiFetch(`/v1/tasks/${taskId}`); taskContent.innerHTML = `

${task.title}

Task Details

Status: ${task.status}

Priority: ${task.priority}

Source: ${task.source_type}

Repository: ${task.repository || 'N/A'}

Project ID: ${task.project_id || 'N/A'}

${task.external_url ? `

Issue: View on GITEA

` : ''}
${task.estimated_hours || task.complexity_score ? `
${task.estimated_hours ? `

Estimated Hours: ${task.estimated_hours}

` : ''} ${task.complexity_score ? `

Complexity Score: ${task.complexity_score.toFixed(2)}

` : ''}
` : ''} ${task.labels?.length || task.tech_stack?.length ? `
${task.labels?.length ? `

Labels:

${task.labels.map(label => `${label}`).join('')}
` : ''} ${task.tech_stack?.length ? `

Tech Stack:

${task.tech_stack.map(tech => `${tech}`).join('')}
` : ''}
` : ''} ${task.requirements?.length ? `

Requirements:

` : ''}

Description:

${task.description || 'No description provided'}
${task.assigned_team_id || task.assigned_agent_id ? `

Assignment:

${task.assigned_team_id ? `

Team: ${task.assigned_team_id}

` : ''} ${task.assigned_agent_id ? `

Agent: ${task.assigned_agent_id}

` : ''}
` : ''}

Created: ${new Date(task.created_at).toLocaleString()}

${task.claimed_at ? `

Claimed: ${new Date(task.claimed_at).toLocaleString()}

` : ''} ${task.started_at ? `

Started: ${new Date(task.started_at).toLocaleString()}

` : ''} ${task.completed_at ? `

Completed: ${new Date(task.completed_at).toLocaleString()}

` : ''}
`; } ``` **1.3 Add Corresponding CSS** Add to `ui/styles.css`: ```css .badge { padding: 0.25rem 0.5rem; border-radius: 4px; font-size: 0.875rem; font-weight: 500; } .status-open { background-color: #3b82f6; color: white; } .status-claimed { background-color: #8b5cf6; color: white; } .status-in_progress { background-color: #f59e0b; color: white; } .status-completed { background-color: #10b981; color: white; } .status-closed { background-color: #6b7280; color: white; } .status-blocked { background-color: #ef4444; color: white; } .priority-critical { background-color: #dc2626; color: white; } .priority-high { background-color: #f59e0b; color: white; } .priority-medium { background-color: #3b82f6; color: white; } .priority-low { background-color: #6b7280; color: white; } .tags { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.5rem; } .tag { padding: 0.25rem 0.75rem; background-color: #e5e7eb; border-radius: 12px; font-size: 0.875rem; } .tag.tech { background-color: #dbeafe; color: #1e40af; } .description { white-space: pre-wrap; line-height: 1.6; padding: 1rem; background-color: #f9fafb; border-radius: 4px; } .timestamps { font-size: 0.875rem; color: #6b7280; } ``` ### Phase 2: Verify API Endpoint (MEDIUM PRIORITY) **2.1 Test Current Endpoint** ```bash # Check if /v1/tasks works curl -v http://whoosh.chorus.services/api/v1/tasks # If 404, try project-scoped endpoint curl http://whoosh.chorus.services/api/v1/projects | jq '.projects[0].id' # Then curl http://whoosh.chorus.services/api/v1/projects/{PROJECT_ID}/tasks ``` **2.2 Update UI Route If Needed** If `/v1/tasks` doesn't exist in deployed version, update UI to use project-scoped endpoint: ```javascript // Option A: Load from specific project const task = await apiFetch(`/v1/projects/${projectId}/tasks/${taskNumber}`); // Option B: Rebuild and deploy WHOOSH with /v1/tasks endpoint ``` ### Phase 3: Task List Enhancement (LOW PRIORITY) **3.1 Improve Task List Display** ```javascript async function loadTasks() { const tasksContent = document.getElementById('tasks-content'); try { const data = await apiFetch('/v1/tasks'); tasksContent.innerHTML = `
${data.tasks.map(task => `

${task.title}

${task.status} ${task.priority} ${task.repository ? `${task.repository}` : ''}
${task.tech_stack?.length ? `
${task.tech_stack.slice(0, 3).map(tech => ` ${tech} `).join('')} ${task.tech_stack.length > 3 ? `+${task.tech_stack.length - 3} more` : ''}
` : ''} ${task.description ? `

${task.description.substring(0, 150)}...

` : ''}
`).join('')}
`; } catch (error) { tasksContent.innerHTML = `

Error loading tasks: ${error.message}

`; } } ``` ## Implementation Plan ### Step 1: Quick Win - Remove Placeholders (5 minutes) 1. Open `ui/script.js` 2. Find `loadTaskDetail` function 3. Remove lines with "Help Promises" and "Retry Budgets" 4. Commit and deploy ### Step 2: Add Essential Fields (30 minutes) 1. Add repository, project_id, external_url to task detail view 2. Add labels and tech_stack display 3. Add timestamps display 4. Test locally ### Step 3: Add Styling (15 minutes) 1. Add badge styles for status/priority 2. Add tag styles for labels/tech stack 3. Add description formatting 4. Test visual appearance ### Step 4: Deploy (10 minutes) 1. Build new WHOOSH image with UI changes 2. Tag as `anthonyrawlins/whoosh:task-ui-fix` 3. Deploy to swarm 4. Verify in browser ### Step 5: API Verification (Optional) 1. Test if `/v1/tasks` endpoint works after deploy 2. If not, rebuild WHOOSH binary with latest code 3. Or update UI to use project-scoped endpoints ## Testing Checklist - [ ] Task detail page loads without "undefined" values - [ ] No placeholder "(Not implemented)" text visible - [ ] Repository name displays correctly - [ ] Labels render as styled tags - [ ] Tech stack renders as styled tags - [ ] External URL link works and opens GITEA issue - [ ] Timestamps format correctly - [ ] Status badge has correct color - [ ] Priority badge has correct color - [ ] Description text wraps properly - [ ] Null/empty fields don't break layout ## Future Enhancements 1. **Interactive Task Management** - Claim task button - Update status dropdown - Add comment/note functionality 2. **Task Filtering** - Filter by status, priority, repository - Search by title/description - Filter by tech stack 3. **Task Analytics** - Time to completion metrics - Complexity vs actual hours - Agent performance by task type 4. **Visualization** - Kanban board view - Timeline view - Dependency graph ## References - Task Model: `internal/tasks/models.go` - Task Service: `internal/tasks/service.go` - UI JavaScript: `ui/script.js` - UI Styles: `ui/styles.css` - API Routes: `internal/server/server.go`