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'; } }