claude-code-kanban 4.19.0 → 4.21.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.
- package/README.md +10 -1
- package/lib/approvals.js +82 -0
- package/lib/session-events.js +99 -0
- package/package.json +2 -2
- package/plugin/plugins/claude-code-kanban/.claude-plugin/plugin.json +5 -2
- package/plugin/plugins/claude-code-kanban/hooks/hooks.json +2 -24
- package/plugin/plugins/claude-code-kanban/monitors.json +8 -0
- package/plugin/plugins/claude-code-kanban/scripts/agent-spy.sh +17 -3
- package/plugin/plugins/claude-code-kanban/scripts/approval-gate.sh +141 -0
- package/plugin/plugins/claude-code-kanban/scripts/postman.js +67 -0
- package/plugin/plugins/claude-code-kanban/skills/kanban/SKILL.md +20 -29
- package/plugin/plugins/claude-code-kanban/skills/kanban-follow/SKILL.md +39 -0
- package/public/app.js +582 -90
- package/public/index.html +2 -1
- package/public/style.css +359 -5
- package/server.js +157 -26
package/public/index.html
CHANGED
|
@@ -285,7 +285,7 @@
|
|
|
285
285
|
|
|
286
286
|
<!-- Message Detail Modal -->
|
|
287
287
|
<div id="msg-detail-modal" class="modal-overlay" onclick="closeMsgDetailModal()">
|
|
288
|
-
<div class="modal" onclick="event.stopPropagation()"
|
|
288
|
+
<div class="modal msg-detail-dialog" onclick="event.stopPropagation()">
|
|
289
289
|
<div class="modal-header">
|
|
290
290
|
<h3 class="modal-title" id="msg-detail-title">Message</h3>
|
|
291
291
|
<div style="display:flex;gap:4px;align-items:center;">
|
|
@@ -313,6 +313,7 @@
|
|
|
313
313
|
<div id="msg-detail-body" class="rendered-md modal-zoomable"></div>
|
|
314
314
|
<div id="msg-detail-meta" style="margin-top: 12px; font-size: 11px; color: var(--text-muted); flex-shrink: 0;"></div>
|
|
315
315
|
</div>
|
|
316
|
+
<div id="msg-detail-waiting-footer"></div>
|
|
316
317
|
</div>
|
|
317
318
|
</div>
|
|
318
319
|
|
package/public/style.css
CHANGED
|
@@ -1172,9 +1172,8 @@ body::before {
|
|
|
1172
1172
|
padding-right: 8px;
|
|
1173
1173
|
}
|
|
1174
1174
|
|
|
1175
|
-
.column-empty
|
|
1176
|
-
|
|
1177
|
-
padding: 32px 16px;
|
|
1175
|
+
.column-empty,
|
|
1176
|
+
.column-add {
|
|
1178
1177
|
color: var(--text-muted);
|
|
1179
1178
|
font-size: 12px;
|
|
1180
1179
|
border: 1px dashed var(--border);
|
|
@@ -1182,13 +1181,62 @@ body::before {
|
|
|
1182
1181
|
margin-top: 4px;
|
|
1183
1182
|
}
|
|
1184
1183
|
|
|
1185
|
-
.column-empty
|
|
1184
|
+
.column-empty {
|
|
1185
|
+
text-align: center;
|
|
1186
|
+
padding: 32px 16px;
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
.column-add {
|
|
1190
|
+
display: flex;
|
|
1191
|
+
align-items: center;
|
|
1192
|
+
justify-content: center;
|
|
1193
|
+
gap: 6px;
|
|
1194
|
+
width: 100%;
|
|
1195
|
+
padding: 8px 16px;
|
|
1196
|
+
font-family: inherit;
|
|
1197
|
+
background: none;
|
|
1198
|
+
cursor: pointer;
|
|
1199
|
+
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
.column-add.empty {
|
|
1203
|
+
flex-direction: column;
|
|
1204
|
+
padding: 32px 16px;
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
.column-add:hover,
|
|
1208
|
+
.column-add:focus-visible {
|
|
1209
|
+
outline: none;
|
|
1210
|
+
color: var(--text-primary);
|
|
1211
|
+
border-color: var(--text-muted);
|
|
1212
|
+
background: var(--bg-hover);
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
.column-empty svg,
|
|
1216
|
+
.column-add.empty svg {
|
|
1186
1217
|
width: 24px;
|
|
1187
1218
|
height: 24px;
|
|
1188
|
-
opacity: 0.5;
|
|
1189
1219
|
margin-bottom: 8px;
|
|
1190
1220
|
}
|
|
1191
1221
|
|
|
1222
|
+
.column-empty svg {
|
|
1223
|
+
opacity: 0.5;
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
.column-add svg {
|
|
1227
|
+
width: 16px;
|
|
1228
|
+
height: 16px;
|
|
1229
|
+
opacity: 0.7;
|
|
1230
|
+
flex-shrink: 0;
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1233
|
+
.column-add-input {
|
|
1234
|
+
margin-top: 4px;
|
|
1235
|
+
font-size: 12px;
|
|
1236
|
+
background: var(--bg-surface);
|
|
1237
|
+
border-color: var(--accent);
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1192
1240
|
/* #endregion */
|
|
1193
1241
|
|
|
1194
1242
|
/* #region TASK_CARD */
|
|
@@ -2993,6 +3041,249 @@ body::before {
|
|
|
2993
3041
|
background: color-mix(in srgb, var(--warning, #f5a623) 16%, transparent);
|
|
2994
3042
|
}
|
|
2995
3043
|
}
|
|
3044
|
+
.msg-waiting-footer {
|
|
3045
|
+
display: flex;
|
|
3046
|
+
align-items: center;
|
|
3047
|
+
justify-content: space-between;
|
|
3048
|
+
gap: 8px;
|
|
3049
|
+
margin-top: 4px;
|
|
3050
|
+
}
|
|
3051
|
+
.msg-waiting-footer .msg-time {
|
|
3052
|
+
margin-top: 0;
|
|
3053
|
+
}
|
|
3054
|
+
.msg-waiting-actions {
|
|
3055
|
+
flex-shrink: 0;
|
|
3056
|
+
display: flex;
|
|
3057
|
+
gap: 6px;
|
|
3058
|
+
}
|
|
3059
|
+
.msg-waiting-actions button {
|
|
3060
|
+
border: 1px solid transparent;
|
|
3061
|
+
border-radius: 4px;
|
|
3062
|
+
padding: 2px 8px;
|
|
3063
|
+
font-family: var(--mono);
|
|
3064
|
+
font-size: 11px;
|
|
3065
|
+
font-weight: 600;
|
|
3066
|
+
cursor: pointer;
|
|
3067
|
+
background: none;
|
|
3068
|
+
}
|
|
3069
|
+
#msg-detail-waiting-footer {
|
|
3070
|
+
display: flex;
|
|
3071
|
+
gap: 8px;
|
|
3072
|
+
justify-content: flex-end;
|
|
3073
|
+
padding: 10px 20px;
|
|
3074
|
+
border-top: 1px solid var(--border);
|
|
3075
|
+
flex-shrink: 0;
|
|
3076
|
+
}
|
|
3077
|
+
#msg-detail-waiting-footer:empty {
|
|
3078
|
+
display: none;
|
|
3079
|
+
}
|
|
3080
|
+
#msg-detail-waiting-footer .waiting-option-input,
|
|
3081
|
+
#plan-approval-footer .waiting-option-input {
|
|
3082
|
+
flex: 1;
|
|
3083
|
+
margin: 0;
|
|
3084
|
+
}
|
|
3085
|
+
#plan-approval-footer {
|
|
3086
|
+
display: flex;
|
|
3087
|
+
gap: 8px;
|
|
3088
|
+
align-items: center;
|
|
3089
|
+
flex: 1;
|
|
3090
|
+
}
|
|
3091
|
+
.waiting-actions {
|
|
3092
|
+
display: flex;
|
|
3093
|
+
flex-direction: column;
|
|
3094
|
+
align-items: stretch;
|
|
3095
|
+
gap: 12px;
|
|
3096
|
+
margin-top: 14px;
|
|
3097
|
+
}
|
|
3098
|
+
.waiting-btn-allow,
|
|
3099
|
+
.waiting-btn-deny {
|
|
3100
|
+
border: 1px solid var(--border);
|
|
3101
|
+
border-radius: 4px;
|
|
3102
|
+
padding: 6px 16px;
|
|
3103
|
+
font-family: var(--mono);
|
|
3104
|
+
font-size: 12px;
|
|
3105
|
+
font-weight: 500;
|
|
3106
|
+
background: none;
|
|
3107
|
+
cursor: pointer;
|
|
3108
|
+
transition: all 0.15s ease;
|
|
3109
|
+
}
|
|
3110
|
+
/* One quiet color treatment for both button families — the card's compact
|
|
3111
|
+
buttons need the descendant selector to out-rank `.msg-waiting-actions button` */
|
|
3112
|
+
.waiting-btn-allow,
|
|
3113
|
+
.msg-waiting-actions .msg-waiting-allow {
|
|
3114
|
+
color: var(--success, #2ea043);
|
|
3115
|
+
border-color: color-mix(in srgb, var(--success, #2ea043) 35%, transparent);
|
|
3116
|
+
}
|
|
3117
|
+
.waiting-btn-allow:hover:not(:disabled),
|
|
3118
|
+
.msg-waiting-actions .msg-waiting-allow:hover {
|
|
3119
|
+
background: color-mix(in srgb, var(--success, #2ea043) 10%, transparent);
|
|
3120
|
+
}
|
|
3121
|
+
.waiting-btn-deny,
|
|
3122
|
+
.msg-waiting-actions .msg-waiting-deny {
|
|
3123
|
+
color: var(--danger, #f85149);
|
|
3124
|
+
border-color: color-mix(in srgb, var(--danger, #f85149) 35%, transparent);
|
|
3125
|
+
}
|
|
3126
|
+
.waiting-btn-deny:hover,
|
|
3127
|
+
.msg-waiting-actions .msg-waiting-deny:hover {
|
|
3128
|
+
background: color-mix(in srgb, var(--danger, #f85149) 10%, transparent);
|
|
3129
|
+
}
|
|
3130
|
+
.waiting-btn-allow:disabled {
|
|
3131
|
+
opacity: 0.4;
|
|
3132
|
+
cursor: default;
|
|
3133
|
+
}
|
|
3134
|
+
.waiting-raw-input {
|
|
3135
|
+
margin-bottom: 12px;
|
|
3136
|
+
}
|
|
3137
|
+
.waiting-raw-input summary {
|
|
3138
|
+
font-size: 11px;
|
|
3139
|
+
color: var(--text-secondary);
|
|
3140
|
+
cursor: pointer;
|
|
3141
|
+
user-select: none;
|
|
3142
|
+
}
|
|
3143
|
+
.waiting-question {
|
|
3144
|
+
border: 1px solid var(--border);
|
|
3145
|
+
border-radius: 6px;
|
|
3146
|
+
padding: 12px 14px;
|
|
3147
|
+
background: color-mix(in srgb, var(--bg-deep) 40%, transparent);
|
|
3148
|
+
}
|
|
3149
|
+
.waiting-question-header {
|
|
3150
|
+
display: inline-block;
|
|
3151
|
+
font-size: 10px;
|
|
3152
|
+
font-weight: 600;
|
|
3153
|
+
text-transform: uppercase;
|
|
3154
|
+
letter-spacing: 0.5px;
|
|
3155
|
+
color: var(--accent);
|
|
3156
|
+
margin-bottom: 4px;
|
|
3157
|
+
}
|
|
3158
|
+
.waiting-question-text {
|
|
3159
|
+
font-weight: 600;
|
|
3160
|
+
font-size: 13px;
|
|
3161
|
+
line-height: 1.5;
|
|
3162
|
+
margin-bottom: 10px;
|
|
3163
|
+
}
|
|
3164
|
+
/* Question text and option descriptions render as markdown (like the TUI),
|
|
3165
|
+
so fenced diagrams, tables, and mermaid keep their shape. */
|
|
3166
|
+
.waiting-question-text p,
|
|
3167
|
+
.waiting-option-desc p,
|
|
3168
|
+
.waiting-option-preview p {
|
|
3169
|
+
margin: 0 0 6px;
|
|
3170
|
+
}
|
|
3171
|
+
.waiting-question-text p:last-child,
|
|
3172
|
+
.waiting-option-desc p:last-child,
|
|
3173
|
+
.waiting-option-preview p:last-child {
|
|
3174
|
+
margin-bottom: 0;
|
|
3175
|
+
}
|
|
3176
|
+
.waiting-question-text pre,
|
|
3177
|
+
.waiting-option-desc pre {
|
|
3178
|
+
font-weight: 400;
|
|
3179
|
+
overflow-x: auto;
|
|
3180
|
+
padding: 8px 10px;
|
|
3181
|
+
border: 1px solid var(--border);
|
|
3182
|
+
border-radius: 4px;
|
|
3183
|
+
background: var(--bg-primary);
|
|
3184
|
+
}
|
|
3185
|
+
.waiting-question-text pre.mermaid,
|
|
3186
|
+
.waiting-option-desc pre.mermaid {
|
|
3187
|
+
background: none;
|
|
3188
|
+
border: none;
|
|
3189
|
+
text-align: center;
|
|
3190
|
+
}
|
|
3191
|
+
.waiting-question-text table,
|
|
3192
|
+
.waiting-option-desc table {
|
|
3193
|
+
border-collapse: collapse;
|
|
3194
|
+
font-weight: 400;
|
|
3195
|
+
}
|
|
3196
|
+
.waiting-question-text th,
|
|
3197
|
+
.waiting-question-text td,
|
|
3198
|
+
.waiting-option-desc th,
|
|
3199
|
+
.waiting-option-desc td {
|
|
3200
|
+
border: 1px solid var(--border);
|
|
3201
|
+
padding: 3px 8px;
|
|
3202
|
+
}
|
|
3203
|
+
.waiting-options {
|
|
3204
|
+
display: flex;
|
|
3205
|
+
flex-direction: column;
|
|
3206
|
+
gap: 6px;
|
|
3207
|
+
}
|
|
3208
|
+
.waiting-option {
|
|
3209
|
+
display: flex;
|
|
3210
|
+
flex-direction: column;
|
|
3211
|
+
gap: 2px;
|
|
3212
|
+
width: 100%;
|
|
3213
|
+
text-align: left;
|
|
3214
|
+
border: 1px solid var(--border);
|
|
3215
|
+
border-radius: 4px;
|
|
3216
|
+
padding: 8px 12px;
|
|
3217
|
+
font-family: var(--mono);
|
|
3218
|
+
font-size: 12px;
|
|
3219
|
+
background: none;
|
|
3220
|
+
color: var(--text-primary);
|
|
3221
|
+
cursor: pointer;
|
|
3222
|
+
transition:
|
|
3223
|
+
border-color 0.15s ease,
|
|
3224
|
+
background 0.15s ease;
|
|
3225
|
+
}
|
|
3226
|
+
.waiting-option:hover {
|
|
3227
|
+
border-color: var(--accent);
|
|
3228
|
+
}
|
|
3229
|
+
.waiting-option.selected {
|
|
3230
|
+
border-color: var(--accent);
|
|
3231
|
+
background: color-mix(in srgb, var(--accent) 14%, transparent);
|
|
3232
|
+
}
|
|
3233
|
+
.waiting-option-label {
|
|
3234
|
+
font-weight: 600;
|
|
3235
|
+
}
|
|
3236
|
+
.waiting-option-desc {
|
|
3237
|
+
display: block;
|
|
3238
|
+
font-size: 11px;
|
|
3239
|
+
line-height: 1.45;
|
|
3240
|
+
color: var(--text-secondary);
|
|
3241
|
+
}
|
|
3242
|
+
.waiting-option-preview {
|
|
3243
|
+
display: block;
|
|
3244
|
+
margin-top: 6px;
|
|
3245
|
+
padding: 8px 10px;
|
|
3246
|
+
border: 1px solid var(--border);
|
|
3247
|
+
border-radius: 4px;
|
|
3248
|
+
background: var(--bg-primary);
|
|
3249
|
+
font-size: 11px;
|
|
3250
|
+
font-weight: 400;
|
|
3251
|
+
overflow-x: auto;
|
|
3252
|
+
}
|
|
3253
|
+
.waiting-option-preview pre {
|
|
3254
|
+
margin: 0;
|
|
3255
|
+
overflow-x: auto;
|
|
3256
|
+
background: none;
|
|
3257
|
+
}
|
|
3258
|
+
.waiting-question-multi {
|
|
3259
|
+
display: inline-block;
|
|
3260
|
+
margin-left: 6px;
|
|
3261
|
+
padding: 1px 6px;
|
|
3262
|
+
border: 1px solid var(--border);
|
|
3263
|
+
border-radius: 10px;
|
|
3264
|
+
font-size: 10px;
|
|
3265
|
+
color: var(--text-secondary);
|
|
3266
|
+
}
|
|
3267
|
+
.waiting-option-input {
|
|
3268
|
+
width: 100%;
|
|
3269
|
+
margin-top: 6px;
|
|
3270
|
+
border: 1px dashed var(--border);
|
|
3271
|
+
border-radius: 4px;
|
|
3272
|
+
padding: 8px 12px;
|
|
3273
|
+
font-family: var(--mono);
|
|
3274
|
+
font-size: 12px;
|
|
3275
|
+
background: none;
|
|
3276
|
+
color: var(--text-primary);
|
|
3277
|
+
transition: border-color 0.15s ease;
|
|
3278
|
+
}
|
|
3279
|
+
.waiting-option-input:hover,
|
|
3280
|
+
.waiting-option-input:focus {
|
|
3281
|
+
border-color: var(--accent);
|
|
3282
|
+
outline: none;
|
|
3283
|
+
}
|
|
3284
|
+
.waiting-option-input::placeholder {
|
|
3285
|
+
color: var(--text-secondary);
|
|
3286
|
+
}
|
|
2996
3287
|
.msg-item.msg-idle .msg-icon {
|
|
2997
3288
|
width: 12px;
|
|
2998
3289
|
height: 12px;
|
|
@@ -3562,11 +3853,17 @@ body::before {
|
|
|
3562
3853
|
background: var(--warning-dim);
|
|
3563
3854
|
border: 1px solid var(--warning);
|
|
3564
3855
|
border-radius: 8px;
|
|
3856
|
+
font-family: var(--mono);
|
|
3565
3857
|
font-size: 12px;
|
|
3566
3858
|
color: var(--warning);
|
|
3567
3859
|
white-space: nowrap;
|
|
3860
|
+
cursor: pointer;
|
|
3568
3861
|
animation: permission-pulse 1.5s ease-in-out infinite;
|
|
3569
3862
|
}
|
|
3863
|
+
.permission-badge:hover {
|
|
3864
|
+
background: color-mix(in srgb, var(--warning) 22%, transparent);
|
|
3865
|
+
animation-play-state: paused;
|
|
3866
|
+
}
|
|
3570
3867
|
@keyframes permission-pulse {
|
|
3571
3868
|
0%,
|
|
3572
3869
|
100% {
|
|
@@ -3721,6 +4018,7 @@ body.light .msg-assistant .msg-text {
|
|
|
3721
4018
|
}
|
|
3722
4019
|
|
|
3723
4020
|
.modal {
|
|
4021
|
+
position: relative;
|
|
3724
4022
|
background: var(--bg-surface);
|
|
3725
4023
|
border: 1px solid var(--border);
|
|
3726
4024
|
border-radius: 12px;
|
|
@@ -3734,6 +4032,16 @@ body.light .msg-assistant .msg-text {
|
|
|
3734
4032
|
overflow-y: auto;
|
|
3735
4033
|
}
|
|
3736
4034
|
|
|
4035
|
+
/* Before .modal.fullscreen on purpose: at equal specificity the later
|
|
4036
|
+
fullscreen rule must win, same as for every other per-modal size. */
|
|
4037
|
+
.modal.msg-detail-dialog {
|
|
4038
|
+
width: 90vw;
|
|
4039
|
+
max-width: 860px;
|
|
4040
|
+
max-height: 90vh;
|
|
4041
|
+
display: flex;
|
|
4042
|
+
flex-direction: column;
|
|
4043
|
+
}
|
|
4044
|
+
|
|
3737
4045
|
/* Height is a cap, not a floor — a two-line message should not sit in a 92vh box.
|
|
3738
4046
|
The HTML preview keeps its explicit height below: its iframe is `height: 100%`
|
|
3739
4047
|
and needs a resolvable parent height. */
|
|
@@ -3743,6 +4051,39 @@ body.light .msg-assistant .msg-text {
|
|
|
3743
4051
|
max-height: 92vh;
|
|
3744
4052
|
}
|
|
3745
4053
|
|
|
4054
|
+
.modal-resize-handle {
|
|
4055
|
+
position: absolute;
|
|
4056
|
+
right: 0;
|
|
4057
|
+
bottom: 0;
|
|
4058
|
+
width: 18px;
|
|
4059
|
+
height: 18px;
|
|
4060
|
+
cursor: nwse-resize;
|
|
4061
|
+
z-index: 1;
|
|
4062
|
+
color: var(--text-muted);
|
|
4063
|
+
opacity: 0.55;
|
|
4064
|
+
border-bottom-right-radius: 11px;
|
|
4065
|
+
background: linear-gradient(
|
|
4066
|
+
135deg,
|
|
4067
|
+
transparent 0 50%,
|
|
4068
|
+
currentColor 50% 56%,
|
|
4069
|
+
transparent 56% 64%,
|
|
4070
|
+
currentColor 64% 70%,
|
|
4071
|
+
transparent 70% 78%,
|
|
4072
|
+
currentColor 78% 84%,
|
|
4073
|
+
transparent 84%
|
|
4074
|
+
);
|
|
4075
|
+
}
|
|
4076
|
+
|
|
4077
|
+
.modal-resize-handle:hover,
|
|
4078
|
+
.modal-resize-handle.dragging {
|
|
4079
|
+
opacity: 1;
|
|
4080
|
+
color: var(--accent);
|
|
4081
|
+
}
|
|
4082
|
+
|
|
4083
|
+
.modal.fullscreen .modal-resize-handle {
|
|
4084
|
+
display: none;
|
|
4085
|
+
}
|
|
4086
|
+
|
|
3746
4087
|
.modal.plan-modal {
|
|
3747
4088
|
width: 60vw;
|
|
3748
4089
|
max-width: 60vw;
|
|
@@ -3839,6 +4180,19 @@ body.light .msg-assistant .msg-text {
|
|
|
3839
4180
|
max-height: 98vh;
|
|
3840
4181
|
}
|
|
3841
4182
|
|
|
4183
|
+
/* User-dragged size (bottom-right grip, app.js initModalResize). Last of the
|
|
4184
|
+
modal sizing rules on purpose: at equal specificity, source order lets it
|
|
4185
|
+
beat every per-modal size above; fullscreen still wins via :not() while
|
|
4186
|
+
active, and JS keeps inline sizing off user-sized modals (autoSizeModal and
|
|
4187
|
+
"Show more" skip them, the drag clears leftovers). Height is a cap, not a
|
|
4188
|
+
floor (same rule as .fullscreen) — short content still collapses. min()
|
|
4189
|
+
keeps a size saved on a large screen inside the current viewport. */
|
|
4190
|
+
.modal.user-sized:not(.fullscreen) {
|
|
4191
|
+
width: min(var(--user-modal-w), 98vw);
|
|
4192
|
+
max-width: min(var(--user-modal-w), 98vw);
|
|
4193
|
+
max-height: min(var(--user-modal-h), 95vh);
|
|
4194
|
+
}
|
|
4195
|
+
|
|
3842
4196
|
.preview-html .modal-body,
|
|
3843
4197
|
.preview-html #preview-modal-body {
|
|
3844
4198
|
flex: 1 1 auto;
|