From 7f12ef0355c0581802e4dc297ec06ceb7e4243ce Mon Sep 17 00:00:00 2001 From: AndyMik90 Date: Sat, 20 Dec 2025 11:37:16 +0100 Subject: [PATCH] fix: task descriptions not showing for specs with compact markdown MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tasks like spec 053 were missing descriptions in the kanban board and task modal because the regex for extracting the overview from spec.md required two newlines after "## Overview" (a blank line). Specs generated with compact markdown (no blank line after headers) were not matched, resulting in empty descriptions. Changes: - Fix regex to accept one or more newlines: /## Overview\s*\n+/ - Add fallback to read from requirements.json task_description field - Extract meaningful content from GitHub issue descriptions 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- auto-claude-ui/src/main/project-store.ts | 40 ++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/auto-claude-ui/src/main/project-store.ts b/auto-claude-ui/src/main/project-store.ts index 5ee38bad..2776b94e 100644 --- a/auto-claude-ui/src/main/project-store.ts +++ b/auto-claude-ui/src/main/project-store.ts @@ -243,8 +243,8 @@ export class ProjectStore { if (existsSync(specFilePath)) { try { const content = readFileSync(specFilePath, 'utf-8'); - // Extract first paragraph after "## Overview" - const overviewMatch = content.match(/## Overview\s*\n\n([^\n#]+)/); + // Extract first paragraph after "## Overview" - handle both with and without blank line + const overviewMatch = content.match(/## Overview\s*\n+([^\n#]+)/); if (overviewMatch) { description = overviewMatch[1].trim(); } @@ -258,6 +258,42 @@ export class ProjectStore { description = plan.description; } + // Fallback: read description from requirements.json if still not found + if (!description) { + const requirementsPath = path.join(specPath, AUTO_BUILD_PATHS.REQUIREMENTS); + if (existsSync(requirementsPath)) { + try { + const reqContent = readFileSync(requirementsPath, 'utf-8'); + const requirements = JSON.parse(reqContent); + if (requirements.task_description) { + // Extract a clean summary from task_description (first line or first ~200 chars) + const taskDesc = requirements.task_description; + const firstLine = taskDesc.split('\n')[0].trim(); + // If the first line is a title like "Investigate GitHub Issue #36", use the next meaningful line + if (firstLine.toLowerCase().startsWith('investigate') && taskDesc.includes('\n\n')) { + const sections = taskDesc.split('\n\n'); + // Find the first paragraph that's not a title + for (const section of sections) { + const trimmed = section.trim(); + // Skip headers and short lines + if (trimmed.startsWith('#') || trimmed.length < 20) continue; + // Skip the "Please analyze" instruction at the end + if (trimmed.startsWith('Please analyze')) continue; + description = trimmed.substring(0, 200).split('\n')[0]; + break; + } + } + // If still no description, use a shortened version of task_description + if (!description) { + description = firstLine.substring(0, 150); + } + } + } catch { + // Ignore parse errors + } + } + } + // Try to read task metadata const metadataPath = path.join(specPath, 'task_metadata.json'); let metadata: TaskMetadata | undefined;