kanban-system 1.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 (48) hide show
  1. package/.env.example +76 -0
  2. package/CLAUDE.md +108 -0
  3. package/README.md +272 -0
  4. package/agents/_TEMPLATE.md +42 -0
  5. package/agents/backend-agent.md +81 -0
  6. package/agents/deploy-gate-agent.md +73 -0
  7. package/agents/frontend-agent.md +73 -0
  8. package/agents/monitor-agent.md +65 -0
  9. package/agents/orchestrator.md +91 -0
  10. package/agents/reviewer-codex.md +51 -0
  11. package/bin/cli.js +171 -0
  12. package/config.example.js +99 -0
  13. package/docs/adapting-to-your-project.md +155 -0
  14. package/docs/example-apex.md +86 -0
  15. package/docs/the-pattern.md +92 -0
  16. package/hooks/launchd.plist.template +66 -0
  17. package/hooks/pre-push.sample +61 -0
  18. package/lib/config.cjs +138 -0
  19. package/lib/detect/_template.cjs +63 -0
  20. package/lib/detect/rules.json +28 -0
  21. package/lib/detect/sentry.cjs +86 -0
  22. package/lib/detect/vercel.cjs +62 -0
  23. package/lib/gate/index.cjs +182 -0
  24. package/lib/runner/adapters/both.cjs +33 -0
  25. package/lib/runner/adapters/claude.cjs +119 -0
  26. package/lib/runner/adapters/codex.cjs +43 -0
  27. package/lib/runner/adapters/reviewer.cjs +91 -0
  28. package/lib/runner/budget.cjs +75 -0
  29. package/lib/runner/index.cjs +93 -0
  30. package/lib/runner/result-merger.cjs +58 -0
  31. package/lib/runner/worktree-manager.cjs +64 -0
  32. package/lib/watch/scheduler.cjs +164 -0
  33. package/package.json +59 -0
  34. package/playbooks/_TEMPLATE.html +54 -0
  35. package/playbooks/build-fail.html +57 -0
  36. package/playbooks/deploy-rollback.html +53 -0
  37. package/playbooks/e2e-regression.html +58 -0
  38. package/playbooks/playbook.css +26 -0
  39. package/playbooks/sentry-spike.html +53 -0
  40. package/server/kanban.cjs +1152 -0
  41. package/skills/archive.md +18 -0
  42. package/skills/gate.md +22 -0
  43. package/skills/standup.md +24 -0
  44. package/skills/triage.md +24 -0
  45. package/ui/kanban.html +628 -0
  46. package/ui/styles/kanban.css +436 -0
  47. package/ui/styles/progress.css +315 -0
  48. package/ui/styles/tokens.css +291 -0
@@ -0,0 +1,436 @@
1
+ /* ============================================================
2
+ kanban-system — 4-column kanban board styles.
3
+ Depends on: tokens.css (import that first).
4
+ ============================================================ */
5
+
6
+ /* ── Reset ─────────────────────────────────────────────────── */
7
+ *, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
8
+
9
+ body {
10
+ font-family: var(--token-font-sans);
11
+ background: var(--bg);
12
+ color: var(--t1);
13
+ font-size: var(--token-size-md); /* 13px */
14
+ line-height: var(--token-lh-normal);
15
+ -webkit-font-smoothing: antialiased;
16
+ }
17
+
18
+ code, .mono {
19
+ font-family: var(--token-font-mono);
20
+ }
21
+
22
+ /* ── Header ─────────────────────────────────────────────────── */
23
+ .header {
24
+ height: 52px;
25
+ padding: 0 var(--token-space-6);
26
+ border-bottom: 1px solid var(--b1);
27
+ display: flex;
28
+ align-items: center;
29
+ justify-content: space-between;
30
+ background: var(--s1);
31
+ position: sticky;
32
+ top: 0;
33
+ z-index: var(--token-z-sticky);
34
+ }
35
+
36
+ .header-left { display: flex; align-items: center; gap: var(--token-space-3); }
37
+ .header-right { display: flex; align-items: center; gap: var(--token-space-2); }
38
+
39
+ .logo {
40
+ font-size: var(--token-size-lg); /* 14px */
41
+ font-weight: var(--token-weight-bold);
42
+ letter-spacing: -0.02em;
43
+ color: var(--t1);
44
+ }
45
+ .logo-dot { color: var(--ac); }
46
+
47
+ .header-sub {
48
+ font-size: var(--token-size-sm); /* 11px */
49
+ color: var(--t3);
50
+ font-family: var(--token-font-mono);
51
+ padding-left: var(--token-space-3);
52
+ border-left: 1px solid var(--b1);
53
+ }
54
+
55
+ /* Stats cluster */
56
+ .stats { display: flex; gap: 2px; }
57
+ .stat {
58
+ padding: var(--token-space-1) 14px;
59
+ text-align: center;
60
+ background: var(--s2);
61
+ border: 1px solid var(--b1);
62
+ }
63
+ .stat:first-child { border-radius: var(--r) 0 0 var(--r); }
64
+ .stat:last-child { border-radius: 0 var(--r) var(--r) 0; }
65
+ .stat:not(:first-child) { border-left: none; }
66
+ .stat .num {
67
+ font-size: var(--token-size-xl); /* 16px */
68
+ font-weight: var(--token-weight-bold);
69
+ font-family: var(--token-font-mono);
70
+ line-height: var(--token-lh-tight);
71
+ }
72
+ .stat .lbl {
73
+ font-size: 9px;
74
+ color: var(--t4);
75
+ text-transform: uppercase;
76
+ letter-spacing: 0.08em;
77
+ font-weight: var(--token-weight-medium);
78
+ }
79
+
80
+ /* Theme switcher */
81
+ .theme-switcher {
82
+ display: flex;
83
+ gap: 2px;
84
+ margin-left: var(--token-space-3);
85
+ padding-left: var(--token-space-3);
86
+ border-left: 1px solid var(--b1);
87
+ }
88
+ .theme-btn {
89
+ width: 22px;
90
+ height: 22px;
91
+ border-radius: var(--token-radius-full);
92
+ border: 2px solid var(--b2);
93
+ cursor: pointer;
94
+ transition: border-color var(--token-duration-fast) var(--token-ease-default),
95
+ transform var(--token-duration-fast) var(--token-ease-default);
96
+ padding: 0;
97
+ }
98
+ .theme-btn:hover { transform: scale(1.15); }
99
+ .theme-btn.active { border-color: var(--ac); box-shadow: 0 0 0 2px var(--ac); }
100
+ .theme-btn[data-t="dark"] { background: #09090B; }
101
+ .theme-btn[data-t="navy"] { background: #0B1220; }
102
+ .theme-btn[data-t="light"] { background: #F4F5F7; }
103
+
104
+ /* ── Toolbar ────────────────────────────────────────────────── */
105
+ .toolbar {
106
+ min-height: 36px;
107
+ padding: var(--token-space-1) var(--token-space-6);
108
+ display: flex;
109
+ align-items: center;
110
+ flex-wrap: wrap;
111
+ gap: 2px;
112
+ border-bottom: 1px solid var(--b1);
113
+ background: var(--s1);
114
+ }
115
+ .toolbar button {
116
+ padding: var(--token-space-1) 10px;
117
+ border: none;
118
+ background: transparent;
119
+ cursor: pointer;
120
+ font-size: var(--token-size-sm);
121
+ font-weight: var(--token-weight-medium);
122
+ color: var(--t3);
123
+ font-family: inherit;
124
+ transition: color var(--token-duration-fast);
125
+ border-radius: var(--r);
126
+ }
127
+ .toolbar button:hover { color: var(--t1); }
128
+ .toolbar button.active { background: var(--s3); color: var(--t1); }
129
+ .toolbar .right { margin-left: auto; display: flex; align-items: center; gap: var(--token-space-1); }
130
+ .toolbar .add-btn {
131
+ background: var(--t1);
132
+ color: var(--bg);
133
+ font-weight: var(--token-weight-semibold);
134
+ padding: 5px 14px;
135
+ border-radius: var(--r);
136
+ font-size: var(--token-size-sm);
137
+ }
138
+ .toolbar .add-btn:hover { opacity: 0.9; color: var(--bg); }
139
+
140
+ /* ── Project Tabs ───────────────────────────────────────────── */
141
+ .project-tabs {
142
+ height: 36px;
143
+ padding: 0 var(--token-space-6);
144
+ display: flex;
145
+ align-items: stretch;
146
+ gap: 2px;
147
+ border-bottom: 1px solid var(--b1);
148
+ background: var(--s1);
149
+ overflow-x: auto;
150
+ }
151
+ .project-tabs:empty { display: none; }
152
+ .tab-btn {
153
+ padding: 0 var(--token-space-3);
154
+ border: none;
155
+ border-bottom: 2px solid transparent;
156
+ background: transparent;
157
+ color: var(--t3);
158
+ font-size: var(--token-size-sm);
159
+ font-weight: var(--token-weight-medium);
160
+ font-family: inherit;
161
+ cursor: pointer;
162
+ white-space: nowrap;
163
+ transition: color var(--token-duration-fast), border-color var(--token-duration-fast);
164
+ display: flex;
165
+ align-items: center;
166
+ gap: var(--token-space-1);
167
+ }
168
+ .tab-btn:hover { color: var(--t1); }
169
+ .tab-btn.active {
170
+ color: var(--t1);
171
+ border-bottom-color: var(--ac);
172
+ }
173
+ .tab-count {
174
+ font-family: var(--token-font-mono);
175
+ font-size: var(--token-size-xs);
176
+ background: var(--s3);
177
+ color: var(--t3);
178
+ padding: 1px 5px;
179
+ border-radius: var(--token-radius-full);
180
+ }
181
+ .tab-btn.active .tab-count { background: var(--ac); color: #fff; }
182
+
183
+ /* ── Kanban Board — 4 columns ───────────────────────────────── */
184
+ .board {
185
+ display: grid;
186
+ grid-template-columns: repeat(4, 1fr);
187
+ gap: var(--token-space-3);
188
+ padding: var(--token-space-4) var(--token-space-6);
189
+ align-items: start;
190
+ min-height: calc(100vh - 180px);
191
+ }
192
+
193
+ @media (max-width: 900px) {
194
+ .board { grid-template-columns: repeat(2, 1fr); }
195
+ }
196
+ @media (max-width: 500px) {
197
+ .board { grid-template-columns: 1fr; }
198
+ }
199
+
200
+ /* ── Column ─────────────────────────────────────────────────── */
201
+ .col {
202
+ background: var(--s1);
203
+ border: 1px solid var(--b1);
204
+ border-radius: var(--r-lg);
205
+ display: flex;
206
+ flex-direction: column;
207
+ min-height: 200px;
208
+ }
209
+
210
+ .col-header {
211
+ padding: var(--token-space-2) var(--token-space-3);
212
+ border-bottom: 1px solid var(--b1);
213
+ display: flex;
214
+ align-items: center;
215
+ gap: var(--token-space-2);
216
+ }
217
+
218
+ .col-dot {
219
+ width: 8px;
220
+ height: 8px;
221
+ border-radius: var(--token-radius-full);
222
+ flex-shrink: 0;
223
+ }
224
+
225
+ .col-label {
226
+ font-size: var(--token-size-sm); /* 11px */
227
+ font-weight: var(--token-weight-semibold);
228
+ color: var(--t1);
229
+ flex: 1;
230
+ }
231
+
232
+ .col-count {
233
+ font-family: var(--token-font-mono);
234
+ font-size: var(--token-size-sm);
235
+ color: var(--t3);
236
+ min-width: 18px;
237
+ text-align: right;
238
+ }
239
+
240
+ /* Column color identifiers */
241
+ .col[data-status="generating"] .col-dot { background: var(--st-gen-dot); }
242
+ .col[data-status="validating"] .col-dot { background: var(--st-val-dot); }
243
+ .col[data-status="passed"] .col-dot { background: var(--st-pass-dot); }
244
+ .col[data-status="flagged"] .col-dot { background: var(--st-flag-dot); }
245
+
246
+ .col-cards {
247
+ padding: var(--token-space-2);
248
+ display: flex;
249
+ flex-direction: column;
250
+ gap: var(--token-space-2);
251
+ flex: 1;
252
+ }
253
+
254
+ /* ── Card ────────────────────────────────────────────────────── */
255
+ .card {
256
+ background: var(--card-bg);
257
+ border: 1px solid var(--b1);
258
+ border-radius: var(--r);
259
+ padding: var(--token-space-2) var(--token-space-3);
260
+ cursor: default;
261
+ transition: background var(--token-duration-fast) var(--token-ease-default),
262
+ box-shadow var(--token-duration-fast) var(--token-ease-default);
263
+ position: relative;
264
+ overflow: hidden;
265
+ }
266
+ .card:hover {
267
+ background: var(--card-hover);
268
+ box-shadow: var(--shadow-sm);
269
+ }
270
+
271
+ /* Status left-border accent */
272
+ .card[data-status="generating"] { border-left: 3px solid var(--st-gen-dot); }
273
+ .card[data-status="validating"] { border-left: 3px solid var(--st-val-dot); }
274
+ .card[data-status="passed"] { border-left: 3px solid var(--st-pass-dot); }
275
+ .card[data-status="flagged"] { border-left: 3px solid var(--st-flag-dot); }
276
+ .card[data-status="regenerating"]{ border-left: 3px solid var(--st-val-dot); }
277
+ .card[data-status="error"] { border-left: 3px solid var(--rd); }
278
+ .card[data-status="idle"] { border-left: 3px solid var(--st-idle-dot); }
279
+
280
+ /* Card top row: type·location + status badge */
281
+ .card-top {
282
+ display: flex;
283
+ align-items: flex-start;
284
+ justify-content: space-between;
285
+ gap: var(--token-space-2);
286
+ margin-bottom: var(--token-space-1);
287
+ }
288
+
289
+ .card-type-loc {
290
+ font-size: var(--token-size-sm); /* 11px */
291
+ font-weight: var(--token-weight-semibold);
292
+ color: var(--t1);
293
+ line-height: var(--token-lh-tight);
294
+ }
295
+ .card-type { color: var(--t1); }
296
+ .card-loc { color: var(--t3); font-weight: var(--token-weight-regular); }
297
+
298
+ /* Status badge */
299
+ .badge {
300
+ display: inline-flex;
301
+ align-items: center;
302
+ gap: 4px;
303
+ padding: 2px var(--token-space-2);
304
+ border-radius: var(--token-radius-full);
305
+ font-size: var(--token-size-xs); /* 10px */
306
+ font-weight: var(--token-weight-semibold);
307
+ white-space: nowrap;
308
+ flex-shrink: 0;
309
+ }
310
+ .badge::before {
311
+ content: '';
312
+ width: 6px;
313
+ height: 6px;
314
+ border-radius: var(--token-radius-full);
315
+ }
316
+
317
+ .badge-generating { background: var(--st-gen-bg); color: var(--st-gen-fg); }
318
+ .badge-generating::before { background: var(--st-gen-dot); }
319
+ .badge-validating { background: var(--st-val-bg); color: var(--st-val-fg); }
320
+ .badge-validating::before { background: var(--st-val-dot); }
321
+ .badge-passed { background: var(--st-pass-bg); color: var(--st-pass-fg); }
322
+ .badge-passed::before { background: var(--st-pass-dot); }
323
+ .badge-flagged { background: var(--st-flag-bg); color: var(--st-flag-fg); }
324
+ .badge-flagged::before { background: var(--st-flag-dot); }
325
+ .badge-regenerating{ background: var(--st-val-bg); color: var(--st-val-fg); }
326
+ .badge-regenerating::before{ background: var(--st-val-dot); }
327
+ .badge-error { background: var(--token-status-error-bg); color: var(--token-status-error-fg); }
328
+ .badge-error::before { background: var(--token-status-error-dot); }
329
+ .badge-idle { background: var(--st-idle-bg); color: var(--st-idle-fg); }
330
+ .badge-idle::before { background: var(--st-idle-dot); }
331
+
332
+ /* Card subtitle (chapter name) */
333
+ .card-subtitle {
334
+ font-size: var(--token-size-base); /* 12px */
335
+ color: var(--t2);
336
+ margin-bottom: var(--token-space-1);
337
+ line-height: var(--token-lh-tight);
338
+ white-space: nowrap;
339
+ overflow: hidden;
340
+ text-overflow: ellipsis;
341
+ }
342
+
343
+ /* Model pair line */
344
+ .card-model {
345
+ font-family: var(--token-font-mono);
346
+ font-size: var(--token-size-xs); /* 10px */
347
+ color: var(--t4);
348
+ display: flex;
349
+ align-items: center;
350
+ gap: var(--token-space-1);
351
+ }
352
+ .card-model .arrow { color: var(--t4); opacity: 0.5; }
353
+
354
+ /* Optional: score (if passed) */
355
+ .card-score {
356
+ font-family: var(--token-font-mono);
357
+ font-size: var(--token-size-xs);
358
+ color: var(--st-pass-fg);
359
+ background: var(--st-pass-bg);
360
+ padding: 1px var(--token-space-1);
361
+ border-radius: var(--token-radius-sm);
362
+ display: inline-block;
363
+ margin-top: var(--token-space-1);
364
+ }
365
+
366
+ /* Optional: flag count (if flagged) */
367
+ .card-flags {
368
+ font-size: var(--token-size-xs);
369
+ color: var(--st-flag-fg);
370
+ background: var(--st-flag-bg);
371
+ padding: 1px var(--token-space-2);
372
+ border-radius: var(--token-radius-sm);
373
+ display: inline-flex;
374
+ align-items: center;
375
+ gap: 3px;
376
+ margin-top: var(--token-space-1);
377
+ }
378
+
379
+ /* ── Card Transition Animations ─────────────────────────────── */
380
+ /* Fade-out when leaving a column: 150ms */
381
+ @keyframes card-leave {
382
+ from { opacity: 1; transform: translateY(0); }
383
+ to { opacity: 0; transform: translateY(-4px); }
384
+ }
385
+ /* Fade-in when entering a column: 250ms */
386
+ @keyframes card-enter {
387
+ from { opacity: 0; transform: translateY(4px); }
388
+ to { opacity: 1; transform: translateY(0); }
389
+ }
390
+
391
+ .card.leaving {
392
+ animation: card-leave var(--token-duration-fast) var(--token-ease-in) forwards;
393
+ }
394
+ .card.entering {
395
+ animation: card-enter var(--token-duration-normal) var(--token-ease-out) forwards;
396
+ }
397
+
398
+ /* ── Empty state ────────────────────────────────────────────── */
399
+ .col-empty {
400
+ display: flex;
401
+ align-items: center;
402
+ justify-content: center;
403
+ padding: var(--token-space-6);
404
+ color: var(--t4);
405
+ font-size: var(--token-size-sm);
406
+ flex: 1;
407
+ min-height: 80px;
408
+ }
409
+
410
+ /* ── Drag-and-drop target ───────────────────────────────────── */
411
+ .col-cards.drag-over {
412
+ background: color-mix(in srgb, var(--ac) 6%, transparent);
413
+ border-radius: var(--r);
414
+ outline: 2px dashed var(--ac);
415
+ outline-offset: -2px;
416
+ }
417
+
418
+ /* ── Flag type chips (review panel) ────────────────────────── */
419
+ .flag-chip {
420
+ display: inline-flex;
421
+ align-items: center;
422
+ padding: 2px var(--token-space-2);
423
+ border-radius: var(--token-radius-full);
424
+ font-size: var(--token-size-xs);
425
+ font-weight: var(--token-weight-medium);
426
+ }
427
+ .flag-fact { background: var(--token-flag-fact-bg); color: var(--token-flag-fact-fg); }
428
+ .flag-schema { background: var(--token-flag-schema-bg); color: var(--token-flag-schema-fg); }
429
+ .flag-borderline { background: var(--token-flag-borderline-bg); color: var(--token-flag-borderline-fg); }
430
+ .flag-sensitive { background: var(--token-flag-sensitive-bg); color: var(--token-flag-sensitive-fg); }
431
+ .flag-consistency { background: var(--token-flag-consistency-bg); color: var(--token-flag-consistency-fg); }
432
+
433
+ /* ── Severity badges ────────────────────────────────────────── */
434
+ .sev-high { color: var(--token-severity-high); }
435
+ .sev-mid { color: var(--token-severity-mid); }
436
+ .sev-low { color: var(--token-severity-low); }