@pennyfarthing/cyclist 9.3.0 → 10.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/dist/api/hook-request.d.ts +11 -0
  2. package/dist/api/hook-request.d.ts.map +1 -1
  3. package/dist/api/hook-request.js +126 -28
  4. package/dist/api/hook-request.js.map +1 -1
  5. package/dist/api/hotspots.d.ts +3 -0
  6. package/dist/api/hotspots.d.ts.map +1 -0
  7. package/dist/api/hotspots.js +54 -0
  8. package/dist/api/hotspots.js.map +1 -0
  9. package/dist/api/index.d.ts +2 -0
  10. package/dist/api/index.d.ts.map +1 -1
  11. package/dist/api/index.js +3 -0
  12. package/dist/api/index.js.map +1 -1
  13. package/dist/api/permissions.d.ts +16 -0
  14. package/dist/api/permissions.d.ts.map +1 -0
  15. package/dist/api/permissions.js +67 -0
  16. package/dist/api/permissions.js.map +1 -0
  17. package/dist/api/settings.d.ts +1 -1
  18. package/dist/api/settings.d.ts.map +1 -1
  19. package/dist/api/settings.js +44 -17
  20. package/dist/api/settings.js.map +1 -1
  21. package/dist/api/theme-agents.d.ts +4 -0
  22. package/dist/api/theme-agents.d.ts.map +1 -1
  23. package/dist/api/theme-agents.js +3 -0
  24. package/dist/api/theme-agents.js.map +1 -1
  25. package/dist/approval-gate.d.ts +3 -75
  26. package/dist/approval-gate.d.ts.map +1 -1
  27. package/dist/approval-gate.js +4 -121
  28. package/dist/approval-gate.js.map +1 -1
  29. package/dist/hooks/cyclist-pretooluse-hook.d.ts +60 -0
  30. package/dist/hooks/cyclist-pretooluse-hook.d.ts.map +1 -0
  31. package/dist/hooks/cyclist-pretooluse-hook.js +57 -0
  32. package/dist/hooks/cyclist-pretooluse-hook.js.map +1 -0
  33. package/dist/hooks/pretooluse-hook.d.ts +89 -0
  34. package/dist/hooks/pretooluse-hook.d.ts.map +1 -0
  35. package/dist/hooks/pretooluse-hook.js +235 -0
  36. package/dist/hooks/pretooluse-hook.js.map +1 -0
  37. package/dist/main.d.ts +1 -134
  38. package/dist/main.d.ts.map +1 -1
  39. package/dist/main.js +42 -373
  40. package/dist/main.js.map +1 -1
  41. package/dist/menu-builder.d.ts +7 -1
  42. package/dist/menu-builder.d.ts.map +1 -1
  43. package/dist/menu-builder.js +36 -1
  44. package/dist/menu-builder.js.map +1 -1
  45. package/dist/otlp-receiver.d.ts.map +1 -1
  46. package/dist/otlp-receiver.js +6 -0
  47. package/dist/otlp-receiver.js.map +1 -1
  48. package/dist/public/css/react.css +1 -1
  49. package/dist/public/js/react/react.js +42 -42
  50. package/dist/server.d.ts.map +1 -1
  51. package/dist/server.js +16 -3
  52. package/dist/server.js.map +1 -1
  53. package/dist/settings-store.d.ts +3 -1
  54. package/dist/settings-store.d.ts.map +1 -1
  55. package/dist/settings-store.js +18 -9
  56. package/dist/settings-store.js.map +1 -1
  57. package/dist/story-parser.d.ts +17 -0
  58. package/dist/story-parser.d.ts.map +1 -1
  59. package/dist/story-parser.js +183 -13
  60. package/dist/story-parser.js.map +1 -1
  61. package/dist/websocket.d.ts +1 -0
  62. package/dist/websocket.d.ts.map +1 -1
  63. package/dist/websocket.js +48 -5
  64. package/dist/websocket.js.map +1 -1
  65. package/dist/workflow-presets.d.ts +72 -0
  66. package/dist/workflow-presets.d.ts.map +1 -0
  67. package/dist/workflow-presets.js +93 -0
  68. package/dist/workflow-presets.js.map +1 -0
  69. package/package.json +2 -2
  70. package/src/public/App.tsx +61 -1
  71. package/src/public/components/ApprovalModal/index.tsx +31 -1
  72. package/src/public/components/ControlBar.tsx +19 -20
  73. package/src/public/components/DockviewWorkspace.tsx +39 -5
  74. package/src/public/components/FontPicker/index.tsx +118 -33
  75. package/src/public/components/FullFileTree.tsx +223 -0
  76. package/src/public/components/Message.tsx +89 -11
  77. package/src/public/components/MessageView.tsx +206 -93
  78. package/src/public/components/PersonaHeader.tsx +47 -15
  79. package/src/public/components/SubagentSpan.tsx +15 -8
  80. package/src/public/components/panels/BackgroundPanel.tsx +1 -1
  81. package/src/public/components/panels/ChangedPanel.tsx +30 -44
  82. package/src/public/components/panels/HotspotsPanel.tsx +365 -0
  83. package/src/public/components/panels/MessagePanel.tsx +79 -5
  84. package/src/public/components/panels/SettingsPanel.tsx +3 -28
  85. package/src/public/components/panels/WorkflowPanel.tsx +108 -13
  86. package/src/public/components/panels/index.ts +1 -0
  87. package/src/public/contexts/ClaudeContext.tsx +16 -1
  88. package/src/public/css/theme-system.css +46 -38
  89. package/src/public/hooks/useColorScheme.ts +27 -0
  90. package/src/public/hooks/useFileBrowser.ts +71 -0
  91. package/src/public/hooks/useHotspots.ts +113 -0
  92. package/src/public/hooks/usePlanModeExit.ts +105 -0
  93. package/src/public/hooks/useStory.ts +12 -3
  94. package/src/public/images/cyclist-dark.png +0 -0
  95. package/src/public/images/cyclist-light.png +0 -0
  96. package/src/public/styles/dockview-theme.css +31 -33
  97. package/src/public/styles/tailwind.css +417 -58
  98. package/src/public/types/message.ts +6 -1
  99. package/src/public/utils/markdown.ts +2 -2
  100. package/src/public/utils/slash-commands.ts +1 -1
  101. package/src/public/utils/toolStackGrouper.ts +5 -6
@@ -265,6 +265,7 @@
265
265
  background: var(--bg-secondary, #252526);
266
266
  border-bottom: 1px solid var(--border-color, #3c3c3c);
267
267
  flex-shrink: 0;
268
+ position: relative;
268
269
  }
269
270
 
270
271
  .persona-header.empty {
@@ -293,8 +294,8 @@
293
294
  }
294
295
 
295
296
  .persona-portrait {
296
- width: 40px;
297
- height: 40px;
297
+ width: 100px;
298
+ height: 100px;
298
299
  border-radius: 50%;
299
300
  overflow: hidden;
300
301
  flex-shrink: 0;
@@ -302,6 +303,7 @@
302
303
  display: flex;
303
304
  align-items: center;
304
305
  justify-content: center;
306
+ transition: width 0.2s ease, height 0.2s ease;
305
307
  }
306
308
 
307
309
  .persona-portrait .portrait-image {
@@ -314,12 +316,8 @@
314
316
  font-size: 1.5rem;
315
317
  }
316
318
 
317
- /* Role badge positioned at bottom of portrait */
318
- .persona-portrait-group .persona-role.badge {
319
- position: absolute;
320
- bottom: -4px;
321
- left: 50%;
322
- transform: translateX(-50%);
319
+ /* Role badge inline in name row */
320
+ .persona-name-row .persona-role.badge {
323
321
  padding: 1px 6px;
324
322
  color: #fff;
325
323
  font-size: 0.6rem;
@@ -328,6 +326,7 @@
328
326
  font-weight: 600;
329
327
  white-space: nowrap;
330
328
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
329
+ flex-shrink: 0;
331
330
  }
332
331
 
333
332
  .persona-info {
@@ -338,9 +337,59 @@
338
337
  flex: 1;
339
338
  }
340
339
 
340
+ .persona-branding {
341
+ height: 80px;
342
+ width: auto;
343
+ flex-shrink: 0;
344
+ opacity: 0.5;
345
+ pointer-events: none;
346
+ transition: height 0.2s ease;
347
+ }
348
+
349
+ /* Compact mode: collapsed header */
350
+ .persona-header.compact .persona-portrait {
351
+ width: 40px;
352
+ height: 40px;
353
+ }
354
+
355
+ .persona-header.compact .persona-portrait .portrait-fallback {
356
+ font-size: 1.2rem;
357
+ }
358
+
359
+ .persona-header.compact .persona-branding {
360
+ height: 32px;
361
+ }
362
+
363
+ .persona-header.compact .persona-catchphrase {
364
+ display: none;
365
+ }
366
+
367
+ /* Collapse toggle button */
368
+ .persona-collapse-toggle {
369
+ position: absolute;
370
+ bottom: 2px;
371
+ right: 8px;
372
+ background: none;
373
+ border: none;
374
+ color: var(--text-secondary, #8b8b8b);
375
+ font-size: 0.6rem;
376
+ cursor: pointer;
377
+ padding: 0 4px;
378
+ opacity: 0;
379
+ transition: opacity 0.15s;
380
+ }
381
+
382
+ .persona-header:hover .persona-collapse-toggle {
383
+ opacity: 1;
384
+ }
385
+
386
+ .persona-collapse-toggle:hover {
387
+ color: var(--text-primary, #d4d4d4);
388
+ }
389
+
341
390
  .persona-name-row {
342
391
  display: flex;
343
- align-items: baseline;
392
+ align-items: center;
344
393
  gap: 8px;
345
394
  flex-wrap: wrap;
346
395
  }
@@ -403,16 +452,15 @@
403
452
  overflow-x: hidden;
404
453
  display: flex;
405
454
  flex-direction: column;
406
- gap: 0.75rem;
407
- padding: 1rem;
455
+ gap: 0;
456
+ padding: 1rem 1.5rem;
408
457
  }
409
458
 
410
- /* Individual message bubbles */
459
+ /* Individual messages — Tufte: no bubbles, no backgrounds */
411
460
  .message {
412
461
  display: flex;
413
462
  gap: 0.75rem;
414
- padding: 0.75rem 1rem;
415
- border-radius: 8px;
463
+ padding: 0.25rem 0;
416
464
  line-height: 1.5;
417
465
  }
418
466
 
@@ -464,17 +512,70 @@
464
512
  border-radius: 3px;
465
513
  }
466
514
 
515
+ .message-content .table-wrapper {
516
+ margin: 0.5rem 0;
517
+ overflow-x: auto;
518
+ border-radius: 4px;
519
+ border: 1px solid var(--border-primary, #333);
520
+ }
521
+
522
+ .message-content table {
523
+ border-collapse: collapse;
524
+ width: 100%;
525
+ font-size: 0.85em;
526
+ }
527
+
528
+ .message-content thead th {
529
+ font-size: 0.75rem;
530
+ font-weight: 600;
531
+ text-transform: uppercase;
532
+ letter-spacing: 0.03em;
533
+ color: var(--text-secondary, #8b8b8b);
534
+ padding: 0.4rem 0.75rem;
535
+ text-align: left;
536
+ background: var(--bg-primary, #1e1e1e);
537
+ border-bottom: 1px solid var(--border-primary, #333);
538
+ white-space: nowrap;
539
+ }
540
+
541
+ .message-content tbody td {
542
+ padding: 0.35rem 0.75rem;
543
+ color: var(--text-primary, #d4d4d4);
544
+ border-bottom: 1px solid var(--border-primary, #333);
545
+ }
546
+
547
+ .message-content tbody tr:last-child td {
548
+ border-bottom: none;
549
+ }
550
+
551
+ .message-content tbody tr:hover {
552
+ background: var(--bg-secondary, #252526);
553
+ }
554
+
555
+ .message-content th.sortable-th {
556
+ cursor: pointer;
557
+ user-select: none;
558
+ }
559
+
560
+ .message-content th.sortable-th:hover {
561
+ color: var(--text-primary, #d4d4d4);
562
+ }
563
+
564
+ .message-content .sort-indicator {
565
+ font-size: 0.65em;
566
+ opacity: 0.7;
567
+ }
568
+
569
+ /* User messages — blockquote left border */
467
570
  .message-user {
468
- background: var(--accent-color, #007acc);
469
- color: #fff;
470
- margin-left: auto;
471
- max-width: 85%;
472
- border-bottom-right-radius: 4px;
571
+ border-left: 2px solid var(--text-secondary, #8b8b8b);
572
+ padding-left: 0.75rem;
573
+ color: var(--text-primary, #d4d4d4);
473
574
  }
474
575
 
475
576
  .message-user .message-content pre,
476
577
  .message-user .message-content :not(pre) > code {
477
- background: rgba(0, 0, 0, 0.2);
578
+ background: var(--bg-tertiary, #2d2d2d);
478
579
  }
479
580
 
480
581
  .message-attachment-indicator {
@@ -489,20 +590,108 @@
489
590
  opacity: 0.8;
490
591
  }
491
592
 
593
+ /* Agent messages — no background, no constraints */
492
594
  .message-agent {
493
- background: var(--bg-tertiary, #2d2d2d);
494
595
  color: var(--text-primary, #d4d4d4);
495
- max-width: 95%;
496
- border-bottom-left-radius: 4px;
596
+ }
597
+
598
+ /* Turn-based grouping — Tufte spacing */
599
+ .turn-group {
600
+ padding-top: 1rem;
601
+ }
602
+
603
+ .turn-group:first-child {
604
+ padding-top: 0;
605
+ }
606
+
607
+ .turn-group + .turn-group {
608
+ border-top: 1px solid var(--border-color, #3c3c3c);
609
+ }
610
+
611
+ /* Turn label — speaker + timestamp + optional role badge */
612
+ .turn-label {
613
+ display: flex;
614
+ align-items: center;
615
+ flex-wrap: wrap;
616
+ gap: 0.5rem;
617
+ padding: 0.25rem 0;
618
+ margin-bottom: 0.25rem;
619
+ }
620
+
621
+ .turn-speaker {
622
+ font-size: 0.75rem;
623
+ font-weight: 600;
624
+ color: var(--text-secondary, #8b8b8b);
625
+ text-transform: uppercase;
626
+ letter-spacing: 0.05em;
627
+ }
628
+
629
+ .turn-timestamp {
630
+ font-size: 0.6875rem;
631
+ color: var(--text-muted, #666);
632
+ margin-left: auto;
633
+ }
634
+
635
+ /* Role badge in turn label — flush right under timestamp */
636
+ .turn-role-badge {
637
+ font-size: 0.5625rem;
638
+ padding: 0px 5px;
639
+ color: #fff;
640
+ border-radius: 3px;
641
+ font-weight: 700;
642
+ letter-spacing: 0.05em;
643
+ line-height: 1.4;
644
+ }
645
+
646
+ /* Context cleared divider bar */
647
+ .context-cleared-bar {
648
+ display: flex;
649
+ align-items: center;
650
+ gap: 0.75rem;
651
+ padding: 0.5rem 0;
652
+ }
653
+
654
+ .context-cleared-line {
655
+ flex: 1;
656
+ background-color: var(--text-muted, #666);
657
+ opacity: 0.4;
658
+ }
659
+
660
+ .context-cleared-label {
661
+ font-size: 0.6875rem;
662
+ font-weight: 600;
663
+ color: var(--text-muted, #666);
664
+ text-transform: uppercase;
665
+ letter-spacing: 0.08em;
666
+ white-space: nowrap;
667
+ }
668
+
669
+ .context-cleared-time {
670
+ font-size: 0.625rem;
671
+ color: var(--text-muted, #666);
672
+ opacity: 0.7;
673
+ white-space: nowrap;
674
+ }
675
+
676
+ /* User turn: left-aligned like agent turns */
677
+
678
+ /* Hide avatar on continuation messages (same speaker, not first in turn) */
679
+ .message.continuation .message-avatar {
680
+ visibility: hidden;
681
+ }
682
+
683
+ /* Same-turn messages: tight spacing */
684
+ .message.continuation {
685
+ padding-top: 0;
497
686
  }
498
687
 
499
688
  /* Hook/System message styling (AC3: Story 75-5) */
500
689
  .message-hook,
501
690
  .message-system {
502
- background: var(--bg-secondary, #252526);
503
- border: 1px dashed var(--border-color, #3c3c3c);
691
+ background: none;
692
+ border-left: 2px dashed var(--border-color, #3c3c3c);
693
+ padding-left: 0.75rem;
504
694
  color: var(--text-secondary, #8b8b8b);
505
- max-width: 100%;
506
695
  font-size: 0.85rem;
507
696
  }
508
697
 
@@ -519,12 +708,11 @@
519
708
 
520
709
  .message-tool_use,
521
710
  .message-tool_result {
522
- background: var(--bg-secondary, #252526);
523
- border: 1px solid var(--border-color, #3c3c3c);
711
+ background: none;
712
+ border: none;
524
713
  color: var(--text-secondary, #8b8b8b);
525
714
  font-family: var(--font-mono, 'SF Mono', Monaco, monospace);
526
715
  font-size: var(--font-size-code, 0.85rem);
527
- max-width: 100%;
528
716
  }
529
717
 
530
718
  .tool-name {
@@ -570,67 +758,99 @@
570
758
  }
571
759
 
572
760
  /* =============================================================================
573
- Subagent Span Styles
761
+ Subagent Span Styles — Tufte: indented left-border, no box
574
762
  ============================================================================= */
575
763
 
576
764
  .subagent-span {
577
765
  margin: 0.5rem 0;
578
- border: 1px solid var(--border-color, #3c3c3c);
579
- border-radius: 6px;
580
- background: var(--bg-secondary, #252526);
766
+ margin-left: 2.75rem; /* align with message content */
767
+ border: none;
768
+ border-left: 2px solid var(--accent-color, #007acc);
769
+ border-radius: 0;
770
+ background: none;
771
+ padding-left: 0.5rem;
581
772
  }
582
773
 
583
774
  .subagent-header {
584
775
  display: flex;
585
776
  align-items: center;
586
777
  gap: 0.5rem;
587
- padding: 0.5rem 0.75rem;
778
+ padding: 0.25rem 0;
588
779
  cursor: pointer;
589
- background: var(--bg-tertiary, #2d2d2d);
590
- border-radius: 5px 5px 0 0;
780
+ background: none;
781
+ border-radius: 0;
591
782
  font-size: 0.8rem;
783
+ transition: background-color 0.15s ease;
592
784
  }
593
785
 
594
- .subagent-span.collapsed .subagent-header {
595
- border-radius: 5px;
786
+ .subagent-header:hover {
787
+ background-color: var(--bg-secondary, #252526);
596
788
  }
597
789
 
598
790
  .subagent-toggle {
599
791
  color: var(--text-secondary, #8b8b8b);
600
- font-size: 0.7rem;
792
+ font-size: 0.625rem;
793
+ width: 0.875rem;
794
+ display: flex;
795
+ align-items: center;
796
+ justify-content: center;
601
797
  }
602
798
 
603
- .subagent-type {
604
- color: var(--accent-color, #007acc);
799
+ .subagent-helper-name {
605
800
  font-weight: 600;
606
- text-transform: capitalize;
801
+ color: var(--text-primary, #d4d4d4);
607
802
  }
608
803
 
609
- .subagent-name {
610
- color: var(--text-primary, #d4d4d4);
804
+ .subagent-friendly-message {
805
+ color: var(--text-secondary, #8b8b8b);
806
+ overflow: hidden;
807
+ text-overflow: ellipsis;
808
+ white-space: nowrap;
809
+ flex: 1;
810
+ min-width: 0;
811
+ }
812
+
813
+ .subagent-type-badge {
814
+ font-size: 0.625rem;
815
+ padding: 0 4px;
816
+ flex-shrink: 0;
611
817
  }
612
818
 
613
819
  .subagent-count {
614
- color: var(--text-secondary, #8b8b8b);
615
- font-size: 0.75rem;
820
+ color: var(--text-muted, #666);
821
+ font-size: 0.6875rem;
822
+ font-family: var(--font-mono, monospace);
616
823
  margin-left: auto;
824
+ flex-shrink: 0;
617
825
  }
618
826
 
619
827
  .subagent-content {
620
- padding: 0.5rem;
828
+ padding: 0.25rem 0;
621
829
  }
622
830
 
623
- /* Subagent prompt - the task/instruction given to subagent */
831
+ /* Subagent prompt truncated single line, no avatar */
624
832
  .message-subagent-prompt {
625
- background: var(--bg-tertiary, #2d2d2d);
626
- border-left: 3px solid var(--accent-color, #007acc);
627
- color: var(--text-secondary, #8b8b8b);
628
- font-size: 0.85rem;
629
- max-width: 100%;
833
+ background: none;
834
+ border-left: none;
835
+ color: var(--text-muted, #666);
836
+ font-size: 0.75rem;
837
+ padding: 0.125rem 0;
630
838
  }
631
839
 
632
840
  .message-subagent-prompt .message-content {
633
841
  font-style: italic;
842
+ overflow: hidden;
843
+ text-overflow: ellipsis;
844
+ white-space: nowrap;
845
+ }
846
+
847
+ /* Tool calls inside subagent: no extra indent (already indented by parent) */
848
+ .subagent-content .tool-call-block {
849
+ margin-left: 0;
850
+ }
851
+
852
+ .subagent-content .message {
853
+ padding: 0.125rem 0;
634
854
  }
635
855
 
636
856
  /* =============================================================================
@@ -1857,6 +2077,125 @@
1857
2077
  font-size: 0.65rem;
1858
2078
  }
1859
2079
 
2080
+ .workflow-content .phase-icon {
2081
+ flex-shrink: 0;
2082
+ width: 14px;
2083
+ text-align: center;
2084
+ }
2085
+
2086
+ .workflow-content .phase-label {
2087
+ white-space: nowrap;
2088
+ }
2089
+
2090
+ /* Stepped workflow progress (Step N of M) */
2091
+ .stepped-progress {
2092
+ display: flex;
2093
+ align-items: baseline;
2094
+ gap: 8px;
2095
+ font-size: 0.75rem;
2096
+ }
2097
+
2098
+ .stepped-counter {
2099
+ color: var(--accent-color, #007acc);
2100
+ font-weight: 600;
2101
+ }
2102
+
2103
+ .stepped-current-label {
2104
+ color: var(--text-secondary, #8b8b8b);
2105
+ font-style: italic;
2106
+ }
2107
+
2108
+ /* Available workflows list (MSSCI-14301) */
2109
+ .available-workflows {
2110
+ padding: 4px 0;
2111
+ }
2112
+
2113
+ .available-workflows-header {
2114
+ padding: 4px 8px;
2115
+ border-bottom: 1px solid var(--border-color, #3c3c3c);
2116
+ }
2117
+
2118
+ .available-workflows-title {
2119
+ font-size: 0.7rem;
2120
+ font-weight: 600;
2121
+ color: var(--text-secondary, #8b8b8b);
2122
+ text-transform: uppercase;
2123
+ letter-spacing: 0.05em;
2124
+ }
2125
+
2126
+ .available-workflows-list {
2127
+ overflow-y: auto;
2128
+ }
2129
+
2130
+ .workflow-entry {
2131
+ padding: 6px 8px;
2132
+ border-bottom: 1px solid var(--border-color, #3c3c3c);
2133
+ }
2134
+
2135
+ .workflow-entry:last-child {
2136
+ border-bottom: none;
2137
+ }
2138
+
2139
+ .workflow-entry-header {
2140
+ display: flex;
2141
+ align-items: center;
2142
+ justify-content: space-between;
2143
+ gap: 6px;
2144
+ }
2145
+
2146
+ .workflow-entry-name {
2147
+ font-size: 0.8rem;
2148
+ font-weight: 500;
2149
+ color: var(--text-primary, #d4d4d4);
2150
+ }
2151
+
2152
+ .workflow-entry-type-badge {
2153
+ font-size: 0.6rem;
2154
+ padding: 0 4px;
2155
+ flex-shrink: 0;
2156
+ }
2157
+
2158
+ .workflow-entry-description {
2159
+ font-size: 0.7rem;
2160
+ color: var(--text-secondary, #8b8b8b);
2161
+ margin-top: 2px;
2162
+ line-height: 1.3;
2163
+ }
2164
+
2165
+ .workflow-entry-hint {
2166
+ font-size: 0.65rem;
2167
+ color: var(--accent-color, #007acc);
2168
+ font-family: var(--font-mono, monospace);
2169
+ margin-top: 4px;
2170
+ opacity: 0.8;
2171
+ }
2172
+
2173
+ .workflow-entry-footer {
2174
+ display: flex;
2175
+ justify-content: flex-end;
2176
+ margin-top: 4px;
2177
+ }
2178
+
2179
+ .workflow-start-button {
2180
+ font-size: 0.65rem;
2181
+ height: 22px;
2182
+ padding: 0 8px;
2183
+ color: var(--accent-color, #007acc);
2184
+ }
2185
+
2186
+ /* Workflow panel container */
2187
+ .workflow-panel {
2188
+ height: 100%;
2189
+ overflow-y: auto;
2190
+ padding: 4px 8px;
2191
+ }
2192
+
2193
+ .workflow-panel .error-message {
2194
+ color: var(--color-danger, #ef4444);
2195
+ font-size: 0.75rem;
2196
+ padding: 8px 0;
2197
+ }
2198
+
1860
2199
  /* AC content within Progress panel */
1861
2200
  .ac-content {
1862
2201
  padding: 4px 0;
@@ -2577,6 +2916,29 @@
2577
2916
  font-style: italic;
2578
2917
  }
2579
2918
 
2919
+ /* Full file tree enhancements */
2920
+ .full-filetree .filetree-scroll {
2921
+ flex: 1;
2922
+ min-height: 0;
2923
+ }
2924
+
2925
+ .full-filetree .tree-loading {
2926
+ color: var(--text-secondary, #8b8b8b);
2927
+ font-size: 0.75rem;
2928
+ font-style: italic;
2929
+ padding: 4px 8px;
2930
+ }
2931
+
2932
+ .full-filetree .tree-error {
2933
+ color: var(--color-danger, #ef4444);
2934
+ font-size: 0.75rem;
2935
+ padding: 4px 8px;
2936
+ }
2937
+
2938
+ .full-filetree .directory-header.has-changes .directory-name {
2939
+ color: var(--color-warning, #f59e0b);
2940
+ }
2941
+
2580
2942
  /* Directory sections */
2581
2943
  .directory-section {
2582
2944
  border-bottom: 1px solid var(--border-color, #3c3c3c);
@@ -3027,11 +3389,8 @@
3027
3389
  ============================================================================= */
3028
3390
 
3029
3391
  .message-bell-injected {
3030
- background: linear-gradient(
3031
- 90deg,
3032
- rgba(255, 193, 7, 0.1) 0%,
3033
- transparent 20%
3034
- );
3392
+ border-left: 2px solid var(--warning-color, #cca700);
3393
+ padding-left: 0.75rem;
3035
3394
  }
3036
3395
 
3037
3396
  .message-bell-injected .bell-indicator {
@@ -14,7 +14,8 @@ export type MessageType =
14
14
  | 'agent'
15
15
  | 'tool_use'
16
16
  | 'tool_result'
17
- | 'bell_injected';
17
+ | 'bell_injected'
18
+ | 'context_cleared';
18
19
 
19
20
  /**
20
21
  * Core message data structure used throughout Cyclist.
@@ -36,6 +37,10 @@ export interface MessageData {
36
37
  durationMs?: number;
37
38
  /** Number of images attached to user message */
38
39
  imageCount?: number;
40
+ /** Agent identity captured at message creation time */
41
+ agentSlug?: string;
42
+ agentTheme?: string;
43
+ agentCharacter?: string;
39
44
  }
40
45
 
41
46
  /**
@@ -97,8 +97,8 @@ function convertTableLinesToHtml(lines: string[]): string {
97
97
  if (headerLine) {
98
98
  const headerCells = parseCells(headerLine);
99
99
  html += '<thead><tr>';
100
- for (const cell of headerCells) {
101
- html += `<th>${cell}</th>`;
100
+ for (let i = 0; i < headerCells.length; i++) {
101
+ html += `<th data-col="${i}" class="sortable-th">${headerCells[i]} <span class="sort-indicator"></span></th>`;
102
102
  }
103
103
  html += '</tr></thead>';
104
104
  }
@@ -186,7 +186,7 @@ export const SLASH_COMMANDS: SlashCommand[] = [
186
186
  },
187
187
  {
188
188
  "name": "/release",
189
- "description": "Merge develop to main and push (optional version bump)"
189
+ "description": "Interactive stepped release with verification gates"
190
190
  },
191
191
  {
192
192
  "name": "/repo-status",
@@ -38,8 +38,8 @@ interface Message {
38
38
  * Rules:
39
39
  * - tool_result messages do NOT break the stack (they're paired with tool_use elsewhere)
40
40
  * - assistant/user messages DO break the stack
41
- * - Single tool_use messages are NOT grouped (returns empty array for that sequence)
42
- * - Returns array of ToolStackData, each representing 2+ consecutive tools
41
+ * - Single tool_use messages ARE grouped (consistent rendering with multi-tool stacks)
42
+ * - Returns array of ToolStackData, each representing 1+ consecutive tools
43
43
  *
44
44
  * @param messages - Array of messages to process
45
45
  * @returns Array of tool stacks (only stacks with 2+ tools)
@@ -75,8 +75,8 @@ export function groupToolsIntoStacks(messages: Message[]): ToolStackData[] {
75
75
  continue;
76
76
  } else {
77
77
  // assistant, user, or other message types break the stack
78
- // Only create stack if 2+ tools (single tools in middle render normally)
79
- if (currentTools.length >= 2) {
78
+ // Create stack for any tools (single tools also get stacked for consistent rendering)
79
+ if (currentTools.length >= 1) {
80
80
  const lastTool = currentTools[currentTools.length - 1];
81
81
  stacks.push({
82
82
  stackId: generateStableStackId(currentTools),
@@ -91,8 +91,7 @@ export function groupToolsIntoStacks(messages: Message[]): ToolStackData[] {
91
91
  }
92
92
 
93
93
  // Handle remaining tools at end of messages
94
- // Same threshold as mid-stream: only stack 2+ tools (single tools render normally)
95
- if (currentTools.length >= 2) {
94
+ if (currentTools.length >= 1) {
96
95
  const lastTool = currentTools[currentTools.length - 1];
97
96
  stacks.push({
98
97
  stackId: generateStableStackId(currentTools),