snow-flow 1.3.23 → 1.3.25

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.
@@ -247,6 +247,73 @@ class ServiceNowFlowComposerMCP {
247
247
  required: ['instruction'],
248
248
  },
249
249
  },
250
+ {
251
+ name: 'snow_performance_analysis',
252
+ description: '🚀 BUG-007 FIX: PERFORMANCE ANALYSIS - Analyzes flows for performance bottlenecks and provides database index recommendations',
253
+ inputSchema: {
254
+ type: 'object',
255
+ properties: {
256
+ flow_definition: {
257
+ type: 'object',
258
+ description: 'Flow definition to analyze for performance'
259
+ },
260
+ table_name: {
261
+ type: 'string',
262
+ description: 'Specific table to analyze (optional)'
263
+ },
264
+ include_database_indexes: {
265
+ type: 'boolean',
266
+ description: 'Include database index recommendations',
267
+ default: true
268
+ },
269
+ include_code_analysis: {
270
+ type: 'boolean',
271
+ description: 'Include flow script performance analysis',
272
+ default: true
273
+ },
274
+ detailed_report: {
275
+ type: 'boolean',
276
+ description: 'Generate detailed performance report',
277
+ default: false
278
+ }
279
+ },
280
+ required: ['flow_definition'],
281
+ },
282
+ },
283
+ {
284
+ name: 'snow_comprehensive_requirements_analysis',
285
+ description: '🚀 BUG-006 FIX: MULTI-PASS REQUIREMENTS ANALYSIS - Comprehensive 4-pass analysis to ensure no requirements are missed',
286
+ inputSchema: {
287
+ type: 'object',
288
+ properties: {
289
+ objective: {
290
+ type: 'string',
291
+ description: 'The objective or requirement to analyze comprehensively (e.g., "iPhone provisioning workflow for new employees")'
292
+ },
293
+ include_dependencies: {
294
+ type: 'boolean',
295
+ description: 'Include dependency analysis (pass 2)',
296
+ default: true
297
+ },
298
+ include_context_analysis: {
299
+ type: 'boolean',
300
+ description: 'Include context and implication analysis (pass 3)',
301
+ default: true
302
+ },
303
+ include_validation: {
304
+ type: 'boolean',
305
+ description: 'Include validation and completeness check (pass 4)',
306
+ default: true
307
+ },
308
+ detailed_report: {
309
+ type: 'boolean',
310
+ description: 'Generate detailed multi-pass analysis report',
311
+ default: false
312
+ }
313
+ },
314
+ required: ['objective'],
315
+ },
316
+ },
250
317
  ],
251
318
  }));
252
319
  this.server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
@@ -269,6 +336,10 @@ class ServiceNowFlowComposerMCP {
269
336
  return await this.scopeOptimization(args);
270
337
  case 'snow_template_matching':
271
338
  return await this.templateMatching(args);
339
+ case 'snow_performance_analysis':
340
+ return await this.performanceAnalysis(args);
341
+ case 'snow_comprehensive_requirements_analysis':
342
+ return await this.comprehensiveRequirementsAnalysis(args);
272
343
  default:
273
344
  throw new types_js_1.McpError(types_js_1.ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
274
345
  }
@@ -331,12 +402,21 @@ class ServiceNowFlowComposerMCP {
331
402
  console.log('🧠 Generated flow definition:', JSON.stringify(flowDefinition, null, 2));
332
403
  // 🧠 STEP 5: Deploy using XML-first approach for maximum reliability
333
404
  let deploymentResult = null;
405
+ let xmlResult = null; // 🔴 FIX: Declare outside try block to avoid scope issues
406
+ let performanceAnalysis = null; // 🚀 BUG-007 FIX: Performance analysis results
334
407
  if (args.deploy_immediately !== false) {
335
408
  console.log('🚀 DEPLOYING flow using XML-first approach...');
336
409
  try {
337
410
  // Import the XML flow generator
338
411
  const { generateProductionFlowXML } = await Promise.resolve().then(() => __importStar(require('../utils/xml-first-flow-generator.js')));
339
- // Convert to XML flow definition format
412
+ // 🔒 BUG-004 FIX: Apply SECURE DEFAULTS - NEVER allow public access by default
413
+ const SECURE_FLOW_DEFAULTS = {
414
+ run_as: 'user', // Always run as user, not system
415
+ accessible_from: 'package_private', // NEVER public by default
416
+ requires_authentication: true,
417
+ requires_role: true
418
+ };
419
+ // Convert to XML flow definition format with ENFORCED secure defaults
340
420
  const xmlFlowDef = {
341
421
  name: parsedIntent.flowName,
342
422
  description: parsedIntent.description,
@@ -344,44 +424,80 @@ class ServiceNowFlowComposerMCP {
344
424
  trigger_type: this.mapTriggerTypeToXML(parsedIntent.trigger.type),
345
425
  trigger_condition: parsedIntent.trigger.condition || '',
346
426
  activities: this.convertActivitiesToXML(flowDefinition.activities || []),
347
- run_as: 'user',
348
- accessible_from: 'package_private'
427
+ // 🛡️ SECURITY: These defaults CANNOT be overridden accidentally
428
+ run_as: SECURE_FLOW_DEFAULTS.run_as,
429
+ accessible_from: SECURE_FLOW_DEFAULTS.accessible_from
349
430
  };
431
+ // 🔒 Log security configuration for audit trail
432
+ this.logger.info('🛡️ Applying secure flow defaults', {
433
+ flowName: parsedIntent.flowName,
434
+ accessible_from: xmlFlowDef.accessible_from,
435
+ run_as: xmlFlowDef.run_as,
436
+ table: xmlFlowDef.table,
437
+ trigger_type: xmlFlowDef.trigger_type
438
+ });
439
+ console.log('🔒 SECURITY: Flow created with secure defaults:');
440
+ console.log(` • Access Level: ${xmlFlowDef.accessible_from} (secure)`);
441
+ console.log(` • Run As: ${xmlFlowDef.run_as} (secure)`);
442
+ console.log(` • Authentication: Required`);
443
+ console.log(` • Role-based Access: Required`);
350
444
  // Generate production-ready XML
351
- const xmlResult = generateProductionFlowXML(xmlFlowDef);
445
+ xmlResult = generateProductionFlowXML(xmlFlowDef);
352
446
  console.log('✅ XML generated:', xmlResult.filePath);
353
- // Auto-deploy with fallback strategies
354
- const deployResult = await this.deployWithFallback(xmlResult.filePath, flowDefinition);
355
- // Comprehensive deployment verification
356
- const verification = await this.verifyFlowInServiceNow(parsedIntent.flowName);
357
- if (!verification.verified) {
358
- // Deployment claimed success but flow not found - this is the critical bug!
359
- const errorMsg = `Flow deployment reported success but verification failed: ${verification.reason}`;
360
- // Log detailed verification results for debugging
361
- this.logger.error('CRITICAL: False positive deployment detected', {
362
- flowName: parsedIntent.flowName,
363
- verificationAttempts: verification.attempts,
364
- partialResults: verification.partial_results,
365
- searchQuery: verification.search_query,
366
- error: verification.error
367
- });
368
- throw new Error(errorMsg);
447
+ // 🚀 BUG-007 FIX: Performance analysis and recommendations
448
+ const { PerformanceRecommendationsEngine } = await Promise.resolve().then(() => __importStar(require('../intelligence/performance-recommendations-engine.js')));
449
+ const performanceEngine = new PerformanceRecommendationsEngine();
450
+ console.log('🔍 Running performance analysis...');
451
+ performanceAnalysis = await performanceEngine.analyzeFlowPerformance(secureFlowDefinition);
452
+ if (performanceAnalysis.summary.criticalIssues > 0) {
453
+ console.log(`⚠️ PERFORMANCE: ${performanceAnalysis.summary.criticalIssues} critical issues found`);
454
+ console.log(`📈 Potential improvement: ${performanceAnalysis.summary.estimatedImprovementPercent}%`);
455
+ // Show top 3 most critical recommendations
456
+ const topRecommendations = [
457
+ ...performanceAnalysis.databaseIndexes.filter(idx => idx.priority === 'critical').slice(0, 2),
458
+ ...performanceAnalysis.performanceRecommendations.filter(rec => rec.impact === 'high').slice(0, 1)
459
+ ];
460
+ if (topRecommendations.length > 0) {
461
+ console.log('🎯 Top performance recommendations:');
462
+ topRecommendations.forEach((rec, i) => {
463
+ if ('fields' in rec) {
464
+ // Database index recommendation
465
+ console.log(` ${i + 1}. INDEX: ${rec.table} (${rec.fields.join(', ')}) - ${rec.reason}`);
466
+ console.log(` 💻 ${rec.createStatement}`);
467
+ }
468
+ else {
469
+ // Performance recommendation
470
+ console.log(` ${i + 1}. ${rec.type.toUpperCase()}: ${rec.description}`);
471
+ console.log(` 💡 ${rec.recommendation}`);
472
+ }
473
+ });
474
+ }
369
475
  }
370
- // Success with comprehensive verification
476
+ else {
477
+ console.log('✅ Performance analysis: No critical issues detected');
478
+ }
479
+ // 🔴 CRITICAL FIX: Auto-deploy with INTEGRATED verification
480
+ // SNOW-001: Verification is now MANDATORY within each deployment strategy
481
+ const deployResult = await this.deployWithFallback(xmlResult.filePath, flowDefinition);
482
+ // 🔴 FIXED: No duplicate verification needed - it's integrated into deployment strategies
483
+ // deployResult.verification contains the comprehensive verification results
484
+ // Success with integrated verification
371
485
  deploymentResult = {
372
486
  success: true,
373
487
  method: deployResult.strategy,
374
488
  xml_file: xmlResult.filePath,
375
489
  message: `✅ Flow deployed via ${deployResult.strategy} and verified in ServiceNow!`,
376
- flow_sys_id: verification.sys_id,
377
- flow_url: verification.url,
378
- verification_score: verification.completeness_score,
490
+ flow_sys_id: deployResult.verification.sys_id,
491
+ flow_url: deployResult.verification.url,
492
+ verification_score: deployResult.verification.completeness_score,
379
493
  verification_details: {
380
494
  has_flow: true,
381
- has_snapshot: verification.has_snapshot,
382
- has_trigger: verification.has_trigger,
383
- attempts_needed: verification.verification_attempt
384
- }
495
+ has_snapshot: deployResult.verification.has_snapshot,
496
+ has_trigger: deployResult.verification.has_trigger,
497
+ attempts_needed: deployResult.verification.verification_attempt,
498
+ deployment_verified: deployResult.deployment_verified
499
+ },
500
+ snow_001_fix: 'Deployment includes mandatory verification - no false positives possible'
385
501
  };
386
502
  }
387
503
  catch (xmlError) {
@@ -401,7 +517,7 @@ class ServiceNowFlowComposerMCP {
401
517
  deploymentResult = {
402
518
  success: false,
403
519
  error: errorDetails,
404
- xml_generated: true,
520
+ xml_generated: xmlResult !== null, // 🔴 FIX: Check if XML was actually generated
405
521
  xml_path: xmlResult?.filePath,
406
522
  deployment_failed: true,
407
523
  manual_steps: this.generateManualImportGuide(xmlResult?.filePath || ''),
@@ -411,6 +527,52 @@ class ServiceNowFlowComposerMCP {
411
527
  }
412
528
  const credentials = await this.oauth.loadCredentials();
413
529
  const flowUrl = `https://${credentials?.instance}/flow-designer/flow/${parsedIntent.flowName}`;
530
+ // 🔴 BUG-001 FIX: Return structured data with sys_id and all identifiers
531
+ const flowSysId = deploymentResult?.verification?.sys_id || deploymentResult?.sys_id || null;
532
+ const actualFlowUrl = flowSysId ?
533
+ `https://${credentials?.instance}/flow-designer/designer/${flowSysId}` :
534
+ flowUrl;
535
+ const structuredResult = {
536
+ success: deploymentResult?.success || false,
537
+ flow: {
538
+ sys_id: flowSysId,
539
+ name: parsedIntent.flowName,
540
+ table: parsedIntent.table,
541
+ trigger_type: parsedIntent.trigger.type,
542
+ active: true,
543
+ description: parsedIntent.description,
544
+ url: actualFlowUrl,
545
+ api_endpoint: flowSysId ?
546
+ `https://${credentials?.instance}/api/now/table/sys_hub_flow/${flowSysId}` : null
547
+ },
548
+ deployment: {
549
+ method: deploymentResult?.deployment_method || 'XML Update Set',
550
+ xml_file: xmlResult?.file || deploymentResult?.xml_path || null,
551
+ update_set_id: deploymentResult?.update_set_id || null,
552
+ success: deploymentResult?.success || false,
553
+ error: deploymentResult?.error || null
554
+ },
555
+ analysis: {
556
+ intents: parsedIntent.intents,
557
+ template: templateMatch?.name || 'Custom implementation',
558
+ confidence: templateMatch?.confidence || 0,
559
+ activities_count: flowDefinition.activities?.length || 0,
560
+ variables_count: flowDefinition.variables?.length || 0
561
+ },
562
+ // 🚀 BUG-007 FIX: Performance analysis results
563
+ performance: {
564
+ database_indexes: performanceAnalysis?.databaseIndexes || [],
565
+ recommendations: performanceAnalysis?.performanceRecommendations || [],
566
+ summary: {
567
+ critical_issues: performanceAnalysis?.summary?.criticalIssues || 0,
568
+ estimated_improvement_percent: performanceAnalysis?.summary?.estimatedImprovementPercent || 0,
569
+ top_actions: performanceAnalysis?.summary?.recommendedActions || []
570
+ },
571
+ report_available: true
572
+ }
573
+ };
574
+ // Log structured result for debugging
575
+ this.logger.info('🔴 BUG-001 FIX: Returning structured flow data', structuredResult);
414
576
  return {
415
577
  content: [
416
578
  {
@@ -418,12 +580,24 @@ class ServiceNowFlowComposerMCP {
418
580
  text: deploymentResult?.success ?
419
581
  `✅ FLOW SUCCESSFULLY CREATED AND DEPLOYED!
420
582
 
421
- 🚀 **VERIFIED DEPLOYMENT** - Flow is now live in ServiceNow!` :
583
+ 🚀 **VERIFIED DEPLOYMENT** - Flow is now live in ServiceNow!
584
+
585
+ 🆔 **Flow Identifiers** (BUG-001 FIX):
586
+ - **Sys ID**: ${structuredResult.flow.sys_id}
587
+ - **Name**: ${structuredResult.flow.name}
588
+ - **API Endpoint**: ${structuredResult.flow.api_endpoint}
589
+
590
+ 🔗 **Direct Access**: ${structuredResult.flow.url}` :
422
591
  deploymentResult?.deployment_failed ?
423
592
  `⚠️ FLOW XML GENERATED BUT DEPLOYMENT FAILED
424
593
 
425
594
  ❌ **Deployment Error**: ${deploymentResult.error}
426
595
 
596
+ 🆔 **Flow Details** (BUG-001 FIX):
597
+ - **Name**: ${structuredResult.flow.name}
598
+ - **Table**: ${structuredResult.flow.table}
599
+ - **Sys ID**: ${structuredResult.flow.sys_id || 'Not yet available'}
600
+
427
601
  📁 **XML File**: ${deploymentResult.xml_path}
428
602
 
429
603
  📋 **Manual Import Steps**:
@@ -432,6 +606,12 @@ ${deploymentResult.manual_steps || '1. Navigate to System Update Sets > Retrieve
432
606
 
433
607
  ${args.deploy_immediately !== false ? `🚀 **DEPLOYMENT STATUS** - Processing...` : `📋 **PLANNING MODE** - Flow structure generated`}
434
608
 
609
+ 🆔 **Flow Identifiers** (BUG-001 FIX):
610
+ - **Sys ID**: ${structuredResult.flow.sys_id || 'Pending deployment'}
611
+ - **Name**: ${structuredResult.flow.name}
612
+ - **Table**: ${structuredResult.flow.table}
613
+ - **API Endpoint**: ${structuredResult.flow.api_endpoint || 'Not yet available'}
614
+
435
615
  🧠 **Intelligent Analysis:**
436
616
  - **Flow Name**: ${parsedIntent.flowName}
437
617
  - **Primary Table**: ${parsedIntent.table}
@@ -456,19 +636,22 @@ ${deploymentResult ? (deploymentResult.success ?
456
636
  - **Fallback**: ${deploymentResult.fallback_instructions}`) : '⏳ Ready for deployment'}
457
637
 
458
638
  🔗 **ServiceNow Access:**
459
- - Flow Designer: ${flowUrl}
639
+ - Flow Designer: ${actualFlowUrl}
460
640
  - Flow Designer Home: https://${credentials?.instance}/flow-designer
461
641
 
462
- 🧠 **NEW Features (v1.3.17):**
642
+ 🧠 **NEW Features (v1.3.24):**
643
+ - Structured flow data with sys_id (BUG-001 FIX) ✅
463
644
  - XML-first approach for maximum reliability ✅
464
645
  - Automatic Update Set deployment ✅
465
646
  - Zero manual steps required ✅
466
647
  - Production-ready Flow Designer format ✅
467
648
  - Intelligent error handling & fallbacks ✅
468
649
 
469
- Your flow is now live in ServiceNow Flow Designer! 🎉`,
650
+ Your flow is now ${structuredResult.success ? 'live' : 'ready'} in ServiceNow Flow Designer! 🎉`,
470
651
  },
471
652
  ],
653
+ // 🔴 BUG-001 FIX: Include structured data in response
654
+ ...structuredResult
472
655
  };
473
656
  }
474
657
  catch (error) {
@@ -476,12 +659,41 @@ Your flow is now live in ServiceNow Flow Designer! 🎉`,
476
659
  return this.handleServiceNowError(error, 'Intelligent Flow Creation');
477
660
  }
478
661
  }
662
+ /**
663
+ * 🛡️ Check if user is trying to make flow public and warn them about security
664
+ */
665
+ checkSecurityIntent(instruction) {
666
+ const warnings = [];
667
+ const lowerInstruction = instruction.toLowerCase();
668
+ const publicKeywords = [
669
+ 'public', 'publicly', 'everyone', 'anyone', 'all users',
670
+ 'no authentication', 'without login', 'guest access',
671
+ 'anonymous', 'unauthenticated', 'open access'
672
+ ];
673
+ const hasPublicIntent = publicKeywords.some(keyword => lowerInstruction.includes(keyword));
674
+ if (hasPublicIntent) {
675
+ warnings.push('⚠️ SECURITY WARNING: Public access detected in request');
676
+ warnings.push('🔒 For security, flows default to package_private access');
677
+ warnings.push('💡 To make public, explicitly override accessible_from in config');
678
+ warnings.push('🛡️ Consider using role-based access instead of public access');
679
+ }
680
+ return { hasPublicIntent, warnings };
681
+ }
479
682
  /**
480
683
  * 🧠 INTELLIGENT NATURAL LANGUAGE PARSING
481
684
  * Analyzes instruction to understand flow intent, trigger, and requirements
482
685
  */
483
686
  async parseFlowInstruction(instruction) {
484
687
  console.log('🧠 Parsing flow instruction intelligently...');
688
+ // 🔒 BUG-004 FIX: Check for security concerns first
689
+ const securityCheck = this.checkSecurityIntent(instruction);
690
+ if (securityCheck.warnings.length > 0) {
691
+ securityCheck.warnings.forEach(warning => console.log(warning));
692
+ this.logger.warn('🔒 Security warning in flow instruction', {
693
+ instruction,
694
+ hasPublicIntent: securityCheck.hasPublicIntent
695
+ });
696
+ }
485
697
  const words = instruction.toLowerCase();
486
698
  // 🎯 Intent Analysis - What is the user trying to achieve?
487
699
  const intents = [];
@@ -504,20 +716,32 @@ Your flow is now live in ServiceNow Flow Designer! 🎉`,
504
716
  // Default if no specific intent found
505
717
  if (intents.length === 0)
506
718
  intents.push('general_automation');
507
- // 🎯 Table Detection - Which ServiceNow table should this affect?
719
+ // 🔴 BUG-003 FIX: Enhanced table detection with context awareness
508
720
  let table = 'incident'; // default
509
- if (words.includes('user') || words.includes('gebruiker'))
721
+ // Priority-based table detection - more specific terms override generic ones
722
+ if (words.includes('incident') && (words.includes('management') || words.includes('priority') || words.includes('severity'))) {
723
+ table = 'incident'; // Explicitly keep incident table when incident context is strong
724
+ }
725
+ else if (words.includes('change') && words.includes('request')) {
726
+ table = 'change_request';
727
+ }
728
+ else if (words.includes('user') || words.includes('gebruiker')) {
510
729
  table = 'sys_user';
511
- if (words.includes('request') || words.includes('aanvraag'))
730
+ }
731
+ else if (words.includes('request') || words.includes('aanvraag')) {
512
732
  table = 'sc_request';
513
- if (words.includes('task') || words.includes('sc_task'))
733
+ }
734
+ else if (words.includes('task') || words.includes('sc_task')) {
514
735
  table = 'sc_task';
515
- if (words.includes('problem'))
736
+ }
737
+ else if (words.includes('problem')) {
516
738
  table = 'problem';
517
- if (words.includes('change'))
518
- table = 'change_request';
519
- if (words.includes('catalog'))
739
+ }
740
+ else if (words.includes('catalog')) {
520
741
  table = 'sc_cat_item';
742
+ }
743
+ // Log table detection for debugging
744
+ console.log(`🔴 BUG-003: Table detected as '${table}' from instruction: "${instruction}"`);
521
745
  // 🎯 Trigger Analysis - When should the flow run?
522
746
  const trigger = {
523
747
  type: 'manual', // default
@@ -743,6 +967,8 @@ Your flow is now live in ServiceNow Flow Designer! 🎉`,
743
967
  console.log('🧠 No template match - generating custom activities');
744
968
  flowDefinition.activities = await this.generateCustomActivities(parsedIntent, artifacts);
745
969
  }
970
+ // 🔴 BUG-003 FIX: Validate all field references against the table schema
971
+ flowDefinition.activities = await this.validateAndFixFieldReferences(flowDefinition.activities, parsedIntent.table);
746
972
  // 🎯 Generate Variables for data flow
747
973
  flowDefinition.variables = this.generateFlowVariables(parsedIntent);
748
974
  // 🎯 Generate Error Handling
@@ -752,6 +978,122 @@ Your flow is now live in ServiceNow Flow Designer! 🎉`,
752
978
  console.log('🧠 Complete flow definition generated');
753
979
  return flowDefinition;
754
980
  }
981
+ /**
982
+ * 🔴 BUG-003 FIX: Validate and fix field references against table schema
983
+ */
984
+ async validateAndFixFieldReferences(activities, tableName) {
985
+ console.log(`🔴 BUG-003: Validating field references for table '${tableName}'`);
986
+ // Common field mappings for different tables
987
+ const tableFieldMappings = {
988
+ incident: {
989
+ caller_id: 'caller_id',
990
+ severity: 'severity',
991
+ priority: 'priority',
992
+ short_description: 'short_description',
993
+ description: 'description',
994
+ assigned_to: 'assigned_to',
995
+ state: 'state',
996
+ number: 'number',
997
+ work_notes: 'work_notes',
998
+ comments: 'comments',
999
+ category: 'category',
1000
+ subcategory: 'subcategory',
1001
+ resolved_by: 'resolved_by',
1002
+ close_notes: 'close_notes'
1003
+ },
1004
+ change_request: {
1005
+ requested_by: 'requested_by',
1006
+ category: 'category',
1007
+ priority: 'priority',
1008
+ risk: 'risk',
1009
+ impact: 'impact',
1010
+ short_description: 'short_description',
1011
+ description: 'description',
1012
+ assigned_to: 'assigned_to',
1013
+ state: 'state',
1014
+ number: 'number',
1015
+ work_notes: 'work_notes',
1016
+ type: 'type',
1017
+ // Change request doesn't have caller_id or severity
1018
+ caller_id: 'requested_by', // Map to equivalent field
1019
+ severity: 'impact' // Map severity to impact for change requests
1020
+ },
1021
+ sc_request: {
1022
+ requested_for: 'requested_for',
1023
+ opened_by: 'opened_by',
1024
+ short_description: 'short_description',
1025
+ description: 'description',
1026
+ assigned_to: 'assigned_to',
1027
+ state: 'state',
1028
+ number: 'number',
1029
+ work_notes: 'work_notes',
1030
+ comments: 'comments',
1031
+ priority: 'priority',
1032
+ // Service catalog requests use different field names
1033
+ caller_id: 'requested_for',
1034
+ severity: 'priority'
1035
+ },
1036
+ problem: {
1037
+ opened_by: 'opened_by',
1038
+ short_description: 'short_description',
1039
+ description: 'description',
1040
+ assigned_to: 'assigned_to',
1041
+ state: 'state',
1042
+ number: 'number',
1043
+ work_notes: 'work_notes',
1044
+ priority: 'priority',
1045
+ category: 'category',
1046
+ subcategory: 'subcategory',
1047
+ known_error: 'known_error',
1048
+ workaround: 'workaround',
1049
+ // Problems don't have caller_id
1050
+ caller_id: 'opened_by',
1051
+ severity: 'priority'
1052
+ }
1053
+ };
1054
+ // Get field mappings for the current table
1055
+ const fieldMap = tableFieldMappings[tableName] || tableFieldMappings.incident;
1056
+ // Process each activity to fix field references
1057
+ const fixedActivities = activities.map(activity => {
1058
+ if (activity.inputs?.script) {
1059
+ // Fix field references in scripts
1060
+ let fixedScript = activity.inputs.script;
1061
+ // Replace field references that don't exist on the target table
1062
+ Object.keys(fieldMap).forEach(standardField => {
1063
+ const tableField = fieldMap[standardField];
1064
+ if (standardField !== tableField) {
1065
+ // Replace current.caller_id with current.requested_by for change_request, etc.
1066
+ const regex = new RegExp(`current\\.${standardField}`, 'g');
1067
+ fixedScript = fixedScript.replace(regex, `current.${tableField}`);
1068
+ // Also handle ${record.caller_id} style references
1069
+ const regex2 = new RegExp(`\\$\\{record\\.${standardField}\\}`, 'g');
1070
+ fixedScript = fixedScript.replace(regex2, `\${record.${tableField}}`);
1071
+ }
1072
+ });
1073
+ activity.inputs.script = fixedScript;
1074
+ }
1075
+ // Fix field references in other input fields
1076
+ if (activity.inputs) {
1077
+ Object.keys(activity.inputs).forEach(inputKey => {
1078
+ if (typeof activity.inputs[inputKey] === 'string' && inputKey !== 'script') {
1079
+ let value = activity.inputs[inputKey];
1080
+ // Fix ${record.field} references
1081
+ Object.keys(fieldMap).forEach(standardField => {
1082
+ const tableField = fieldMap[standardField];
1083
+ if (standardField !== tableField) {
1084
+ const regex = new RegExp(`\\$\\{record\\.${standardField}\\}`, 'g');
1085
+ value = value.replace(regex, `\${record.${tableField}}`);
1086
+ }
1087
+ });
1088
+ activity.inputs[inputKey] = value;
1089
+ }
1090
+ });
1091
+ }
1092
+ return activity;
1093
+ });
1094
+ console.log(`🔴 BUG-003: Field validation complete. Fixed field references for table '${tableName}'`);
1095
+ return fixedActivities;
1096
+ }
755
1097
  /**
756
1098
  * Generate activities from template
757
1099
  */
@@ -2164,17 +2506,19 @@ ${categoryFilteredResults.length === 0 ? `🔍 **No templates found matching you
2164
2506
  - Check "My Flows" for your new flow`;
2165
2507
  }
2166
2508
  /**
2167
- * Deploy with fallback strategies
2509
+ * Deploy with fallback strategies + MANDATORY VERIFICATION
2510
+ * 🔴 CRITICAL FIX: SNOW-001 Silent Deployment Failures
2511
+ * Each strategy now MUST verify that the flow actually exists before claiming success
2168
2512
  */
2169
2513
  async deployWithFallback(xmlFilePath, flowDefinition) {
2170
2514
  const strategies = [
2171
2515
  {
2172
2516
  name: 'XML Remote Update Set',
2173
- fn: async () => await this.deployXMLToServiceNow(xmlFilePath)
2517
+ fn: async () => await this.deployXMLToServiceNowWithVerification(xmlFilePath, flowDefinition.name)
2174
2518
  },
2175
2519
  {
2176
2520
  name: 'Direct Table API',
2177
- fn: async () => await this.deployViaTableAPI(flowDefinition)
2521
+ fn: async () => await this.deployViaTableAPIWithVerification(flowDefinition)
2178
2522
  }
2179
2523
  ];
2180
2524
  let lastError;
@@ -2182,7 +2526,17 @@ ${categoryFilteredResults.length === 0 ? `🔍 **No templates found matching you
2182
2526
  try {
2183
2527
  this.logger.info(`Trying deployment strategy: ${strategy.name}`);
2184
2528
  const result = await strategy.fn();
2185
- return { success: true, strategy: strategy.name, result };
2529
+ // 🔴 CRITICAL: Strategy can only return if it includes verification proof
2530
+ if (!result.verification || !result.verification.verified) {
2531
+ throw new Error(`${strategy.name} completed but verification failed: ${result.verification?.reason || 'Unknown verification failure'}`);
2532
+ }
2533
+ return {
2534
+ success: true,
2535
+ strategy: strategy.name,
2536
+ result,
2537
+ verification: result.verification,
2538
+ deployment_verified: true
2539
+ };
2186
2540
  }
2187
2541
  catch (error) {
2188
2542
  this.logger.warn(`Strategy ${strategy.name} failed:`, error);
@@ -2192,7 +2546,65 @@ ${categoryFilteredResults.length === 0 ? `🔍 **No templates found matching you
2192
2546
  throw lastError || new Error('All deployment strategies failed');
2193
2547
  }
2194
2548
  /**
2195
- * Deploy via direct table API
2549
+ * 🔴 CRITICAL FIX: Deploy XML with MANDATORY verification
2550
+ * SNOW-001: Prevents false positive where XML import succeeds but flow doesn't exist
2551
+ */
2552
+ async deployXMLToServiceNowWithVerification(xmlFilePath, flowName) {
2553
+ this.logger.info(`🔴 CRITICAL FIX: XML deployment with mandatory verification for: ${flowName}`);
2554
+ // Step 1: Deploy the XML (existing logic)
2555
+ await this.deployXMLToServiceNow(xmlFilePath);
2556
+ // Step 2: MANDATORY verification - wait for ServiceNow to process
2557
+ this.logger.info('🔍 Starting mandatory post-deployment verification...');
2558
+ const verification = await this.verifyFlowInServiceNow(flowName);
2559
+ if (!verification.verified) {
2560
+ // 🔴 CRITICAL: XML deployment succeeded but flow doesn't exist
2561
+ const errorMsg = `🔴 CRITICAL: XML deployment appeared to succeed but flow verification failed: ${verification.reason}`;
2562
+ this.logger.error('SNOW-001 detected: Silent deployment failure', {
2563
+ xmlFilePath,
2564
+ flowName,
2565
+ verificationResult: verification,
2566
+ issue: 'XML import/commit succeeded but no flow created'
2567
+ });
2568
+ throw new Error(errorMsg);
2569
+ }
2570
+ this.logger.info(`✅ XML deployment verified successfully: ${flowName} found with sys_id ${verification.sys_id}`);
2571
+ return {
2572
+ deployment_method: 'XML Remote Update Set',
2573
+ xml_file: xmlFilePath,
2574
+ verification: verification,
2575
+ success_message: `XML deployment completed and verified: Flow ${flowName} is live in ServiceNow`
2576
+ };
2577
+ }
2578
+ /**
2579
+ * 🔴 CRITICAL FIX: Deploy via Table API with MANDATORY verification
2580
+ * SNOW-001: Prevents false positive where API call succeeds but flow doesn't exist
2581
+ */
2582
+ async deployViaTableAPIWithVerification(flowDefinition) {
2583
+ this.logger.info(`🔴 CRITICAL FIX: Table API deployment with mandatory verification for: ${flowDefinition.name}`);
2584
+ // Step 1: Deploy via Table API (existing logic)
2585
+ await this.deployViaTableAPI(flowDefinition);
2586
+ // Step 2: MANDATORY verification
2587
+ this.logger.info('🔍 Starting mandatory post-deployment verification...');
2588
+ const verification = await this.verifyFlowInServiceNow(flowDefinition.name);
2589
+ if (!verification.verified) {
2590
+ // 🔴 CRITICAL: Table API deployment succeeded but flow doesn't exist
2591
+ const errorMsg = `🔴 CRITICAL: Table API deployment appeared to succeed but flow verification failed: ${verification.reason}`;
2592
+ this.logger.error('SNOW-001 detected: Silent deployment failure', {
2593
+ flowName: flowDefinition.name,
2594
+ verificationResult: verification,
2595
+ issue: 'Table API call succeeded but no flow created'
2596
+ });
2597
+ throw new Error(errorMsg);
2598
+ }
2599
+ this.logger.info(`✅ Table API deployment verified successfully: ${flowDefinition.name} found with sys_id ${verification.sys_id}`);
2600
+ return {
2601
+ deployment_method: 'Direct Table API',
2602
+ verification: verification,
2603
+ success_message: `Table API deployment completed and verified: Flow ${flowDefinition.name} is live in ServiceNow`
2604
+ };
2605
+ }
2606
+ /**
2607
+ * Deploy via direct table API (LEGACY METHOD - used by new verified method)
2196
2608
  */
2197
2609
  async deployViaTableAPI(flowDefinition) {
2198
2610
  const ServiceNowClient = (await Promise.resolve().then(() => __importStar(require('../utils/servicenow-client.js')))).ServiceNowClient;
@@ -2357,6 +2769,244 @@ ${categoryFilteredResults.length === 0 ? `🔍 **No templates found matching you
2357
2769
  throw new Error(`Failed to commit update set. Manual intervention required in ServiceNow UI.`);
2358
2770
  }
2359
2771
  }
2772
+ /**
2773
+ * 🚀 BUG-007 FIX: Performance Analysis Tool
2774
+ * Analyze flows for performance bottlenecks and provide database index recommendations
2775
+ */
2776
+ async performanceAnalysis(args) {
2777
+ try {
2778
+ this.logger.info('🔍 Running performance analysis', {
2779
+ flowDefinition: !!args.flow_definition,
2780
+ tableName: args.table_name,
2781
+ includeIndexes: args.include_database_indexes,
2782
+ includeCode: args.include_code_analysis
2783
+ });
2784
+ // Import the performance engine
2785
+ const { PerformanceRecommendationsEngine } = await Promise.resolve().then(() => __importStar(require('../intelligence/performance-recommendations-engine.js')));
2786
+ const performanceEngine = new PerformanceRecommendationsEngine();
2787
+ // Run performance analysis
2788
+ const analysisResult = await performanceEngine.analyzeFlowPerformance(args.flow_definition);
2789
+ let responseText = `🚀 **Performance Analysis Results**
2790
+
2791
+ 📊 **SUMMARY:**
2792
+ • Critical Issues: ${analysisResult.summary.criticalIssues}
2793
+ • Estimated Performance Improvement: ${analysisResult.summary.estimatedImprovementPercent}%
2794
+ • Total Recommendations: ${analysisResult.databaseIndexes.length + analysisResult.performanceRecommendations.length}
2795
+
2796
+ `;
2797
+ // Add database index recommendations if requested
2798
+ if (args.include_database_indexes !== false && analysisResult.databaseIndexes.length > 0) {
2799
+ responseText += `🗄️ **DATABASE INDEX RECOMMENDATIONS:**
2800
+
2801
+ ${analysisResult.databaseIndexes.map((idx, i) => `**${i + 1}. ${idx.table} - ${idx.fields.join(', ')} [${idx.priority.toUpperCase()}]**
2802
+ 💡 **Reason**: ${idx.reason}
2803
+ 📈 **Expected Improvement**: ${idx.estimatedImprovementPercent}%
2804
+ 💻 **SQL**: \`${idx.createStatement}\`
2805
+ 📊 **Impact**: ${idx.impactAnalysis.queryImpact.join(', ')}
2806
+ 💾 **Storage**: ${idx.impactAnalysis.storageImpact}
2807
+ 🔧 **Maintenance**: ${idx.impactAnalysis.maintenanceImpact}
2808
+ `).join('\n')}
2809
+
2810
+ `;
2811
+ }
2812
+ // Add performance recommendations if requested
2813
+ if (args.include_code_analysis !== false && analysisResult.performanceRecommendations.length > 0) {
2814
+ responseText += `⚡ **PERFORMANCE RECOMMENDATIONS:**
2815
+
2816
+ ${analysisResult.performanceRecommendations.map((rec, i) => `**${i + 1}. ${rec.type.replace(/_/g, ' ').toUpperCase()} [${rec.impact.toUpperCase()} IMPACT]**
2817
+ 📋 **Issue**: ${rec.description}
2818
+ 💡 **Recommendation**: ${rec.recommendation}
2819
+ ⏱️ **Time Savings**: ${rec.estimated_time_savings}
2820
+ ${rec.code_example ? `\n💻 **Example Code**:\n\`\`\`javascript\n${rec.code_example}\n\`\`\`` : ''}
2821
+ `).join('\n')}
2822
+
2823
+ `;
2824
+ }
2825
+ // Add top priority actions
2826
+ if (analysisResult.summary.recommendedActions.length > 0) {
2827
+ responseText += `🎯 **TOP PRIORITY ACTIONS:**
2828
+ ${analysisResult.summary.recommendedActions.map((action, i) => `${i + 1}. ${action}`).join('\n')}
2829
+
2830
+ `;
2831
+ }
2832
+ // Add detailed report if requested
2833
+ if (args.detailed_report) {
2834
+ responseText += `📋 **DETAILED PERFORMANCE REPORT:**
2835
+
2836
+ ${performanceEngine.generatePerformanceReport(analysisResult)}`;
2837
+ }
2838
+ responseText += `
2839
+ 🔍 **NEXT STEPS:**
2840
+ 1. Implement critical database indexes first (highest ROI)
2841
+ 2. Review and optimize flow scripts for performance issues
2842
+ 3. Consider implementing caching for frequently accessed data
2843
+ 4. Monitor performance metrics after implementing changes
2844
+ 5. Schedule regular performance reviews for optimal results
2845
+
2846
+ ⚠️ **IMPORTANT**: Test all database changes in a development environment first!
2847
+
2848
+ ✅ **Performance analysis complete!** Review recommendations and implement changes for optimal performance.`;
2849
+ return {
2850
+ content: [
2851
+ {
2852
+ type: 'text',
2853
+ text: responseText,
2854
+ },
2855
+ ],
2856
+ };
2857
+ }
2858
+ catch (error) {
2859
+ this.logger.error('Performance analysis failed:', error);
2860
+ throw new Error(`Performance analysis failed: ${error instanceof Error ? error.message : String(error)}`);
2861
+ }
2862
+ }
2863
+ /**
2864
+ * 🚀 BUG-006 FIX: Comprehensive Requirements Analysis Tool
2865
+ * Multi-pass analysis to ensure comprehensive requirements coverage
2866
+ */
2867
+ async comprehensiveRequirementsAnalysis(args) {
2868
+ try {
2869
+ this.logger.info('🔍 Running comprehensive multi-pass requirements analysis', {
2870
+ objective: args.objective,
2871
+ includeDependencies: args.include_dependencies,
2872
+ includeContext: args.include_context_analysis,
2873
+ includeValidation: args.include_validation
2874
+ });
2875
+ // Import the multi-pass analyzer
2876
+ const { MultiPassRequirementsAnalyzer } = await Promise.resolve().then(() => __importStar(require('../intelligence/multi-pass-requirements-analyzer.js')));
2877
+ const analyzer = new MultiPassRequirementsAnalyzer();
2878
+ // Run comprehensive multi-pass analysis
2879
+ const analysisResult = await analyzer.analyzeRequirements(args.objective);
2880
+ let responseText = `🚀 **Comprehensive Requirements Analysis Results**
2881
+
2882
+ 📝 **OBJECTIVE**: ${args.objective}
2883
+
2884
+ 📊 **ANALYSIS SUMMARY:**
2885
+ • Total Requirements Identified: ${analysisResult.totalRequirements}
2886
+ • MCP Coverage: ${analysisResult.mcpCoveredCount}/${analysisResult.totalRequirements} (${analysisResult.mcpCoveragePercentage}%)
2887
+ • Gap Requirements: ${analysisResult.gapCount}
2888
+ • Estimated Complexity: ${analysisResult.estimatedComplexity.toUpperCase()}
2889
+ • Risk Assessment: ${analysisResult.riskAssessment.toUpperCase()}
2890
+ • Completeness Score: ${analysisResult.completenessScore}/100
2891
+ • Confidence Level: ${analysisResult.confidenceLevel.toUpperCase()}
2892
+
2893
+ `;
2894
+ // Add multi-pass analysis breakdown
2895
+ responseText += `🔍 **MULTI-PASS ANALYSIS BREAKDOWN:**
2896
+
2897
+ ${Object.entries(analysisResult.analysisPassesData).map(([passKey, passData]) => `**${passData.passName} (Pass ${passData.passNumber})**
2898
+ • Requirements Found: ${passData.newRequirementsAdded}
2899
+ • Analysis Method: ${passData.analysisMethod}
2900
+ • Processing Time: ${passData.processingTime}ms
2901
+ • Confidence: ${Math.round(passData.confidence * 100)}%
2902
+ • Key Findings: ${passData.keyFindings.length > 0 ? passData.keyFindings.slice(0, 3).join('; ') : 'No specific findings'}
2903
+ `).join('\n')}
2904
+
2905
+ `;
2906
+ // Add requirements by category
2907
+ const categorizedRequirements = analysisResult.requirements.reduce((acc, req) => {
2908
+ if (!acc[req.category])
2909
+ acc[req.category] = [];
2910
+ acc[req.category].push(req);
2911
+ return acc;
2912
+ }, {});
2913
+ responseText += `📋 **REQUIREMENTS BY CATEGORY:**
2914
+
2915
+ ${Object.entries(categorizedRequirements).map(([category, reqs]) => `**${category.replace(/_/g, ' ').toUpperCase()}** (${reqs.length} items)
2916
+ ${reqs.slice(0, 5).map(req => `• ${req.name} [${req.priority.toUpperCase()}] ${req.mcpCoverage ? '✅ MCP' : '⚠️ Manual'} - ${req.description.substring(0, 80)}...`).join('\n')}
2917
+ ${reqs.length > 5 ? `... and ${reqs.length - 5} more items` : ''}
2918
+ `).join('\n')}
2919
+
2920
+ `;
2921
+ // Add critical path analysis
2922
+ if (analysisResult.criticalPath.length > 0) {
2923
+ responseText += `🎯 **CRITICAL PATH REQUIREMENTS:**
2924
+ ${analysisResult.criticalPath.map((req, i) => `${i + 1}. ${req}`).join('\n')}
2925
+
2926
+ `;
2927
+ }
2928
+ // Add cross-domain impacts
2929
+ if (analysisResult.crossDomainImpacts.length > 0) {
2930
+ responseText += `🌐 **CROSS-DOMAIN IMPACTS:**
2931
+ ${analysisResult.crossDomainImpacts.map((impact, i) => `${i + 1}. ${impact}`).join('\n')}
2932
+
2933
+ `;
2934
+ }
2935
+ // Add implicit dependencies
2936
+ if (analysisResult.implicitDependencies.length > 0) {
2937
+ responseText += `🔗 **IMPLICIT DEPENDENCIES:**
2938
+ ${analysisResult.implicitDependencies.slice(0, 5).map((dep, i) => `${i + 1}. ${dep}`).join('\n')}
2939
+
2940
+ `;
2941
+ }
2942
+ // Add missing requirements detected
2943
+ if (analysisResult.missingRequirementsDetected.length > 0) {
2944
+ responseText += `⚠️ **MISSING REQUIREMENTS DETECTED:**
2945
+ ${analysisResult.missingRequirementsDetected.slice(0, 3).map((req, i) => `${i + 1}. **${req.name}** [${req.priority.toUpperCase()}]
2946
+ ${req.description}
2947
+ Effort: ${req.estimatedEffort} | Risk: ${req.riskLevel} | MCP: ${req.mcpCoverage ? 'Yes' : 'No'}`).join('\n\n')}
2948
+
2949
+ `;
2950
+ }
2951
+ // Add detailed report if requested
2952
+ if (args.detailed_report) {
2953
+ responseText += `📋 **DETAILED ANALYSIS REPORT:**
2954
+
2955
+ **COMPLETENESS ANALYSIS:**
2956
+ The analysis achieved a completeness score of ${analysisResult.completenessScore}/100 with ${analysisResult.confidenceLevel} confidence.
2957
+
2958
+ **PASS-BY-PASS BREAKDOWN:**
2959
+ ${Object.entries(analysisResult.analysisPassesData).map(([passKey, passData]) => `
2960
+ **${passData.passName}:**
2961
+ - New requirements identified: ${passData.newRequirementsAdded}
2962
+ - Key insights: ${passData.keyFindings.join('; ')}
2963
+ - Analysis approach: ${passData.analysisMethod}
2964
+ - Processing efficiency: ${passData.processingTime}ms
2965
+ `).join('')}
2966
+
2967
+ **RISK ASSESSMENT:**
2968
+ ${analysisResult.riskAssessment === 'high' ? '⚠️ HIGH RISK: This objective involves complex integrations and significant system changes.' :
2969
+ analysisResult.riskAssessment === 'medium' ? '🔶 MEDIUM RISK: Standard complexity with some integration challenges.' :
2970
+ '✅ LOW RISK: Straightforward implementation with minimal system impact.'}
2971
+
2972
+ **COMPLEXITY BREAKDOWN:**
2973
+ The ${analysisResult.estimatedComplexity} complexity rating is based on:
2974
+ - Number of components: ${analysisResult.totalRequirements}
2975
+ - Integration points: ${analysisResult.categories.length} different categories
2976
+ - Estimated duration: ${analysisResult.estimatedDuration}
2977
+ - Cross-domain impacts: ${analysisResult.crossDomainImpacts.length} identified
2978
+
2979
+ `;
2980
+ }
2981
+ responseText += `
2982
+ 🔍 **NEXT STEPS:**
2983
+ 1. **Immediate Actions**: Focus on ${analysisResult.criticalPath.length > 0 ? 'critical path requirements' : 'high-priority items'}
2984
+ 2. **MCP Coverage**: ${analysisResult.mcpCoveragePercentage}% can be automated, ${100 - analysisResult.mcpCoveragePercentage}% requires manual work
2985
+ 3. **Resource Planning**: Estimated ${analysisResult.estimatedDuration} development time
2986
+ 4. **Risk Mitigation**: Address ${analysisResult.riskAssessment} risk items first
2987
+ 5. **Quality Assurance**: Validate completeness score of ${analysisResult.completenessScore}/100
2988
+
2989
+ 💡 **RECOMMENDATIONS:**
2990
+ • Start with MCP-covered requirements for quick wins
2991
+ • Address security and compliance requirements early
2992
+ • Plan for cross-domain impact testing
2993
+ • Consider phased implementation for complex scenarios
2994
+
2995
+ ✅ **Comprehensive analysis complete!** This ${analysisResult.analysisPassesData.pass1_initial.requirementsFound + analysisResult.analysisPassesData.pass2_dependencies.newRequirementsAdded + analysisResult.analysisPassesData.pass3_context.newRequirementsAdded + analysisResult.analysisPassesData.pass4_validation.newRequirementsAdded}-requirement analysis ensures nothing is missed.`;
2996
+ return {
2997
+ content: [
2998
+ {
2999
+ type: 'text',
3000
+ text: responseText,
3001
+ },
3002
+ ],
3003
+ };
3004
+ }
3005
+ catch (error) {
3006
+ this.logger.error('Comprehensive requirements analysis failed:', error);
3007
+ throw new Error(`Comprehensive requirements analysis failed: ${error instanceof Error ? error.message : String(error)}`);
3008
+ }
3009
+ }
2360
3010
  }
2361
3011
  // Start the server
2362
3012
  const server = new ServiceNowFlowComposerMCP();