From 49284d2911b422542fbf7bb6454876fd191d13fd Mon Sep 17 00:00:00 2001 From: Christian Gick Date: Sun, 25 Jan 2026 13:26:23 +0200 Subject: [PATCH] feat(CF-450): Check completed tasks on task creation to avoid circular work MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enhanced task_add to search both open AND completed tasks when checking for duplicates. Previously only checked non-completed tasks. **Changes:** - Removed `status != 'completed'` filter from similarity search - Increased search limit from 3 to 5 tasks - Separated display: open tasks vs previously completed - Show 150-char context snippet from completed task descriptions - Suggest using "task show " to see full solution **Benefits:** - Prevents recreating already-solved tasks - Surfaces solutions from previous attempts - Reduces circular work on recurring issues - Maintains context from closed tasks **Example output:** ``` ⚠️ Similar tasks found: **Open/In Progress:** - CF-442: Next.js cache issue (92% match, open) **Previously Completed:** - CF-378: Pre-test validation (85% match) Context: "Created comprehensive pre-test quality validation workflow..." 💡 Use "task show " to see full solution before recreating work ``` Fixes: CF-450 Co-Authored-By: Claude Sonnet 4.5 --- src/tools/crud.ts | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/src/tools/crud.ts b/src/tools/crud.ts index d554e7f..5a121cf 100644 --- a/src/tools/crud.ts +++ b/src/tools/crud.ts @@ -95,14 +95,15 @@ export async function taskAdd(args: TaskAddArgs): Promise { const embeddingValue = embedding ? formatEmbedding(embedding) : null; // Check for similar/duplicate tasks (only if embedding succeeded) + // CF-450: Check both open AND completed tasks to avoid circular work let duplicateWarning = ''; if (embeddingValue) { - const similarTasks = await query<{ id: string; title: string; status: string; similarity: number }>( - `SELECT id, title, status, 1 - (embedding <=> $1) as similarity + const similarTasks = await query<{ id: string; title: string; status: string; description: string; similarity: number }>( + `SELECT id, title, status, description, 1 - (embedding <=> $1) as similarity FROM tasks - WHERE project = $2 AND embedding IS NOT NULL AND status != 'completed' + WHERE project = $2 AND embedding IS NOT NULL ORDER BY embedding <=> $1 - LIMIT 3`, + LIMIT 5`, [embeddingValue, projectKey] ); @@ -110,11 +111,35 @@ export async function taskAdd(args: TaskAddArgs): Promise { const highSimilarity = similarTasks.filter(t => t.similarity > 0.70); if (highSimilarity.length > 0) { duplicateWarning = '\n\n⚠️ Similar tasks found:\n'; - for (const t of highSimilarity) { - const pct = Math.round(t.similarity * 100); - duplicateWarning += ` - ${t.id}: ${t.title} (${pct}% match, ${t.status})\n`; + + const openTasks = highSimilarity.filter(t => t.status !== 'completed'); + const completedTasks = highSimilarity.filter(t => t.status === 'completed'); + + if (openTasks.length > 0) { + duplicateWarning += '\n**Open/In Progress:**\n'; + for (const t of openTasks) { + const pct = Math.round(t.similarity * 100); + duplicateWarning += ` - ${t.id}: ${t.title} (${pct}% match, ${t.status})\n`; + } } - duplicateWarning += '\nConsider linking with: task link relates_to'; + + if (completedTasks.length > 0) { + duplicateWarning += '\n**Previously Completed:**\n'; + for (const t of completedTasks) { + const pct = Math.round(t.similarity * 100); + duplicateWarning += ` - ${t.id}: ${t.title} (${pct}% match)\n`; + + // Show snippet of solution/outcome from description + if (t.description) { + const snippet = t.description.substring(0, 150).replace(/\n/g, ' ').replace(/"/g, '\\"'); + const ellipsis = t.description.length > 150 ? '...' : ''; + duplicateWarning += ` Context: "${snippet}${ellipsis}"\n`; + } + } + duplicateWarning += '\n 💡 Use "task show " to see full solution before recreating work\n'; + } + + duplicateWarning += '\nConsider linking with: task link relates_to'; } }