snow-flow 10.0.1-dev.421 → 10.0.1-dev.423

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
- "version": "10.0.1-dev.421",
3
+ "version": "10.0.1-dev.423",
4
4
  "name": "snow-flow",
5
5
  "description": "Snow-Flow - ServiceNow Multi-Agent Development Framework powered by AI",
6
6
  "license": "Elastic-2.0",
@@ -152,43 +152,7 @@ async function createFlowViaScheduledJob(
152
152
  " verSysId = v.insert();",
153
153
  " r.steps.version_insert = { success: !!verSysId, sys_id: verSysId + '' };",
154
154
  "",
155
- // Create snapshot in sys_hub_flow_snapshot (this is what latest_snapshot points to!)
156
- // Reference snapshot fields: parent_flow, master, internal_name, type, run_as,
157
- // access, active, status, name, sc_callable, callable_by_client_api
158
- " var snapId = null;",
159
- " try {",
160
- " var snap = new GlideRecord('sys_hub_flow_snapshot');",
161
- " if (snap.isValid()) {",
162
- " snap.initialize();",
163
- " snap.setValue('name', flowName);",
164
- " snap.setValue('internal_name', intName);",
165
- " snap.setValue('parent_flow', flowSysId);",
166
- " snap.setValue('type', isSubflow ? 'subflow' : 'flow');",
167
- " snap.setValue('run_as', runAs);",
168
- " snap.setValue('access', 'public');",
169
- " snap.setValue('active', true);",
170
- " snap.setValue('master', true);",
171
- " snap.setValue('status', 'published');",
172
- " snap.setValue('label_cache', '[]');",
173
- " try { snap.setValue('sc_callable', false); } catch(e) {}",
174
- " try { snap.setValue('callable_by_client_api', false); } catch(e) {}",
175
- " snapId = snap.insert();",
176
- " r.steps.snapshot_insert = { success: !!snapId, sys_id: snapId + '' };",
177
- " } else { r.steps.snapshot_insert = { success: false, error: 'table not valid' }; }",
178
- " } catch(snapE) { r.steps.snapshot_insert = { success: false, error: snapE.getMessage ? snapE.getMessage() : snapE + '' }; }",
179
- "",
180
- // Set latest_snapshot on flow to point to the snapshot record
181
- " var snapshotRef = snapId || verSysId;",
182
- " if (snapshotRef) {",
183
- " try {",
184
- " var flowUpd = new GlideRecord('sys_hub_flow');",
185
- " if (flowUpd.get(flowSysId)) {",
186
- " flowUpd.setValue('latest_snapshot', snapshotRef);",
187
- " flowUpd.update();",
188
- " r.steps.latest_snapshot_set = { value: snapshotRef + '', source: snapId ? 'snapshot' : 'version' };",
189
- " }",
190
- " } catch(lsE) { r.steps.latest_snapshot_set = { error: lsE.getMessage ? lsE.getMessage() : lsE + '' }; }",
191
- " }",
155
+ // No snapshot/latest_snapshot let the engine create these via Business Rule post-compile
192
156
  " r.tier_used = 'gliderecord_scheduled'; r.success = true;",
193
157
  " }",
194
158
  " } catch(t2e) { r.steps.tier2 = { success: false, error: t2e.getMessage ? t2e.getMessage() : t2e + '' }; }",
@@ -297,157 +261,8 @@ async function createFlowViaScheduledJob(
297
261
  " }",
298
262
  " }",
299
263
  " r.steps.variables = { success: true, created: varsCreated };",
300
- "",
301
- // ── Duplicate trigger/action instances to snapshot ──
302
- // Reference flow analysis: snapshot has its OWN action instances (flow=snapshot_id).
303
- // Flow Designer loads the snapshot and queries instances where flow=snapshot_id.
304
- " if (snapId) {",
305
- " var snapTrigCreated = 0; var snapActCreated = 0;",
306
- // Duplicate trigger instances
307
- " var trigQ = new GlideRecord('sys_hub_trigger_instance');",
308
- " trigQ.addQuery('flow', flowSysId); trigQ.query();",
309
- " while (trigQ.next()) {",
310
- " try {",
311
- " var st = new GlideRecord('sys_hub_trigger_instance');",
312
- " st.initialize();",
313
- " st.setValue('flow', snapId);",
314
- " st.setValue('name', trigQ.getValue('name'));",
315
- " st.setValue('order', trigQ.getValue('order'));",
316
- " st.setValue('active', trigQ.getValue('active'));",
317
- " var atVal = trigQ.getValue('action_type');",
318
- " if (atVal) st.setValue('action_type', atVal);",
319
- " var tblVal = trigQ.getValue('table');",
320
- " if (tblVal) st.setValue('table', tblVal);",
321
- " var condVal = trigQ.getValue('condition');",
322
- " if (condVal) st.setValue('condition', condVal);",
323
- " if (st.insert()) snapTrigCreated++;",
324
- " } catch(e) {}",
325
- " }",
326
- // Duplicate action instances
327
- " var actQ = new GlideRecord('sys_hub_action_instance');",
328
- " actQ.addQuery('flow', flowSysId); actQ.query();",
329
- " while (actQ.next()) {",
330
- " try {",
331
- " var sa = new GlideRecord('sys_hub_action_instance');",
332
- " sa.initialize();",
333
- " sa.setValue('flow', snapId);",
334
- " sa.setValue('name', actQ.getValue('name'));",
335
- " sa.setValue('order', actQ.getValue('order'));",
336
- " sa.setValue('active', actQ.getValue('active'));",
337
- " var aatVal = actQ.getValue('action_type');",
338
- " if (aatVal) sa.setValue('action_type', aatVal);",
339
- " if (sa.insert()) snapActCreated++;",
340
- " } catch(e) {}",
341
- " }",
342
- " r.steps.snapshot_instances = { triggers: snapTrigCreated, actions: snapActCreated };",
343
- " }",
344
- "",
345
- // ── Reference: deep-inspect a published flow to find what latest_snapshot points to ──
346
- " r.steps.reference_flow = null;",
347
- " try {",
348
- " var refGr = new GlideRecord('sys_hub_flow');",
349
- " refGr.addQuery('status', 'published');",
350
- " refGr.addQuery('active', true);",
351
- " refGr.setLimit(1); refGr.query();",
352
- " if (refGr.next()) {",
353
- " var refId = refGr.getUniqueValue();",
354
- " var refLs = refGr.getValue('latest_snapshot') + '';",
355
- " r.steps.reference_flow = {",
356
- " sys_id: refId,",
357
- " name: refGr.getValue('name'),",
358
- " latest_snapshot_value: refLs,",
359
- " latest_version: refGr.getValue('latest_version') + ''",
360
- " };",
361
- // Read the reference snapshot record fields (sys_hub_flow_snapshot)
362
- " if (refLs !== 'null' && refLs.length === 32) {",
363
- " try {",
364
- " var refSnap = new GlideRecord('sys_hub_flow_snapshot');",
365
- " if (refSnap.get(refLs)) {",
366
- " r.steps.reference_flow.snapshot_table = 'sys_hub_flow_snapshot';",
367
- // Read all non-null fields to learn the schema
368
- " var snapFields = {};",
369
- " var snapEl = refSnap.getFields();",
370
- " for (var si = 0; si < snapEl.size(); si++) {",
371
- " var sField = snapEl.get(si);",
372
- " var sName = sField.getName() + '';",
373
- " var sVal = refSnap.getValue(sName);",
374
- " if (sVal && sName.indexOf('sys_') !== 0) {",
375
- " var sStr = sVal + '';",
376
- " snapFields[sName] = sStr.length > 100 ? sStr.substring(0, 100) + '...(len:' + sStr.length + ')' : sStr;",
377
- " }",
378
- " }",
379
- " r.steps.reference_flow.snapshot_fields = snapFields;",
380
- " }",
381
- " } catch(snapRefE) { r.steps.reference_flow.snapshot_error = snapRefE + ''; }",
382
- " }",
383
- // Count trigger/action instances for reference flow AND its snapshot
384
- " var refTrig = new GlideAggregate('sys_hub_trigger_instance');",
385
- " refTrig.addQuery('flow', refId); refTrig.addAggregate('COUNT'); refTrig.query();",
386
- " r.steps.reference_flow.trigger_count_on_flow = refTrig.next() ? parseInt(refTrig.getAggregate('COUNT')) : 0;",
387
- " var refAct = new GlideAggregate('sys_hub_action_instance');",
388
- " refAct.addQuery('flow', refId); refAct.addAggregate('COUNT'); refAct.query();",
389
- " r.steps.reference_flow.action_count_on_flow = refAct.next() ? parseInt(refAct.getAggregate('COUNT')) : 0;",
390
- // KEY: check if snapshot has its OWN action/trigger instances
391
- " if (refLs !== 'null' && refLs.length === 32) {",
392
- " var snapTrig = new GlideAggregate('sys_hub_trigger_instance');",
393
- " snapTrig.addQuery('flow', refLs); snapTrig.addAggregate('COUNT'); snapTrig.query();",
394
- " r.steps.reference_flow.trigger_count_on_snapshot = snapTrig.next() ? parseInt(snapTrig.getAggregate('COUNT')) : 0;",
395
- " var snapAct = new GlideAggregate('sys_hub_action_instance');",
396
- " snapAct.addQuery('flow', refLs); snapAct.addAggregate('COUNT'); snapAct.query();",
397
- " r.steps.reference_flow.action_count_on_snapshot = snapAct.next() ? parseInt(snapAct.getAggregate('COUNT')) : 0;",
398
- // Check sys_class_name of the snapshot (to understand table hierarchy)
399
- " try {",
400
- " var snapMeta = new GlideRecord('sys_metadata');",
401
- " if (snapMeta.get(refLs)) {",
402
- " r.steps.reference_flow.snapshot_sys_class = snapMeta.getValue('sys_class_name') + '';",
403
- " }",
404
- " } catch(e) {}",
405
- // Check table hierarchy: does sys_hub_flow_snapshot extend sys_hub_flow?
406
- " try {",
407
- " var td = GlideDBObjectManager.get().getAbsoluteBase('sys_hub_flow_snapshot');",
408
- " r.steps.reference_flow.snapshot_base_table = td + '';",
409
- " } catch(e) { r.steps.reference_flow.snapshot_base_table = 'error'; }",
410
- " }",
411
- " }",
412
- " } catch(refE) { r.steps.reference_flow = { error: refE + '' }; }",
413
- "",
414
- // ── Engine: try FlowAPI.compile on snapshot and flow ──
415
- " r.steps.engine = { mode: 'compile', sn_fd: typeof sn_fd !== 'undefined' ? 'available' : 'unavailable' };",
416
- " if (typeof sn_fd !== 'undefined' && sn_fd.FlowAPI) {",
417
- " r.steps.engine.FlowAPI = 'available';",
418
- // Try compile on snapshot first (snapshot extends sys_hub_flow_block)
419
- " if (snapId) {",
420
- " try {",
421
- " var snapCompResult = sn_fd.FlowAPI.compile(snapId);",
422
- " r.steps.engine.compile_snapshot = snapCompResult ? (snapCompResult + '').substring(0, 200) : 'success (null return)';",
423
- " } catch(sce) { r.steps.engine.compile_snapshot = 'error: ' + (sce.getMessage ? sce.getMessage() : sce + ''); }",
424
- " }",
425
- // Then compile the flow record itself
426
- " if (flowSysId) {",
427
- " try {",
428
- " var flowCompResult = sn_fd.FlowAPI.compile(flowSysId);",
429
- " r.steps.engine.compile_flow = flowCompResult ? (flowCompResult + '').substring(0, 200) : 'success (null return)';",
430
- " } catch(fce) { r.steps.engine.compile_flow = 'error: ' + (fce.getMessage ? fce.getMessage() : fce + ''); }",
431
- " }",
432
- // After compile, re-read snapshot to check if label_cache was populated
433
- " if (snapId) {",
434
- " try {",
435
- " var postSnap = new GlideRecord('sys_hub_flow_snapshot');",
436
- " if (postSnap.get(snapId)) {",
437
- " var lc = postSnap.getValue('label_cache') + '';",
438
- " r.steps.engine.label_cache_after_compile = lc.length > 5 ? lc.substring(0, 100) + '...(len:' + lc.length + ')' : lc;",
439
- " }",
440
- " } catch(e) {}",
441
- " }",
442
- // Try other known APIs
443
- " var otherApis = ['FlowDesigner', 'FlowPublisher', 'FlowCompiler'];",
444
- " r.steps.engine.other_apis = {};",
445
- " for (var oa = 0; oa < otherApis.length; oa++) {",
446
- " r.steps.engine.other_apis[otherApis[oa]] = typeof sn_fd[otherApis[oa]] !== 'undefined' ? 'available' : 'unavailable';",
447
- " }",
448
- " } else {",
449
- " r.steps.engine.FlowAPI = 'unavailable';",
450
- " }",
264
+ // Engine compilation delegated to Business Rule (runs in Flow Designer context)
265
+ " r.steps.engine = 'deferred_to_business_rule';",
451
266
  " }",
452
267
  "",
453
268
  " r.flow_sys_id = flowSysId ? flowSysId + '' : null;",
@@ -535,6 +350,188 @@ async function createFlowViaScheduledJob(
535
350
  }
536
351
  }
537
352
 
353
+ // ── Business Rule compile: create a temp BR on sys_hub_flow to trigger engine compile ──
354
+
355
+ /**
356
+ * After the scheduled job creates the flow records, this function:
357
+ * 1. Creates a temporary Business Rule on sys_hub_flow (after update)
358
+ * 2. PATCHes the flow record to trigger the BR
359
+ * 3. The BR runs in the Flow Designer engine context and tries to compile/publish
360
+ * 4. Reads the result from a sys_property
361
+ * 5. Cleans up both the BR and the property
362
+ *
363
+ * Why a BR instead of scheduled job? BRs on sys_hub_flow run in the Flow Designer
364
+ * application scope, which may have access to APIs (like sn_fd.FlowDesigner) that
365
+ * aren't available in global-scope scheduled jobs.
366
+ */
367
+ async function tryCompileViaBusinessRule(
368
+ client: any,
369
+ flowSysId: string,
370
+ flowDescription: string
371
+ ): Promise<{ success: boolean; result?: any; error?: string }> {
372
+ var brResultProp = 'snow_flow.br_compile.' + Date.now();
373
+
374
+ // The BR script: runs server-side in sys_hub_flow context
375
+ // Probes all available APIs and tries compile/publish
376
+ var brScript = [
377
+ "(function executeRule(current, previous) {",
378
+ " var PROP = '" + escForScript(brResultProp) + "';",
379
+ " var r = { fired: true, context: 'business_rule', flow_id: current.sys_id + '' };",
380
+ " try {",
381
+ // Probe sn_fd namespace
382
+ " if (typeof sn_fd !== 'undefined') {",
383
+ " r.sn_fd = 'available';",
384
+ " var snfdKeys = [];",
385
+ " try { for (var k in sn_fd) { snfdKeys.push(k + ':' + typeof sn_fd[k]); } } catch(e) {}",
386
+ " r.sn_fd_keys = snfdKeys;",
387
+ "",
388
+ // Try FlowDesigner (not available in scheduled job, might be available in BR)
389
+ " if (typeof sn_fd.FlowDesigner !== 'undefined') {",
390
+ " r.FlowDesigner = 'available';",
391
+ " var fdMethods = [];",
392
+ " try { for (var fm in sn_fd.FlowDesigner) { if (typeof sn_fd.FlowDesigner[fm] === 'function') fdMethods.push(fm); } } catch(e) {}",
393
+ " r.FlowDesigner_methods = fdMethods;",
394
+ " try {",
395
+ " sn_fd.FlowDesigner.publishFlow(current.sys_id + '');",
396
+ " r.publishFlow = 'success';",
397
+ " } catch(pe) { r.publishFlow = (pe.getMessage ? pe.getMessage() : pe + '').substring(0, 200); }",
398
+ " } else { r.FlowDesigner = 'unavailable'; }",
399
+ "",
400
+ // Try FlowAPI
401
+ " if (typeof sn_fd.FlowAPI !== 'undefined') {",
402
+ " r.FlowAPI = 'available';",
403
+ " var faMethods = [];",
404
+ " try { for (var am in sn_fd.FlowAPI) { if (typeof sn_fd.FlowAPI[am] === 'function') faMethods.push(am); } } catch(e) {}",
405
+ " r.FlowAPI_methods = faMethods;",
406
+ " try {",
407
+ " var compRes = sn_fd.FlowAPI.compile(current.sys_id + '');",
408
+ " r.compile = compRes ? (compRes + '').substring(0, 200) : 'success (null return)';",
409
+ " } catch(ce) { r.compile = 'error: ' + (ce.getMessage ? ce.getMessage() : ce + '').substring(0, 200); }",
410
+ " try {",
411
+ " var pubRes = sn_fd.FlowAPI.publish(current.sys_id + '');",
412
+ " r.publish = pubRes ? (pubRes + '').substring(0, 200) : 'success (null return)';",
413
+ " } catch(pue) { r.publish = 'error: ' + (pue.getMessage ? pue.getMessage() : pue + '').substring(0, 200); }",
414
+ " } else { r.FlowAPI = 'unavailable'; }",
415
+ "",
416
+ // Search for flow-related Script Includes
417
+ " var si = new GlideRecord('sys_script_include');",
418
+ " si.addQuery('name', 'CONTAINS', 'FlowDesigner');",
419
+ " si.addOrCondition('name', 'CONTAINS', 'FlowCompiler');",
420
+ " si.addOrCondition('name', 'CONTAINS', 'FlowPublish');",
421
+ " si.addQuery('active', true);",
422
+ " si.setLimit(15); si.query();",
423
+ " r.script_includes = [];",
424
+ " while (si.next()) {",
425
+ " r.script_includes.push(si.getValue('name') + ' [api:' + si.getValue('api_name') + ', scope:' + si.getValue('sys_scope') + ']');",
426
+ " }",
427
+ "",
428
+ // Try instantiating common Script Includes
429
+ " var tryClasses = ['FlowDesignerScriptable', 'FlowDesignerService', 'FlowDesignerPublishService',",
430
+ " 'FlowDesignerCompileService', 'FlowDesignerActionService', 'sn_fd.FlowDesignerScriptable'];",
431
+ " r.script_include_tests = {};",
432
+ " for (var tc = 0; tc < tryClasses.length; tc++) {",
433
+ " try {",
434
+ " var cls = eval(tryClasses[tc]);",
435
+ " if (typeof cls === 'function') {",
436
+ " var inst = new cls();",
437
+ " r.script_include_tests[tryClasses[tc]] = 'instantiated';",
438
+ // Try compile/publish methods on instance
439
+ " if (typeof inst.compile === 'function') {",
440
+ " try { inst.compile(current.sys_id + ''); r.script_include_tests[tryClasses[tc] + '.compile'] = 'success'; }",
441
+ " catch(e) { r.script_include_tests[tryClasses[tc] + '.compile'] = (e + '').substring(0, 100); }",
442
+ " }",
443
+ " if (typeof inst.publishFlow === 'function') {",
444
+ " try { inst.publishFlow(current.sys_id + ''); r.script_include_tests[tryClasses[tc] + '.publishFlow'] = 'success'; }",
445
+ " catch(e) { r.script_include_tests[tryClasses[tc] + '.publishFlow'] = (e + '').substring(0, 100); }",
446
+ " }",
447
+ " } else { r.script_include_tests[tryClasses[tc]] = 'not a function: ' + typeof cls; }",
448
+ " } catch(e) { r.script_include_tests[tryClasses[tc]] = 'error: ' + (e + '').substring(0, 100); }",
449
+ " }",
450
+ " } else { r.sn_fd = 'unavailable'; }",
451
+ "",
452
+ // Post-check: read back flow state
453
+ " var post = new GlideRecord('sys_hub_flow');",
454
+ " if (post.get(current.sys_id + '')) {",
455
+ " r.post_latest_version = post.getValue('latest_version') + '';",
456
+ " r.post_latest_snapshot = post.getValue('latest_snapshot') + '';",
457
+ " r.post_status = post.getValue('status') + '';",
458
+ " }",
459
+ " } catch(topE) { r.error = (topE.getMessage ? topE.getMessage() : topE + '').substring(0, 300); }",
460
+ " gs.setProperty(PROP, JSON.stringify(r));",
461
+ "})(current, previous);"
462
+ ].join('\n');
463
+
464
+ try {
465
+ // 1. Create result property
466
+ await client.post('/api/now/table/sys_properties', {
467
+ name: brResultProp,
468
+ value: 'pending',
469
+ type: 'string',
470
+ description: 'Snow-Flow BR compile result (auto-cleanup)'
471
+ });
472
+
473
+ // 2. Create temporary Business Rule on sys_hub_flow
474
+ var brResp = await client.post('/api/now/table/sys_script', {
475
+ name: 'Snow-Flow Auto-Compile (temp-cleanup)',
476
+ collection: 'sys_hub_flow',
477
+ when: 'after',
478
+ action_insert: false,
479
+ action_update: true,
480
+ action_delete: false,
481
+ active: true,
482
+ script: brScript,
483
+ order: 10000,
484
+ filter_condition: 'sys_id=' + flowSysId
485
+ });
486
+ var brSysId = brResp.data?.result?.sys_id;
487
+
488
+ // 3. PATCH the flow record to trigger the BR (tiny description change)
489
+ await new Promise(resolve => setTimeout(resolve, 1000)); // Let BR register
490
+ await client.patch('/api/now/table/sys_hub_flow/' + flowSysId, {
491
+ description: (flowDescription || '').trim() + ' '
492
+ });
493
+
494
+ // 4. Poll for result (5 attempts, 2s each = 10s max)
495
+ for (var i = 0; i < 5; i++) {
496
+ await new Promise(resolve => setTimeout(resolve, 2000));
497
+ var propResp = await client.get('/api/now/table/sys_properties', {
498
+ params: {
499
+ sysparm_query: 'name=' + brResultProp,
500
+ sysparm_fields: 'sys_id,value',
501
+ sysparm_limit: 1
502
+ }
503
+ });
504
+ var propRecord = propResp.data.result?.[0];
505
+ var propValue = propRecord?.value;
506
+
507
+ if (propValue && propValue !== 'pending') {
508
+ // Got result — clean up
509
+ try { if (propRecord?.sys_id) await client.delete('/api/now/table/sys_properties/' + propRecord.sys_id); } catch (_) {}
510
+ try { if (brSysId) await client.delete('/api/now/table/sys_script/' + brSysId); } catch (_) {}
511
+
512
+ try {
513
+ return { success: true, result: JSON.parse(propValue) };
514
+ } catch (_) {
515
+ return { success: true, result: { raw: propValue.substring(0, 500) } };
516
+ }
517
+ }
518
+ }
519
+
520
+ // Timeout — clean up
521
+ try {
522
+ var cleanProp = await client.get('/api/now/table/sys_properties', {
523
+ params: { sysparm_query: 'name=' + brResultProp, sysparm_fields: 'sys_id', sysparm_limit: 1 }
524
+ });
525
+ if (cleanProp.data.result?.[0]?.sys_id) await client.delete('/api/now/table/sys_properties/' + cleanProp.data.result[0].sys_id);
526
+ } catch (_) {}
527
+ try { if (brSysId) await client.delete('/api/now/table/sys_script/' + brSysId); } catch (_) {}
528
+
529
+ return { success: false, error: 'Business Rule did not fire within 10s — BR may not have registered or flow update was ignored' };
530
+ } catch (e: any) {
531
+ return { success: false, error: 'BR compile setup failed: ' + (e.message || e) };
532
+ }
533
+ }
534
+
538
535
  // ── Flow Factory (Scripted REST API bootstrap) ──────────────────────
539
536
 
540
537
  var FLOW_FACTORY_API_NAME = 'Snow-Flow Flow Factory';
@@ -1554,6 +1551,22 @@ export async function execute(args: any, context: ServiceNowContext): Promise<To
1554
1551
  factoryWarnings.push('Scheduled job failed: ' + (schedErr.message || schedErr));
1555
1552
  }
1556
1553
 
1554
+ // ── Business Rule compile: trigger engine in Flow Designer context ──
1555
+ if (flowSysId) {
1556
+ try {
1557
+ var brResult = await tryCompileViaBusinessRule(client, flowSysId, flowDescription);
1558
+ diagnostics.br_compile = brResult.result || { error: brResult.error };
1559
+ if (brResult.success && brResult.result) {
1560
+ // Check if publish or compile succeeded
1561
+ if (brResult.result.publishFlow === 'success' || brResult.result.publish === 'success (null return)') {
1562
+ factoryWarnings.length = 0; // Clear warnings — compilation worked!
1563
+ }
1564
+ }
1565
+ } catch (brErr: any) {
1566
+ diagnostics.br_compile = { error: brErr.message || 'unknown' };
1567
+ }
1568
+ }
1569
+
1557
1570
  // ── Table API fallback (last resort) ─────────────────────────
1558
1571
  if (!flowSysId) {
1559
1572
  diagnostics.table_api_used = true;
@@ -1877,32 +1890,36 @@ export async function execute(args: any, context: ServiceNowContext): Promise<To
1877
1890
  }
1878
1891
  createSummary.indented('Table API used: ' + diagnostics.table_api_used);
1879
1892
  createSummary.indented('Version created: ' + diagnostics.version_created + (diagnostics.version_method ? ' (' + diagnostics.version_method + ')' : ''));
1893
+ // Business Rule compile results
1894
+ if (diagnostics.br_compile) {
1895
+ var br = diagnostics.br_compile;
1896
+ if (br.error) {
1897
+ createSummary.indented('BR compile: FAILED — ' + br.error);
1898
+ } else {
1899
+ createSummary.indented('BR compile: fired=' + (br.fired || false));
1900
+ createSummary.indented(' sn_fd=' + (br.sn_fd || 'unknown') + ', FlowDesigner=' + (br.FlowDesigner || 'unknown') + ', FlowAPI=' + (br.FlowAPI || 'unknown'));
1901
+ if (br.FlowDesigner_methods) createSummary.indented(' FlowDesigner methods: [' + br.FlowDesigner_methods.join(', ') + ']');
1902
+ if (br.FlowAPI_methods) createSummary.indented(' FlowAPI methods: [' + br.FlowAPI_methods.join(', ') + ']');
1903
+ if (br.publishFlow) createSummary.indented(' FlowDesigner.publishFlow: ' + br.publishFlow);
1904
+ if (br.compile) createSummary.indented(' FlowAPI.compile: ' + br.compile);
1905
+ if (br.publish) createSummary.indented(' FlowAPI.publish: ' + br.publish);
1906
+ if (br.sn_fd_keys && br.sn_fd_keys.length > 0) createSummary.indented(' sn_fd keys: [' + br.sn_fd_keys.join(', ') + ']');
1907
+ if (br.script_includes && br.script_includes.length > 0) createSummary.indented(' Script Includes: [' + br.script_includes.join(', ') + ']');
1908
+ if (br.script_include_tests) {
1909
+ var siKeys = Object.keys(br.script_include_tests);
1910
+ for (var sk = 0; sk < siKeys.length; sk++) {
1911
+ createSummary.indented(' SI ' + siKeys[sk] + ': ' + br.script_include_tests[siKeys[sk]]);
1912
+ }
1913
+ }
1914
+ if (br.post_latest_version) createSummary.indented(' post_latest_version: ' + br.post_latest_version);
1915
+ if (br.post_latest_snapshot) createSummary.indented(' post_latest_snapshot: ' + br.post_latest_snapshot);
1916
+ if (br.post_status) createSummary.indented(' post_status: ' + br.post_status);
1917
+ }
1918
+ }
1880
1919
  if (diagnostics.engine_registration) {
1881
1920
  var eng = diagnostics.engine_registration;
1882
- if (eng.mode === 'compile') {
1883
- // New compile mode (scheduled job path)
1884
- var engineLabel = 'sn_fd=' + eng.sn_fd + ', FlowAPI=' + (eng.FlowAPI || 'unknown');
1885
- if (eng.compile_snapshot) engineLabel += ', compile(snapshot)=' + eng.compile_snapshot;
1886
- if (eng.compile_flow) engineLabel += ', compile(flow)=' + eng.compile_flow;
1887
- if (eng.label_cache_after_compile) engineLabel += ', label_cache=' + eng.label_cache_after_compile;
1888
- createSummary.indented('Engine (compile): ' + engineLabel);
1889
- if (eng.other_apis) {
1890
- var apiList = Object.keys(eng.other_apis).map(function(k: string) { return k + '=' + eng.other_apis[k]; }).join(', ');
1891
- createSummary.indented(' Other APIs: ' + apiList);
1892
- }
1893
- } else if (eng.sn_fd) {
1894
- // Legacy probe-only mode (from scheduled job)
1895
- var legacyLabel = 'sn_fd=' + eng.sn_fd;
1896
- if (eng.apis_found && eng.apis_found.length > 0) {
1897
- legacyLabel += ', APIs=[' + eng.apis_found.join(', ') + ']';
1898
- }
1899
- if (eng.publish) legacyLabel += ', publishFlow=' + eng.publish;
1900
- if (eng.compile) legacyLabel += ', compile=' + eng.compile;
1901
- if (eng.error) legacyLabel += ', error=' + eng.error;
1902
- createSummary.indented('Engine (server-side): ' + legacyLabel);
1903
- } else if (eng.success !== undefined) {
1904
- // REST-based engine registration (Table API path)
1905
- createSummary.indented('Engine registration: ' + (eng.success ? eng.method : 'FAILED'));
1921
+ if (eng.success !== undefined) {
1922
+ createSummary.indented('Engine REST registration: ' + (eng.success ? eng.method : 'FAILED'));
1906
1923
  if (eng.attempts) {
1907
1924
  for (var ea = 0; ea < eng.attempts.length; ea++) {
1908
1925
  createSummary.indented(' ' + eng.attempts[ea]);