@bbearai/mcp-server 0.3.3 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index-api.js CHANGED
@@ -115,7 +115,7 @@ const tools = [
115
115
  enum: ['new', 'reviewed', 'in_progress', 'resolved', 'closed'],
116
116
  description: 'New status',
117
117
  },
118
- resolution: {
118
+ resolution_notes: {
119
119
  type: 'string',
120
120
  description: 'Resolution notes (optional)',
121
121
  },
@@ -227,6 +227,33 @@ const tools = [
227
227
  required: ['test_key', 'title', 'steps', 'expected_result'],
228
228
  },
229
229
  },
230
+ {
231
+ name: 'delete_test_cases',
232
+ description: 'Delete one or more test cases. Supports single delete by ID or test_key, or bulk delete with arrays (max 50). WARNING: cascade-deletes associated test_assignments, test_feedback, and ai_test_runs.',
233
+ inputSchema: {
234
+ type: 'object',
235
+ properties: {
236
+ test_case_id: {
237
+ type: 'string',
238
+ description: 'UUID of a single test case to delete',
239
+ },
240
+ test_key: {
241
+ type: 'string',
242
+ description: 'Delete a single test case by test_key (e.g., TC-001)',
243
+ },
244
+ test_case_ids: {
245
+ type: 'array',
246
+ items: { type: 'string' },
247
+ description: 'Array of test case UUIDs to bulk delete (max 50)',
248
+ },
249
+ test_keys: {
250
+ type: 'array',
251
+ items: { type: 'string' },
252
+ description: 'Array of test_keys to bulk delete (max 50)',
253
+ },
254
+ },
255
+ },
256
+ },
230
257
  {
231
258
  name: 'get_qa_tracks',
232
259
  description: 'Get QA tracks for the project',
@@ -267,7 +294,7 @@ async function handleTool(name, args) {
267
294
  case 'update_report_status':
268
295
  result = await apiRequest(`/reports/${args.report_id}`, 'PATCH', {
269
296
  status: args.status,
270
- resolution: args.resolution,
297
+ resolution_notes: args.resolution_notes,
271
298
  });
272
299
  break;
273
300
  case 'create_bug_report': {
@@ -319,6 +346,24 @@ async function handleTool(name, args) {
319
346
  priority: args.priority || 'P2',
320
347
  });
321
348
  break;
349
+ case 'delete_test_cases': {
350
+ const ids = args.test_case_ids || (args.test_case_id ? [args.test_case_id] : undefined);
351
+ const keys = args.test_keys || (args.test_key ? [args.test_key] : undefined);
352
+ if (ids) {
353
+ const params = new URLSearchParams();
354
+ ids.forEach((id) => params.append('ids', id));
355
+ result = await apiRequest(`/test-cases?${params.toString()}`, 'DELETE');
356
+ }
357
+ else if (keys) {
358
+ const params = new URLSearchParams();
359
+ keys.forEach((k) => params.append('keys', k));
360
+ result = await apiRequest(`/test-cases?${params.toString()}`, 'DELETE');
361
+ }
362
+ else {
363
+ result = { error: 'Must provide test_case_id, test_key, test_case_ids, or test_keys' };
364
+ }
365
+ break;
366
+ }
322
367
  case 'get_qa_tracks':
323
368
  result = await apiRequest('/qa-tracks');
324
369
  break;
package/dist/index.js CHANGED
@@ -127,7 +127,7 @@ const tools = [
127
127
  enum: ['new', 'triaging', 'confirmed', 'in_progress', 'fixed', 'resolved', 'verified', 'wont_fix', 'duplicate'],
128
128
  description: 'The new status for the report',
129
129
  },
130
- resolution: {
130
+ resolution_notes: {
131
131
  type: 'string',
132
132
  description: 'Optional resolution notes when marking as resolved',
133
133
  },
@@ -275,6 +275,33 @@ const tools = [
275
275
  },
276
276
  },
277
277
  },
278
+ {
279
+ name: 'delete_test_cases',
280
+ description: 'Delete one or more test cases. Supports single delete by ID or test_key, or bulk delete with arrays (max 50). WARNING: cascade-deletes associated test_assignments, test_feedback, and ai_test_runs. Reports/qa_findings keep their records but test_case_id becomes null.',
281
+ inputSchema: {
282
+ type: 'object',
283
+ properties: {
284
+ test_case_id: {
285
+ type: 'string',
286
+ description: 'UUID of a single test case to delete',
287
+ },
288
+ test_key: {
289
+ type: 'string',
290
+ description: 'Delete a single test case by test_key (e.g., TC-001)',
291
+ },
292
+ test_case_ids: {
293
+ type: 'array',
294
+ items: { type: 'string' },
295
+ description: 'Array of test case UUIDs to bulk delete (max 50)',
296
+ },
297
+ test_keys: {
298
+ type: 'array',
299
+ items: { type: 'string' },
300
+ description: 'Array of test_keys to bulk delete (max 50)',
301
+ },
302
+ },
303
+ },
304
+ },
278
305
  {
279
306
  name: 'list_test_cases',
280
307
  description: 'List all test cases in the project. Returns test_key, title, target_route, and other metadata. Use this to see existing tests before updating them.',
@@ -880,7 +907,7 @@ const tools = [
880
907
  async function listReports(args) {
881
908
  let query = supabase
882
909
  .from('reports')
883
- .select('id, report_type, severity, status, description, app_context, created_at, tester:testers(name, email)')
910
+ .select('id, report_type, severity, status, description, app_context, created_at, reporter_name, reporter_email, tester:testers(name, email)')
884
911
  .eq('project_id', PROJECT_ID)
885
912
  .order('created_at', { ascending: false })
886
913
  .limit(Math.min(args.limit || 10, 50));
@@ -902,7 +929,7 @@ async function listReports(args) {
902
929
  status: r.status,
903
930
  description: r.description,
904
931
  route: r.app_context?.currentRoute,
905
- reporter: r.tester?.name || 'Anonymous',
932
+ reporter: r.tester?.name || r.reporter_name || 'Anonymous',
906
933
  created_at: r.created_at,
907
934
  })),
908
935
  total: data?.length || 0,
@@ -937,7 +964,10 @@ async function getReport(args) {
937
964
  reporter: data.tester ? {
938
965
  name: data.tester.name,
939
966
  email: data.tester.email,
940
- } : null,
967
+ } : (data.reporter_name ? {
968
+ name: data.reporter_name,
969
+ email: data.reporter_email,
970
+ } : null),
941
971
  track: data.track ? {
942
972
  name: data.track.name,
943
973
  icon: data.track.icon,
@@ -987,8 +1017,8 @@ async function updateReportStatus(args) {
987
1017
  return { error: 'Invalid report_id format' };
988
1018
  }
989
1019
  const updates = { status: args.status };
990
- if (args.resolution) {
991
- updates.resolution = args.resolution;
1020
+ if (args.resolution_notes) {
1021
+ updates.resolution_notes = args.resolution_notes;
992
1022
  }
993
1023
  const { error } = await supabase
994
1024
  .from('reports')
@@ -1194,6 +1224,110 @@ async function updateTestCase(args) {
1194
1224
  updatedFields: Object.keys(updates),
1195
1225
  };
1196
1226
  }
1227
+ async function deleteTestCases(args) {
1228
+ // Validate: exactly one input mode
1229
+ const modes = [
1230
+ args.test_case_id,
1231
+ args.test_key,
1232
+ args.test_case_ids,
1233
+ args.test_keys,
1234
+ ].filter(v => v !== undefined && v !== null);
1235
+ if (modes.length === 0) {
1236
+ return { error: 'Must provide one of: test_case_id, test_key, test_case_ids, or test_keys' };
1237
+ }
1238
+ if (modes.length > 1) {
1239
+ return { error: 'Provide only one of: test_case_id, test_key, test_case_ids, or test_keys' };
1240
+ }
1241
+ let idsToDelete = [];
1242
+ // Single ID
1243
+ if (args.test_case_id) {
1244
+ if (!isValidUUID(args.test_case_id)) {
1245
+ return { error: 'Invalid test_case_id format (must be UUID)' };
1246
+ }
1247
+ idsToDelete = [args.test_case_id];
1248
+ }
1249
+ // Single key
1250
+ if (args.test_key) {
1251
+ const { data: existing } = await supabase
1252
+ .from('test_cases')
1253
+ .select('id')
1254
+ .eq('project_id', PROJECT_ID)
1255
+ .eq('test_key', args.test_key)
1256
+ .single();
1257
+ if (!existing) {
1258
+ return { error: `Test case with key "${args.test_key}" not found` };
1259
+ }
1260
+ idsToDelete = [existing.id];
1261
+ }
1262
+ // Bulk IDs
1263
+ if (args.test_case_ids) {
1264
+ if (!Array.isArray(args.test_case_ids) || args.test_case_ids.length === 0) {
1265
+ return { error: 'test_case_ids must be a non-empty array' };
1266
+ }
1267
+ if (args.test_case_ids.length > 50) {
1268
+ return { error: 'Cannot delete more than 50 test cases at once' };
1269
+ }
1270
+ const invalidIds = args.test_case_ids.filter(id => !isValidUUID(id));
1271
+ if (invalidIds.length > 0) {
1272
+ return { error: `Invalid UUID(s): ${invalidIds.join(', ')}` };
1273
+ }
1274
+ idsToDelete = args.test_case_ids;
1275
+ }
1276
+ // Bulk keys
1277
+ if (args.test_keys) {
1278
+ if (!Array.isArray(args.test_keys) || args.test_keys.length === 0) {
1279
+ return { error: 'test_keys must be a non-empty array' };
1280
+ }
1281
+ if (args.test_keys.length > 50) {
1282
+ return { error: 'Cannot delete more than 50 test cases at once' };
1283
+ }
1284
+ const { data: existing, error: lookupError } = await supabase
1285
+ .from('test_cases')
1286
+ .select('id, test_key')
1287
+ .eq('project_id', PROJECT_ID)
1288
+ .in('test_key', args.test_keys);
1289
+ if (lookupError) {
1290
+ return { error: lookupError.message };
1291
+ }
1292
+ const foundKeys = (existing || []).map((tc) => tc.test_key);
1293
+ const notFound = args.test_keys.filter(k => !foundKeys.includes(k));
1294
+ if (notFound.length > 0) {
1295
+ return { error: `Test case(s) not found: ${notFound.join(', ')}` };
1296
+ }
1297
+ idsToDelete = (existing || []).map((tc) => tc.id);
1298
+ }
1299
+ // Pre-fetch details for the response
1300
+ const { data: toDelete } = await supabase
1301
+ .from('test_cases')
1302
+ .select('id, test_key, title')
1303
+ .eq('project_id', PROJECT_ID)
1304
+ .in('id', idsToDelete);
1305
+ if (!toDelete || toDelete.length === 0) {
1306
+ return { error: 'No matching test cases found in this project' };
1307
+ }
1308
+ // Delete
1309
+ const { error: deleteError } = await supabase
1310
+ .from('test_cases')
1311
+ .delete()
1312
+ .eq('project_id', PROJECT_ID)
1313
+ .in('id', idsToDelete);
1314
+ if (deleteError) {
1315
+ return { error: deleteError.message };
1316
+ }
1317
+ return {
1318
+ success: true,
1319
+ deletedCount: toDelete.length,
1320
+ deleted: toDelete.map((tc) => ({
1321
+ id: tc.id,
1322
+ testKey: tc.test_key,
1323
+ title: tc.title,
1324
+ })),
1325
+ message: toDelete.length === 1
1326
+ ? `Test case ${toDelete[0].test_key} deleted successfully`
1327
+ : `${toDelete.length} test cases deleted successfully`,
1328
+ warning: 'Associated test_assignments, test_feedback, and ai_test_runs have been cascade-deleted. Reports and qa_findings referencing these tests now have null test_case_id.',
1329
+ };
1330
+ }
1197
1331
  async function listTestCases(args) {
1198
1332
  let query = supabase
1199
1333
  .from('test_cases')
@@ -3157,7 +3291,7 @@ async function markFixedWithCommit(args) {
3157
3291
  const updates = {
3158
3292
  status: 'resolved',
3159
3293
  resolved_at: new Date().toISOString(),
3160
- resolution: args.resolution_notes || `Fixed in commit ${args.commit_sha.slice(0, 7)}`,
3294
+ resolution_notes: args.resolution_notes || `Fixed in commit ${args.commit_sha.slice(0, 7)}`,
3161
3295
  code_context: {
3162
3296
  ...existingContext,
3163
3297
  fix: {
@@ -3387,7 +3521,7 @@ async function createRegressionTest(args) {
3387
3521
  {
3388
3522
  stepNumber: 3,
3389
3523
  action: 'Verify the fix is working',
3390
- expectedResult: report.resolution || 'Feature works as expected',
3524
+ expectedResult: report.resolution_notes || 'Feature works as expected',
3391
3525
  },
3392
3526
  ],
3393
3527
  expected_result: `The bug "${report.title}" should not recur`,
@@ -3952,6 +4086,9 @@ async function main() {
3952
4086
  case 'update_test_case':
3953
4087
  result = await updateTestCase(args);
3954
4088
  break;
4089
+ case 'delete_test_cases':
4090
+ result = await deleteTestCases(args);
4091
+ break;
3955
4092
  case 'list_test_cases':
3956
4093
  result = await listTestCases(args);
3957
4094
  break;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bbearai/mcp-server",
3
- "version": "0.3.3",
3
+ "version": "0.5.0",
4
4
  "description": "MCP server for BugBear - allows Claude Code to query bug reports",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
package/src/index-api.ts CHANGED
@@ -40,7 +40,7 @@ function validateConfig() {
40
40
  // API helper
41
41
  async function apiRequest(
42
42
  endpoint: string,
43
- method: 'GET' | 'POST' | 'PATCH' = 'GET',
43
+ method: 'GET' | 'POST' | 'PATCH' | 'DELETE' = 'GET',
44
44
  body?: Record<string, unknown>
45
45
  ): Promise<{ data?: unknown; error?: string }> {
46
46
  try {
@@ -129,7 +129,7 @@ const tools = [
129
129
  enum: ['new', 'reviewed', 'in_progress', 'resolved', 'closed'],
130
130
  description: 'New status',
131
131
  },
132
- resolution: {
132
+ resolution_notes: {
133
133
  type: 'string',
134
134
  description: 'Resolution notes (optional)',
135
135
  },
@@ -241,6 +241,33 @@ const tools = [
241
241
  required: ['test_key', 'title', 'steps', 'expected_result'],
242
242
  },
243
243
  },
244
+ {
245
+ name: 'delete_test_cases',
246
+ description: 'Delete one or more test cases. Supports single delete by ID or test_key, or bulk delete with arrays (max 50). WARNING: cascade-deletes associated test_assignments, test_feedback, and ai_test_runs.',
247
+ inputSchema: {
248
+ type: 'object' as const,
249
+ properties: {
250
+ test_case_id: {
251
+ type: 'string',
252
+ description: 'UUID of a single test case to delete',
253
+ },
254
+ test_key: {
255
+ type: 'string',
256
+ description: 'Delete a single test case by test_key (e.g., TC-001)',
257
+ },
258
+ test_case_ids: {
259
+ type: 'array',
260
+ items: { type: 'string' },
261
+ description: 'Array of test case UUIDs to bulk delete (max 50)',
262
+ },
263
+ test_keys: {
264
+ type: 'array',
265
+ items: { type: 'string' },
266
+ description: 'Array of test_keys to bulk delete (max 50)',
267
+ },
268
+ },
269
+ },
270
+ },
244
271
  {
245
272
  name: 'get_qa_tracks',
246
273
  description: 'Get QA tracks for the project',
@@ -284,7 +311,7 @@ async function handleTool(
284
311
  case 'update_report_status':
285
312
  result = await apiRequest(`/reports/${args.report_id}`, 'PATCH', {
286
313
  status: args.status,
287
- resolution: args.resolution,
314
+ resolution_notes: args.resolution_notes,
288
315
  });
289
316
  break;
290
317
 
@@ -340,6 +367,24 @@ async function handleTool(
340
367
  });
341
368
  break;
342
369
 
370
+ case 'delete_test_cases': {
371
+ const ids = args.test_case_ids as string[] || (args.test_case_id ? [args.test_case_id as string] : undefined);
372
+ const keys = args.test_keys as string[] || (args.test_key ? [args.test_key as string] : undefined);
373
+
374
+ if (ids) {
375
+ const params = new URLSearchParams();
376
+ ids.forEach((id: string) => params.append('ids', id));
377
+ result = await apiRequest(`/test-cases?${params.toString()}`, 'DELETE');
378
+ } else if (keys) {
379
+ const params = new URLSearchParams();
380
+ keys.forEach((k: string) => params.append('keys', k));
381
+ result = await apiRequest(`/test-cases?${params.toString()}`, 'DELETE');
382
+ } else {
383
+ result = { error: 'Must provide test_case_id, test_key, test_case_ids, or test_keys' };
384
+ }
385
+ break;
386
+ }
387
+
343
388
  case 'get_qa_tracks':
344
389
  result = await apiRequest('/qa-tracks');
345
390
  break;
package/src/index.ts CHANGED
@@ -144,7 +144,7 @@ const tools = [
144
144
  enum: ['new', 'triaging', 'confirmed', 'in_progress', 'fixed', 'resolved', 'verified', 'wont_fix', 'duplicate'],
145
145
  description: 'The new status for the report',
146
146
  },
147
- resolution: {
147
+ resolution_notes: {
148
148
  type: 'string',
149
149
  description: 'Optional resolution notes when marking as resolved',
150
150
  },
@@ -292,6 +292,33 @@ const tools = [
292
292
  },
293
293
  },
294
294
  },
295
+ {
296
+ name: 'delete_test_cases',
297
+ description: 'Delete one or more test cases. Supports single delete by ID or test_key, or bulk delete with arrays (max 50). WARNING: cascade-deletes associated test_assignments, test_feedback, and ai_test_runs. Reports/qa_findings keep their records but test_case_id becomes null.',
298
+ inputSchema: {
299
+ type: 'object' as const,
300
+ properties: {
301
+ test_case_id: {
302
+ type: 'string',
303
+ description: 'UUID of a single test case to delete',
304
+ },
305
+ test_key: {
306
+ type: 'string',
307
+ description: 'Delete a single test case by test_key (e.g., TC-001)',
308
+ },
309
+ test_case_ids: {
310
+ type: 'array',
311
+ items: { type: 'string' },
312
+ description: 'Array of test case UUIDs to bulk delete (max 50)',
313
+ },
314
+ test_keys: {
315
+ type: 'array',
316
+ items: { type: 'string' },
317
+ description: 'Array of test_keys to bulk delete (max 50)',
318
+ },
319
+ },
320
+ },
321
+ },
295
322
  {
296
323
  name: 'list_test_cases',
297
324
  description: 'List all test cases in the project. Returns test_key, title, target_route, and other metadata. Use this to see existing tests before updating them.',
@@ -1024,15 +1051,15 @@ async function searchReports(args: { query?: string; route?: string }) {
1024
1051
  async function updateReportStatus(args: {
1025
1052
  report_id: string;
1026
1053
  status: string;
1027
- resolution?: string;
1054
+ resolution_notes?: string;
1028
1055
  }) {
1029
1056
  if (!isValidUUID(args.report_id)) {
1030
1057
  return { error: 'Invalid report_id format' };
1031
1058
  }
1032
1059
 
1033
1060
  const updates: Record<string, unknown> = { status: args.status };
1034
- if (args.resolution) {
1035
- updates.resolution = args.resolution;
1061
+ if (args.resolution_notes) {
1062
+ updates.resolution_notes = args.resolution_notes;
1036
1063
  }
1037
1064
 
1038
1065
  const { error } = await supabase
@@ -1281,6 +1308,130 @@ async function updateTestCase(args: {
1281
1308
  };
1282
1309
  }
1283
1310
 
1311
+ async function deleteTestCases(args: {
1312
+ test_case_id?: string;
1313
+ test_key?: string;
1314
+ test_case_ids?: string[];
1315
+ test_keys?: string[];
1316
+ }) {
1317
+ // Validate: exactly one input mode
1318
+ const modes = [
1319
+ args.test_case_id,
1320
+ args.test_key,
1321
+ args.test_case_ids,
1322
+ args.test_keys,
1323
+ ].filter(v => v !== undefined && v !== null);
1324
+
1325
+ if (modes.length === 0) {
1326
+ return { error: 'Must provide one of: test_case_id, test_key, test_case_ids, or test_keys' };
1327
+ }
1328
+ if (modes.length > 1) {
1329
+ return { error: 'Provide only one of: test_case_id, test_key, test_case_ids, or test_keys' };
1330
+ }
1331
+
1332
+ let idsToDelete: string[] = [];
1333
+
1334
+ // Single ID
1335
+ if (args.test_case_id) {
1336
+ if (!isValidUUID(args.test_case_id)) {
1337
+ return { error: 'Invalid test_case_id format (must be UUID)' };
1338
+ }
1339
+ idsToDelete = [args.test_case_id];
1340
+ }
1341
+
1342
+ // Single key
1343
+ if (args.test_key) {
1344
+ const { data: existing } = await supabase
1345
+ .from('test_cases')
1346
+ .select('id')
1347
+ .eq('project_id', PROJECT_ID)
1348
+ .eq('test_key', args.test_key)
1349
+ .single();
1350
+
1351
+ if (!existing) {
1352
+ return { error: `Test case with key "${args.test_key}" not found` };
1353
+ }
1354
+ idsToDelete = [existing.id];
1355
+ }
1356
+
1357
+ // Bulk IDs
1358
+ if (args.test_case_ids) {
1359
+ if (!Array.isArray(args.test_case_ids) || args.test_case_ids.length === 0) {
1360
+ return { error: 'test_case_ids must be a non-empty array' };
1361
+ }
1362
+ if (args.test_case_ids.length > 50) {
1363
+ return { error: 'Cannot delete more than 50 test cases at once' };
1364
+ }
1365
+ const invalidIds = args.test_case_ids.filter(id => !isValidUUID(id));
1366
+ if (invalidIds.length > 0) {
1367
+ return { error: `Invalid UUID(s): ${invalidIds.join(', ')}` };
1368
+ }
1369
+ idsToDelete = args.test_case_ids;
1370
+ }
1371
+
1372
+ // Bulk keys
1373
+ if (args.test_keys) {
1374
+ if (!Array.isArray(args.test_keys) || args.test_keys.length === 0) {
1375
+ return { error: 'test_keys must be a non-empty array' };
1376
+ }
1377
+ if (args.test_keys.length > 50) {
1378
+ return { error: 'Cannot delete more than 50 test cases at once' };
1379
+ }
1380
+ const { data: existing, error: lookupError } = await supabase
1381
+ .from('test_cases')
1382
+ .select('id, test_key')
1383
+ .eq('project_id', PROJECT_ID)
1384
+ .in('test_key', args.test_keys);
1385
+
1386
+ if (lookupError) {
1387
+ return { error: lookupError.message };
1388
+ }
1389
+
1390
+ const foundKeys = (existing || []).map((tc: any) => tc.test_key);
1391
+ const notFound = args.test_keys.filter(k => !foundKeys.includes(k));
1392
+ if (notFound.length > 0) {
1393
+ return { error: `Test case(s) not found: ${notFound.join(', ')}` };
1394
+ }
1395
+ idsToDelete = (existing || []).map((tc: any) => tc.id);
1396
+ }
1397
+
1398
+ // Pre-fetch details for the response
1399
+ const { data: toDelete } = await supabase
1400
+ .from('test_cases')
1401
+ .select('id, test_key, title')
1402
+ .eq('project_id', PROJECT_ID)
1403
+ .in('id', idsToDelete);
1404
+
1405
+ if (!toDelete || toDelete.length === 0) {
1406
+ return { error: 'No matching test cases found in this project' };
1407
+ }
1408
+
1409
+ // Delete
1410
+ const { error: deleteError } = await supabase
1411
+ .from('test_cases')
1412
+ .delete()
1413
+ .eq('project_id', PROJECT_ID)
1414
+ .in('id', idsToDelete);
1415
+
1416
+ if (deleteError) {
1417
+ return { error: deleteError.message };
1418
+ }
1419
+
1420
+ return {
1421
+ success: true,
1422
+ deletedCount: toDelete.length,
1423
+ deleted: toDelete.map((tc: any) => ({
1424
+ id: tc.id,
1425
+ testKey: tc.test_key,
1426
+ title: tc.title,
1427
+ })),
1428
+ message: toDelete.length === 1
1429
+ ? `Test case ${toDelete[0].test_key} deleted successfully`
1430
+ : `${toDelete.length} test cases deleted successfully`,
1431
+ warning: 'Associated test_assignments, test_feedback, and ai_test_runs have been cascade-deleted. Reports and qa_findings referencing these tests now have null test_case_id.',
1432
+ };
1433
+ }
1434
+
1284
1435
  async function listTestCases(args: {
1285
1436
  track?: string;
1286
1437
  priority?: string;
@@ -3607,7 +3758,7 @@ async function markFixedWithCommit(args: {
3607
3758
  const updates = {
3608
3759
  status: 'resolved',
3609
3760
  resolved_at: new Date().toISOString(),
3610
- resolution: args.resolution_notes || `Fixed in commit ${args.commit_sha.slice(0, 7)}`,
3761
+ resolution_notes: args.resolution_notes || `Fixed in commit ${args.commit_sha.slice(0, 7)}`,
3611
3762
  code_context: {
3612
3763
  ...existingContext,
3613
3764
  fix: {
@@ -3889,7 +4040,7 @@ async function createRegressionTest(args: {
3889
4040
  {
3890
4041
  stepNumber: 3,
3891
4042
  action: 'Verify the fix is working',
3892
- expectedResult: report.resolution || 'Feature works as expected',
4043
+ expectedResult: report.resolution_notes || 'Feature works as expected',
3893
4044
  },
3894
4045
  ],
3895
4046
  expected_result: `The bug "${report.title}" should not recur`,
@@ -4527,6 +4678,9 @@ async function main() {
4527
4678
  case 'update_test_case':
4528
4679
  result = await updateTestCase(args as any);
4529
4680
  break;
4681
+ case 'delete_test_cases':
4682
+ result = await deleteTestCases(args as any);
4683
+ break;
4530
4684
  case 'list_test_cases':
4531
4685
  result = await listTestCases(args as any);
4532
4686
  break;