@@ -2,7 +2,6 @@ import { db } from '@sim/db'
22import {
33 copilotAsyncToolCalls ,
44 copilotChats ,
5- copilotFeedback ,
65 copilotRunCheckpoints ,
76 copilotRuns ,
87 mothershipInboxTask ,
@@ -103,14 +102,6 @@ export async function runCleanupTasks(payload: CleanupJobPayload): Promise<void>
103102 if ( r . deleted > 0 ) logger . info ( `[${ r . table } ] ${ r . deleted } deleted` )
104103 }
105104
106- // Delete feedback — no direct workspaceId, reuse chat IDs collected above
107- const feedbackResult = await deleteRowsById (
108- copilotFeedback ,
109- copilotFeedback . chatId ,
110- doomedChatIds ,
111- `${ label } /copilotFeedback`
112- )
113-
114105 // Delete copilot runs (has workspaceId directly, cascades checkpoints)
115106 const runsResult = await batchDeleteByWorkspaceAndTimestamp ( {
116107 tableDef : copilotRuns ,
@@ -126,6 +117,8 @@ export async function runCleanupTasks(payload: CleanupJobPayload): Promise<void>
126117 // Re-check the retention cutoff in the DELETE: a chat restored from Recently
127118 // Deleted mid-run gets a fresh `updatedAt`, so it survives here (and
128119 // chatCleanup.execute() re-checks row existence before purging its data).
120+ // Chat-scoped children (copilot_messages, copilot_feedback) go with the row
121+ // via FK cascade, so they are removed only for chats actually deleted.
129122 const chatsResult = { deleted : 0 , failed : 0 }
130123 for ( const batch of chunkArray ( doomedChatIds , DEFAULT_DELETE_CHUNK_SIZE ) ) {
131124 try {
@@ -152,7 +145,6 @@ export async function runCleanupTasks(payload: CleanupJobPayload): Promise<void>
152145
153146 const totalDeleted =
154147 runChildResults . reduce ( ( s , r ) => s + r . deleted , 0 ) +
155- feedbackResult . deleted +
156148 runsResult . deleted +
157149 chatsResult . deleted +
158150 inboxResult . deleted
0 commit comments