claude-code-kanban 5.1.1 → 5.2.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 (42) hide show
  1. package/README.md +3 -2
  2. package/lib/auto-compact.js +42 -0
  3. package/lib/claude-settings.js +21 -0
  4. package/lib/dispatch.js +11 -4
  5. package/lib/retention.js +137 -0
  6. package/lib/session-events.js +30 -7
  7. package/lib/terminal.js +23 -3
  8. package/package.json +1 -1
  9. package/plugin/plugins/claude-code-kanban/.claude-plugin/plugin.json +1 -1
  10. package/plugin/plugins/claude-code-kanban/hooks/hooks.json +14 -7
  11. package/plugin/plugins/claude-code-kanban/monitors.json +3 -3
  12. package/plugin/plugins/claude-code-kanban/scripts/postman.js +2 -2
  13. package/plugin/plugins/claude-code-kanban/skills/{kanban-dispatch → dispatch}/SKILL.md +2 -2
  14. package/plugin/plugins/claude-code-kanban/skills/{kanban-follow → follow}/SKILL.md +17 -9
  15. package/plugin/plugins/claude-code-kanban/skills/kanban/SKILL.md +1 -1
  16. package/public/app.js +699 -138
  17. package/public/fonts/OFL-IBM-Plex.txt +93 -0
  18. package/public/fonts/OFL-Playfair-Display.txt +93 -0
  19. package/public/fonts/fonts.css +244 -0
  20. package/public/fonts/ibm-plex-mono-cyrillic-400.woff2 +0 -0
  21. package/public/fonts/ibm-plex-mono-cyrillic-500.woff2 +0 -0
  22. package/public/fonts/ibm-plex-mono-cyrillic-600.woff2 +0 -0
  23. package/public/fonts/ibm-plex-mono-cyrillic-ext-400.woff2 +0 -0
  24. package/public/fonts/ibm-plex-mono-cyrillic-ext-500.woff2 +0 -0
  25. package/public/fonts/ibm-plex-mono-cyrillic-ext-600.woff2 +0 -0
  26. package/public/fonts/ibm-plex-mono-latin-400.woff2 +0 -0
  27. package/public/fonts/ibm-plex-mono-latin-500.woff2 +0 -0
  28. package/public/fonts/ibm-plex-mono-latin-600.woff2 +0 -0
  29. package/public/fonts/ibm-plex-mono-latin-ext-400.woff2 +0 -0
  30. package/public/fonts/ibm-plex-mono-latin-ext-500.woff2 +0 -0
  31. package/public/fonts/ibm-plex-mono-latin-ext-600.woff2 +0 -0
  32. package/public/fonts/ibm-plex-mono-vietnamese-400.woff2 +0 -0
  33. package/public/fonts/ibm-plex-mono-vietnamese-500.woff2 +0 -0
  34. package/public/fonts/ibm-plex-mono-vietnamese-600.woff2 +0 -0
  35. package/public/fonts/playfair-display-cyrillic-400.woff2 +0 -0
  36. package/public/fonts/playfair-display-latin-400.woff2 +0 -0
  37. package/public/fonts/playfair-display-latin-ext-400.woff2 +0 -0
  38. package/public/fonts/playfair-display-vietnamese-400.woff2 +0 -0
  39. package/public/index.html +20 -14
  40. package/public/style.css +277 -44
  41. package/server.js +152 -15
  42. package/skill-guides/dispatch.md +1 -1
package/public/style.css CHANGED
@@ -43,6 +43,7 @@
43
43
  --ansi-bright-cyan: #7ddede;
44
44
  --mono: 'IBM Plex Mono', monospace;
45
45
  --serif: 'Playfair Display', serif;
46
+ --sans: Arial, Helvetica, sans-serif;
46
47
  --card-gap: 7px;
47
48
  /* the name's supporting lines read as one unit with it, so they sit tighter
48
49
  than the gap separating the card's independent rows */
@@ -72,6 +73,13 @@ body {
72
73
  padding: 0;
73
74
  }
74
75
 
76
+ button,
77
+ input,
78
+ select,
79
+ textarea {
80
+ font-family: inherit;
81
+ }
82
+
75
83
  body {
76
84
  font-family: var(--mono);
77
85
  font-size: 14px;
@@ -480,9 +488,8 @@ body::before {
480
488
 
481
489
  .section-header-label {
482
490
  flex: 0 0 auto;
491
+ font-size: 12px;
483
492
  font-weight: 500;
484
- text-transform: uppercase;
485
- letter-spacing: 0.12em;
486
493
  }
487
494
 
488
495
  /* Non-default filters, spelled out in the header so folding them into the popover
@@ -1001,6 +1008,7 @@ body.booting .boot-splash {
1001
1008
  }
1002
1009
 
1003
1010
  .session-name {
1011
+ font-family: var(--sans);
1004
1012
  font-size: 14px;
1005
1013
  font-weight: 500;
1006
1014
  color: var(--text-primary);
@@ -1069,6 +1077,7 @@ body.booting .boot-splash {
1069
1077
  }
1070
1078
 
1071
1079
  .session-secondary {
1080
+ font-family: var(--sans);
1072
1081
  font-size: 12px;
1073
1082
  font-weight: 450;
1074
1083
  color: var(--text-tertiary);
@@ -1108,26 +1117,36 @@ body.booting .boot-splash {
1108
1117
  text-overflow: ellipsis;
1109
1118
  }
1110
1119
 
1111
- .session-plan {
1112
- font-size: 10px;
1113
- color: var(--plan);
1114
- margin-top: var(--card-gap-tight);
1115
- white-space: nowrap;
1116
- overflow: hidden;
1117
- text-overflow: ellipsis;
1118
- }
1119
-
1120
1120
  .session-item.plan-reveal {
1121
1121
  outline: 1.5px solid var(--plan);
1122
1122
  background: var(--plan-dim);
1123
1123
  }
1124
1124
 
1125
+ .session-metrics {
1126
+ display: flex;
1127
+ flex-direction: column;
1128
+ gap: var(--card-gap);
1129
+ margin-top: var(--card-gap);
1130
+ line-height: 1;
1131
+ }
1132
+
1125
1133
  .session-progress {
1126
1134
  display: flex;
1127
1135
  align-items: center;
1128
1136
  gap: 9px;
1137
+ }
1138
+
1139
+ .session-footer {
1140
+ display: flex;
1141
+ align-items: center;
1142
+ justify-content: space-between;
1143
+ gap: 8px;
1129
1144
  margin-top: var(--card-gap);
1130
- line-height: 1;
1145
+ min-height: 18px;
1146
+ }
1147
+
1148
+ .session-footer .session-time {
1149
+ min-width: 0;
1131
1150
  }
1132
1151
 
1133
1152
  .progress-bar {
@@ -1158,12 +1177,15 @@ body.booting .boot-splash {
1158
1177
  font-variant-numeric: tabular-nums;
1159
1178
  }
1160
1179
 
1161
- .context-bar {
1162
- display: none;
1163
- margin-top: var(--card-gap);
1164
- }
1165
- .has-context .context-bar {
1166
- display: block;
1180
+ .context-bar-labels {
1181
+ display: flex;
1182
+ justify-content: space-between;
1183
+ gap: 6px;
1184
+ margin-top: 4px;
1185
+ font-size: 10px;
1186
+ font-family: var(--font-mono);
1187
+ color: var(--text-tertiary);
1188
+ white-space: nowrap;
1167
1189
  }
1168
1190
  .context-bar-track {
1169
1191
  height: 2px;
@@ -1188,15 +1210,6 @@ body.booting .boot-splash {
1188
1210
  z-index: 2;
1189
1211
  border-radius: 1px;
1190
1212
  }
1191
- .context-bar-labels {
1192
- display: flex;
1193
- justify-content: space-between;
1194
- margin-top: 2px;
1195
- font-size: 10px;
1196
- font-family: var(--font-mono);
1197
- color: var(--text-tertiary);
1198
- }
1199
-
1200
1213
  .detail-context {
1201
1214
  margin-bottom: 16px;
1202
1215
  }
@@ -1314,7 +1327,6 @@ body.booting .boot-splash {
1314
1327
  font-size: 11px;
1315
1328
  font-weight: 450;
1316
1329
  color: var(--text-tertiary);
1317
- margin-top: var(--card-gap);
1318
1330
  }
1319
1331
 
1320
1332
  .session-latest-msg {
@@ -2430,6 +2442,7 @@ body.booting .boot-splash {
2430
2442
  .plan-indicator,
2431
2443
  .loop-badge,
2432
2444
  .workflow-badge,
2445
+ .dispatched-badge,
2433
2446
  .terminal-badge {
2434
2447
  width: 18px;
2435
2448
  height: 18px;
@@ -3759,6 +3772,10 @@ body.booting .boot-splash {
3759
3772
  .toast-action:hover {
3760
3773
  background: var(--accent-dim);
3761
3774
  }
3775
+ .toast-hint {
3776
+ margin-top: 2px;
3777
+ color: var(--text-muted);
3778
+ }
3762
3779
  .toast.toast-success {
3763
3780
  border-color: var(--success);
3764
3781
  color: var(--success);
@@ -3822,9 +3839,6 @@ body.booting .boot-splash {
3822
3839
  background: var(--bg-hover);
3823
3840
  font-weight: 600;
3824
3841
  }
3825
- .rendered-md tr:hover td {
3826
- background: var(--bg-hover);
3827
- }
3828
3842
  .rendered-md hr {
3829
3843
  margin: 0.8em 0;
3830
3844
  border-color: var(--border);
@@ -4650,6 +4664,12 @@ body.booting .boot-splash {
4650
4664
  .terminal-badge:hover {
4651
4665
  color: var(--accent, var(--text-primary));
4652
4666
  }
4667
+ .dispatched-badge:not([onclick]) {
4668
+ cursor: default;
4669
+ }
4670
+ .dispatched-badge[onclick]:hover {
4671
+ color: var(--accent, var(--text-primary));
4672
+ }
4653
4673
  .agent-badge-waiting {
4654
4674
  color: var(--warning);
4655
4675
  animation: agent-badge-pulse 1.6s ease-in-out infinite;
@@ -5225,6 +5245,7 @@ body.booting .boot-splash {
5225
5245
 
5226
5246
  /* #region LIGHT_THEME */
5227
5247
  body.light {
5248
+ --on-accent: white;
5228
5249
  --bg-deep: #e8e6e3;
5229
5250
  --bg-surface: #efede9;
5230
5251
  --bg-elevated: #fbfaf9;
@@ -5466,9 +5487,27 @@ body.light .msg-assistant .msg-text {
5466
5487
  max-height: 92vh;
5467
5488
  }
5468
5489
 
5490
+ /* The comment panel opens beside the content, so the dialog grows by `--review-extra`
5491
+ instead of squeezing what is under review. */
5492
+ .modal.review-host {
5493
+ --review-panel-w: 320px;
5494
+ --review-extra: 0px;
5495
+ }
5496
+
5497
+ .review-host .modal-body {
5498
+ display: flex;
5499
+ flex-direction: column;
5500
+ overflow: hidden;
5501
+ }
5502
+
5503
+ #plan-modal .modal:not(.fullscreen):not(.user-sized) {
5504
+ width: min(calc(60vw + var(--review-extra)), 96vw);
5505
+ max-width: min(calc(60vw + var(--review-extra)), 96vw);
5506
+ }
5507
+
5469
5508
  .modal.preview-modal-dialog {
5470
- width: 90vw;
5471
- max-width: 1200px;
5509
+ width: min(calc(90vw + var(--review-extra)), 96vw);
5510
+ max-width: calc(1200px + var(--review-extra));
5472
5511
  max-height: 90vh;
5473
5512
  display: flex;
5474
5513
  flex-direction: column;
@@ -5483,9 +5522,6 @@ body.light .msg-assistant .msg-text {
5483
5522
 
5484
5523
  .preview-modal-dialog .modal-body {
5485
5524
  flex: 0 1 auto;
5486
- display: flex;
5487
- flex-direction: column;
5488
- overflow: hidden;
5489
5525
  }
5490
5526
 
5491
5527
  #msg-detail-body,
@@ -5565,11 +5601,45 @@ body.light .msg-assistant .msg-text {
5565
5601
  floor (same rule as .fullscreen) — short content still collapses. min()
5566
5602
  keeps a size saved on a large screen inside the current viewport. */
5567
5603
  .modal.user-sized:not(.fullscreen) {
5568
- width: min(var(--user-modal-w), 98vw);
5569
- max-width: min(var(--user-modal-w), 98vw);
5604
+ width: min(calc(var(--user-modal-w) + var(--review-extra, 0px)), 98vw);
5605
+ max-width: min(calc(var(--user-modal-w) + var(--review-extra, 0px)), 98vw);
5570
5606
  max-height: min(var(--user-modal-h), 95vh);
5571
5607
  }
5572
5608
 
5609
+ .modal.review-host.has-review {
5610
+ --review-extra: var(--review-panel-w);
5611
+ }
5612
+
5613
+ /* Not on user-sized dialogs: the grip drag sets the width on every move and must not lag. */
5614
+ .modal.review-host:not(.user-sized) {
5615
+ transition:
5616
+ width 150ms ease-out,
5617
+ max-width 150ms ease-out;
5618
+ }
5619
+
5620
+ @media (prefers-reduced-motion: reduce) {
5621
+ .modal.review-host {
5622
+ transition: none;
5623
+ }
5624
+ }
5625
+
5626
+ .preview-split {
5627
+ display: flex;
5628
+ gap: 14px;
5629
+ flex: 0 1 auto;
5630
+ min-height: 0;
5631
+ }
5632
+
5633
+ .preview-html .preview-split {
5634
+ flex: 1 1 auto;
5635
+ }
5636
+
5637
+ .preview-split > #preview-modal-body,
5638
+ .preview-split > #plan-modal-body {
5639
+ flex: 1 1 auto;
5640
+ min-width: 0;
5641
+ }
5642
+
5573
5643
  .preview-html .modal-body,
5574
5644
  .preview-html #preview-modal-body {
5575
5645
  flex: 1 1 auto;
@@ -6024,6 +6094,172 @@ select.form-input option:checked {
6024
6094
 
6025
6095
  /* #endregion */
6026
6096
 
6097
+ /* #region REVIEW */
6098
+ ::highlight(review) {
6099
+ background-color: var(--warning-dim);
6100
+ }
6101
+
6102
+ ::highlight(review-hot) {
6103
+ background-color: color-mix(in srgb, var(--warning) 45%, transparent);
6104
+ }
6105
+
6106
+ #review-pop {
6107
+ display: none;
6108
+ position: fixed;
6109
+ z-index: 10010;
6110
+ font-family: var(--mono);
6111
+ font-size: 12px;
6112
+ }
6113
+
6114
+ #review-pop.visible {
6115
+ display: block;
6116
+ }
6117
+
6118
+ #review-pop.editor {
6119
+ width: 320px;
6120
+ padding: 8px;
6121
+ background: var(--bg-elevated);
6122
+ border: 1px solid var(--border);
6123
+ border-radius: 6px;
6124
+ box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
6125
+ }
6126
+
6127
+ #review-pop textarea {
6128
+ width: 100%;
6129
+ box-sizing: border-box;
6130
+ margin: 6px 0;
6131
+ padding: 6px;
6132
+ resize: vertical;
6133
+ font: inherit;
6134
+ color: var(--text-primary);
6135
+ background: var(--bg-surface);
6136
+ border: 1px solid var(--border);
6137
+ border-radius: 4px;
6138
+ }
6139
+
6140
+ .review-pop-quote,
6141
+ .review-card-quote {
6142
+ overflow: hidden;
6143
+ padding-left: 8px;
6144
+ color: var(--text-muted);
6145
+ border-left: 2px solid var(--warning);
6146
+ }
6147
+
6148
+ .review-pop-quote {
6149
+ max-height: 3.2em;
6150
+ }
6151
+
6152
+ .review-pop-actions {
6153
+ display: flex;
6154
+ justify-content: flex-end;
6155
+ gap: 6px;
6156
+ }
6157
+
6158
+ #review-pop button,
6159
+ .review-panel button {
6160
+ padding: 3px 10px;
6161
+ font: inherit;
6162
+ color: var(--text-primary);
6163
+ background: var(--bg-hover);
6164
+ border: 1px solid var(--border);
6165
+ border-radius: 4px;
6166
+ cursor: pointer;
6167
+ }
6168
+
6169
+ #review-pop button.primary,
6170
+ .review-panel button.primary {
6171
+ color: var(--on-accent, var(--bg-deep));
6172
+ background: var(--accent);
6173
+ border-color: var(--accent);
6174
+ }
6175
+
6176
+ .review-panel {
6177
+ display: flex;
6178
+ flex-direction: column;
6179
+ flex: 0 0 calc(var(--review-panel-w) - 14px);
6180
+ min-height: 0;
6181
+ padding-left: 12px;
6182
+ font-family: var(--mono);
6183
+ font-size: 12px;
6184
+ border-left: 1px solid var(--border);
6185
+ }
6186
+
6187
+ .review-panel[hidden] {
6188
+ display: none;
6189
+ }
6190
+
6191
+ .review-panel-head {
6192
+ display: flex;
6193
+ align-items: center;
6194
+ gap: 6px;
6195
+ padding-bottom: 8px;
6196
+ }
6197
+
6198
+ .review-panel-head span {
6199
+ flex: 1;
6200
+ color: var(--text-muted);
6201
+ }
6202
+
6203
+ .review-panel-list {
6204
+ flex: 1 1 auto;
6205
+ min-height: 0;
6206
+ overflow-y: auto;
6207
+ margin: 0;
6208
+ padding: 0;
6209
+ list-style: none;
6210
+ }
6211
+
6212
+ .review-panel button.review-discard,
6213
+ .review-panel button.review-remove {
6214
+ padding: 3px 4px;
6215
+ color: var(--text-muted);
6216
+ background: none;
6217
+ border: none;
6218
+ }
6219
+
6220
+ .review-panel button.review-discard:hover,
6221
+ .review-panel button.review-discard:focus-visible {
6222
+ color: var(--text-primary);
6223
+ text-decoration: underline;
6224
+ }
6225
+
6226
+ .review-card {
6227
+ position: relative;
6228
+ padding: 8px 24px 10px 0;
6229
+ cursor: pointer;
6230
+ }
6231
+
6232
+ .review-card + .review-card {
6233
+ border-top: 1px solid var(--border);
6234
+ }
6235
+
6236
+ .review-card-quote {
6237
+ display: -webkit-box;
6238
+ -webkit-line-clamp: 3;
6239
+ -webkit-box-orient: vertical;
6240
+ margin-bottom: 4px;
6241
+ border-left-color: var(--warning-dim);
6242
+ }
6243
+
6244
+ .review-card:hover .review-card-quote,
6245
+ .review-card.hot .review-card-quote {
6246
+ color: var(--text-primary);
6247
+ border-left-color: var(--warning);
6248
+ }
6249
+
6250
+ .review-card-comment {
6251
+ white-space: pre-wrap;
6252
+ word-break: break-word;
6253
+ }
6254
+
6255
+ .review-panel button.review-remove {
6256
+ position: absolute;
6257
+ top: 4px;
6258
+ right: 4px;
6259
+ padding: 0 6px;
6260
+ }
6261
+ /* #endregion */
6262
+
6027
6263
  /* #region SESSION_PICKER */
6028
6264
  .modal.session-picker {
6029
6265
  max-height: 70vh;
@@ -6921,6 +7157,7 @@ select.form-input option:checked {
6921
7157
  /* #region MEDIA_QUERIES */
6922
7158
  @media (prefers-color-scheme: light) {
6923
7159
  body:not(.dark-forced) {
7160
+ --on-accent: white;
6924
7161
  --bg-deep: #e8e6e3;
6925
7162
  --bg-surface: #efede9;
6926
7163
  --bg-elevated: #fbfaf9;
@@ -7068,8 +7305,6 @@ pre.mermaid svg {
7068
7305
  font-size: 11px;
7069
7306
  font-weight: 600;
7070
7307
  color: var(--text-secondary);
7071
- text-transform: uppercase;
7072
- letter-spacing: 0.5px;
7073
7308
  }
7074
7309
 
7075
7310
  .project-group-header:first-child {
@@ -7190,7 +7425,7 @@ pre.mermaid svg {
7190
7425
  font-size: 10px;
7191
7426
  color: var(--text-muted);
7192
7427
  padding: 0 10px 0 28px;
7193
- font-family: 'IBM Plex Mono', monospace;
7428
+ font-family: var(--mono);
7194
7429
  overflow: hidden;
7195
7430
  max-height: 0;
7196
7431
  opacity: 0;
@@ -7321,10 +7556,8 @@ pre.mermaid svg {
7321
7556
  .sg-section-label {
7322
7557
  padding: 10px 10px 2px;
7323
7558
  margin-top: 10px;
7324
- font-size: 10px;
7559
+ font-size: 11px;
7325
7560
  font-weight: 600;
7326
- letter-spacing: 0.6px;
7327
- text-transform: uppercase;
7328
7561
  color: var(--text-muted);
7329
7562
  user-select: none;
7330
7563
  }