diff --git a/packages/core/src/store.ts b/packages/core/src/store.ts index ca2c4495b..94791655f 100644 --- a/packages/core/src/store.ts +++ b/packages/core/src/store.ts @@ -5687,6 +5687,9 @@ export class TaskStore extends EventEmitter { /** * Soft-delete a live task by setting tasks.deletedAt/updatedAt while leaving * the row and on-disk task artifacts in place for potential recovery. + * + * Idempotent (FN-5127): calling deleteTask on an already-soft-deleted task is + * a no-op and does not re-emit task:deleted. */ async deleteTask( id: string, @@ -5696,11 +5699,15 @@ export class TaskStore extends EventEmitter { // Flush buffered agent logs inside the lock so no new appends for this // task can sneak in between flush and soft-delete mutation. this.flushAgentLogBuffer(); - const task = this.readTaskFromDb(id); + const task = this.readTaskFromDb(id, { includeDeleted: true }); if (!task) { throw new Error(`Task ${id} not found`); } + if (task.deletedAt) { + return task; + } + // Refuse to delete a task that is still referenced as a dependency // by another live task unless the caller explicitly opts into // removing those incoming references as part of this delete.