@memberjunction/ng-dashboards 6.1.4 → 6.1.5

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.
@@ -14,7 +14,7 @@ import { BaseDashboard, BaseResourceComponent } from '@memberjunction/ng-shared'
14
14
  import { TaskGraphDebuggerComponent } from '@memberjunction/ng-task-graph-editor';
15
15
  import { SortWorkflowRuns } from './workflow-run-sorting';
16
16
  import { WorkflowRunLayout } from './workflow-run-layout';
17
- import { EmptyDebugState, ParseWorkflowRunParentBag, TryParseJsonObject, } from './workflow-run-debug-state';
17
+ import { EmptyDebugState, ParseWorkflowRunParentBag, StepFailureReason, TryParseJsonObject, } from './workflow-run-debug-state';
18
18
  import * as i0 from "@angular/core";
19
19
  import * as i1 from "@angular/common";
20
20
  import * as i2 from "@angular/forms";
@@ -380,19 +380,30 @@ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional
380
380
  i0.ɵɵadvance(2);
381
381
  i0.ɵɵconditional(ctx_r0.SelectedEdgeIsConditional ? 10 : 11);
382
382
  } }
383
- function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_8_Conditional_5_Template(rf, ctx) { if (rf & 1) {
383
+ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_6_Template(rf, ctx) { if (rf & 1) {
384
+ i0.ɵɵelementStart(0, "div", 94)(1, "span", 89);
385
+ i0.ɵɵtext(2, "Why it failed");
386
+ i0.ɵɵelementEnd();
387
+ i0.ɵɵelementStart(3, "span");
388
+ i0.ɵɵtext(4);
389
+ i0.ɵɵelementEnd()();
390
+ } if (rf & 2) {
391
+ i0.ɵɵadvance(4);
392
+ i0.ɵɵtextInterpolate(ctx);
393
+ } }
394
+ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_9_Conditional_5_Template(rf, ctx) { if (rf & 1) {
384
395
  i0.ɵɵtext(0);
385
396
  } if (rf & 2) {
386
397
  const progress_r26 = i0.ɵɵnextContext();
387
398
  i0.ɵɵtextInterpolate1(" (", progress_r26.progressPercent, "%) ");
388
399
  } }
389
- function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_8_Template(rf, ctx) { if (rf & 1) {
400
+ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_9_Template(rf, ctx) { if (rf & 1) {
390
401
  i0.ɵɵelementStart(0, "div", 88)(1, "span", 89);
391
402
  i0.ɵɵtext(2, "Doing now");
392
403
  i0.ɵɵelementEnd();
393
404
  i0.ɵɵelementStart(3, "span");
394
405
  i0.ɵɵtext(4);
395
- i0.ɵɵconditionalCreate(5, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_8_Conditional_5_Template, 1, 1);
406
+ i0.ɵɵconditionalCreate(5, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_9_Conditional_5_Template, 1, 1);
396
407
  i0.ɵɵelementEnd()();
397
408
  } if (rf & 2) {
398
409
  const progress_r26 = ctx;
@@ -401,27 +412,27 @@ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional
401
412
  i0.ɵɵadvance();
402
413
  i0.ɵɵconditional(progress_r26.progressPercent != null ? 5 : -1);
403
414
  } }
404
- function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_9_Case_4_Template(rf, ctx) { if (rf & 1) {
415
+ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_10_Case_4_Template(rf, ctx) { if (rf & 1) {
405
416
  i0.ɵɵtext(0);
406
417
  } if (rf & 2) {
407
418
  const claim_r27 = i0.ɵɵnextContext();
408
419
  i0.ɵɵtextInterpolate1(" ", claim_r27.claimedBy, " \u2014 working ");
409
420
  } }
410
- function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_9_Case_5_Template(rf, ctx) { if (rf & 1) {
421
+ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_10_Case_5_Template(rf, ctx) { if (rf & 1) {
411
422
  i0.ɵɵtext(0);
412
423
  } if (rf & 2) {
413
424
  const claim_r27 = i0.ɵɵnextContext();
414
425
  i0.ɵɵtextInterpolate1(" ", claim_r27.claimedBy, " \u2014 lost, will be requeued ");
415
426
  } }
416
- function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_9_Case_6_Template(rf, ctx) { if (rf & 1) {
427
+ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_10_Case_6_Template(rf, ctx) { if (rf & 1) {
417
428
  i0.ɵɵtext(0, " requeued by the engine ");
418
429
  } }
419
- function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_9_Template(rf, ctx) { if (rf & 1) {
430
+ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_10_Template(rf, ctx) { if (rf & 1) {
420
431
  i0.ɵɵelementStart(0, "div", 88)(1, "span", 89);
421
432
  i0.ɵɵtext(2, "Worker");
422
433
  i0.ɵɵelementEnd();
423
434
  i0.ɵɵelementStart(3, "span");
424
- i0.ɵɵconditionalCreate(4, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_9_Case_4_Template, 1, 1)(5, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_9_Case_5_Template, 1, 1)(6, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_9_Case_6_Template, 1, 0);
435
+ i0.ɵɵconditionalCreate(4, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_10_Case_4_Template, 1, 1)(5, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_10_Case_5_Template, 1, 1)(6, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_10_Case_6_Template, 1, 0);
425
436
  i0.ɵɵelementEnd()();
426
437
  } if (rf & 2) {
427
438
  let tmp_11_0;
@@ -430,16 +441,16 @@ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional
430
441
  i0.ɵɵadvance(4);
431
442
  i0.ɵɵconditional((tmp_11_0 = claim_r27.claimEvent) === "claimed" ? 4 : tmp_11_0 === "heartbeat-lost" ? 5 : tmp_11_0 === "reclaimed" ? 6 : -1);
432
443
  } }
433
- function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_For_11_Case_2_Template(rf, ctx) { if (rf & 1) {
444
+ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_For_12_Case_2_Template(rf, ctx) { if (rf & 1) {
434
445
  i0.ɵɵtext(0, " Path taken ");
435
446
  } }
436
- function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_For_11_Case_3_Template(rf, ctx) { if (rf & 1) {
447
+ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_For_12_Case_3_Template(rf, ctx) { if (rf & 1) {
437
448
  i0.ɵɵtext(0, " Path not taken ");
438
449
  } }
439
- function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_For_11_Case_4_Template(rf, ctx) { if (rf & 1) {
450
+ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_For_12_Case_4_Template(rf, ctx) { if (rf & 1) {
440
451
  i0.ɵɵtext(0, " Path can't be answered ");
441
452
  } }
442
- function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_For_11_Conditional_6_Template(rf, ctx) { if (rf & 1) {
453
+ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_For_12_Conditional_6_Template(rf, ctx) { if (rf & 1) {
443
454
  i0.ɵɵelementStart(0, "code");
444
455
  i0.ɵɵtext(1);
445
456
  i0.ɵɵelementEnd();
@@ -448,19 +459,19 @@ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional
448
459
  i0.ɵɵadvance();
449
460
  i0.ɵɵtextInterpolate(verdict_r28.conditionText);
450
461
  } }
451
- function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_For_11_Conditional_7_Template(rf, ctx) { if (rf & 1) {
462
+ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_For_12_Conditional_7_Template(rf, ctx) { if (rf & 1) {
452
463
  i0.ɵɵtext(0);
453
464
  } if (rf & 2) {
454
465
  const verdict_r28 = i0.ɵɵnextContext().$implicit;
455
466
  i0.ɵɵtextInterpolate1(" \u2014 ", verdict_r28.reason, " ");
456
467
  } }
457
- function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_For_11_Template(rf, ctx) { if (rf & 1) {
468
+ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_For_12_Template(rf, ctx) { if (rf & 1) {
458
469
  i0.ɵɵelementStart(0, "div", 88)(1, "span", 89);
459
- i0.ɵɵconditionalCreate(2, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_For_11_Case_2_Template, 1, 0)(3, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_For_11_Case_3_Template, 1, 0)(4, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_For_11_Case_4_Template, 1, 0);
470
+ i0.ɵɵconditionalCreate(2, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_For_12_Case_2_Template, 1, 0)(3, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_For_12_Case_3_Template, 1, 0)(4, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_For_12_Case_4_Template, 1, 0);
460
471
  i0.ɵɵelementEnd();
461
472
  i0.ɵɵelementStart(5, "span");
462
- i0.ɵɵconditionalCreate(6, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_For_11_Conditional_6_Template, 2, 1, "code");
463
- i0.ɵɵconditionalCreate(7, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_For_11_Conditional_7_Template, 1, 1);
473
+ i0.ɵɵconditionalCreate(6, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_For_12_Conditional_6_Template, 2, 1, "code");
474
+ i0.ɵɵconditionalCreate(7, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_For_12_Conditional_7_Template, 1, 1);
464
475
  i0.ɵɵelementEnd()();
465
476
  } if (rf & 2) {
466
477
  let tmp_19_0;
@@ -473,7 +484,7 @@ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional
473
484
  i0.ɵɵadvance();
474
485
  i0.ɵɵconditional(verdict_r28.reason ? 7 : -1);
475
486
  } }
476
- function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_12_Template(rf, ctx) { if (rf & 1) {
487
+ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_13_Template(rf, ctx) { if (rf & 1) {
477
488
  i0.ɵɵelementStart(0, "div", 88)(1, "span", 89);
478
489
  i0.ɵɵtext(2, "If this step fails");
479
490
  i0.ɵɵelementEnd();
@@ -485,22 +496,22 @@ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional
485
496
  i0.ɵɵadvance(4);
486
497
  i0.ɵɵtextInterpolate2("", whatIf_r29.BlockedCount, " step", whatIf_r29.BlockedCount === 1 ? "" : "s", " can no longer run");
487
498
  } }
488
- function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_13_Conditional_1_Template(rf, ctx) { if (rf & 1) {
499
+ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_14_Conditional_1_Template(rf, ctx) { if (rf & 1) {
489
500
  const _r30 = i0.ɵɵgetCurrentView();
490
- i0.ɵɵelementStart(0, "button", 103);
491
- i0.ɵɵlistener("click", function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_13_Conditional_1_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r30); const step_r25 = i0.ɵɵnextContext(2); const ctx_r0 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r0.OnSkipStep(step_r25)); });
492
- i0.ɵɵelement(1, "i", 104);
501
+ i0.ɵɵelementStart(0, "button", 104);
502
+ i0.ɵɵlistener("click", function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_14_Conditional_1_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r30); const step_r25 = i0.ɵɵnextContext(2); const ctx_r0 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r0.OnSkipStep(step_r25)); });
503
+ i0.ɵɵelement(1, "i", 105);
493
504
  i0.ɵɵtext(2, " Skip step ");
494
505
  i0.ɵɵelementEnd();
495
506
  } if (rf & 2) {
496
507
  const ctx_r0 = i0.ɵɵnextContext(7);
497
508
  i0.ɵɵproperty("disabled", ctx_r0.ControlBusy);
498
509
  } }
499
- function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_13_Conditional_2_Template(rf, ctx) { if (rf & 1) {
510
+ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_14_Conditional_2_Template(rf, ctx) { if (rf & 1) {
500
511
  const _r31 = i0.ɵɵgetCurrentView();
501
512
  i0.ɵɵelementStart(0, "button", 59);
502
- i0.ɵɵlistener("click", function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_13_Conditional_2_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r31); const step_r25 = i0.ɵɵnextContext(2); const ctx_r0 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r0.OpenEditInput(step_r25)); });
503
- i0.ɵɵelement(1, "i", 105);
513
+ i0.ɵɵlistener("click", function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_14_Conditional_2_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r31); const step_r25 = i0.ɵɵnextContext(2); const ctx_r0 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r0.OpenEditInput(step_r25)); });
514
+ i0.ɵɵelement(1, "i", 106);
504
515
  i0.ɵɵtext(2);
505
516
  i0.ɵɵelementEnd();
506
517
  } if (rf & 2) {
@@ -510,34 +521,34 @@ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional
510
521
  i0.ɵɵadvance(2);
511
522
  i0.ɵɵtextInterpolate1(" ", step_r25.Status === "Failed" ? "Edit input & retry" : "Edit input", " ");
512
523
  } }
513
- function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_13_Conditional_3_Template(rf, ctx) { if (rf & 1) {
524
+ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_14_Conditional_3_Template(rf, ctx) { if (rf & 1) {
514
525
  const _r32 = i0.ɵɵgetCurrentView();
515
526
  i0.ɵɵelementStart(0, "button", 59);
516
- i0.ɵɵlistener("click", function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_13_Conditional_3_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r32); const step_r25 = i0.ɵɵnextContext(2); const ctx_r0 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r0.OnRetryStep(step_r25)); });
517
- i0.ɵɵelement(1, "i", 106);
527
+ i0.ɵɵlistener("click", function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_14_Conditional_3_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r32); const step_r25 = i0.ɵɵnextContext(2); const ctx_r0 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r0.OnRetryStep(step_r25)); });
528
+ i0.ɵɵelement(1, "i", 107);
518
529
  i0.ɵɵtext(2, " Retry ");
519
530
  i0.ɵɵelementEnd();
520
531
  } if (rf & 2) {
521
532
  const ctx_r0 = i0.ɵɵnextContext(7);
522
533
  i0.ɵɵproperty("disabled", ctx_r0.ControlBusy);
523
534
  } }
524
- function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_13_Conditional_4_Template(rf, ctx) { if (rf & 1) {
535
+ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_14_Conditional_4_Template(rf, ctx) { if (rf & 1) {
525
536
  const _r33 = i0.ɵɵgetCurrentView();
526
- i0.ɵɵelementStart(0, "button", 107);
527
- i0.ɵɵlistener("click", function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_13_Conditional_4_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r33); const step_r25 = i0.ɵɵnextContext(2); const ctx_r0 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r0.OpenForceComplete(step_r25)); });
528
- i0.ɵɵelement(1, "i", 108);
537
+ i0.ɵɵelementStart(0, "button", 108);
538
+ i0.ɵɵlistener("click", function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_14_Conditional_4_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r33); const step_r25 = i0.ɵɵnextContext(2); const ctx_r0 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r0.OpenForceComplete(step_r25)); });
539
+ i0.ɵɵelement(1, "i", 109);
529
540
  i0.ɵɵtext(2, " Force complete ");
530
541
  i0.ɵɵelementEnd();
531
542
  } if (rf & 2) {
532
543
  const ctx_r0 = i0.ɵɵnextContext(7);
533
544
  i0.ɵɵproperty("disabled", ctx_r0.ControlBusy);
534
545
  } }
535
- function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_13_Template(rf, ctx) { if (rf & 1) {
546
+ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_14_Template(rf, ctx) { if (rf & 1) {
536
547
  i0.ɵɵelementStart(0, "div", 90);
537
- i0.ɵɵconditionalCreate(1, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_13_Conditional_1_Template, 3, 1, "button", 100);
538
- i0.ɵɵconditionalCreate(2, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_13_Conditional_2_Template, 3, 2, "button", 101);
539
- i0.ɵɵconditionalCreate(3, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_13_Conditional_3_Template, 3, 1, "button", 101);
540
- i0.ɵɵconditionalCreate(4, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_13_Conditional_4_Template, 3, 1, "button", 102);
548
+ i0.ɵɵconditionalCreate(1, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_14_Conditional_1_Template, 3, 1, "button", 101);
549
+ i0.ɵɵconditionalCreate(2, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_14_Conditional_2_Template, 3, 2, "button", 102);
550
+ i0.ɵɵconditionalCreate(3, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_14_Conditional_3_Template, 3, 1, "button", 102);
551
+ i0.ɵɵconditionalCreate(4, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_14_Conditional_4_Template, 3, 1, "button", 103);
541
552
  i0.ɵɵelementEnd();
542
553
  } if (rf & 2) {
543
554
  const step_r25 = i0.ɵɵnextContext();
@@ -551,8 +562,8 @@ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional
551
562
  i0.ɵɵadvance();
552
563
  i0.ɵɵconditional(ctx_r0.CanForceComplete(step_r25) ? 4 : -1);
553
564
  } }
554
- function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_14_Conditional_6_Template(rf, ctx) { if (rf & 1) {
555
- i0.ɵɵelementStart(0, "span", 110);
565
+ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_15_Conditional_6_Template(rf, ctx) { if (rf & 1) {
566
+ i0.ɵɵelementStart(0, "span", 111);
556
567
  i0.ɵɵtext(1);
557
568
  i0.ɵɵelementEnd();
558
569
  } if (rf & 2) {
@@ -560,24 +571,24 @@ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional
560
571
  i0.ɵɵadvance();
561
572
  i0.ɵɵtextInterpolate(ctx_r0.EditInputError);
562
573
  } }
563
- function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_14_Template(rf, ctx) { if (rf & 1) {
574
+ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_15_Template(rf, ctx) { if (rf & 1) {
564
575
  const _r34 = i0.ɵɵgetCurrentView();
565
- i0.ɵɵelementStart(0, "div", 97)(1, "span", 89);
576
+ i0.ɵɵelementStart(0, "div", 98)(1, "span", 89);
566
577
  i0.ɵɵtext(2);
567
578
  i0.ɵɵelementEnd();
568
579
  i0.ɵɵelementStart(3, "p", 91);
569
580
  i0.ɵɵtext(4, "Applies to this run only. Invalid JSON is refused here.");
570
581
  i0.ɵɵelementEnd();
571
- i0.ɵɵelementStart(5, "textarea", 109);
572
- i0.ɵɵtwoWayListener("ngModelChange", function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_14_Template_textarea_ngModelChange_5_listener($event) { i0.ɵɵrestoreView(_r34); const ctx_r0 = i0.ɵɵnextContext(6); i0.ɵɵtwoWayBindingSet(ctx_r0.EditInputJson, $event) || (ctx_r0.EditInputJson = $event); return i0.ɵɵresetView($event); });
582
+ i0.ɵɵelementStart(5, "textarea", 110);
583
+ i0.ɵɵtwoWayListener("ngModelChange", function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_15_Template_textarea_ngModelChange_5_listener($event) { i0.ɵɵrestoreView(_r34); const ctx_r0 = i0.ɵɵnextContext(6); i0.ɵɵtwoWayBindingSet(ctx_r0.EditInputJson, $event) || (ctx_r0.EditInputJson = $event); return i0.ɵɵresetView($event); });
573
584
  i0.ɵɵelementEnd();
574
- i0.ɵɵconditionalCreate(6, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_14_Conditional_6_Template, 2, 1, "span", 110);
585
+ i0.ɵɵconditionalCreate(6, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_15_Conditional_6_Template, 2, 1, "span", 111);
575
586
  i0.ɵɵelementStart(7, "div", 90)(8, "button", 58);
576
- i0.ɵɵlistener("click", function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_14_Template_button_click_8_listener() { i0.ɵɵrestoreView(_r34); const step_r25 = i0.ɵɵnextContext(); const ctx_r0 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r0.SubmitEditInput(step_r25)); });
587
+ i0.ɵɵlistener("click", function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_15_Template_button_click_8_listener() { i0.ɵɵrestoreView(_r34); const step_r25 = i0.ɵɵnextContext(); const ctx_r0 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r0.SubmitEditInput(step_r25)); });
577
588
  i0.ɵɵtext(9);
578
589
  i0.ɵɵelementEnd();
579
590
  i0.ɵɵelementStart(10, "button", 49);
580
- i0.ɵɵlistener("click", function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_14_Template_button_click_10_listener() { i0.ɵɵrestoreView(_r34); const ctx_r0 = i0.ɵɵnextContext(6); return i0.ɵɵresetView(ctx_r0.EditInputOpen = false); });
591
+ i0.ɵɵlistener("click", function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_15_Template_button_click_10_listener() { i0.ɵɵrestoreView(_r34); const ctx_r0 = i0.ɵɵnextContext(6); return i0.ɵɵresetView(ctx_r0.EditInputOpen = false); });
581
592
  i0.ɵɵtext(11, "Cancel");
582
593
  i0.ɵɵelementEnd()()();
583
594
  } if (rf & 2) {
@@ -594,8 +605,8 @@ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional
594
605
  i0.ɵɵadvance();
595
606
  i0.ɵɵtextInterpolate1(" ", step_r25.Status === "Failed" ? "Apply & retry" : "Apply", " ");
596
607
  } }
597
- function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_15_Conditional_7_Template(rf, ctx) { if (rf & 1) {
598
- i0.ɵɵelementStart(0, "span", 110);
608
+ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_16_Conditional_7_Template(rf, ctx) { if (rf & 1) {
609
+ i0.ɵɵelementStart(0, "span", 111);
599
610
  i0.ɵɵtext(1);
600
611
  i0.ɵɵelementEnd();
601
612
  } if (rf & 2) {
@@ -603,27 +614,27 @@ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional
603
614
  i0.ɵɵadvance();
604
615
  i0.ɵɵtextInterpolate(ctx_r0.ForceCompleteError);
605
616
  } }
606
- function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_15_Template(rf, ctx) { if (rf & 1) {
617
+ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_16_Template(rf, ctx) { if (rf & 1) {
607
618
  const _r35 = i0.ɵɵgetCurrentView();
608
- i0.ɵɵelementStart(0, "div", 98)(1, "span", 89);
619
+ i0.ɵɵelementStart(0, "div", 99)(1, "span", 89);
609
620
  i0.ɵɵtext(2, "Force complete");
610
621
  i0.ɵɵelementEnd();
611
622
  i0.ɵɵelementStart(3, "p", 91);
612
623
  i0.ɵɵtext(4, "Downstream conditions will evaluate against this output as if the step had produced it. Type the step name to confirm.");
613
624
  i0.ɵɵelementEnd();
614
- i0.ɵɵelementStart(5, "textarea", 111);
615
- i0.ɵɵtwoWayListener("ngModelChange", function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_15_Template_textarea_ngModelChange_5_listener($event) { i0.ɵɵrestoreView(_r35); const ctx_r0 = i0.ɵɵnextContext(6); i0.ɵɵtwoWayBindingSet(ctx_r0.ForceCompleteJson, $event) || (ctx_r0.ForceCompleteJson = $event); return i0.ɵɵresetView($event); });
625
+ i0.ɵɵelementStart(5, "textarea", 112);
626
+ i0.ɵɵtwoWayListener("ngModelChange", function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_16_Template_textarea_ngModelChange_5_listener($event) { i0.ɵɵrestoreView(_r35); const ctx_r0 = i0.ɵɵnextContext(6); i0.ɵɵtwoWayBindingSet(ctx_r0.ForceCompleteJson, $event) || (ctx_r0.ForceCompleteJson = $event); return i0.ɵɵresetView($event); });
616
627
  i0.ɵɵelementEnd();
617
- i0.ɵɵelementStart(6, "input", 112);
618
- i0.ɵɵtwoWayListener("ngModelChange", function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_15_Template_input_ngModelChange_6_listener($event) { i0.ɵɵrestoreView(_r35); const ctx_r0 = i0.ɵɵnextContext(6); i0.ɵɵtwoWayBindingSet(ctx_r0.ForceCompleteName, $event) || (ctx_r0.ForceCompleteName = $event); return i0.ɵɵresetView($event); });
628
+ i0.ɵɵelementStart(6, "input", 113);
629
+ i0.ɵɵtwoWayListener("ngModelChange", function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_16_Template_input_ngModelChange_6_listener($event) { i0.ɵɵrestoreView(_r35); const ctx_r0 = i0.ɵɵnextContext(6); i0.ɵɵtwoWayBindingSet(ctx_r0.ForceCompleteName, $event) || (ctx_r0.ForceCompleteName = $event); return i0.ɵɵresetView($event); });
619
630
  i0.ɵɵelementEnd();
620
- i0.ɵɵconditionalCreate(7, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_15_Conditional_7_Template, 2, 1, "span", 110);
621
- i0.ɵɵelementStart(8, "div", 90)(9, "button", 107);
622
- i0.ɵɵlistener("click", function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_15_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r35); const step_r25 = i0.ɵɵnextContext(); const ctx_r0 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r0.SubmitForceComplete(step_r25)); });
631
+ i0.ɵɵconditionalCreate(7, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_16_Conditional_7_Template, 2, 1, "span", 111);
632
+ i0.ɵɵelementStart(8, "div", 90)(9, "button", 108);
633
+ i0.ɵɵlistener("click", function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_16_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r35); const step_r25 = i0.ɵɵnextContext(); const ctx_r0 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r0.SubmitForceComplete(step_r25)); });
623
634
  i0.ɵɵtext(10, "Force complete");
624
635
  i0.ɵɵelementEnd();
625
636
  i0.ɵɵelementStart(11, "button", 49);
626
- i0.ɵɵlistener("click", function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_15_Template_button_click_11_listener() { i0.ɵɵrestoreView(_r35); const ctx_r0 = i0.ɵɵnextContext(6); return i0.ɵɵresetView(ctx_r0.ForceCompleteOpen = false); });
637
+ i0.ɵɵlistener("click", function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_16_Template_button_click_11_listener() { i0.ɵɵrestoreView(_r35); const ctx_r0 = i0.ɵɵnextContext(6); return i0.ɵɵresetView(ctx_r0.ForceCompleteOpen = false); });
627
638
  i0.ɵɵtext(12, "Cancel");
628
639
  i0.ɵɵelementEnd()()();
629
640
  } if (rf & 2) {
@@ -647,23 +658,25 @@ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional
647
658
  i0.ɵɵelementStart(4, "span", 36);
648
659
  i0.ɵɵtext(5);
649
660
  i0.ɵɵelementEnd()();
650
- i0.ɵɵelementStart(6, "button", 94);
651
- i0.ɵɵlistener("click", function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Template_button_click_6_listener() { const step_r25 = i0.ɵɵrestoreView(_r24); const ctx_r0 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r0.OnBreakpointToggled({ TaskID: step_r25.ID, Enabled: !ctx_r0.HasBreakpoint(step_r25.ID) })); });
652
- i0.ɵɵelement(7, "i", 95);
653
- i0.ɵɵelementEnd();
654
- i0.ɵɵconditionalCreate(8, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_8_Template, 6, 2, "div", 88);
655
- i0.ɵɵconditionalCreate(9, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_9_Template, 7, 3, "div", 96);
656
- i0.ɵɵrepeaterCreate(10, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_For_11_Template, 8, 4, "div", 88, _forTrack2);
657
- i0.ɵɵconditionalCreate(12, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_12_Template, 5, 2, "div", 88);
658
- i0.ɵɵconditionalCreate(13, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_13_Template, 5, 4, "div", 90);
659
- i0.ɵɵconditionalCreate(14, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_14_Template, 12, 5, "div", 97);
660
- i0.ɵɵconditionalCreate(15, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_15_Template, 13, 5, "div", 98);
661
- i0.ɵɵelement(16, "mj-task-graph-variables", 99);
661
+ i0.ɵɵconditionalCreate(6, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_6_Template, 5, 1, "div", 94);
662
+ i0.ɵɵelementStart(7, "button", 95);
663
+ i0.ɵɵlistener("click", function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Template_button_click_7_listener() { const step_r25 = i0.ɵɵrestoreView(_r24); const ctx_r0 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r0.OnBreakpointToggled({ TaskID: step_r25.ID, Enabled: !ctx_r0.HasBreakpoint(step_r25.ID) })); });
664
+ i0.ɵɵelement(8, "i", 96);
665
+ i0.ɵɵelementEnd();
666
+ i0.ɵɵconditionalCreate(9, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_9_Template, 6, 2, "div", 88);
667
+ i0.ɵɵconditionalCreate(10, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_10_Template, 7, 3, "div", 97);
668
+ i0.ɵɵrepeaterCreate(11, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_For_12_Template, 8, 4, "div", 88, _forTrack2);
669
+ i0.ɵɵconditionalCreate(13, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_13_Template, 5, 2, "div", 88);
670
+ i0.ɵɵconditionalCreate(14, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_14_Template, 5, 4, "div", 90);
671
+ i0.ɵɵconditionalCreate(15, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_15_Template, 12, 5, "div", 98);
672
+ i0.ɵɵconditionalCreate(16, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Conditional_16_Template, 13, 5, "div", 99);
673
+ i0.ɵɵelement(17, "mj-task-graph-variables", 100);
662
674
  i0.ɵɵelementEnd();
663
675
  } if (rf & 2) {
664
- let tmp_17_0;
676
+ let tmp_11_0;
665
677
  let tmp_18_0;
666
- let tmp_20_0;
678
+ let tmp_19_0;
679
+ let tmp_21_0;
667
680
  const step_r25 = ctx;
668
681
  const ctx_r0 = i0.ɵɵnextContext(5);
669
682
  i0.ɵɵadvance(3);
@@ -673,25 +686,27 @@ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional
673
686
  i0.ɵɵadvance();
674
687
  i0.ɵɵtextInterpolate(step_r25.Status);
675
688
  i0.ɵɵadvance();
689
+ i0.ɵɵconditional((tmp_11_0 = ctx_r0.SelectedStepFailureReason) ? 6 : -1, tmp_11_0);
690
+ i0.ɵɵadvance();
676
691
  i0.ɵɵclassProp("wfr-bp-on", ctx_r0.HasBreakpoint(step_r25.ID));
677
692
  i0.ɵɵproperty("disabled", ctx_r0.ControlBusy)("title", ctx_r0.HasBreakpoint(step_r25.ID) ? "Remove breakpoint" : "Break before this step");
678
693
  i0.ɵɵattribute("aria-pressed", ctx_r0.HasBreakpoint(step_r25.ID));
679
694
  i0.ɵɵadvance();
680
695
  i0.ɵɵclassProp("fa-solid", ctx_r0.HasBreakpoint(step_r25.ID))("fa-regular", !ctx_r0.HasBreakpoint(step_r25.ID));
681
696
  i0.ɵɵadvance();
682
- i0.ɵɵconditional((tmp_17_0 = ctx_r0.SelectedStepProgress) ? 8 : -1, tmp_17_0);
697
+ i0.ɵɵconditional((tmp_18_0 = ctx_r0.SelectedStepProgress) ? 9 : -1, tmp_18_0);
683
698
  i0.ɵɵadvance();
684
- i0.ɵɵconditional((tmp_18_0 = ctx_r0.SelectedStepClaim) ? 9 : -1, tmp_18_0);
699
+ i0.ɵɵconditional((tmp_19_0 = ctx_r0.SelectedStepClaim) ? 10 : -1, tmp_19_0);
685
700
  i0.ɵɵadvance();
686
701
  i0.ɵɵrepeater(ctx_r0.SelectedStepVerdicts);
687
702
  i0.ɵɵadvance(2);
688
- i0.ɵɵconditional((tmp_20_0 = ctx_r0.SelectedStepWhatIf) ? 12 : -1, tmp_20_0);
703
+ i0.ɵɵconditional((tmp_21_0 = ctx_r0.SelectedStepWhatIf) ? 13 : -1, tmp_21_0);
689
704
  i0.ɵɵadvance();
690
- i0.ɵɵconditional(step_r25.Status === "Pending" || step_r25.Status === "Failed" || ctx_r0.CanForceComplete(step_r25) ? 13 : -1);
705
+ i0.ɵɵconditional(step_r25.Status === "Pending" || step_r25.Status === "Failed" || ctx_r0.CanForceComplete(step_r25) ? 14 : -1);
691
706
  i0.ɵɵadvance();
692
- i0.ɵɵconditional(ctx_r0.EditInputOpen ? 14 : -1);
707
+ i0.ɵɵconditional(ctx_r0.EditInputOpen ? 15 : -1);
693
708
  i0.ɵɵadvance();
694
- i0.ɵɵconditional(ctx_r0.ForceCompleteOpen ? 15 : -1);
709
+ i0.ɵɵconditional(ctx_r0.ForceCompleteOpen ? 16 : -1);
695
710
  i0.ɵɵadvance();
696
711
  i0.ɵɵproperty("InputPayload", ctx_r0.StepPayload(step_r25, "InputPayload"))("OutputPayload", ctx_r0.StepPayload(step_r25, "OutputPayload"))("Invocation", ctx_r0.Invocation);
697
712
  } }
@@ -702,7 +717,7 @@ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional
702
717
  i0.ɵɵelementStart(0, "div", 79);
703
718
  i0.ɵɵrepeaterCreate(1, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_For_2_Template, 5, 5, "button", 80, _forTrack0);
704
719
  i0.ɵɵelementEnd();
705
- i0.ɵɵconditionalCreate(3, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_3_Template, 12, 5, "div", 81)(4, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Template, 17, 21, "div", 81)(5, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_5_Template, 1, 0, "mj-empty-state", 82);
720
+ i0.ɵɵconditionalCreate(3, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_3_Template, 12, 5, "div", 81)(4, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_4_Template, 18, 22, "div", 81)(5, WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_20_Conditional_11_Conditional_5_Template, 1, 0, "mj-empty-state", 82);
706
721
  } if (rf & 2) {
707
722
  let tmp_7_0;
708
723
  const ctx_r0 = i0.ɵɵnextContext(4);
@@ -747,7 +762,7 @@ function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional
747
762
  } }
748
763
  function WorkflowRunsResourceComponent_Conditional_16_Conditional_22_Conditional_21_Template(rf, ctx) { if (rf & 1) {
749
764
  i0.ɵɵelementStart(0, "div", 48);
750
- i0.ɵɵelement(1, "mj-code-editor", 113);
765
+ i0.ɵɵelement(1, "mj-code-editor", 114);
751
766
  i0.ɵɵelementEnd();
752
767
  } if (rf & 2) {
753
768
  const ctx_r0 = i0.ɵɵnextContext(3);
@@ -1530,6 +1545,7 @@ let WorkflowRunsResourceComponent = class WorkflowRunsResourceComponent extends
1530
1545
  StepType: t.StepType,
1531
1546
  StartedAt: t.StartedAt,
1532
1547
  CompletedAt: t.CompletedAt,
1548
+ ErrorMessage: t.ErrorMessage,
1533
1549
  Record: t.GetAll(),
1534
1550
  }));
1535
1551
  }
@@ -1565,6 +1581,11 @@ let WorkflowRunsResourceComponent = class WorkflowRunsResourceComponent extends
1565
1581
  get SelectedStep() {
1566
1582
  return this.SelectedSteps.find((s) => UUIDsEqual(s.ID, this.SelectedStepID ?? '')) ?? null;
1567
1583
  }
1584
+ /** Why the selected step failed, or `null` — the inspector otherwise shows FAILED with no reason. */
1585
+ get SelectedStepFailureReason() {
1586
+ const step = this.SelectedStep;
1587
+ return step ? StepFailureReason(step.Status, step.ErrorMessage) : null;
1588
+ }
1568
1589
  /** The selected step, as formatted JSON for the viewer. */
1569
1590
  get SelectedStepJson() {
1570
1591
  const step = this.SelectedStep;
@@ -1775,7 +1796,7 @@ let WorkflowRunsResourceComponent = class WorkflowRunsResourceComponent extends
1775
1796
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.GraphDebug = _t.first);
1776
1797
  } }, hostBindings: function WorkflowRunsResourceComponent_HostBindings(rf, ctx) { if (rf & 1) {
1777
1798
  i0.ɵɵlistener("resize", function WorkflowRunsResourceComponent_resize_HostBindingHandler() { return ctx.onViewportResized(); }, i0.ɵɵresolveWindow);
1778
- } }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 17, vars: 4, consts: [["GraphDebug", ""], ["Title", "Runs", "Icon", "fa-solid fa-timeline", "Subtitle", "Every workflow that has run \u2014 however it was started."], ["meta", ""], ["Label", "runs", 3, "Count", "Total"], ["actions", ""], [3, "Clicked", "Loading"], ["toolbar", ""], ["Placeholder", "Search runs", 3, "ValueChange", "Value"], [1, "wfr-status-filters"], ["type", "button", "mjButton", "", "size", "sm", 3, "variant"], ["text", "Loading runs..."], ["Variant", "error", 3, "Message"], ["Icon", "fa-solid fa-timeline", "Title", "Nothing has run yet", "Message", "When a workflow runs \u2014 started by hand, on a schedule, or by an agent \u2014 it will appear here."], ["Icon", "fa-solid fa-filter", "Title", "No runs match", "Message", "Nothing matches the current filter. Clear it to see everything that has run."], ["direction", "horizontal", "unit", "percent", 1, "wfr-split", 3, "gutterSize", "disabled"], ["type", "button", "mjButton", "", "size", "sm", 3, "click", "variant"], ["direction", "horizontal", "unit", "percent", 1, "wfr-split", 3, "dragEnd", "gutterSize", "disabled"], [3, "size", "minSize"], [1, "wfr-list"], ["role", "row", 1, "wfr-head"], ["type", "button", 1, "wfr-head-cell", "wfr-col-name", 3, "click"], ["aria-hidden", "true", 3, "ngClass"], ["type", "button", 1, "wfr-head-cell", "wfr-col-time", 3, "click"], ["type", "button", 1, "wfr-head-cell", "wfr-col-duration", 3, "click"], ["type", "button", 1, "wfr-head-cell", "wfr-col-status", 3, "click"], ["type", "button", 1, "wfr-row", 3, "wfr-row-selected"], [3, "size", "minSize", "visible"], [1, "wfr-detail"], ["type", "button", 1, "wfr-row", 3, "click"], [1, "wfr-col-name", "wfr-row-name"], [1, "wfr-col-time"], [1, "wfr-col-duration"], [1, "wfr-col-status", "wfr-row-status"], [1, "wfr-detail-head"], [1, "wfr-detail-title"], [1, "wfr-detail-name"], [1, "wfr-row-status"], [1, "wfr-detail-actions"], ["mjButton", "", "variant", "flat", "size", "sm"], ["mjButton", "", "variant", "flat", "size", "sm", 3, "title"], ["mjButton", "", "variant", "flat", "size", "sm", "aria-label", "Close", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-xmark"], ["role", "tablist", 1, "wfr-detail-tabs"], ["type", "button", 1, "wfr-tab", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-diagram-project"], ["aria-hidden", "true", 1, "fa-solid", "fa-code"], ["role", "status", 1, "wfr-stall"], ["unit", "percent", 1, "wfr-graph-split", 3, "direction", "gutterSize"], [1, "wfr-json-pane"], ["mjButton", "", "variant", "flat", "size", "sm", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-arrow-up-right-from-square"], ["mjButton", "", "variant", "flat", "size", "sm", 3, "click", "title"], ["aria-hidden", "true", 1, "fa-solid"], [1, "wfr-stall-body"], ["aria-hidden", "true", 1, "fa-solid", "fa-triangle-exclamation"], [1, "wfr-stall-copy"], [1, "wfr-stall-reason"], [1, "wfr-stall-actions"], ["mjButton", "", "variant", "primary", "size", "sm", 3, "click", "disabled"], ["mjButton", "", "variant", "secondary", "size", "sm", 3, "click", "disabled"], ["unit", "percent", 1, "wfr-graph-split", 3, "dragEnd", "direction", "gutterSize"], [1, "wfr-graph-pane"], ["Height", "100%", 3, "NodeSelected", "ConnectionSelected", "LegendToggled", "Settled", "Frame", "PausedChange", "Provider", "ParentTaskID", "WorkflowName", "LiveUpdates", "ReplayAt", "ShowLegend"], [1, "wfr-replay"], ["aria-label", "Armed breakpoints", 1, "wfr-bp-bar"], ["aria-label", "Engine activity", 1, "wfr-engine"], [1, "wfr-steps-pane"], ["text", "Loading steps..."], ["aria-hidden", "true", 1, "fa-solid", "fa-clock-rotate-left"], ["type", "range", "min", "0", "max", "100", "step", "1", "aria-label", "Replay position", 3, "input", "value"], [1, "wfr-chip", "wfr-chip-paused"], ["type", "button", 1, "wfr-chip", "wfr-chip-break"], ["aria-hidden", "true", 1, "fa-solid", "fa-pause"], ["type", "button", 1, "wfr-chip", "wfr-chip-break", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-circle"], ["role", "button", "tabindex", "0", "aria-label", "Remove breakpoint", 1, "wfr-chip-x", 3, "click"], [1, "wfr-tick", 3, "wfr-tick-held"], [1, "wfr-tick", "wfr-tick-paused"], [1, "wfr-tick"], [1, "wfr-step-list"], ["type", "button", 1, "wfr-step", 3, "wfr-step-selected"], [1, "wfr-step-json"], ["Size", "compact", "Icon", "fa-solid fa-hand-pointer", "Title", "Select a step", "Message", "Click a step on the canvas or in the list to see everything it recorded."], ["type", "button", 1, "wfr-step", 3, "click"], [1, "wfr-step-name"], [1, "wfr-step-meta"], [1, "wfr-step-json-head"], [1, "wfr-chip", "wfr-chip-forced"], [1, "wfr-insp-card"], [1, "wfr-insp-label"], [1, "wfr-insp-actions"], [1, "wfr-insp-hint"], ["mjButton", "", "variant", "flat", "size", "sm", 3, "disabled"], ["mjButton", "", "variant", "flat", "size", "sm", 3, "click", "disabled"], ["type", "button", 1, "wfr-bp", 3, "click", "disabled", "title"], ["aria-hidden", "true", 1, "fa-circle"], [1, "wfr-insp-card", 3, "wfr-insp-bad"], [1, "wfr-editor-card"], [1, "wfr-editor-card", "wfr-editor-danger"], [3, "InputPayload", "OutputPayload", "Invocation"], ["mjButton", "", "variant", "secondary", "size", "sm", "title", "Declare this step not-taken; later steps proceed", 3, "disabled"], ["mjButton", "", "variant", "secondary", "size", "sm", 3, "disabled"], ["mjButton", "", "variant", "danger", "size", "sm", 3, "disabled"], ["mjButton", "", "variant", "secondary", "size", "sm", "title", "Declare this step not-taken; later steps proceed", 3, "click", "disabled"], ["aria-hidden", "true", 1, "fa-solid", "fa-forward"], ["aria-hidden", "true", 1, "fa-solid", "fa-pen-to-square"], ["aria-hidden", "true", 1, "fa-solid", "fa-rotate-right"], ["mjButton", "", "variant", "danger", "size", "sm", 3, "click", "disabled"], ["aria-hidden", "true", 1, "fa-solid", "fa-flag-checkered"], ["rows", "8", "spellcheck", "false", 1, "mj-textarea", "wfr-json-edit", 3, "ngModelChange", "ngModel"], [1, "wfr-editor-error"], ["rows", "6", "spellcheck", "false", 1, "mj-textarea", "wfr-json-edit", 3, "ngModelChange", "ngModel"], ["type", "text", 1, "mj-input", 3, "ngModelChange", "ngModel", "placeholder"], [2, "width", "100%", 3, "ngModel", "language", "readonly"]], template: function WorkflowRunsResourceComponent_Template(rf, ctx) { if (rf & 1) {
1799
+ } }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 17, vars: 4, consts: [["GraphDebug", ""], ["Title", "Runs", "Icon", "fa-solid fa-timeline", "Subtitle", "Every workflow that has run \u2014 however it was started."], ["meta", ""], ["Label", "runs", 3, "Count", "Total"], ["actions", ""], [3, "Clicked", "Loading"], ["toolbar", ""], ["Placeholder", "Search runs", 3, "ValueChange", "Value"], [1, "wfr-status-filters"], ["type", "button", "mjButton", "", "size", "sm", 3, "variant"], ["text", "Loading runs..."], ["Variant", "error", 3, "Message"], ["Icon", "fa-solid fa-timeline", "Title", "Nothing has run yet", "Message", "When a workflow runs \u2014 started by hand, on a schedule, or by an agent \u2014 it will appear here."], ["Icon", "fa-solid fa-filter", "Title", "No runs match", "Message", "Nothing matches the current filter. Clear it to see everything that has run."], ["direction", "horizontal", "unit", "percent", 1, "wfr-split", 3, "gutterSize", "disabled"], ["type", "button", "mjButton", "", "size", "sm", 3, "click", "variant"], ["direction", "horizontal", "unit", "percent", 1, "wfr-split", 3, "dragEnd", "gutterSize", "disabled"], [3, "size", "minSize"], [1, "wfr-list"], ["role", "row", 1, "wfr-head"], ["type", "button", 1, "wfr-head-cell", "wfr-col-name", 3, "click"], ["aria-hidden", "true", 3, "ngClass"], ["type", "button", 1, "wfr-head-cell", "wfr-col-time", 3, "click"], ["type", "button", 1, "wfr-head-cell", "wfr-col-duration", 3, "click"], ["type", "button", 1, "wfr-head-cell", "wfr-col-status", 3, "click"], ["type", "button", 1, "wfr-row", 3, "wfr-row-selected"], [3, "size", "minSize", "visible"], [1, "wfr-detail"], ["type", "button", 1, "wfr-row", 3, "click"], [1, "wfr-col-name", "wfr-row-name"], [1, "wfr-col-time"], [1, "wfr-col-duration"], [1, "wfr-col-status", "wfr-row-status"], [1, "wfr-detail-head"], [1, "wfr-detail-title"], [1, "wfr-detail-name"], [1, "wfr-row-status"], [1, "wfr-detail-actions"], ["mjButton", "", "variant", "flat", "size", "sm"], ["mjButton", "", "variant", "flat", "size", "sm", 3, "title"], ["mjButton", "", "variant", "flat", "size", "sm", "aria-label", "Close", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-xmark"], ["role", "tablist", 1, "wfr-detail-tabs"], ["type", "button", 1, "wfr-tab", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-diagram-project"], ["aria-hidden", "true", 1, "fa-solid", "fa-code"], ["role", "status", 1, "wfr-stall"], ["unit", "percent", 1, "wfr-graph-split", 3, "direction", "gutterSize"], [1, "wfr-json-pane"], ["mjButton", "", "variant", "flat", "size", "sm", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-arrow-up-right-from-square"], ["mjButton", "", "variant", "flat", "size", "sm", 3, "click", "title"], ["aria-hidden", "true", 1, "fa-solid"], [1, "wfr-stall-body"], ["aria-hidden", "true", 1, "fa-solid", "fa-triangle-exclamation"], [1, "wfr-stall-copy"], [1, "wfr-stall-reason"], [1, "wfr-stall-actions"], ["mjButton", "", "variant", "primary", "size", "sm", 3, "click", "disabled"], ["mjButton", "", "variant", "secondary", "size", "sm", 3, "click", "disabled"], ["unit", "percent", 1, "wfr-graph-split", 3, "dragEnd", "direction", "gutterSize"], [1, "wfr-graph-pane"], ["Height", "100%", 3, "NodeSelected", "ConnectionSelected", "LegendToggled", "Settled", "Frame", "PausedChange", "Provider", "ParentTaskID", "WorkflowName", "LiveUpdates", "ReplayAt", "ShowLegend"], [1, "wfr-replay"], ["aria-label", "Armed breakpoints", 1, "wfr-bp-bar"], ["aria-label", "Engine activity", 1, "wfr-engine"], [1, "wfr-steps-pane"], ["text", "Loading steps..."], ["aria-hidden", "true", 1, "fa-solid", "fa-clock-rotate-left"], ["type", "range", "min", "0", "max", "100", "step", "1", "aria-label", "Replay position", 3, "input", "value"], [1, "wfr-chip", "wfr-chip-paused"], ["type", "button", 1, "wfr-chip", "wfr-chip-break"], ["aria-hidden", "true", 1, "fa-solid", "fa-pause"], ["type", "button", 1, "wfr-chip", "wfr-chip-break", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-circle"], ["role", "button", "tabindex", "0", "aria-label", "Remove breakpoint", 1, "wfr-chip-x", 3, "click"], [1, "wfr-tick", 3, "wfr-tick-held"], [1, "wfr-tick", "wfr-tick-paused"], [1, "wfr-tick"], [1, "wfr-step-list"], ["type", "button", 1, "wfr-step", 3, "wfr-step-selected"], [1, "wfr-step-json"], ["Size", "compact", "Icon", "fa-solid fa-hand-pointer", "Title", "Select a step", "Message", "Click a step on the canvas or in the list to see everything it recorded."], ["type", "button", 1, "wfr-step", 3, "click"], [1, "wfr-step-name"], [1, "wfr-step-meta"], [1, "wfr-step-json-head"], [1, "wfr-chip", "wfr-chip-forced"], [1, "wfr-insp-card"], [1, "wfr-insp-label"], [1, "wfr-insp-actions"], [1, "wfr-insp-hint"], ["mjButton", "", "variant", "flat", "size", "sm", 3, "disabled"], ["mjButton", "", "variant", "flat", "size", "sm", 3, "click", "disabled"], ["role", "status", 1, "wfr-insp-card", "wfr-insp-failure"], ["type", "button", 1, "wfr-bp", 3, "click", "disabled", "title"], ["aria-hidden", "true", 1, "fa-circle"], [1, "wfr-insp-card", 3, "wfr-insp-bad"], [1, "wfr-editor-card"], [1, "wfr-editor-card", "wfr-editor-danger"], [3, "InputPayload", "OutputPayload", "Invocation"], ["mjButton", "", "variant", "secondary", "size", "sm", "title", "Declare this step not-taken; later steps proceed", 3, "disabled"], ["mjButton", "", "variant", "secondary", "size", "sm", 3, "disabled"], ["mjButton", "", "variant", "danger", "size", "sm", 3, "disabled"], ["mjButton", "", "variant", "secondary", "size", "sm", "title", "Declare this step not-taken; later steps proceed", 3, "click", "disabled"], ["aria-hidden", "true", 1, "fa-solid", "fa-forward"], ["aria-hidden", "true", 1, "fa-solid", "fa-pen-to-square"], ["aria-hidden", "true", 1, "fa-solid", "fa-rotate-right"], ["mjButton", "", "variant", "danger", "size", "sm", 3, "click", "disabled"], ["aria-hidden", "true", 1, "fa-solid", "fa-flag-checkered"], ["rows", "8", "spellcheck", "false", 1, "mj-textarea", "wfr-json-edit", 3, "ngModelChange", "ngModel"], [1, "wfr-editor-error"], ["rows", "6", "spellcheck", "false", 1, "mj-textarea", "wfr-json-edit", 3, "ngModelChange", "ngModel"], ["type", "text", 1, "mj-input", 3, "ngModelChange", "ngModel", "placeholder"], [2, "width", "100%", 3, "ngModel", "language", "readonly"]], template: function WorkflowRunsResourceComponent_Template(rf, ctx) { if (rf & 1) {
1779
1800
  i0.ɵɵelementStart(0, "mj-page-layout")(1, "mj-page-header", 1)(2, "div", 2);
1780
1801
  i0.ɵɵconditionalCreate(3, WorkflowRunsResourceComponent_Conditional_3_Template, 1, 2, "mj-stat-badge", 3);
1781
1802
  i0.ɵɵelementEnd();
@@ -1802,7 +1823,7 @@ let WorkflowRunsResourceComponent = class WorkflowRunsResourceComponent extends
1802
1823
  i0.ɵɵrepeater(ctx.StatusFilters);
1803
1824
  i0.ɵɵadvance(3);
1804
1825
  i0.ɵɵconditional(ctx.IsLoading ? 12 : ctx.LoadError ? 13 : ctx.Runs.length === 0 ? 14 : ctx.VisibleRuns.length === 0 ? 15 : 16);
1805
- } }, dependencies: [i1.NgClass, i2.DefaultValueAccessor, i2.NgControlStatus, i2.NgModel, i3.MJAlertComponent, i3.MJButtonDirective, i3.MJEmptyStateComponent, i3.MJPageBodyComponent, i3.MJPageHeaderComponent, i3.MJPageLayoutComponent, i3.MJPageSearchComponent, i3.MJRefreshButtonComponent, i3.MJStatBadgeComponent, i4.LoadingComponent, i5.TaskGraphVariablesComponent, i5.TaskGraphDebuggerComponent, i6.CodeEditorComponent, i7.SplitComponent, i7.SplitAreaComponent, i1.DatePipe], styles: ["[_nghost-%COMP%] {\n display: block;\n height: 100%;\n}\n\n.wfr-status-filters[_ngcontent-%COMP%] {\n display: flex;\n gap: var(--mj-space-1);\n align-items: center;\n}\n\n\n\n.wfr-split[_ngcontent-%COMP%] {\n height: 100%;\n min-height: 0;\n}\n\n\n[_nghost-%COMP%] .wfr-split > .as-split-gutter, \n[_nghost-%COMP%] .wfr-graph-split > .as-split-gutter {\n background: transparent !important;\n position: relative;\n}\n\n[_nghost-%COMP%] .wfr-split > .as-split-gutter::after, \n[_nghost-%COMP%] .wfr-graph-split > .as-split-gutter::after {\n content: '';\n position: absolute;\n inset: 0;\n margin: auto;\n background: var(--mj-border-default);\n border-radius: var(--mj-radius-full);\n}\n\n[_nghost-%COMP%] .wfr-split.as-horizontal > .as-split-gutter::after, \n[_nghost-%COMP%] .wfr-graph-split.as-horizontal > .as-split-gutter::after {\n width: 2px;\n}\n\n[_nghost-%COMP%] .wfr-graph-split.as-vertical > .as-split-gutter::after {\n height: 2px;\n}\n\n[_nghost-%COMP%] .wfr-split > .as-split-gutter:hover::after, \n[_nghost-%COMP%] .wfr-graph-split > .as-split-gutter:hover::after {\n background: var(--mj-brand-primary);\n}\n\n\n\n\n.wfr-graph-split[_ngcontent-%COMP%] {\n flex: 1 1 auto;\n min-height: 0;\n}\n\n.wfr-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-1);\n overflow-y: auto;\n min-height: 0;\n}\n\n.wfr-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--mj-space-2);\n width: 100%;\n padding: var(--mj-space-2) var(--mj-space-3);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n text-align: left;\n cursor: pointer;\n color: var(--mj-text-primary);\n}\n\n.wfr-row[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-border-strong);\n}\n\n.wfr-row[_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n.wfr-row-selected[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n}\n\n.wfr-row-main[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.wfr-row-name[_ngcontent-%COMP%] {\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.wfr-row-when[_ngcontent-%COMP%] {\n font-size: var(--mj-font-size-sm);\n color: var(--mj-text-secondary);\n font-variant-numeric: tabular-nums;\n}\n\n.wfr-row-status[_ngcontent-%COMP%] {\n flex: none;\n font-size: var(--mj-font-size-xs);\n text-transform: uppercase;\n letter-spacing: 0.04em;\n padding: 2px var(--mj-space-2);\n border-radius: var(--mj-radius-full);\n background: var(--mj-bg-page);\n color: var(--mj-text-secondary);\n border: 1px solid var(--mj-border-default);\n}\n\n\n\n\n.wfr-row-status[data-status='Complete'][_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n border-color: color-mix(in srgb, var(--mj-status-success) 40%, transparent);\n}\n\n.wfr-row-status[data-status='Failed'][_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n border-color: color-mix(in srgb, var(--mj-status-error) 40%, transparent);\n}\n\n.wfr-row-status[data-status='Running'][_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n border-color: color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n}\n\n.wfr-detail[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n \n\n height: 100%;\n min-height: 0;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n overflow: hidden;\n}\n\n.wfr-detail-head[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--mj-space-2);\n padding: var(--mj-space-2) var(--mj-space-3);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.wfr-detail-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n min-width: 0;\n}\n\n.wfr-detail-name[_ngcontent-%COMP%] {\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.wfr-detail-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: var(--mj-space-1);\n flex: none;\n}\n\n\n\n\n\n\n\n.wfr-head[_ngcontent-%COMP%], \n.wfr-row[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: minmax(0, 2fr) minmax(0, 1.3fr) minmax(0, 1.3fr) minmax(0, 0.7fr) minmax(0, 0.9fr);\n gap: var(--mj-space-2);\n align-items: center;\n}\n\n.wfr-head[_ngcontent-%COMP%] {\n position: sticky;\n top: 0;\n z-index: 1;\n padding: 0 var(--mj-space-3) var(--mj-space-1);\n background: var(--mj-bg-page);\n}\n\n.wfr-head-cell[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n background: none;\n border: none;\n padding: var(--mj-space-1) 0;\n font-size: var(--mj-font-size-xs);\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--mj-text-secondary);\n cursor: pointer;\n text-align: left;\n}\n\n.wfr-head-cell[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-primary);\n}\n\n.wfr-head-cell[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n opacity: 0.65;\n font-size: 0.85em;\n}\n\n.wfr-col-time[_ngcontent-%COMP%], \n.wfr-col-duration[_ngcontent-%COMP%] {\n font-size: var(--mj-font-size-sm);\n color: var(--mj-text-secondary);\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.wfr-col-status[_ngcontent-%COMP%] {\n justify-self: start;\n}\n\n\n\n\n.wfr-detail-tabs[_ngcontent-%COMP%] {\n display: flex;\n gap: var(--mj-space-1);\n padding: 0 var(--mj-space-3);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.wfr-tab[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n background: none;\n border: none;\n border-bottom: 2px solid transparent;\n padding: var(--mj-space-2) var(--mj-space-2);\n font-size: var(--mj-font-size-sm);\n font-weight: 600;\n color: var(--mj-text-secondary);\n cursor: pointer;\n}\n\n.wfr-tab-active[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n border-bottom-color: var(--mj-brand-primary);\n}\n\n.wfr-graph-pane[_ngcontent-%COMP%] {\n height: 100%;\n min-height: 12rem;\n}\n\n.wfr-steps-pane[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n border-left: 1px solid var(--mj-border-default);\n overflow: hidden;\n}\n\n\n[_nghost-%COMP%] .as-vertical .wfr-steps-pane {\n border-left: none;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.wfr-step-list[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: var(--mj-space-1);\n padding: var(--mj-space-2);\n border-bottom: 1px solid var(--mj-border-default);\n max-height: 8rem;\n overflow-y: auto;\n flex: none;\n}\n\n.wfr-step[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: var(--mj-space-2);\n padding: var(--mj-space-1) var(--mj-space-2);\n background: var(--mj-bg-page);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n color: var(--mj-text-primary);\n font-size: var(--mj-font-size-sm);\n cursor: pointer;\n text-align: left;\n}\n\n.wfr-step[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-border-strong);\n}\n\n.wfr-step-selected[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n}\n\n\n.wfr-step[data-status='Skipped'][_ngcontent-%COMP%] .wfr-step-name[_ngcontent-%COMP%] {\n text-decoration: line-through;\n color: var(--mj-text-secondary);\n}\n\n.wfr-step-name[_ngcontent-%COMP%] {\n font-weight: 600;\n}\n\n.wfr-step-meta[_ngcontent-%COMP%] {\n font-size: var(--mj-font-size-xs);\n color: var(--mj-text-secondary);\n}\n\n.wfr-step-json[_ngcontent-%COMP%], \n.wfr-json-pane[_ngcontent-%COMP%] {\n flex: 1 1 auto;\n min-height: 0;\n display: flex;\n flex-direction: column;\n overflow: auto;\n}\n\n.wfr-step-json-head[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--mj-space-2);\n padding: var(--mj-space-1) var(--mj-space-3);\n font-weight: 600;\n font-size: var(--mj-font-size-sm);\n color: var(--mj-text-secondary);\n flex: none;\n}\n\n\n\n.wfr-stall[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 8px 12px;\n margin: 0 12px 8px;\n border: 1px solid color-mix(in srgb, var(--mj-status-warning) 45%, var(--mj-border-default));\n border-left: 4px solid var(--mj-status-warning);\n border-radius: var(--mj-radius-md);\n background: color-mix(in srgb, var(--mj-status-warning) 8%, var(--mj-bg-surface));\n color: var(--mj-text-primary);\n font-size: var(--mj-font-size-sm);\n}\n.wfr-stall-body[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n}\n.wfr-stall[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { color: var(--mj-status-warning); }\n.wfr-stall-copy[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n.wfr-stall-copy[_ngcontent-%COMP%] code[_ngcontent-%COMP%] {\n font-family: var(--mj-font-mono, ui-monospace, monospace);\n font-size: var(--mj-font-size-xs);\n}\n.wfr-stall-reason[_ngcontent-%COMP%] { color: var(--mj-text-secondary); }\n.wfr-stall-actions[_ngcontent-%COMP%] { display: flex; flex-wrap: wrap; gap: 6px; }\n\n.wfr-replay[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 6px 12px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-page);\n}\n.wfr-replay[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { color: var(--mj-text-secondary); }\n.wfr-replay[_ngcontent-%COMP%] input[type='range'][_ngcontent-%COMP%] { flex: 1; accent-color: var(--mj-brand-primary); }\n\n.wfr-engine[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n overflow-x: auto;\n padding: 6px 12px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-page);\n font-family: var(--mj-font-mono, ui-monospace, monospace);\n font-size: var(--mj-font-size-xs);\n color: var(--mj-text-secondary);\n font-variant-numeric: tabular-nums;\n}\n.wfr-tick[_ngcontent-%COMP%] {\n flex: none;\n padding: 3px 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface);\n white-space: nowrap;\n}\n.wfr-tick-held[_ngcontent-%COMP%] {\n border-color: color-mix(in srgb, var(--mj-status-warning, #d97706) 45%, var(--mj-border-default));\n background: color-mix(in srgb, var(--mj-status-warning, #d97706) 8%, var(--mj-bg-surface));\n}\n.wfr-tick-paused[_ngcontent-%COMP%] { color: var(--mj-brand-primary); border-color: var(--mj-border-strong); }\n\n.wfr-insp-card[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding: 7px 10px;\n margin: 0 0 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface);\n font-size: var(--mj-font-size-sm);\n color: var(--mj-text-primary);\n}\n.wfr-insp-card[_ngcontent-%COMP%] code[_ngcontent-%COMP%] {\n font-family: var(--mj-font-mono, ui-monospace, monospace);\n font-size: var(--mj-font-size-xs);\n}\n.wfr-insp-label[_ngcontent-%COMP%] {\n font-size: var(--mj-font-size-xs);\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--mj-text-secondary);\n}\n.wfr-insp-card[data-verdict='held'][_ngcontent-%COMP%], \n.wfr-insp-bad[_ngcontent-%COMP%] {\n border-color: color-mix(in srgb, var(--mj-status-warning, #d97706) 45%, var(--mj-border-default));\n background: color-mix(in srgb, var(--mj-status-warning, #d97706) 8%, var(--mj-bg-surface));\n}\n.wfr-insp-card[data-verdict='satisfied'][_ngcontent-%COMP%] .wfr-insp-label[_ngcontent-%COMP%] { color: var(--mj-status-success); }\n.wfr-insp-actions[_ngcontent-%COMP%] { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 8px; }\n.wfr-insp-hint[_ngcontent-%COMP%] {\n margin: 0 0 8px;\n font-size: var(--mj-font-size-xs);\n color: var(--mj-text-muted);\n}\n\n.wfr-bp-bar[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n padding: 6px 12px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-page);\n}\n.wfr-chip[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 2px 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-full);\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: var(--mj-font-size-xs);\n cursor: pointer;\n}\n.wfr-chip-break[_ngcontent-%COMP%] { color: var(--mj-status-error); border-color: color-mix(in srgb, var(--mj-status-error) 40%, transparent); }\n.wfr-chip-break[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { font-size: 7px; }\n.wfr-chip-paused[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n border-color: color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n cursor: default;\n}\n.wfr-chip-forced[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n border-color: color-mix(in srgb, var(--mj-status-warning) 40%, transparent);\n cursor: default;\n}\n.wfr-chip-x[_ngcontent-%COMP%] {\n font-size: 14px;\n line-height: 1;\n padding: 0 2px;\n}\n.wfr-chip-x[_ngcontent-%COMP%]:hover { color: var(--mj-text-primary); }\n\n.wfr-bp[_ngcontent-%COMP%] {\n width: 22px;\n height: 22px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n margin: 0 0 8px;\n padding: 0;\n border: none;\n border-radius: 50%;\n background: transparent;\n color: var(--mj-text-muted);\n cursor: pointer;\n}\n.wfr-bp[_ngcontent-%COMP%]:hover { color: var(--mj-status-error); }\n.wfr-bp-on[_ngcontent-%COMP%], \n.wfr-bp-on[_ngcontent-%COMP%]:hover { color: var(--mj-status-error); }\n.wfr-bp[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { font-size: 10px; }\n.wfr-bp[_ngcontent-%COMP%]:disabled { opacity: 0.45; cursor: default; }\n\n.wfr-editor-card[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 10px;\n margin: 0 0 10px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface-card);\n}\n.wfr-editor-danger[_ngcontent-%COMP%] {\n border-color: color-mix(in srgb, var(--mj-status-error) 40%, var(--mj-border-default));\n}\n.wfr-json-edit[_ngcontent-%COMP%] {\n width: 100%;\n min-height: 120px;\n font-family: var(--mj-font-mono, ui-monospace, monospace);\n font-size: var(--mj-font-size-xs);\n resize: vertical;\n}\n.wfr-editor-error[_ngcontent-%COMP%] { color: var(--mj-status-error); font-size: var(--mj-font-size-xs); }"], changeDetection: 0 });
1826
+ } }, dependencies: [i1.NgClass, i2.DefaultValueAccessor, i2.NgControlStatus, i2.NgModel, i3.MJAlertComponent, i3.MJButtonDirective, i3.MJEmptyStateComponent, i3.MJPageBodyComponent, i3.MJPageHeaderComponent, i3.MJPageLayoutComponent, i3.MJPageSearchComponent, i3.MJRefreshButtonComponent, i3.MJStatBadgeComponent, i4.LoadingComponent, i5.TaskGraphVariablesComponent, i5.TaskGraphDebuggerComponent, i6.CodeEditorComponent, i7.SplitComponent, i7.SplitAreaComponent, i1.DatePipe], styles: ["[_nghost-%COMP%] {\n display: block;\n height: 100%;\n}\n\n.wfr-status-filters[_ngcontent-%COMP%] {\n display: flex;\n gap: var(--mj-space-1);\n align-items: center;\n}\n\n\n\n.wfr-split[_ngcontent-%COMP%] {\n height: 100%;\n min-height: 0;\n}\n\n\n[_nghost-%COMP%] .wfr-split > .as-split-gutter, \n[_nghost-%COMP%] .wfr-graph-split > .as-split-gutter {\n background: transparent !important;\n position: relative;\n}\n\n[_nghost-%COMP%] .wfr-split > .as-split-gutter::after, \n[_nghost-%COMP%] .wfr-graph-split > .as-split-gutter::after {\n content: '';\n position: absolute;\n inset: 0;\n margin: auto;\n background: var(--mj-border-default);\n border-radius: var(--mj-radius-full);\n}\n\n[_nghost-%COMP%] .wfr-split.as-horizontal > .as-split-gutter::after, \n[_nghost-%COMP%] .wfr-graph-split.as-horizontal > .as-split-gutter::after {\n width: 2px;\n}\n\n[_nghost-%COMP%] .wfr-graph-split.as-vertical > .as-split-gutter::after {\n height: 2px;\n}\n\n[_nghost-%COMP%] .wfr-split > .as-split-gutter:hover::after, \n[_nghost-%COMP%] .wfr-graph-split > .as-split-gutter:hover::after {\n background: var(--mj-brand-primary);\n}\n\n\n\n\n.wfr-graph-split[_ngcontent-%COMP%] {\n flex: 1 1 auto;\n min-height: 0;\n}\n\n.wfr-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-1);\n overflow-y: auto;\n min-height: 0;\n}\n\n.wfr-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--mj-space-2);\n width: 100%;\n padding: var(--mj-space-2) var(--mj-space-3);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n text-align: left;\n cursor: pointer;\n color: var(--mj-text-primary);\n}\n\n.wfr-row[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-border-strong);\n}\n\n.wfr-row[_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n.wfr-row-selected[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n}\n\n.wfr-row-main[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.wfr-row-name[_ngcontent-%COMP%] {\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.wfr-row-when[_ngcontent-%COMP%] {\n font-size: var(--mj-font-size-sm);\n color: var(--mj-text-secondary);\n font-variant-numeric: tabular-nums;\n}\n\n.wfr-row-status[_ngcontent-%COMP%] {\n flex: none;\n font-size: var(--mj-font-size-xs);\n text-transform: uppercase;\n letter-spacing: 0.04em;\n padding: 2px var(--mj-space-2);\n border-radius: var(--mj-radius-full);\n background: var(--mj-bg-page);\n color: var(--mj-text-secondary);\n border: 1px solid var(--mj-border-default);\n}\n\n\n\n\n.wfr-row-status[data-status='Complete'][_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n border-color: color-mix(in srgb, var(--mj-status-success) 40%, transparent);\n}\n\n.wfr-row-status[data-status='Failed'][_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n border-color: color-mix(in srgb, var(--mj-status-error) 40%, transparent);\n}\n\n.wfr-row-status[data-status='Running'][_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n border-color: color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n}\n\n.wfr-detail[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n \n\n height: 100%;\n min-height: 0;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n overflow: hidden;\n}\n\n.wfr-detail-head[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--mj-space-2);\n padding: var(--mj-space-2) var(--mj-space-3);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.wfr-detail-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n min-width: 0;\n}\n\n.wfr-detail-name[_ngcontent-%COMP%] {\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.wfr-detail-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: var(--mj-space-1);\n flex: none;\n}\n\n\n\n\n\n\n\n.wfr-head[_ngcontent-%COMP%], \n.wfr-row[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: minmax(0, 2fr) minmax(0, 1.3fr) minmax(0, 1.3fr) minmax(0, 0.7fr) minmax(0, 0.9fr);\n gap: var(--mj-space-2);\n align-items: center;\n}\n\n.wfr-head[_ngcontent-%COMP%] {\n position: sticky;\n top: 0;\n z-index: 1;\n padding: 0 var(--mj-space-3) var(--mj-space-1);\n background: var(--mj-bg-page);\n}\n\n.wfr-head-cell[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n background: none;\n border: none;\n padding: var(--mj-space-1) 0;\n font-size: var(--mj-font-size-xs);\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--mj-text-secondary);\n cursor: pointer;\n text-align: left;\n}\n\n.wfr-head-cell[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-primary);\n}\n\n.wfr-head-cell[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n opacity: 0.65;\n font-size: 0.85em;\n}\n\n.wfr-col-time[_ngcontent-%COMP%], \n.wfr-col-duration[_ngcontent-%COMP%] {\n font-size: var(--mj-font-size-sm);\n color: var(--mj-text-secondary);\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.wfr-col-status[_ngcontent-%COMP%] {\n justify-self: start;\n}\n\n\n\n\n.wfr-detail-tabs[_ngcontent-%COMP%] {\n display: flex;\n gap: var(--mj-space-1);\n padding: 0 var(--mj-space-3);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.wfr-tab[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n background: none;\n border: none;\n border-bottom: 2px solid transparent;\n padding: var(--mj-space-2) var(--mj-space-2);\n font-size: var(--mj-font-size-sm);\n font-weight: 600;\n color: var(--mj-text-secondary);\n cursor: pointer;\n}\n\n.wfr-tab-active[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n border-bottom-color: var(--mj-brand-primary);\n}\n\n.wfr-graph-pane[_ngcontent-%COMP%] {\n height: 100%;\n min-height: 12rem;\n}\n\n.wfr-steps-pane[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n border-left: 1px solid var(--mj-border-default);\n overflow: hidden;\n}\n\n\n[_nghost-%COMP%] .as-vertical .wfr-steps-pane {\n border-left: none;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.wfr-step-list[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: var(--mj-space-1);\n padding: var(--mj-space-2);\n border-bottom: 1px solid var(--mj-border-default);\n max-height: 8rem;\n overflow-y: auto;\n flex: none;\n}\n\n.wfr-step[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: var(--mj-space-2);\n padding: var(--mj-space-1) var(--mj-space-2);\n background: var(--mj-bg-page);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n color: var(--mj-text-primary);\n font-size: var(--mj-font-size-sm);\n cursor: pointer;\n text-align: left;\n}\n\n.wfr-step[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-border-strong);\n}\n\n.wfr-step-selected[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n}\n\n\n.wfr-step[data-status='Skipped'][_ngcontent-%COMP%] .wfr-step-name[_ngcontent-%COMP%] {\n text-decoration: line-through;\n color: var(--mj-text-secondary);\n}\n\n.wfr-step-name[_ngcontent-%COMP%] {\n font-weight: 600;\n}\n\n.wfr-step-meta[_ngcontent-%COMP%] {\n font-size: var(--mj-font-size-xs);\n color: var(--mj-text-secondary);\n}\n\n.wfr-step-json[_ngcontent-%COMP%], \n.wfr-json-pane[_ngcontent-%COMP%] {\n flex: 1 1 auto;\n min-height: 0;\n display: flex;\n flex-direction: column;\n overflow: auto;\n}\n\n.wfr-step-json-head[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--mj-space-2);\n padding: var(--mj-space-1) var(--mj-space-3);\n font-weight: 600;\n font-size: var(--mj-font-size-sm);\n color: var(--mj-text-secondary);\n flex: none;\n}\n\n\n\n.wfr-stall[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 8px 12px;\n margin: 0 12px 8px;\n border: 1px solid color-mix(in srgb, var(--mj-status-warning) 45%, var(--mj-border-default));\n border-left: 4px solid var(--mj-status-warning);\n border-radius: var(--mj-radius-md);\n background: color-mix(in srgb, var(--mj-status-warning) 8%, var(--mj-bg-surface));\n color: var(--mj-text-primary);\n font-size: var(--mj-font-size-sm);\n}\n.wfr-stall-body[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n}\n.wfr-stall[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { color: var(--mj-status-warning); }\n.wfr-stall-copy[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n.wfr-stall-copy[_ngcontent-%COMP%] code[_ngcontent-%COMP%] {\n font-family: var(--mj-font-mono, ui-monospace, monospace);\n font-size: var(--mj-font-size-xs);\n}\n.wfr-stall-reason[_ngcontent-%COMP%] { color: var(--mj-text-secondary); }\n.wfr-stall-actions[_ngcontent-%COMP%] { display: flex; flex-wrap: wrap; gap: 6px; }\n\n.wfr-replay[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 6px 12px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-page);\n}\n.wfr-replay[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { color: var(--mj-text-secondary); }\n.wfr-replay[_ngcontent-%COMP%] input[type='range'][_ngcontent-%COMP%] { flex: 1; accent-color: var(--mj-brand-primary); }\n\n.wfr-engine[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n overflow-x: auto;\n padding: 6px 12px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-page);\n font-family: var(--mj-font-mono, ui-monospace, monospace);\n font-size: var(--mj-font-size-xs);\n color: var(--mj-text-secondary);\n font-variant-numeric: tabular-nums;\n}\n.wfr-tick[_ngcontent-%COMP%] {\n flex: none;\n padding: 3px 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface);\n white-space: nowrap;\n}\n.wfr-tick-held[_ngcontent-%COMP%] {\n border-color: color-mix(in srgb, var(--mj-status-warning, #d97706) 45%, var(--mj-border-default));\n background: color-mix(in srgb, var(--mj-status-warning, #d97706) 8%, var(--mj-bg-surface));\n}\n.wfr-tick-paused[_ngcontent-%COMP%] { color: var(--mj-brand-primary); border-color: var(--mj-border-strong); }\n\n.wfr-insp-card[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding: 7px 10px;\n margin: 0 0 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface);\n font-size: var(--mj-font-size-sm);\n color: var(--mj-text-primary);\n}\n.wfr-insp-card[_ngcontent-%COMP%] code[_ngcontent-%COMP%] {\n font-family: var(--mj-font-mono, ui-monospace, monospace);\n font-size: var(--mj-font-size-xs);\n}\n.wfr-insp-label[_ngcontent-%COMP%] {\n font-size: var(--mj-font-size-xs);\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--mj-text-secondary);\n}\n.wfr-insp-card[data-verdict='held'][_ngcontent-%COMP%], \n.wfr-insp-bad[_ngcontent-%COMP%] {\n border-color: color-mix(in srgb, var(--mj-status-warning, #d97706) 45%, var(--mj-border-default));\n background: color-mix(in srgb, var(--mj-status-warning, #d97706) 8%, var(--mj-bg-surface));\n}\n.wfr-insp-card[data-verdict='satisfied'][_ngcontent-%COMP%] .wfr-insp-label[_ngcontent-%COMP%] { color: var(--mj-status-success); }\n.wfr-insp-actions[_ngcontent-%COMP%] { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 8px; }\n.wfr-insp-hint[_ngcontent-%COMP%] {\n margin: 0 0 8px;\n font-size: var(--mj-font-size-xs);\n color: var(--mj-text-muted);\n}\n\n.wfr-bp-bar[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n padding: 6px 12px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-page);\n}\n.wfr-chip[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 2px 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-full);\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: var(--mj-font-size-xs);\n cursor: pointer;\n}\n.wfr-chip-break[_ngcontent-%COMP%] { color: var(--mj-status-error); border-color: color-mix(in srgb, var(--mj-status-error) 40%, transparent); }\n.wfr-chip-break[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { font-size: 7px; }\n.wfr-chip-paused[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n border-color: color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n cursor: default;\n}\n.wfr-chip-forced[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n border-color: color-mix(in srgb, var(--mj-status-warning) 40%, transparent);\n cursor: default;\n}\n.wfr-chip-x[_ngcontent-%COMP%] {\n font-size: 14px;\n line-height: 1;\n padding: 0 2px;\n}\n.wfr-chip-x[_ngcontent-%COMP%]:hover { color: var(--mj-text-primary); }\n\n.wfr-bp[_ngcontent-%COMP%] {\n width: 22px;\n height: 22px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n margin: 0 0 8px;\n padding: 0;\n border: none;\n border-radius: 50%;\n background: transparent;\n color: var(--mj-text-muted);\n cursor: pointer;\n}\n.wfr-bp[_ngcontent-%COMP%]:hover { color: var(--mj-status-error); }\n.wfr-bp-on[_ngcontent-%COMP%], \n.wfr-bp-on[_ngcontent-%COMP%]:hover { color: var(--mj-status-error); }\n.wfr-bp[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { font-size: 10px; }\n.wfr-bp[_ngcontent-%COMP%]:disabled { opacity: 0.45; cursor: default; }\n\n.wfr-editor-card[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 10px;\n margin: 0 0 10px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface-card);\n}\n.wfr-editor-danger[_ngcontent-%COMP%] {\n border-color: color-mix(in srgb, var(--mj-status-error) 40%, var(--mj-border-default));\n}\n.wfr-json-edit[_ngcontent-%COMP%] {\n width: 100%;\n min-height: 120px;\n font-family: var(--mj-font-mono, ui-monospace, monospace);\n font-size: var(--mj-font-size-xs);\n resize: vertical;\n}\n.wfr-editor-error[_ngcontent-%COMP%] { color: var(--mj-status-error); font-size: var(--mj-font-size-xs); }\n.wfr-insp-failure[_ngcontent-%COMP%] { border-color: var(--mj-status-error); color: var(--mj-status-error); }"], changeDetection: 0 });
1806
1827
  };
1807
1828
  WorkflowRunsResourceComponent = WorkflowRunsResourceComponent_1 = __decorate([
1808
1829
  RegisterClass(BaseResourceComponent, 'WorkflowRunsResource')
@@ -1810,7 +1831,7 @@ WorkflowRunsResourceComponent = WorkflowRunsResourceComponent_1 = __decorate([
1810
1831
  export { WorkflowRunsResourceComponent };
1811
1832
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(WorkflowRunsResourceComponent, [{
1812
1833
  type: Component,
1813
- args: [{ standalone: false, selector: 'mj-workflow-runs', changeDetection: ChangeDetectionStrategy.OnPush, template: "<mj-page-layout>\n <mj-page-header\n Title=\"Runs\"\n Icon=\"fa-solid fa-timeline\"\n Subtitle=\"Every workflow that has run \u2014 however it was started.\">\n\n <div meta>\n @if (!IsLoading && Runs.length > 0) {\n <mj-stat-badge\n [Count]=\"VisibleRuns.length\"\n [Total]=\"Runs.length\"\n Label=\"runs\"></mj-stat-badge>\n }\n </div>\n\n <div actions>\n <mj-refresh-button [Loading]=\"IsLoading\" (Clicked)=\"loadData()\"></mj-refresh-button>\n </div>\n\n <div toolbar>\n <mj-page-search\n [Value]=\"SearchText\"\n Placeholder=\"Search runs\"\n (ValueChange)=\"OnSearch($event)\"></mj-page-search>\n\n <div class=\"wfr-status-filters\">\n @for (status of StatusFilters; track status) {\n <button\n type=\"button\"\n mjButton\n [variant]=\"StatusFilter === status ? 'primary' : 'flat'\"\n size=\"sm\"\n (click)=\"OnFilterByStatus(status)\">\n {{ status === 'all' ? 'All' : status }}\n </button>\n }\n </div>\n </div>\n </mj-page-header>\n\n <mj-page-body>\n @if (IsLoading) {\n <mj-loading text=\"Loading runs...\"></mj-loading>\n } @else if (LoadError) {\n <mj-alert Variant=\"error\" [Message]=\"LoadError\"></mj-alert>\n } @else if (Runs.length === 0) {\n <mj-empty-state\n Icon=\"fa-solid fa-timeline\"\n Title=\"Nothing has run yet\"\n Message=\"When a workflow runs \u2014 started by hand, on a schedule, or by an agent \u2014 it will appear here.\">\n </mj-empty-state>\n } @else if (VisibleRuns.length === 0) {\n <mj-empty-state\n Icon=\"fa-solid fa-filter\"\n Title=\"No runs match\"\n Message=\"Nothing matches the current filter. Clear it to see everything that has run.\">\n </mj-empty-state>\n } @else {\n <as-split class=\"wfr-split\" direction=\"horizontal\" unit=\"percent\"\n [gutterSize]=\"8\" [disabled]=\"!SelectedRun\" (dragEnd)=\"OnSplitDragEnd($event.sizes)\">\n <as-split-area [size]=\"SelectedRun ? Layout.SplitSizes[0] : 100\" [minSize]=\"20\">\n <div class=\"wfr-list\">\n <!-- A header row that sorts. Every column a person scans by is sortable, because \"the\n longest run\" and \"the one that failed this morning\" are the two questions this list\n exists to answer and neither is answerable by scrolling. -->\n <div class=\"wfr-head\" role=\"row\">\n <button type=\"button\" class=\"wfr-head-cell wfr-col-name\" (click)=\"OnSort('Name')\">\n Workflow <i [ngClass]=\"SortIcon('Name')\" aria-hidden=\"true\"></i>\n </button>\n <button type=\"button\" class=\"wfr-head-cell wfr-col-time\" (click)=\"OnSort('StartedAt')\">\n Started <i [ngClass]=\"SortIcon('StartedAt')\" aria-hidden=\"true\"></i>\n </button>\n <button type=\"button\" class=\"wfr-head-cell wfr-col-time\" (click)=\"OnSort('CompletedAt')\">\n Ended <i [ngClass]=\"SortIcon('CompletedAt')\" aria-hidden=\"true\"></i>\n </button>\n <button type=\"button\" class=\"wfr-head-cell wfr-col-duration\" (click)=\"OnSort('Duration')\">\n Duration <i [ngClass]=\"SortIcon('Duration')\" aria-hidden=\"true\"></i>\n </button>\n <button type=\"button\" class=\"wfr-head-cell wfr-col-status\" (click)=\"OnSort('Status')\">\n Status <i [ngClass]=\"SortIcon('Status')\" aria-hidden=\"true\"></i>\n </button>\n </div>\n\n @for (run of VisibleRuns; track run.ID) {\n <button\n type=\"button\"\n class=\"wfr-row\"\n [class.wfr-row-selected]=\"run.ID === SelectedRunID\"\n (click)=\"OnSelectRun(run)\">\n <span class=\"wfr-col-name wfr-row-name\">{{ run.Name }}</span>\n <!-- An em dash, never a fabricated time: a run that has not started has no start, and\n printing one would read as data. -->\n <span class=\"wfr-col-time\">{{ run.StartedAt ? (run.StartedAt | date:'MMM d, h:mm:ss a') : '\u2014' }}</span>\n <span class=\"wfr-col-time\">{{ run.CompletedAt ? (run.CompletedAt | date:'MMM d, h:mm:ss a') : '\u2014' }}</span>\n <span class=\"wfr-col-duration\">{{ run.Duration }}</span>\n <span class=\"wfr-col-status wfr-row-status\" [attr.data-status]=\"run.Status\">{{ run.Status }}</span>\n </button>\n }\n </div>\n </as-split-area>\n\n <as-split-area [size]=\"SelectedRun ? Layout.SplitSizes[1] : 0\" [minSize]=\"25\" [visible]=\"!!SelectedRun\">\n @if (SelectedRun; as selected) {\n <!-- The canvas lives in the RIGHT PANEL on selection, not nested inside the list row.\n A graph needs room to be read; inlining one per row turns a scannable list into a\n stack of diagrams. -->\n <aside class=\"wfr-detail\">\n <header class=\"wfr-detail-head\">\n <div class=\"wfr-detail-title\">\n <span class=\"wfr-detail-name\">{{ selected.Name }}</span>\n <span class=\"wfr-row-status\" [attr.data-status]=\"selected.Status\">{{ selected.Status }}</span>\n </div>\n <div class=\"wfr-detail-actions\">\n @if (selected.AgentRunID) {\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"OnOpenAgentRun(selected)\">\n <i class=\"fa-solid fa-arrow-up-right-from-square\" aria-hidden=\"true\"></i>\n Agent run\n </button>\n }\n @if (DetailTab === 'graph') {\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"ToggleStepPanel()\"\n [title]=\"Layout.StepPanelOpen ? 'Hide step details' : 'Show step details'\">\n <i class=\"fa-solid\" [class.fa-square-caret-right]=\"Layout.StepPanelOpen\"\n [class.fa-square-caret-left]=\"!Layout.StepPanelOpen\" aria-hidden=\"true\"></i>\n </button>\n }\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"OnSelectRun(selected)\" aria-label=\"Close\">\n <i class=\"fa-solid fa-xmark\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </header>\n\n <div class=\"wfr-detail-tabs\" role=\"tablist\">\n <button type=\"button\" class=\"wfr-tab\" [class.wfr-tab-active]=\"DetailTab === 'graph'\"\n (click)=\"OnDetailTab('graph')\">\n <i class=\"fa-solid fa-diagram-project\" aria-hidden=\"true\"></i> Workflow\n </button>\n <button type=\"button\" class=\"wfr-tab\" [class.wfr-tab-active]=\"DetailTab === 'json'\"\n (click)=\"OnDetailTab('json')\">\n <i class=\"fa-solid fa-code\" aria-hidden=\"true\"></i> JSON\n </button>\n </div>\n\n @if (Stall) {\n <!-- The hardening review's signature failure \u2014 \"the run strands silently\" \u2014 made\n loud. A held path is now something the operator can answer, not just read. -->\n <div class=\"wfr-stall\" role=\"status\" [attr.data-kind]=\"Stall.kind\">\n <div class=\"wfr-stall-body\">\n <i class=\"fa-solid fa-triangle-exclamation\" aria-hidden=\"true\"></i>\n <div class=\"wfr-stall-copy\">\n <span>{{ Stall.message }}</span>\n @if (Stall.conditionText) {\n <code>{{ Stall.conditionText }}</code>\n }\n @if (Stall.reason) {\n <span class=\"wfr-stall-reason\">{{ Stall.reason }}</span>\n }\n </div>\n </div>\n @if (Stall.kind === 'held' && Stall.edgeID) {\n <div class=\"wfr-stall-actions\">\n <button mjButton variant=\"primary\" size=\"sm\" [disabled]=\"ControlBusy\"\n (click)=\"OnOverrideEdge(Stall.edgeID!, 'true')\">\n Answer true\n </button>\n <button mjButton variant=\"secondary\" size=\"sm\" [disabled]=\"ControlBusy\"\n (click)=\"OnOverrideEdge(Stall.edgeID!, 'false')\">\n Answer false\n </button>\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"OnDismissStall()\">\n Leave held\n </button>\n </div>\n }\n </div>\n }\n\n @if (DetailTab === 'graph') {\n <!-- Canvas BESIDE the step it opened, not above it. A JSON record in a strip along the\n bottom shows about ten lines, which is not enough of a record to read. -->\n <as-split class=\"wfr-graph-split\" [direction]=\"InnerSplitDirection\" unit=\"percent\"\n [gutterSize]=\"8\" (dragEnd)=\"OnStepSplitDragEnd($event.sizes)\">\n <as-split-area [size]=\"Layout.StepPanelOpen ? Layout.StepSplitSizes[0] : 100\" [minSize]=\"25\">\n <div class=\"wfr-graph-pane\">\n <mj-task-graph-debugger\n #GraphDebug\n [Provider]=\"ProviderToUse\"\n [ParentTaskID]=\"selected.ID\"\n [WorkflowName]=\"selected.Name\"\n [LiveUpdates]=\"selected.Status === 'Running' || selected.Status === 'In Progress'\"\n [ReplayAt]=\"ReplayAt\"\n [ShowLegend]=\"Layout.ShowLegend\"\n Height=\"100%\"\n (NodeSelected)=\"OnGraphNodeSelected($event)\"\n (ConnectionSelected)=\"OnGraphConnectionSelected($event)\"\n (LegendToggled)=\"OnLegendToggled($event)\"\n (Settled)=\"OnCanvasSettled()\"\n (Frame)=\"OnFrame($event)\"\n (PausedChange)=\"DebugPaused = $event\">\n </mj-task-graph-debugger>\n\n @if (CanReplay) {\n <!-- Replay: scrub through the settled run on the same canvas, reconstructed\n from each step's own timestamps. Read-only by construction. -->\n <div class=\"wfr-replay\">\n <i class=\"fa-solid fa-clock-rotate-left\" aria-hidden=\"true\"></i>\n <input type=\"range\" min=\"0\" max=\"100\" step=\"1\"\n [value]=\"ReplayPercent ?? 100\"\n (input)=\"OnReplayScrub($any($event.target).value)\"\n aria-label=\"Replay position\" />\n @if (ReplayPercent !== null) {\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"OnReplayReset()\">Now</button>\n }\n </div>\n }\n\n @if (GraphDebug.Breakpoints.length > 0 || GraphDebug.PausedAtTaskID) {\n <div class=\"wfr-bp-bar\" aria-label=\"Armed breakpoints\">\n @if (GraphDebug.PausedAtTaskID) {\n <span class=\"wfr-chip wfr-chip-paused\">\n <i class=\"fa-solid fa-pause\" aria-hidden=\"true\"></i>\n Paused at {{ StepName(GraphDebug.PausedAtTaskID) }}\n </span>\n }\n @for (id of GraphDebug.Breakpoints; track id) {\n <button type=\"button\" class=\"wfr-chip wfr-chip-break\" (click)=\"OnSelectBreakpoint(id)\">\n <i class=\"fa-solid fa-circle\" aria-hidden=\"true\"></i>\n {{ StepName(id) }}\n <span class=\"wfr-chip-x\" (click)=\"OnRemoveBreakpoint(id); $event.stopPropagation()\"\n role=\"button\" tabindex=\"0\" aria-label=\"Remove breakpoint\">\u00D7</span>\n </button>\n }\n </div>\n }\n\n @if (EngineTicks.length > 0) {\n <!-- The engine strip: one tick per dispatcher pass. A stuck run is a strip\n that keeps ticking with nothing moving \u2014 the honest visual of a stall. -->\n <div class=\"wfr-engine\" aria-label=\"Engine activity\">\n @for (tick of EngineTicks; track tick.passNumber) {\n <span class=\"wfr-tick\" [class.wfr-tick-held]=\"(tick.heldCount ?? 0) > 0\">\n #{{ tick.passNumber }} \u00B7 ready {{ tick.eligibleCount ?? 0 }}\n \u00B7 held {{ tick.heldCount ?? 0 }} \u00B7 took {{ tick.claimedCount ?? 0 }}\n </span>\n }\n @if (GraphDebug.Paused) {\n <span class=\"wfr-tick wfr-tick-paused\">\u23F8 paused \u2014 nothing new starts</span>\n }\n </div>\n }\n </div>\n </as-split-area>\n\n <as-split-area [size]=\"Layout.StepPanelOpen ? Layout.StepSplitSizes[1] : 0\" [minSize]=\"20\"\n [visible]=\"Layout.StepPanelOpen\">\n <div class=\"wfr-steps-pane\">\n @if (StepsLoading) {\n <mj-loading text=\"Loading steps...\"></mj-loading>\n } @else {\n <div class=\"wfr-step-list\">\n @for (step of SelectedSteps; track step.ID) {\n <button type=\"button\" class=\"wfr-step\"\n [class.wfr-step-selected]=\"step.ID === SelectedStepID\"\n [attr.data-status]=\"step.Status\"\n (click)=\"OnSelectStep(step)\">\n <span class=\"wfr-step-name\">{{ step.Name }}</span>\n <span class=\"wfr-step-meta\">{{ step.StepType || 'Step' }}</span>\n </button>\n }\n </div>\n\n @if (InspectorMode === 'edge' && SelectedEdge; as edge) {\n <div class=\"wfr-step-json\">\n <div class=\"wfr-step-json-head\">\n <span>{{ SelectedEdgeFromName }} \u2192 {{ SelectedEdgeToName }}</span>\n @if (SelectedEdgeOverride) {\n <span class=\"wfr-chip wfr-chip-forced\">forced {{ SelectedEdgeOverride }}</span>\n }\n </div>\n <div class=\"wfr-insp-card\">\n <span class=\"wfr-insp-label\">Condition</span>\n @if (edge.Condition?.trim()) {\n <code>{{ edge.Condition }}</code>\n } @else {\n <span>Unconditional \u2014 this path always runs.</span>\n }\n </div>\n @if (SelectedEdgeIsConditional) {\n <div class=\"wfr-insp-actions\">\n <button mjButton variant=\"primary\" size=\"sm\" [disabled]=\"ControlBusy\"\n (click)=\"OnOverrideEdge(edge.ID, 'true')\">Answer true</button>\n <button mjButton variant=\"secondary\" size=\"sm\" [disabled]=\"ControlBusy\"\n (click)=\"OnOverrideEdge(edge.ID, 'false')\">Answer false</button>\n @if (SelectedEdgeOverride) {\n <button mjButton variant=\"flat\" size=\"sm\" [disabled]=\"ControlBusy\"\n (click)=\"OnOverrideEdge(edge.ID, null)\">Clear override</button>\n }\n </div>\n } @else {\n <p class=\"wfr-insp-hint\">Skip the target step instead of overriding an unconditional path.</p>\n }\n </div>\n } @else if (SelectedStep; as step) {\n <div class=\"wfr-step-json\">\n <div class=\"wfr-step-json-head\">\n <span>{{ step.Name }}</span>\n <span class=\"wfr-row-status\" [attr.data-status]=\"step.Status\">{{ step.Status }}</span>\n </div>\n\n <button type=\"button\" class=\"wfr-bp\"\n [class.wfr-bp-on]=\"HasBreakpoint(step.ID)\"\n [disabled]=\"ControlBusy\"\n (click)=\"OnBreakpointToggled({ TaskID: step.ID, Enabled: !HasBreakpoint(step.ID) })\"\n [attr.aria-pressed]=\"HasBreakpoint(step.ID)\"\n [title]=\"HasBreakpoint(step.ID) ? 'Remove breakpoint' : 'Break before this step'\">\n <i class=\"fa-circle\"\n [class.fa-solid]=\"HasBreakpoint(step.ID)\"\n [class.fa-regular]=\"!HasBreakpoint(step.ID)\"\n aria-hidden=\"true\"></i>\n </button>\n\n <!-- The inspector: live engine facts about this step, from the frame\n stream \u2014 claim, path verdicts, runner progress, what-if. -->\n @if (SelectedStepProgress; as progress) {\n <div class=\"wfr-insp-card\">\n <span class=\"wfr-insp-label\">Doing now</span>\n <span>{{ progress.progressMessage }}\n @if (progress.progressPercent != null) { ({{ progress.progressPercent }}%) }\n </span>\n </div>\n }\n @if (SelectedStepClaim; as claim) {\n <div class=\"wfr-insp-card\" [class.wfr-insp-bad]=\"claim.claimEvent === 'heartbeat-lost'\">\n <span class=\"wfr-insp-label\">Worker</span>\n <span>\n @switch (claim.claimEvent) {\n @case ('claimed') { {{ claim.claimedBy }} \u2014 working }\n @case ('heartbeat-lost') { {{ claim.claimedBy }} \u2014 lost, will be requeued }\n @case ('reclaimed') { requeued by the engine }\n }\n </span>\n </div>\n }\n @for (verdict of SelectedStepVerdicts; track verdict.edgeId) {\n <div class=\"wfr-insp-card\" [attr.data-verdict]=\"verdict.verdict\">\n <span class=\"wfr-insp-label\">\n @switch (verdict.verdict) {\n @case ('satisfied') { Path taken }\n @case ('notTaken') { Path not taken }\n @case ('held') { Path can't be answered }\n }\n </span>\n <span>\n @if (verdict.conditionText) { <code>{{ verdict.conditionText }}</code> }\n @if (verdict.reason) { \u2014 {{ verdict.reason }} }\n </span>\n </div>\n }\n @if (SelectedStepWhatIf; as whatIf) {\n <div class=\"wfr-insp-card\">\n <span class=\"wfr-insp-label\">If this step fails</span>\n <span>{{ whatIf.BlockedCount }} step{{ whatIf.BlockedCount === 1 ? '' : 's' }} can no longer run</span>\n </div>\n }\n @if (step.Status === 'Pending' || step.Status === 'Failed' || CanForceComplete(step)) {\n <div class=\"wfr-insp-actions\">\n @if (step.Status === 'Pending') {\n <button mjButton variant=\"secondary\" size=\"sm\" [disabled]=\"ControlBusy\"\n (click)=\"OnSkipStep(step)\"\n title=\"Declare this step not-taken; later steps proceed\">\n <i class=\"fa-solid fa-forward\" aria-hidden=\"true\"></i> Skip step\n </button>\n }\n @if (CanEditInput(step)) {\n <button mjButton variant=\"secondary\" size=\"sm\" [disabled]=\"ControlBusy\"\n (click)=\"OpenEditInput(step)\">\n <i class=\"fa-solid fa-pen-to-square\" aria-hidden=\"true\"></i>\n {{ step.Status === 'Failed' ? 'Edit input & retry' : 'Edit input' }}\n </button>\n }\n @if (step.Status === 'Failed') {\n <button mjButton variant=\"secondary\" size=\"sm\" [disabled]=\"ControlBusy\"\n (click)=\"OnRetryStep(step)\">\n <i class=\"fa-solid fa-rotate-right\" aria-hidden=\"true\"></i> Retry\n </button>\n }\n @if (CanForceComplete(step)) {\n <button mjButton variant=\"danger\" size=\"sm\" [disabled]=\"ControlBusy\"\n (click)=\"OpenForceComplete(step)\">\n <i class=\"fa-solid fa-flag-checkered\" aria-hidden=\"true\"></i> Force complete\n </button>\n }\n </div>\n }\n\n @if (EditInputOpen) {\n <div class=\"wfr-editor-card\">\n <span class=\"wfr-insp-label\">{{ step.Status === 'Failed' ? 'Edit input and retry' : 'Edit input' }}</span>\n <p class=\"wfr-insp-hint\">Applies to this run only. Invalid JSON is refused here.</p>\n <textarea class=\"mj-textarea wfr-json-edit\" [(ngModel)]=\"EditInputJson\"\n rows=\"8\" spellcheck=\"false\"></textarea>\n @if (EditInputError) {\n <span class=\"wfr-editor-error\">{{ EditInputError }}</span>\n }\n <div class=\"wfr-insp-actions\">\n <button mjButton variant=\"primary\" size=\"sm\" [disabled]=\"ControlBusy\"\n (click)=\"SubmitEditInput(step)\">\n {{ step.Status === 'Failed' ? 'Apply & retry' : 'Apply' }}\n </button>\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"EditInputOpen = false\">Cancel</button>\n </div>\n </div>\n }\n\n @if (ForceCompleteOpen) {\n <div class=\"wfr-editor-card wfr-editor-danger\">\n <span class=\"wfr-insp-label\">Force complete</span>\n <p class=\"wfr-insp-hint\">Downstream conditions will evaluate against this output as if the step had produced it. Type the step name to confirm.</p>\n <textarea class=\"mj-textarea wfr-json-edit\" [(ngModel)]=\"ForceCompleteJson\"\n rows=\"6\" spellcheck=\"false\"></textarea>\n <input class=\"mj-input\" type=\"text\" [(ngModel)]=\"ForceCompleteName\"\n [placeholder]=\"'Type \u201C' + step.Name + '\u201D to confirm'\" />\n @if (ForceCompleteError) {\n <span class=\"wfr-editor-error\">{{ ForceCompleteError }}</span>\n }\n <div class=\"wfr-insp-actions\">\n <button mjButton variant=\"danger\" size=\"sm\" [disabled]=\"ControlBusy\"\n (click)=\"SubmitForceComplete(step)\">Force complete</button>\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"ForceCompleteOpen = false\">Cancel</button>\n </div>\n </div>\n }\n\n <mj-task-graph-variables\n [InputPayload]=\"StepPayload(step, 'InputPayload')\"\n [OutputPayload]=\"StepPayload(step, 'OutputPayload')\"\n [Invocation]=\"Invocation\">\n </mj-task-graph-variables>\n </div>\n } @else {\n <mj-empty-state\n Size=\"compact\"\n Icon=\"fa-solid fa-hand-pointer\"\n Title=\"Select a step\"\n Message=\"Click a step on the canvas or in the list to see everything it recorded.\">\n </mj-empty-state>\n }\n }\n </div>\n </as-split-area>\n </as-split>\n } @else {\n <div class=\"wfr-json-pane\">\n <mj-code-editor\n [ngModel]=\"SelectedRunJson\"\n [language]=\"'json'\"\n [readonly]=\"true\"\n style=\"width: 100%;\">\n </mj-code-editor>\n </div>\n }\n </aside>\n }\n </as-split-area>\n </as-split>\n }\n </mj-page-body>\n</mj-page-layout>\n", styles: [":host {\n display: block;\n height: 100%;\n}\n\n.wfr-status-filters {\n display: flex;\n gap: var(--mj-space-1);\n align-items: center;\n}\n\n/* List alone until something is selected; two resizable panes after. The size is the user's \u2014 see\n the LAYOUT_KEYS note on the component for why it is persisted server-side rather than locally. */\n.wfr-split {\n height: 100%;\n min-height: 0;\n}\n\n/* A gutter you can find. The default is a hairline, which is discoverable only by accident. */\n:host ::ng-deep .wfr-split > .as-split-gutter,\n:host ::ng-deep .wfr-graph-split > .as-split-gutter {\n background: transparent !important;\n position: relative;\n}\n\n:host ::ng-deep .wfr-split > .as-split-gutter::after,\n:host ::ng-deep .wfr-graph-split > .as-split-gutter::after {\n content: '';\n position: absolute;\n inset: 0;\n margin: auto;\n background: var(--mj-border-default);\n border-radius: var(--mj-radius-full);\n}\n\n:host ::ng-deep .wfr-split.as-horizontal > .as-split-gutter::after,\n:host ::ng-deep .wfr-graph-split.as-horizontal > .as-split-gutter::after {\n width: 2px;\n}\n\n:host ::ng-deep .wfr-graph-split.as-vertical > .as-split-gutter::after {\n height: 2px;\n}\n\n:host ::ng-deep .wfr-split > .as-split-gutter:hover::after,\n:host ::ng-deep .wfr-graph-split > .as-split-gutter:hover::after {\n background: var(--mj-brand-primary);\n}\n\n/* The canvas and the step record sit SIDE BY SIDE \u2014 a JSON record in a strip along the bottom shows\n about ten lines. Stacks below the breakpoint, where three columns would leave each too narrow to\n use. */\n.wfr-graph-split {\n flex: 1 1 auto;\n min-height: 0;\n}\n\n.wfr-list {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-1);\n overflow-y: auto;\n min-height: 0;\n}\n\n.wfr-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--mj-space-2);\n width: 100%;\n padding: var(--mj-space-2) var(--mj-space-3);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n text-align: left;\n cursor: pointer;\n color: var(--mj-text-primary);\n}\n\n.wfr-row:hover {\n border-color: var(--mj-border-strong);\n}\n\n.wfr-row:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n.wfr-row-selected {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n}\n\n.wfr-row-main {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.wfr-row-name {\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.wfr-row-when {\n font-size: var(--mj-font-size-sm);\n color: var(--mj-text-secondary);\n font-variant-numeric: tabular-nums;\n}\n\n.wfr-row-status {\n flex: none;\n font-size: var(--mj-font-size-xs);\n text-transform: uppercase;\n letter-spacing: 0.04em;\n padding: 2px var(--mj-space-2);\n border-radius: var(--mj-radius-full);\n background: var(--mj-bg-page);\n color: var(--mj-text-secondary);\n border: 1px solid var(--mj-border-default);\n}\n\n/* Status carries meaning, so it is encoded in colour as well as text \u2014 a failed run should be\n findable without reading every row. Skipped stays grey on purpose: a branch that was not taken\n is a normal outcome, not a warning. */\n.wfr-row-status[data-status='Complete'] {\n color: var(--mj-status-success);\n border-color: color-mix(in srgb, var(--mj-status-success) 40%, transparent);\n}\n\n.wfr-row-status[data-status='Failed'] {\n color: var(--mj-status-error);\n border-color: color-mix(in srgb, var(--mj-status-error) 40%, transparent);\n}\n\n.wfr-row-status[data-status='Running'] {\n color: var(--mj-brand-primary);\n border-color: color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n}\n\n.wfr-detail {\n display: flex;\n flex-direction: column;\n /* Fills its split area. Without it the column sizes to its CONTENT, so the canvas below \u2014\n `flex: 1 1 auto` of an auto-height parent \u2014 got its intrinsic height and left dead space. */\n height: 100%;\n min-height: 0;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n overflow: hidden;\n}\n\n.wfr-detail-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--mj-space-2);\n padding: var(--mj-space-2) var(--mj-space-3);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.wfr-detail-title {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n min-width: 0;\n}\n\n.wfr-detail-name {\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.wfr-detail-actions {\n display: flex;\n align-items: center;\n gap: var(--mj-space-1);\n flex: none;\n}\n\n/* ============================================================\n The run list as a sortable table\n ============================================================\n A run list is scanned for two things \u2014 the slowest run and the one that failed \u2014 and neither is\n answerable by scrolling. Columns line up so a reader compares down a column rather than reading\n each row; `tabular-nums` keeps the timestamps from jittering as digits change. */\n.wfr-head,\n.wfr-row {\n display: grid;\n grid-template-columns: minmax(0, 2fr) minmax(0, 1.3fr) minmax(0, 1.3fr) minmax(0, 0.7fr) minmax(0, 0.9fr);\n gap: var(--mj-space-2);\n align-items: center;\n}\n\n.wfr-head {\n position: sticky;\n top: 0;\n z-index: 1;\n padding: 0 var(--mj-space-3) var(--mj-space-1);\n background: var(--mj-bg-page);\n}\n\n.wfr-head-cell {\n display: flex;\n align-items: center;\n gap: 6px;\n background: none;\n border: none;\n padding: var(--mj-space-1) 0;\n font-size: var(--mj-font-size-xs);\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--mj-text-secondary);\n cursor: pointer;\n text-align: left;\n}\n\n.wfr-head-cell:hover {\n color: var(--mj-text-primary);\n}\n\n.wfr-head-cell i {\n opacity: 0.65;\n font-size: 0.85em;\n}\n\n.wfr-col-time,\n.wfr-col-duration {\n font-size: var(--mj-font-size-sm);\n color: var(--mj-text-secondary);\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.wfr-col-status {\n justify-self: start;\n}\n\n/* ============================================================\n Detail panel: canvas + step JSON, or the whole run as JSON\n ============================================================ */\n.wfr-detail-tabs {\n display: flex;\n gap: var(--mj-space-1);\n padding: 0 var(--mj-space-3);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.wfr-tab {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n background: none;\n border: none;\n border-bottom: 2px solid transparent;\n padding: var(--mj-space-2) var(--mj-space-2);\n font-size: var(--mj-font-size-sm);\n font-weight: 600;\n color: var(--mj-text-secondary);\n cursor: pointer;\n}\n\n.wfr-tab-active {\n color: var(--mj-brand-primary);\n border-bottom-color: var(--mj-brand-primary);\n}\n\n.wfr-graph-pane {\n height: 100%;\n min-height: 12rem;\n}\n\n.wfr-steps-pane {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n border-left: 1px solid var(--mj-border-default);\n overflow: hidden;\n}\n\n/* Stacked layout puts the divider back on top, where the eye expects it. */\n:host ::ng-deep .as-vertical .wfr-steps-pane {\n border-left: none;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.wfr-step-list {\n display: flex;\n flex-wrap: wrap;\n gap: var(--mj-space-1);\n padding: var(--mj-space-2);\n border-bottom: 1px solid var(--mj-border-default);\n max-height: 8rem;\n overflow-y: auto;\n flex: none;\n}\n\n.wfr-step {\n display: inline-flex;\n align-items: center;\n gap: var(--mj-space-2);\n padding: var(--mj-space-1) var(--mj-space-2);\n background: var(--mj-bg-page);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n color: var(--mj-text-primary);\n font-size: var(--mj-font-size-sm);\n cursor: pointer;\n text-align: left;\n}\n\n.wfr-step:hover {\n border-color: var(--mj-border-strong);\n}\n\n.wfr-step-selected {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n}\n\n/* Work that never ran must not read like work that did \u2014 the same rule the run timeline follows. */\n.wfr-step[data-status='Skipped'] .wfr-step-name {\n text-decoration: line-through;\n color: var(--mj-text-secondary);\n}\n\n.wfr-step-name {\n font-weight: 600;\n}\n\n.wfr-step-meta {\n font-size: var(--mj-font-size-xs);\n color: var(--mj-text-secondary);\n}\n\n.wfr-step-json,\n.wfr-json-pane {\n flex: 1 1 auto;\n min-height: 0;\n display: flex;\n flex-direction: column;\n overflow: auto;\n}\n\n.wfr-step-json-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--mj-space-2);\n padding: var(--mj-space-1) var(--mj-space-3);\n font-weight: 600;\n font-size: var(--mj-font-size-sm);\n color: var(--mj-text-secondary);\n flex: none;\n}\n\n/* \u2500\u2500 live console \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.wfr-stall {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 8px 12px;\n margin: 0 12px 8px;\n border: 1px solid color-mix(in srgb, var(--mj-status-warning) 45%, var(--mj-border-default));\n border-left: 4px solid var(--mj-status-warning);\n border-radius: var(--mj-radius-md);\n background: color-mix(in srgb, var(--mj-status-warning) 8%, var(--mj-bg-surface));\n color: var(--mj-text-primary);\n font-size: var(--mj-font-size-sm);\n}\n.wfr-stall-body {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n}\n.wfr-stall i { color: var(--mj-status-warning); }\n.wfr-stall-copy {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n.wfr-stall-copy code {\n font-family: var(--mj-font-mono, ui-monospace, monospace);\n font-size: var(--mj-font-size-xs);\n}\n.wfr-stall-reason { color: var(--mj-text-secondary); }\n.wfr-stall-actions { display: flex; flex-wrap: wrap; gap: 6px; }\n\n.wfr-replay {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 6px 12px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-page);\n}\n.wfr-replay i { color: var(--mj-text-secondary); }\n.wfr-replay input[type='range'] { flex: 1; accent-color: var(--mj-brand-primary); }\n\n.wfr-engine {\n display: flex;\n gap: 8px;\n overflow-x: auto;\n padding: 6px 12px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-page);\n font-family: var(--mj-font-mono, ui-monospace, monospace);\n font-size: var(--mj-font-size-xs);\n color: var(--mj-text-secondary);\n font-variant-numeric: tabular-nums;\n}\n.wfr-tick {\n flex: none;\n padding: 3px 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface);\n white-space: nowrap;\n}\n.wfr-tick-held {\n border-color: color-mix(in srgb, var(--mj-status-warning, #d97706) 45%, var(--mj-border-default));\n background: color-mix(in srgb, var(--mj-status-warning, #d97706) 8%, var(--mj-bg-surface));\n}\n.wfr-tick-paused { color: var(--mj-brand-primary); border-color: var(--mj-border-strong); }\n\n.wfr-insp-card {\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding: 7px 10px;\n margin: 0 0 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface);\n font-size: var(--mj-font-size-sm);\n color: var(--mj-text-primary);\n}\n.wfr-insp-card code {\n font-family: var(--mj-font-mono, ui-monospace, monospace);\n font-size: var(--mj-font-size-xs);\n}\n.wfr-insp-label {\n font-size: var(--mj-font-size-xs);\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--mj-text-secondary);\n}\n.wfr-insp-card[data-verdict='held'],\n.wfr-insp-bad {\n border-color: color-mix(in srgb, var(--mj-status-warning, #d97706) 45%, var(--mj-border-default));\n background: color-mix(in srgb, var(--mj-status-warning, #d97706) 8%, var(--mj-bg-surface));\n}\n.wfr-insp-card[data-verdict='satisfied'] .wfr-insp-label { color: var(--mj-status-success); }\n.wfr-insp-actions { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 8px; }\n.wfr-insp-hint {\n margin: 0 0 8px;\n font-size: var(--mj-font-size-xs);\n color: var(--mj-text-muted);\n}\n\n.wfr-bp-bar {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n padding: 6px 12px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-page);\n}\n.wfr-chip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 2px 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-full);\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: var(--mj-font-size-xs);\n cursor: pointer;\n}\n.wfr-chip-break { color: var(--mj-status-error); border-color: color-mix(in srgb, var(--mj-status-error) 40%, transparent); }\n.wfr-chip-break i { font-size: 7px; }\n.wfr-chip-paused {\n color: var(--mj-brand-primary);\n border-color: color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n cursor: default;\n}\n.wfr-chip-forced {\n color: var(--mj-status-warning);\n border-color: color-mix(in srgb, var(--mj-status-warning) 40%, transparent);\n cursor: default;\n}\n.wfr-chip-x {\n font-size: 14px;\n line-height: 1;\n padding: 0 2px;\n}\n.wfr-chip-x:hover { color: var(--mj-text-primary); }\n\n.wfr-bp {\n width: 22px;\n height: 22px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n margin: 0 0 8px;\n padding: 0;\n border: none;\n border-radius: 50%;\n background: transparent;\n color: var(--mj-text-muted);\n cursor: pointer;\n}\n.wfr-bp:hover { color: var(--mj-status-error); }\n.wfr-bp-on,\n.wfr-bp-on:hover { color: var(--mj-status-error); }\n.wfr-bp i { font-size: 10px; }\n.wfr-bp:disabled { opacity: 0.45; cursor: default; }\n\n.wfr-editor-card {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 10px;\n margin: 0 0 10px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface-card);\n}\n.wfr-editor-danger {\n border-color: color-mix(in srgb, var(--mj-status-error) 40%, var(--mj-border-default));\n}\n.wfr-json-edit {\n width: 100%;\n min-height: 120px;\n font-family: var(--mj-font-mono, ui-monospace, monospace);\n font-size: var(--mj-font-size-xs);\n resize: vertical;\n}\n.wfr-editor-error { color: var(--mj-status-error); font-size: var(--mj-font-size-xs); }\n"] }]
1834
+ args: [{ standalone: false, selector: 'mj-workflow-runs', changeDetection: ChangeDetectionStrategy.OnPush, template: "<mj-page-layout>\n <mj-page-header\n Title=\"Runs\"\n Icon=\"fa-solid fa-timeline\"\n Subtitle=\"Every workflow that has run \u2014 however it was started.\">\n\n <div meta>\n @if (!IsLoading && Runs.length > 0) {\n <mj-stat-badge\n [Count]=\"VisibleRuns.length\"\n [Total]=\"Runs.length\"\n Label=\"runs\"></mj-stat-badge>\n }\n </div>\n\n <div actions>\n <mj-refresh-button [Loading]=\"IsLoading\" (Clicked)=\"loadData()\"></mj-refresh-button>\n </div>\n\n <div toolbar>\n <mj-page-search\n [Value]=\"SearchText\"\n Placeholder=\"Search runs\"\n (ValueChange)=\"OnSearch($event)\"></mj-page-search>\n\n <div class=\"wfr-status-filters\">\n @for (status of StatusFilters; track status) {\n <button\n type=\"button\"\n mjButton\n [variant]=\"StatusFilter === status ? 'primary' : 'flat'\"\n size=\"sm\"\n (click)=\"OnFilterByStatus(status)\">\n {{ status === 'all' ? 'All' : status }}\n </button>\n }\n </div>\n </div>\n </mj-page-header>\n\n <mj-page-body>\n @if (IsLoading) {\n <mj-loading text=\"Loading runs...\"></mj-loading>\n } @else if (LoadError) {\n <mj-alert Variant=\"error\" [Message]=\"LoadError\"></mj-alert>\n } @else if (Runs.length === 0) {\n <mj-empty-state\n Icon=\"fa-solid fa-timeline\"\n Title=\"Nothing has run yet\"\n Message=\"When a workflow runs \u2014 started by hand, on a schedule, or by an agent \u2014 it will appear here.\">\n </mj-empty-state>\n } @else if (VisibleRuns.length === 0) {\n <mj-empty-state\n Icon=\"fa-solid fa-filter\"\n Title=\"No runs match\"\n Message=\"Nothing matches the current filter. Clear it to see everything that has run.\">\n </mj-empty-state>\n } @else {\n <as-split class=\"wfr-split\" direction=\"horizontal\" unit=\"percent\"\n [gutterSize]=\"8\" [disabled]=\"!SelectedRun\" (dragEnd)=\"OnSplitDragEnd($event.sizes)\">\n <as-split-area [size]=\"SelectedRun ? Layout.SplitSizes[0] : 100\" [minSize]=\"20\">\n <div class=\"wfr-list\">\n <!-- A header row that sorts. Every column a person scans by is sortable, because \"the\n longest run\" and \"the one that failed this morning\" are the two questions this list\n exists to answer and neither is answerable by scrolling. -->\n <div class=\"wfr-head\" role=\"row\">\n <button type=\"button\" class=\"wfr-head-cell wfr-col-name\" (click)=\"OnSort('Name')\">\n Workflow <i [ngClass]=\"SortIcon('Name')\" aria-hidden=\"true\"></i>\n </button>\n <button type=\"button\" class=\"wfr-head-cell wfr-col-time\" (click)=\"OnSort('StartedAt')\">\n Started <i [ngClass]=\"SortIcon('StartedAt')\" aria-hidden=\"true\"></i>\n </button>\n <button type=\"button\" class=\"wfr-head-cell wfr-col-time\" (click)=\"OnSort('CompletedAt')\">\n Ended <i [ngClass]=\"SortIcon('CompletedAt')\" aria-hidden=\"true\"></i>\n </button>\n <button type=\"button\" class=\"wfr-head-cell wfr-col-duration\" (click)=\"OnSort('Duration')\">\n Duration <i [ngClass]=\"SortIcon('Duration')\" aria-hidden=\"true\"></i>\n </button>\n <button type=\"button\" class=\"wfr-head-cell wfr-col-status\" (click)=\"OnSort('Status')\">\n Status <i [ngClass]=\"SortIcon('Status')\" aria-hidden=\"true\"></i>\n </button>\n </div>\n\n @for (run of VisibleRuns; track run.ID) {\n <button\n type=\"button\"\n class=\"wfr-row\"\n [class.wfr-row-selected]=\"run.ID === SelectedRunID\"\n (click)=\"OnSelectRun(run)\">\n <span class=\"wfr-col-name wfr-row-name\">{{ run.Name }}</span>\n <!-- An em dash, never a fabricated time: a run that has not started has no start, and\n printing one would read as data. -->\n <span class=\"wfr-col-time\">{{ run.StartedAt ? (run.StartedAt | date:'MMM d, h:mm:ss a') : '\u2014' }}</span>\n <span class=\"wfr-col-time\">{{ run.CompletedAt ? (run.CompletedAt | date:'MMM d, h:mm:ss a') : '\u2014' }}</span>\n <span class=\"wfr-col-duration\">{{ run.Duration }}</span>\n <span class=\"wfr-col-status wfr-row-status\" [attr.data-status]=\"run.Status\">{{ run.Status }}</span>\n </button>\n }\n </div>\n </as-split-area>\n\n <as-split-area [size]=\"SelectedRun ? Layout.SplitSizes[1] : 0\" [minSize]=\"25\" [visible]=\"!!SelectedRun\">\n @if (SelectedRun; as selected) {\n <!-- The canvas lives in the RIGHT PANEL on selection, not nested inside the list row.\n A graph needs room to be read; inlining one per row turns a scannable list into a\n stack of diagrams. -->\n <aside class=\"wfr-detail\">\n <header class=\"wfr-detail-head\">\n <div class=\"wfr-detail-title\">\n <span class=\"wfr-detail-name\">{{ selected.Name }}</span>\n <span class=\"wfr-row-status\" [attr.data-status]=\"selected.Status\">{{ selected.Status }}</span>\n </div>\n <div class=\"wfr-detail-actions\">\n @if (selected.AgentRunID) {\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"OnOpenAgentRun(selected)\">\n <i class=\"fa-solid fa-arrow-up-right-from-square\" aria-hidden=\"true\"></i>\n Agent run\n </button>\n }\n @if (DetailTab === 'graph') {\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"ToggleStepPanel()\"\n [title]=\"Layout.StepPanelOpen ? 'Hide step details' : 'Show step details'\">\n <i class=\"fa-solid\" [class.fa-square-caret-right]=\"Layout.StepPanelOpen\"\n [class.fa-square-caret-left]=\"!Layout.StepPanelOpen\" aria-hidden=\"true\"></i>\n </button>\n }\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"OnSelectRun(selected)\" aria-label=\"Close\">\n <i class=\"fa-solid fa-xmark\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </header>\n\n <div class=\"wfr-detail-tabs\" role=\"tablist\">\n <button type=\"button\" class=\"wfr-tab\" [class.wfr-tab-active]=\"DetailTab === 'graph'\"\n (click)=\"OnDetailTab('graph')\">\n <i class=\"fa-solid fa-diagram-project\" aria-hidden=\"true\"></i> Workflow\n </button>\n <button type=\"button\" class=\"wfr-tab\" [class.wfr-tab-active]=\"DetailTab === 'json'\"\n (click)=\"OnDetailTab('json')\">\n <i class=\"fa-solid fa-code\" aria-hidden=\"true\"></i> JSON\n </button>\n </div>\n\n @if (Stall) {\n <!-- The hardening review's signature failure \u2014 \"the run strands silently\" \u2014 made\n loud. A held path is now something the operator can answer, not just read. -->\n <div class=\"wfr-stall\" role=\"status\" [attr.data-kind]=\"Stall.kind\">\n <div class=\"wfr-stall-body\">\n <i class=\"fa-solid fa-triangle-exclamation\" aria-hidden=\"true\"></i>\n <div class=\"wfr-stall-copy\">\n <span>{{ Stall.message }}</span>\n @if (Stall.conditionText) {\n <code>{{ Stall.conditionText }}</code>\n }\n @if (Stall.reason) {\n <span class=\"wfr-stall-reason\">{{ Stall.reason }}</span>\n }\n </div>\n </div>\n @if (Stall.kind === 'held' && Stall.edgeID) {\n <div class=\"wfr-stall-actions\">\n <button mjButton variant=\"primary\" size=\"sm\" [disabled]=\"ControlBusy\"\n (click)=\"OnOverrideEdge(Stall.edgeID!, 'true')\">\n Answer true\n </button>\n <button mjButton variant=\"secondary\" size=\"sm\" [disabled]=\"ControlBusy\"\n (click)=\"OnOverrideEdge(Stall.edgeID!, 'false')\">\n Answer false\n </button>\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"OnDismissStall()\">\n Leave held\n </button>\n </div>\n }\n </div>\n }\n\n @if (DetailTab === 'graph') {\n <!-- Canvas BESIDE the step it opened, not above it. A JSON record in a strip along the\n bottom shows about ten lines, which is not enough of a record to read. -->\n <as-split class=\"wfr-graph-split\" [direction]=\"InnerSplitDirection\" unit=\"percent\"\n [gutterSize]=\"8\" (dragEnd)=\"OnStepSplitDragEnd($event.sizes)\">\n <as-split-area [size]=\"Layout.StepPanelOpen ? Layout.StepSplitSizes[0] : 100\" [minSize]=\"25\">\n <div class=\"wfr-graph-pane\">\n <mj-task-graph-debugger\n #GraphDebug\n [Provider]=\"ProviderToUse\"\n [ParentTaskID]=\"selected.ID\"\n [WorkflowName]=\"selected.Name\"\n [LiveUpdates]=\"selected.Status === 'Running' || selected.Status === 'In Progress'\"\n [ReplayAt]=\"ReplayAt\"\n [ShowLegend]=\"Layout.ShowLegend\"\n Height=\"100%\"\n (NodeSelected)=\"OnGraphNodeSelected($event)\"\n (ConnectionSelected)=\"OnGraphConnectionSelected($event)\"\n (LegendToggled)=\"OnLegendToggled($event)\"\n (Settled)=\"OnCanvasSettled()\"\n (Frame)=\"OnFrame($event)\"\n (PausedChange)=\"DebugPaused = $event\">\n </mj-task-graph-debugger>\n\n @if (CanReplay) {\n <!-- Replay: scrub through the settled run on the same canvas, reconstructed\n from each step's own timestamps. Read-only by construction. -->\n <div class=\"wfr-replay\">\n <i class=\"fa-solid fa-clock-rotate-left\" aria-hidden=\"true\"></i>\n <input type=\"range\" min=\"0\" max=\"100\" step=\"1\"\n [value]=\"ReplayPercent ?? 100\"\n (input)=\"OnReplayScrub($any($event.target).value)\"\n aria-label=\"Replay position\" />\n @if (ReplayPercent !== null) {\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"OnReplayReset()\">Now</button>\n }\n </div>\n }\n\n @if (GraphDebug.Breakpoints.length > 0 || GraphDebug.PausedAtTaskID) {\n <div class=\"wfr-bp-bar\" aria-label=\"Armed breakpoints\">\n @if (GraphDebug.PausedAtTaskID) {\n <span class=\"wfr-chip wfr-chip-paused\">\n <i class=\"fa-solid fa-pause\" aria-hidden=\"true\"></i>\n Paused at {{ StepName(GraphDebug.PausedAtTaskID) }}\n </span>\n }\n @for (id of GraphDebug.Breakpoints; track id) {\n <button type=\"button\" class=\"wfr-chip wfr-chip-break\" (click)=\"OnSelectBreakpoint(id)\">\n <i class=\"fa-solid fa-circle\" aria-hidden=\"true\"></i>\n {{ StepName(id) }}\n <span class=\"wfr-chip-x\" (click)=\"OnRemoveBreakpoint(id); $event.stopPropagation()\"\n role=\"button\" tabindex=\"0\" aria-label=\"Remove breakpoint\">\u00D7</span>\n </button>\n }\n </div>\n }\n\n @if (EngineTicks.length > 0) {\n <!-- The engine strip: one tick per dispatcher pass. A stuck run is a strip\n that keeps ticking with nothing moving \u2014 the honest visual of a stall. -->\n <div class=\"wfr-engine\" aria-label=\"Engine activity\">\n @for (tick of EngineTicks; track tick.passNumber) {\n <span class=\"wfr-tick\" [class.wfr-tick-held]=\"(tick.heldCount ?? 0) > 0\">\n #{{ tick.passNumber }} \u00B7 ready {{ tick.eligibleCount ?? 0 }}\n \u00B7 held {{ tick.heldCount ?? 0 }} \u00B7 took {{ tick.claimedCount ?? 0 }}\n </span>\n }\n @if (GraphDebug.Paused) {\n <span class=\"wfr-tick wfr-tick-paused\">\u23F8 paused \u2014 nothing new starts</span>\n }\n </div>\n }\n </div>\n </as-split-area>\n\n <as-split-area [size]=\"Layout.StepPanelOpen ? Layout.StepSplitSizes[1] : 0\" [minSize]=\"20\"\n [visible]=\"Layout.StepPanelOpen\">\n <div class=\"wfr-steps-pane\">\n @if (StepsLoading) {\n <mj-loading text=\"Loading steps...\"></mj-loading>\n } @else {\n <div class=\"wfr-step-list\">\n @for (step of SelectedSteps; track step.ID) {\n <button type=\"button\" class=\"wfr-step\"\n [class.wfr-step-selected]=\"step.ID === SelectedStepID\"\n [attr.data-status]=\"step.Status\"\n (click)=\"OnSelectStep(step)\">\n <span class=\"wfr-step-name\">{{ step.Name }}</span>\n <span class=\"wfr-step-meta\">{{ step.StepType || 'Step' }}</span>\n </button>\n }\n </div>\n\n @if (InspectorMode === 'edge' && SelectedEdge; as edge) {\n <div class=\"wfr-step-json\">\n <div class=\"wfr-step-json-head\">\n <span>{{ SelectedEdgeFromName }} \u2192 {{ SelectedEdgeToName }}</span>\n @if (SelectedEdgeOverride) {\n <span class=\"wfr-chip wfr-chip-forced\">forced {{ SelectedEdgeOverride }}</span>\n }\n </div>\n <div class=\"wfr-insp-card\">\n <span class=\"wfr-insp-label\">Condition</span>\n @if (edge.Condition?.trim()) {\n <code>{{ edge.Condition }}</code>\n } @else {\n <span>Unconditional \u2014 this path always runs.</span>\n }\n </div>\n @if (SelectedEdgeIsConditional) {\n <div class=\"wfr-insp-actions\">\n <button mjButton variant=\"primary\" size=\"sm\" [disabled]=\"ControlBusy\"\n (click)=\"OnOverrideEdge(edge.ID, 'true')\">Answer true</button>\n <button mjButton variant=\"secondary\" size=\"sm\" [disabled]=\"ControlBusy\"\n (click)=\"OnOverrideEdge(edge.ID, 'false')\">Answer false</button>\n @if (SelectedEdgeOverride) {\n <button mjButton variant=\"flat\" size=\"sm\" [disabled]=\"ControlBusy\"\n (click)=\"OnOverrideEdge(edge.ID, null)\">Clear override</button>\n }\n </div>\n } @else {\n <p class=\"wfr-insp-hint\">Skip the target step instead of overriding an unconditional path.</p>\n }\n </div>\n } @else if (SelectedStep; as step) {\n <div class=\"wfr-step-json\">\n <div class=\"wfr-step-json-head\">\n <span>{{ step.Name }}</span>\n <span class=\"wfr-row-status\" [attr.data-status]=\"step.Status\">{{ step.Status }}</span>\n </div>\n\n @if (SelectedStepFailureReason; as reason) {\n <div class=\"wfr-insp-card wfr-insp-failure\" role=\"status\">\n <span class=\"wfr-insp-label\">Why it failed</span>\n <span>{{ reason }}</span>\n </div>\n }\n\n <button type=\"button\" class=\"wfr-bp\"\n [class.wfr-bp-on]=\"HasBreakpoint(step.ID)\"\n [disabled]=\"ControlBusy\"\n (click)=\"OnBreakpointToggled({ TaskID: step.ID, Enabled: !HasBreakpoint(step.ID) })\"\n [attr.aria-pressed]=\"HasBreakpoint(step.ID)\"\n [title]=\"HasBreakpoint(step.ID) ? 'Remove breakpoint' : 'Break before this step'\">\n <i class=\"fa-circle\"\n [class.fa-solid]=\"HasBreakpoint(step.ID)\"\n [class.fa-regular]=\"!HasBreakpoint(step.ID)\"\n aria-hidden=\"true\"></i>\n </button>\n\n <!-- The inspector: live engine facts about this step, from the frame\n stream \u2014 claim, path verdicts, runner progress, what-if. -->\n @if (SelectedStepProgress; as progress) {\n <div class=\"wfr-insp-card\">\n <span class=\"wfr-insp-label\">Doing now</span>\n <span>{{ progress.progressMessage }}\n @if (progress.progressPercent != null) { ({{ progress.progressPercent }}%) }\n </span>\n </div>\n }\n @if (SelectedStepClaim; as claim) {\n <div class=\"wfr-insp-card\" [class.wfr-insp-bad]=\"claim.claimEvent === 'heartbeat-lost'\">\n <span class=\"wfr-insp-label\">Worker</span>\n <span>\n @switch (claim.claimEvent) {\n @case ('claimed') { {{ claim.claimedBy }} \u2014 working }\n @case ('heartbeat-lost') { {{ claim.claimedBy }} \u2014 lost, will be requeued }\n @case ('reclaimed') { requeued by the engine }\n }\n </span>\n </div>\n }\n @for (verdict of SelectedStepVerdicts; track verdict.edgeId) {\n <div class=\"wfr-insp-card\" [attr.data-verdict]=\"verdict.verdict\">\n <span class=\"wfr-insp-label\">\n @switch (verdict.verdict) {\n @case ('satisfied') { Path taken }\n @case ('notTaken') { Path not taken }\n @case ('held') { Path can't be answered }\n }\n </span>\n <span>\n @if (verdict.conditionText) { <code>{{ verdict.conditionText }}</code> }\n @if (verdict.reason) { \u2014 {{ verdict.reason }} }\n </span>\n </div>\n }\n @if (SelectedStepWhatIf; as whatIf) {\n <div class=\"wfr-insp-card\">\n <span class=\"wfr-insp-label\">If this step fails</span>\n <span>{{ whatIf.BlockedCount }} step{{ whatIf.BlockedCount === 1 ? '' : 's' }} can no longer run</span>\n </div>\n }\n @if (step.Status === 'Pending' || step.Status === 'Failed' || CanForceComplete(step)) {\n <div class=\"wfr-insp-actions\">\n @if (step.Status === 'Pending') {\n <button mjButton variant=\"secondary\" size=\"sm\" [disabled]=\"ControlBusy\"\n (click)=\"OnSkipStep(step)\"\n title=\"Declare this step not-taken; later steps proceed\">\n <i class=\"fa-solid fa-forward\" aria-hidden=\"true\"></i> Skip step\n </button>\n }\n @if (CanEditInput(step)) {\n <button mjButton variant=\"secondary\" size=\"sm\" [disabled]=\"ControlBusy\"\n (click)=\"OpenEditInput(step)\">\n <i class=\"fa-solid fa-pen-to-square\" aria-hidden=\"true\"></i>\n {{ step.Status === 'Failed' ? 'Edit input & retry' : 'Edit input' }}\n </button>\n }\n @if (step.Status === 'Failed') {\n <button mjButton variant=\"secondary\" size=\"sm\" [disabled]=\"ControlBusy\"\n (click)=\"OnRetryStep(step)\">\n <i class=\"fa-solid fa-rotate-right\" aria-hidden=\"true\"></i> Retry\n </button>\n }\n @if (CanForceComplete(step)) {\n <button mjButton variant=\"danger\" size=\"sm\" [disabled]=\"ControlBusy\"\n (click)=\"OpenForceComplete(step)\">\n <i class=\"fa-solid fa-flag-checkered\" aria-hidden=\"true\"></i> Force complete\n </button>\n }\n </div>\n }\n\n @if (EditInputOpen) {\n <div class=\"wfr-editor-card\">\n <span class=\"wfr-insp-label\">{{ step.Status === 'Failed' ? 'Edit input and retry' : 'Edit input' }}</span>\n <p class=\"wfr-insp-hint\">Applies to this run only. Invalid JSON is refused here.</p>\n <textarea class=\"mj-textarea wfr-json-edit\" [(ngModel)]=\"EditInputJson\"\n rows=\"8\" spellcheck=\"false\"></textarea>\n @if (EditInputError) {\n <span class=\"wfr-editor-error\">{{ EditInputError }}</span>\n }\n <div class=\"wfr-insp-actions\">\n <button mjButton variant=\"primary\" size=\"sm\" [disabled]=\"ControlBusy\"\n (click)=\"SubmitEditInput(step)\">\n {{ step.Status === 'Failed' ? 'Apply & retry' : 'Apply' }}\n </button>\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"EditInputOpen = false\">Cancel</button>\n </div>\n </div>\n }\n\n @if (ForceCompleteOpen) {\n <div class=\"wfr-editor-card wfr-editor-danger\">\n <span class=\"wfr-insp-label\">Force complete</span>\n <p class=\"wfr-insp-hint\">Downstream conditions will evaluate against this output as if the step had produced it. Type the step name to confirm.</p>\n <textarea class=\"mj-textarea wfr-json-edit\" [(ngModel)]=\"ForceCompleteJson\"\n rows=\"6\" spellcheck=\"false\"></textarea>\n <input class=\"mj-input\" type=\"text\" [(ngModel)]=\"ForceCompleteName\"\n [placeholder]=\"'Type \u201C' + step.Name + '\u201D to confirm'\" />\n @if (ForceCompleteError) {\n <span class=\"wfr-editor-error\">{{ ForceCompleteError }}</span>\n }\n <div class=\"wfr-insp-actions\">\n <button mjButton variant=\"danger\" size=\"sm\" [disabled]=\"ControlBusy\"\n (click)=\"SubmitForceComplete(step)\">Force complete</button>\n <button mjButton variant=\"flat\" size=\"sm\" (click)=\"ForceCompleteOpen = false\">Cancel</button>\n </div>\n </div>\n }\n\n <mj-task-graph-variables\n [InputPayload]=\"StepPayload(step, 'InputPayload')\"\n [OutputPayload]=\"StepPayload(step, 'OutputPayload')\"\n [Invocation]=\"Invocation\">\n </mj-task-graph-variables>\n </div>\n } @else {\n <mj-empty-state\n Size=\"compact\"\n Icon=\"fa-solid fa-hand-pointer\"\n Title=\"Select a step\"\n Message=\"Click a step on the canvas or in the list to see everything it recorded.\">\n </mj-empty-state>\n }\n }\n </div>\n </as-split-area>\n </as-split>\n } @else {\n <div class=\"wfr-json-pane\">\n <mj-code-editor\n [ngModel]=\"SelectedRunJson\"\n [language]=\"'json'\"\n [readonly]=\"true\"\n style=\"width: 100%;\">\n </mj-code-editor>\n </div>\n }\n </aside>\n }\n </as-split-area>\n </as-split>\n }\n </mj-page-body>\n</mj-page-layout>\n", styles: [":host {\n display: block;\n height: 100%;\n}\n\n.wfr-status-filters {\n display: flex;\n gap: var(--mj-space-1);\n align-items: center;\n}\n\n/* List alone until something is selected; two resizable panes after. The size is the user's \u2014 see\n the LAYOUT_KEYS note on the component for why it is persisted server-side rather than locally. */\n.wfr-split {\n height: 100%;\n min-height: 0;\n}\n\n/* A gutter you can find. The default is a hairline, which is discoverable only by accident. */\n:host ::ng-deep .wfr-split > .as-split-gutter,\n:host ::ng-deep .wfr-graph-split > .as-split-gutter {\n background: transparent !important;\n position: relative;\n}\n\n:host ::ng-deep .wfr-split > .as-split-gutter::after,\n:host ::ng-deep .wfr-graph-split > .as-split-gutter::after {\n content: '';\n position: absolute;\n inset: 0;\n margin: auto;\n background: var(--mj-border-default);\n border-radius: var(--mj-radius-full);\n}\n\n:host ::ng-deep .wfr-split.as-horizontal > .as-split-gutter::after,\n:host ::ng-deep .wfr-graph-split.as-horizontal > .as-split-gutter::after {\n width: 2px;\n}\n\n:host ::ng-deep .wfr-graph-split.as-vertical > .as-split-gutter::after {\n height: 2px;\n}\n\n:host ::ng-deep .wfr-split > .as-split-gutter:hover::after,\n:host ::ng-deep .wfr-graph-split > .as-split-gutter:hover::after {\n background: var(--mj-brand-primary);\n}\n\n/* The canvas and the step record sit SIDE BY SIDE \u2014 a JSON record in a strip along the bottom shows\n about ten lines. Stacks below the breakpoint, where three columns would leave each too narrow to\n use. */\n.wfr-graph-split {\n flex: 1 1 auto;\n min-height: 0;\n}\n\n.wfr-list {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-1);\n overflow-y: auto;\n min-height: 0;\n}\n\n.wfr-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--mj-space-2);\n width: 100%;\n padding: var(--mj-space-2) var(--mj-space-3);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n text-align: left;\n cursor: pointer;\n color: var(--mj-text-primary);\n}\n\n.wfr-row:hover {\n border-color: var(--mj-border-strong);\n}\n\n.wfr-row:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n.wfr-row-selected {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n}\n\n.wfr-row-main {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.wfr-row-name {\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.wfr-row-when {\n font-size: var(--mj-font-size-sm);\n color: var(--mj-text-secondary);\n font-variant-numeric: tabular-nums;\n}\n\n.wfr-row-status {\n flex: none;\n font-size: var(--mj-font-size-xs);\n text-transform: uppercase;\n letter-spacing: 0.04em;\n padding: 2px var(--mj-space-2);\n border-radius: var(--mj-radius-full);\n background: var(--mj-bg-page);\n color: var(--mj-text-secondary);\n border: 1px solid var(--mj-border-default);\n}\n\n/* Status carries meaning, so it is encoded in colour as well as text \u2014 a failed run should be\n findable without reading every row. Skipped stays grey on purpose: a branch that was not taken\n is a normal outcome, not a warning. */\n.wfr-row-status[data-status='Complete'] {\n color: var(--mj-status-success);\n border-color: color-mix(in srgb, var(--mj-status-success) 40%, transparent);\n}\n\n.wfr-row-status[data-status='Failed'] {\n color: var(--mj-status-error);\n border-color: color-mix(in srgb, var(--mj-status-error) 40%, transparent);\n}\n\n.wfr-row-status[data-status='Running'] {\n color: var(--mj-brand-primary);\n border-color: color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n}\n\n.wfr-detail {\n display: flex;\n flex-direction: column;\n /* Fills its split area. Without it the column sizes to its CONTENT, so the canvas below \u2014\n `flex: 1 1 auto` of an auto-height parent \u2014 got its intrinsic height and left dead space. */\n height: 100%;\n min-height: 0;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n overflow: hidden;\n}\n\n.wfr-detail-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--mj-space-2);\n padding: var(--mj-space-2) var(--mj-space-3);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.wfr-detail-title {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n min-width: 0;\n}\n\n.wfr-detail-name {\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.wfr-detail-actions {\n display: flex;\n align-items: center;\n gap: var(--mj-space-1);\n flex: none;\n}\n\n/* ============================================================\n The run list as a sortable table\n ============================================================\n A run list is scanned for two things \u2014 the slowest run and the one that failed \u2014 and neither is\n answerable by scrolling. Columns line up so a reader compares down a column rather than reading\n each row; `tabular-nums` keeps the timestamps from jittering as digits change. */\n.wfr-head,\n.wfr-row {\n display: grid;\n grid-template-columns: minmax(0, 2fr) minmax(0, 1.3fr) minmax(0, 1.3fr) minmax(0, 0.7fr) minmax(0, 0.9fr);\n gap: var(--mj-space-2);\n align-items: center;\n}\n\n.wfr-head {\n position: sticky;\n top: 0;\n z-index: 1;\n padding: 0 var(--mj-space-3) var(--mj-space-1);\n background: var(--mj-bg-page);\n}\n\n.wfr-head-cell {\n display: flex;\n align-items: center;\n gap: 6px;\n background: none;\n border: none;\n padding: var(--mj-space-1) 0;\n font-size: var(--mj-font-size-xs);\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--mj-text-secondary);\n cursor: pointer;\n text-align: left;\n}\n\n.wfr-head-cell:hover {\n color: var(--mj-text-primary);\n}\n\n.wfr-head-cell i {\n opacity: 0.65;\n font-size: 0.85em;\n}\n\n.wfr-col-time,\n.wfr-col-duration {\n font-size: var(--mj-font-size-sm);\n color: var(--mj-text-secondary);\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.wfr-col-status {\n justify-self: start;\n}\n\n/* ============================================================\n Detail panel: canvas + step JSON, or the whole run as JSON\n ============================================================ */\n.wfr-detail-tabs {\n display: flex;\n gap: var(--mj-space-1);\n padding: 0 var(--mj-space-3);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.wfr-tab {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n background: none;\n border: none;\n border-bottom: 2px solid transparent;\n padding: var(--mj-space-2) var(--mj-space-2);\n font-size: var(--mj-font-size-sm);\n font-weight: 600;\n color: var(--mj-text-secondary);\n cursor: pointer;\n}\n\n.wfr-tab-active {\n color: var(--mj-brand-primary);\n border-bottom-color: var(--mj-brand-primary);\n}\n\n.wfr-graph-pane {\n height: 100%;\n min-height: 12rem;\n}\n\n.wfr-steps-pane {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n border-left: 1px solid var(--mj-border-default);\n overflow: hidden;\n}\n\n/* Stacked layout puts the divider back on top, where the eye expects it. */\n:host ::ng-deep .as-vertical .wfr-steps-pane {\n border-left: none;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.wfr-step-list {\n display: flex;\n flex-wrap: wrap;\n gap: var(--mj-space-1);\n padding: var(--mj-space-2);\n border-bottom: 1px solid var(--mj-border-default);\n max-height: 8rem;\n overflow-y: auto;\n flex: none;\n}\n\n.wfr-step {\n display: inline-flex;\n align-items: center;\n gap: var(--mj-space-2);\n padding: var(--mj-space-1) var(--mj-space-2);\n background: var(--mj-bg-page);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n color: var(--mj-text-primary);\n font-size: var(--mj-font-size-sm);\n cursor: pointer;\n text-align: left;\n}\n\n.wfr-step:hover {\n border-color: var(--mj-border-strong);\n}\n\n.wfr-step-selected {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n}\n\n/* Work that never ran must not read like work that did \u2014 the same rule the run timeline follows. */\n.wfr-step[data-status='Skipped'] .wfr-step-name {\n text-decoration: line-through;\n color: var(--mj-text-secondary);\n}\n\n.wfr-step-name {\n font-weight: 600;\n}\n\n.wfr-step-meta {\n font-size: var(--mj-font-size-xs);\n color: var(--mj-text-secondary);\n}\n\n.wfr-step-json,\n.wfr-json-pane {\n flex: 1 1 auto;\n min-height: 0;\n display: flex;\n flex-direction: column;\n overflow: auto;\n}\n\n.wfr-step-json-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--mj-space-2);\n padding: var(--mj-space-1) var(--mj-space-3);\n font-weight: 600;\n font-size: var(--mj-font-size-sm);\n color: var(--mj-text-secondary);\n flex: none;\n}\n\n/* \u2500\u2500 live console \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.wfr-stall {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 8px 12px;\n margin: 0 12px 8px;\n border: 1px solid color-mix(in srgb, var(--mj-status-warning) 45%, var(--mj-border-default));\n border-left: 4px solid var(--mj-status-warning);\n border-radius: var(--mj-radius-md);\n background: color-mix(in srgb, var(--mj-status-warning) 8%, var(--mj-bg-surface));\n color: var(--mj-text-primary);\n font-size: var(--mj-font-size-sm);\n}\n.wfr-stall-body {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n}\n.wfr-stall i { color: var(--mj-status-warning); }\n.wfr-stall-copy {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n.wfr-stall-copy code {\n font-family: var(--mj-font-mono, ui-monospace, monospace);\n font-size: var(--mj-font-size-xs);\n}\n.wfr-stall-reason { color: var(--mj-text-secondary); }\n.wfr-stall-actions { display: flex; flex-wrap: wrap; gap: 6px; }\n\n.wfr-replay {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 6px 12px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-page);\n}\n.wfr-replay i { color: var(--mj-text-secondary); }\n.wfr-replay input[type='range'] { flex: 1; accent-color: var(--mj-brand-primary); }\n\n.wfr-engine {\n display: flex;\n gap: 8px;\n overflow-x: auto;\n padding: 6px 12px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-page);\n font-family: var(--mj-font-mono, ui-monospace, monospace);\n font-size: var(--mj-font-size-xs);\n color: var(--mj-text-secondary);\n font-variant-numeric: tabular-nums;\n}\n.wfr-tick {\n flex: none;\n padding: 3px 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface);\n white-space: nowrap;\n}\n.wfr-tick-held {\n border-color: color-mix(in srgb, var(--mj-status-warning, #d97706) 45%, var(--mj-border-default));\n background: color-mix(in srgb, var(--mj-status-warning, #d97706) 8%, var(--mj-bg-surface));\n}\n.wfr-tick-paused { color: var(--mj-brand-primary); border-color: var(--mj-border-strong); }\n\n.wfr-insp-card {\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding: 7px 10px;\n margin: 0 0 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface);\n font-size: var(--mj-font-size-sm);\n color: var(--mj-text-primary);\n}\n.wfr-insp-card code {\n font-family: var(--mj-font-mono, ui-monospace, monospace);\n font-size: var(--mj-font-size-xs);\n}\n.wfr-insp-label {\n font-size: var(--mj-font-size-xs);\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--mj-text-secondary);\n}\n.wfr-insp-card[data-verdict='held'],\n.wfr-insp-bad {\n border-color: color-mix(in srgb, var(--mj-status-warning, #d97706) 45%, var(--mj-border-default));\n background: color-mix(in srgb, var(--mj-status-warning, #d97706) 8%, var(--mj-bg-surface));\n}\n.wfr-insp-card[data-verdict='satisfied'] .wfr-insp-label { color: var(--mj-status-success); }\n.wfr-insp-actions { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 8px; }\n.wfr-insp-hint {\n margin: 0 0 8px;\n font-size: var(--mj-font-size-xs);\n color: var(--mj-text-muted);\n}\n\n.wfr-bp-bar {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n padding: 6px 12px;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-page);\n}\n.wfr-chip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 2px 8px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-full);\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: var(--mj-font-size-xs);\n cursor: pointer;\n}\n.wfr-chip-break { color: var(--mj-status-error); border-color: color-mix(in srgb, var(--mj-status-error) 40%, transparent); }\n.wfr-chip-break i { font-size: 7px; }\n.wfr-chip-paused {\n color: var(--mj-brand-primary);\n border-color: color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n cursor: default;\n}\n.wfr-chip-forced {\n color: var(--mj-status-warning);\n border-color: color-mix(in srgb, var(--mj-status-warning) 40%, transparent);\n cursor: default;\n}\n.wfr-chip-x {\n font-size: 14px;\n line-height: 1;\n padding: 0 2px;\n}\n.wfr-chip-x:hover { color: var(--mj-text-primary); }\n\n.wfr-bp {\n width: 22px;\n height: 22px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n margin: 0 0 8px;\n padding: 0;\n border: none;\n border-radius: 50%;\n background: transparent;\n color: var(--mj-text-muted);\n cursor: pointer;\n}\n.wfr-bp:hover { color: var(--mj-status-error); }\n.wfr-bp-on,\n.wfr-bp-on:hover { color: var(--mj-status-error); }\n.wfr-bp i { font-size: 10px; }\n.wfr-bp:disabled { opacity: 0.45; cursor: default; }\n\n.wfr-editor-card {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 10px;\n margin: 0 0 10px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface-card);\n}\n.wfr-editor-danger {\n border-color: color-mix(in srgb, var(--mj-status-error) 40%, var(--mj-border-default));\n}\n.wfr-json-edit {\n width: 100%;\n min-height: 120px;\n font-family: var(--mj-font-mono, ui-monospace, monospace);\n font-size: var(--mj-font-size-xs);\n resize: vertical;\n}\n.wfr-editor-error { color: var(--mj-status-error); font-size: var(--mj-font-size-xs); }\n.wfr-insp-failure { border-color: var(--mj-status-error); color: var(--mj-status-error); }\n"] }]
1814
1835
  }], () => [{ type: i0.ChangeDetectorRef }], { onViewportResized: [{
1815
1836
  type: HostListener,
1816
1837
  args: ['window:resize']
@@ -1818,5 +1839,5 @@ export { WorkflowRunsResourceComponent };
1818
1839
  type: ViewChild,
1819
1840
  args: [TaskGraphDebuggerComponent]
1820
1841
  }] }); })();
1821
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(WorkflowRunsResourceComponent, { className: "WorkflowRunsResourceComponent", filePath: "src/Workflows/components/workflow-runs-resource.component.ts", lineNumber: 101 }); })();
1842
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(WorkflowRunsResourceComponent, { className: "WorkflowRunsResourceComponent", filePath: "src/Workflows/components/workflow-runs-resource.component.ts", lineNumber: 104 }); })();
1822
1843
  //# sourceMappingURL=workflow-runs-resource.component.js.map