feat(CF-450): Check completed tasks on task creation to avoid circular work
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 <id>" 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 <id>" to see full solution before recreating work ``` Fixes: CF-450 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -95,14 +95,15 @@ export async function taskAdd(args: TaskAddArgs): Promise<string> {
|
|||||||
const embeddingValue = embedding ? formatEmbedding(embedding) : null;
|
const embeddingValue = embedding ? formatEmbedding(embedding) : null;
|
||||||
|
|
||||||
// Check for similar/duplicate tasks (only if embedding succeeded)
|
// Check for similar/duplicate tasks (only if embedding succeeded)
|
||||||
|
// CF-450: Check both open AND completed tasks to avoid circular work
|
||||||
let duplicateWarning = '';
|
let duplicateWarning = '';
|
||||||
if (embeddingValue) {
|
if (embeddingValue) {
|
||||||
const similarTasks = await query<{ id: string; title: string; status: string; similarity: number }>(
|
const similarTasks = await query<{ id: string; title: string; status: string; description: string; similarity: number }>(
|
||||||
`SELECT id, title, status, 1 - (embedding <=> $1) as similarity
|
`SELECT id, title, status, description, 1 - (embedding <=> $1) as similarity
|
||||||
FROM tasks
|
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
|
ORDER BY embedding <=> $1
|
||||||
LIMIT 3`,
|
LIMIT 5`,
|
||||||
[embeddingValue, projectKey]
|
[embeddingValue, projectKey]
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -110,11 +111,35 @@ export async function taskAdd(args: TaskAddArgs): Promise<string> {
|
|||||||
const highSimilarity = similarTasks.filter(t => t.similarity > 0.70);
|
const highSimilarity = similarTasks.filter(t => t.similarity > 0.70);
|
||||||
if (highSimilarity.length > 0) {
|
if (highSimilarity.length > 0) {
|
||||||
duplicateWarning = '\n\n⚠️ Similar tasks found:\n';
|
duplicateWarning = '\n\n⚠️ Similar tasks found:\n';
|
||||||
for (const t of highSimilarity) {
|
|
||||||
|
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);
|
const pct = Math.round(t.similarity * 100);
|
||||||
duplicateWarning += ` - ${t.id}: ${t.title} (${pct}% match, ${t.status})\n`;
|
duplicateWarning += ` - ${t.id}: ${t.title} (${pct}% match, ${t.status})\n`;
|
||||||
}
|
}
|
||||||
duplicateWarning += '\nConsider linking with: task link <from> <to> 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 <id>" to see full solution before recreating work\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
duplicateWarning += '\nConsider linking with: task link <new-id> <related-id> relates_to';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user