@sienklogic/plan-build-run 2.34.0 → 2.38.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 (160) hide show
  1. package/CHANGELOG.md +683 -0
  2. package/dashboard/public/css/command-center.css +152 -65
  3. package/dashboard/public/css/explorer.css +22 -41
  4. package/dashboard/public/css/layout.css +119 -1
  5. package/dashboard/public/css/tokens.css +13 -0
  6. package/dashboard/src/components/Layout.tsx +32 -6
  7. package/dashboard/src/components/explorer/tabs/PhasesTab.tsx +11 -1
  8. package/dashboard/src/components/explorer/tabs/TodosTab.tsx +18 -2
  9. package/dashboard/src/components/partials/AttentionPanel.tsx +7 -1
  10. package/dashboard/src/components/partials/CurrentPhaseCard.tsx +26 -24
  11. package/dashboard/src/components/partials/QuickActions.tsx +21 -11
  12. package/dashboard/src/components/partials/StatCardGrid.tsx +67 -0
  13. package/dashboard/src/components/partials/StatusHeader.tsx +1 -0
  14. package/dashboard/src/routes/command-center.routes.tsx +8 -7
  15. package/dashboard/src/routes/index.routes.tsx +32 -29
  16. package/package.json +2 -2
  17. package/plugins/copilot-pbr/agents/audit.agent.md +129 -16
  18. package/plugins/copilot-pbr/agents/codebase-mapper.agent.md +49 -1
  19. package/plugins/copilot-pbr/agents/debugger.agent.md +50 -1
  20. package/plugins/copilot-pbr/agents/dev-sync.agent.md +23 -0
  21. package/plugins/copilot-pbr/agents/executor.agent.md +153 -8
  22. package/plugins/copilot-pbr/agents/general.agent.md +46 -1
  23. package/plugins/copilot-pbr/agents/integration-checker.agent.md +55 -2
  24. package/plugins/copilot-pbr/agents/plan-checker.agent.md +50 -2
  25. package/plugins/copilot-pbr/agents/planner.agent.md +80 -1
  26. package/plugins/copilot-pbr/agents/researcher.agent.md +50 -2
  27. package/plugins/copilot-pbr/agents/synthesizer.agent.md +49 -1
  28. package/plugins/copilot-pbr/agents/verifier.agent.md +114 -13
  29. package/plugins/copilot-pbr/commands/test.md +5 -0
  30. package/plugins/copilot-pbr/hooks/hooks.json +11 -0
  31. package/plugins/copilot-pbr/plugin.json +1 -1
  32. package/plugins/copilot-pbr/references/agent-contracts.md +27 -0
  33. package/plugins/copilot-pbr/references/checkpoints.md +32 -1
  34. package/plugins/copilot-pbr/references/context-quality-tiers.md +45 -0
  35. package/plugins/copilot-pbr/references/pbr-tools-cli.md +115 -0
  36. package/plugins/copilot-pbr/references/questioning.md +21 -1
  37. package/plugins/copilot-pbr/references/verification-patterns.md +96 -18
  38. package/plugins/copilot-pbr/skills/audit/SKILL.md +19 -3
  39. package/plugins/copilot-pbr/skills/begin/SKILL.md +57 -4
  40. package/plugins/copilot-pbr/skills/build/SKILL.md +39 -2
  41. package/plugins/copilot-pbr/skills/config/SKILL.md +12 -2
  42. package/plugins/copilot-pbr/skills/debug/SKILL.md +12 -1
  43. package/plugins/copilot-pbr/skills/explore/SKILL.md +13 -2
  44. package/plugins/copilot-pbr/skills/health/SKILL.md +13 -5
  45. package/plugins/copilot-pbr/skills/import/SKILL.md +26 -1
  46. package/plugins/copilot-pbr/skills/milestone/SKILL.md +15 -3
  47. package/plugins/copilot-pbr/skills/plan/SKILL.md +50 -0
  48. package/plugins/copilot-pbr/skills/quick/SKILL.md +21 -0
  49. package/plugins/copilot-pbr/skills/review/SKILL.md +45 -0
  50. package/plugins/copilot-pbr/skills/scan/SKILL.md +20 -0
  51. package/plugins/copilot-pbr/skills/setup/SKILL.md +9 -1
  52. package/plugins/copilot-pbr/skills/shared/context-budget.md +10 -0
  53. package/plugins/copilot-pbr/skills/shared/universal-anti-patterns.md +6 -0
  54. package/plugins/copilot-pbr/skills/test/SKILL.md +210 -0
  55. package/plugins/copilot-pbr/templates/SUMMARY-complex.md.tmpl +95 -0
  56. package/plugins/copilot-pbr/templates/SUMMARY-minimal.md.tmpl +48 -0
  57. package/plugins/cursor-pbr/.cursor-plugin/plugin.json +1 -1
  58. package/plugins/cursor-pbr/agents/audit.md +52 -5
  59. package/plugins/cursor-pbr/agents/codebase-mapper.md +49 -1
  60. package/plugins/cursor-pbr/agents/debugger.md +50 -1
  61. package/plugins/cursor-pbr/agents/dev-sync.md +23 -0
  62. package/plugins/cursor-pbr/agents/executor.md +153 -8
  63. package/plugins/cursor-pbr/agents/general.md +46 -1
  64. package/plugins/cursor-pbr/agents/integration-checker.md +54 -1
  65. package/plugins/cursor-pbr/agents/plan-checker.md +49 -1
  66. package/plugins/cursor-pbr/agents/planner.md +80 -1
  67. package/plugins/cursor-pbr/agents/researcher.md +49 -1
  68. package/plugins/cursor-pbr/agents/synthesizer.md +49 -1
  69. package/plugins/cursor-pbr/agents/verifier.md +113 -12
  70. package/plugins/cursor-pbr/commands/test.md +5 -0
  71. package/plugins/cursor-pbr/hooks/hooks.json +9 -0
  72. package/plugins/cursor-pbr/references/agent-contracts.md +27 -0
  73. package/plugins/cursor-pbr/references/checkpoints.md +32 -1
  74. package/plugins/cursor-pbr/references/context-quality-tiers.md +45 -0
  75. package/plugins/cursor-pbr/references/pbr-tools-cli.md +115 -0
  76. package/plugins/cursor-pbr/references/questioning.md +21 -1
  77. package/plugins/cursor-pbr/references/verification-patterns.md +96 -18
  78. package/plugins/cursor-pbr/skills/audit/SKILL.md +19 -3
  79. package/plugins/cursor-pbr/skills/begin/SKILL.md +57 -4
  80. package/plugins/cursor-pbr/skills/build/SKILL.md +37 -2
  81. package/plugins/cursor-pbr/skills/config/SKILL.md +12 -2
  82. package/plugins/cursor-pbr/skills/debug/SKILL.md +12 -1
  83. package/plugins/cursor-pbr/skills/explore/SKILL.md +13 -2
  84. package/plugins/cursor-pbr/skills/health/SKILL.md +14 -5
  85. package/plugins/cursor-pbr/skills/import/SKILL.md +26 -1
  86. package/plugins/cursor-pbr/skills/milestone/SKILL.md +15 -3
  87. package/plugins/cursor-pbr/skills/plan/SKILL.md +50 -0
  88. package/plugins/cursor-pbr/skills/quick/SKILL.md +21 -0
  89. package/plugins/cursor-pbr/skills/review/SKILL.md +45 -0
  90. package/plugins/cursor-pbr/skills/scan/SKILL.md +20 -0
  91. package/plugins/cursor-pbr/skills/setup/SKILL.md +9 -1
  92. package/plugins/cursor-pbr/skills/shared/context-budget.md +10 -0
  93. package/plugins/cursor-pbr/skills/shared/universal-anti-patterns.md +6 -0
  94. package/plugins/cursor-pbr/skills/test/SKILL.md +211 -0
  95. package/plugins/cursor-pbr/templates/SUMMARY-complex.md.tmpl +95 -0
  96. package/plugins/cursor-pbr/templates/SUMMARY-minimal.md.tmpl +48 -0
  97. package/plugins/pbr/.claude-plugin/plugin.json +1 -1
  98. package/plugins/pbr/agents/audit.md +45 -0
  99. package/plugins/pbr/agents/codebase-mapper.md +48 -0
  100. package/plugins/pbr/agents/debugger.md +49 -0
  101. package/plugins/pbr/agents/dev-sync.md +23 -0
  102. package/plugins/pbr/agents/executor.md +151 -6
  103. package/plugins/pbr/agents/general.md +45 -0
  104. package/plugins/pbr/agents/integration-checker.md +53 -0
  105. package/plugins/pbr/agents/plan-checker.md +48 -0
  106. package/plugins/pbr/agents/planner.md +78 -1
  107. package/plugins/pbr/agents/researcher.md +48 -0
  108. package/plugins/pbr/agents/synthesizer.md +48 -0
  109. package/plugins/pbr/agents/verifier.md +112 -11
  110. package/plugins/pbr/commands/test.md +5 -0
  111. package/plugins/pbr/hooks/hooks.json +9 -0
  112. package/plugins/pbr/references/agent-contracts.md +27 -0
  113. package/plugins/pbr/references/checkpoints.md +32 -0
  114. package/plugins/pbr/references/context-quality-tiers.md +45 -0
  115. package/plugins/pbr/references/pbr-tools-cli.md +115 -0
  116. package/plugins/pbr/references/questioning.md +21 -0
  117. package/plugins/pbr/references/verification-patterns.md +96 -17
  118. package/plugins/pbr/scripts/check-plan-format.js +13 -1
  119. package/plugins/pbr/scripts/check-state-sync.js +26 -7
  120. package/plugins/pbr/scripts/check-subagent-output.js +30 -2
  121. package/plugins/pbr/scripts/config-schema.json +11 -1
  122. package/plugins/pbr/scripts/context-bridge.js +265 -0
  123. package/plugins/pbr/scripts/lib/config.js +271 -0
  124. package/plugins/pbr/scripts/lib/core.js +587 -0
  125. package/plugins/pbr/scripts/lib/history.js +73 -0
  126. package/plugins/pbr/scripts/lib/init.js +166 -0
  127. package/plugins/pbr/scripts/lib/migrate.js +169 -0
  128. package/plugins/pbr/scripts/lib/phase.js +364 -0
  129. package/plugins/pbr/scripts/lib/roadmap.js +175 -0
  130. package/plugins/pbr/scripts/lib/state.js +397 -0
  131. package/plugins/pbr/scripts/lib/todo.js +300 -0
  132. package/plugins/pbr/scripts/pbr-tools.js +425 -1310
  133. package/plugins/pbr/scripts/post-write-dispatch.js +5 -4
  134. package/plugins/pbr/scripts/pre-write-dispatch.js +1 -1
  135. package/plugins/pbr/scripts/progress-tracker.js +1 -1
  136. package/plugins/pbr/scripts/suggest-compact.js +1 -1
  137. package/plugins/pbr/scripts/track-context-budget.js +53 -2
  138. package/plugins/pbr/scripts/validate-task.js +20 -28
  139. package/plugins/pbr/skills/audit/SKILL.md +19 -3
  140. package/plugins/pbr/skills/begin/SKILL.md +48 -2
  141. package/plugins/pbr/skills/build/SKILL.md +39 -2
  142. package/plugins/pbr/skills/config/SKILL.md +12 -2
  143. package/plugins/pbr/skills/debug/SKILL.md +12 -1
  144. package/plugins/pbr/skills/debug/templates/continuation-prompt.md.tmpl +12 -1
  145. package/plugins/pbr/skills/debug/templates/initial-investigation-prompt.md.tmpl +12 -5
  146. package/plugins/pbr/skills/explore/SKILL.md +13 -2
  147. package/plugins/pbr/skills/health/SKILL.md +14 -3
  148. package/plugins/pbr/skills/help/SKILL.md +2 -0
  149. package/plugins/pbr/skills/import/SKILL.md +26 -1
  150. package/plugins/pbr/skills/milestone/SKILL.md +15 -3
  151. package/plugins/pbr/skills/plan/SKILL.md +52 -2
  152. package/plugins/pbr/skills/quick/SKILL.md +21 -0
  153. package/plugins/pbr/skills/review/SKILL.md +46 -0
  154. package/plugins/pbr/skills/scan/SKILL.md +20 -0
  155. package/plugins/pbr/skills/setup/SKILL.md +9 -1
  156. package/plugins/pbr/skills/shared/context-budget.md +10 -0
  157. package/plugins/pbr/skills/shared/universal-anti-patterns.md +6 -0
  158. package/plugins/pbr/skills/test/SKILL.md +212 -0
  159. package/plugins/pbr/templates/SUMMARY-complex.md.tmpl +95 -0
  160. package/plugins/pbr/templates/SUMMARY-minimal.md.tmpl +48 -0
@@ -5,6 +5,83 @@
5
5
  All values use tokens from tokens.css.
6
6
  ============================================ */
7
7
 
8
+ /* --- Stat Card Grid --- */
9
+ .stat-card-grid {
10
+ display: grid;
11
+ grid-template-columns: repeat(4, 1fr);
12
+ gap: var(--space-md);
13
+ margin-bottom: var(--space-lg);
14
+ }
15
+
16
+ .stat-card {
17
+ background: var(--card-bg);
18
+ border: 1px solid var(--card-border);
19
+ border-radius: var(--card-radius);
20
+ box-shadow: var(--card-shadow);
21
+ padding: var(--stat-card-padding);
22
+ display: flex;
23
+ flex-direction: column;
24
+ gap: var(--space-xs);
25
+ transition: box-shadow var(--transition-fast);
26
+ }
27
+
28
+ .stat-card:hover {
29
+ box-shadow: var(--shadow-md);
30
+ }
31
+
32
+ .stat-card--accent {
33
+ border-left: 3px solid var(--color-accent);
34
+ }
35
+
36
+ .stat-card__label {
37
+ font-size: var(--stat-card-label-size);
38
+ font-weight: 600;
39
+ text-transform: uppercase;
40
+ letter-spacing: 0.08em;
41
+ color: var(--color-text-muted);
42
+ }
43
+
44
+ .stat-card__value {
45
+ font-size: var(--stat-card-value-size);
46
+ font-weight: 700;
47
+ line-height: 1.1;
48
+ color: var(--color-text);
49
+ letter-spacing: -0.02em;
50
+ }
51
+
52
+ .stat-card__sub {
53
+ font-size: var(--stat-card-sub-size);
54
+ color: var(--color-text-dim);
55
+ line-height: 1.4;
56
+ }
57
+
58
+ .stat-card__mini-bar {
59
+ height: 4px;
60
+ border-radius: var(--radius-lg);
61
+ background: var(--color-border);
62
+ overflow: hidden;
63
+ margin-top: var(--space-xs);
64
+ }
65
+
66
+ .stat-card__mini-bar-fill {
67
+ height: 100%;
68
+ border-radius: var(--radius-lg);
69
+ background: var(--color-accent);
70
+ transition: width var(--transition-base);
71
+ }
72
+
73
+ @media (max-width: 900px) {
74
+ .stat-card-grid {
75
+ grid-template-columns: repeat(2, 1fr);
76
+ }
77
+ }
78
+
79
+ @media (max-width: 480px) {
80
+ .stat-card-grid {
81
+ grid-template-columns: 1fr;
82
+ }
83
+ }
84
+
8
85
  /* --- Command Center Layout --- */
9
86
  .command-center {
10
87
  display: flex;
@@ -26,6 +103,68 @@
26
103
  }
27
104
  }
28
105
 
106
+ /* --- Command Center Two-Column Layout --- */
107
+ .cc-two-col {
108
+ display: grid;
109
+ grid-template-columns: 1fr 360px;
110
+ gap: var(--space-lg);
111
+ align-items: start;
112
+ }
113
+
114
+ .cc-col-main {
115
+ display: flex;
116
+ flex-direction: column;
117
+ gap: var(--space-lg);
118
+ }
119
+
120
+ .cc-col-side {
121
+ display: flex;
122
+ flex-direction: column;
123
+ gap: var(--space-lg);
124
+ }
125
+
126
+ @media (max-width: 900px) {
127
+ .cc-two-col {
128
+ grid-template-columns: 1fr;
129
+ }
130
+ }
131
+
132
+ /* --- Empty State --- */
133
+ .empty-state {
134
+ display: flex;
135
+ flex-direction: column;
136
+ align-items: center;
137
+ justify-content: center;
138
+ padding: var(--space-xl) var(--space-lg);
139
+ text-align: center;
140
+ gap: var(--space-sm);
141
+ }
142
+
143
+ .empty-state__icon {
144
+ font-size: 2rem;
145
+ color: var(--color-text-muted);
146
+ line-height: 1;
147
+ margin-bottom: var(--space-xs);
148
+ }
149
+
150
+ .empty-state__heading {
151
+ font-size: 0.9375rem;
152
+ font-weight: 600;
153
+ color: var(--color-text);
154
+ margin: 0;
155
+ }
156
+
157
+ .empty-state__body {
158
+ font-size: 0.875rem;
159
+ color: var(--color-text-dim);
160
+ margin: 0;
161
+ max-width: 240px;
162
+ }
163
+
164
+ .empty-state__action {
165
+ margin-top: var(--space-xs);
166
+ }
167
+
29
168
  /* --- Status Header --- */
30
169
  .status-header {
31
170
  display: flex;
@@ -119,11 +258,11 @@
119
258
  }
120
259
 
121
260
  .card__header {
122
- font-size: 0.75rem;
123
- font-weight: 600;
261
+ font-size: var(--section-label-size);
262
+ font-weight: var(--section-label-weight);
124
263
  text-transform: uppercase;
125
- letter-spacing: 0.08em;
126
- color: var(--color-text-muted);
264
+ letter-spacing: var(--section-label-spacing);
265
+ color: var(--section-label-color);
127
266
  padding-bottom: var(--space-sm);
128
267
  border-bottom: 1px solid var(--color-border);
129
268
  margin-bottom: var(--space-md);
@@ -203,11 +342,11 @@
203
342
  }
204
343
 
205
344
  .phase-timeline__label {
206
- font-size: 0.75rem;
207
- font-weight: 600;
345
+ font-size: var(--section-label-size);
346
+ font-weight: var(--section-label-weight);
208
347
  text-transform: uppercase;
209
- letter-spacing: 0.08em;
210
- color: var(--color-text-muted);
348
+ letter-spacing: var(--section-label-spacing);
349
+ color: var(--section-label-color);
211
350
  margin-bottom: var(--space-sm);
212
351
  }
213
352
 
@@ -314,11 +453,11 @@
314
453
  }
315
454
 
316
455
  .quick-actions__label {
317
- font-size: 0.75rem;
318
- font-weight: 600;
456
+ font-size: var(--section-label-size);
457
+ font-weight: var(--section-label-weight);
319
458
  text-transform: uppercase;
320
- letter-spacing: 0.08em;
321
- color: var(--color-text-muted);
459
+ letter-spacing: var(--section-label-spacing);
460
+ color: var(--section-label-color);
322
461
  }
323
462
 
324
463
  .quick-actions__buttons {
@@ -327,56 +466,4 @@
327
466
  gap: var(--space-sm);
328
467
  }
329
468
 
330
- /* --- Buttons --- */
331
- .btn {
332
- display: inline-flex;
333
- align-items: center;
334
- justify-content: center;
335
- padding: var(--space-xs) var(--space-md);
336
- border-radius: var(--radius-sm);
337
- font-size: 0.875rem;
338
- font-weight: 500;
339
- text-decoration: none;
340
- cursor: pointer;
341
- border: 1px solid transparent;
342
- transition: background var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast);
343
- }
344
-
345
- .btn--primary {
346
- background: var(--color-accent);
347
- color: #fff;
348
- border-color: var(--color-accent);
349
- }
350
-
351
- .btn--primary:hover {
352
- background: var(--color-accent-hover);
353
- border-color: var(--color-accent-hover);
354
- color: #fff;
355
- text-decoration: none;
356
- }
357
-
358
- .btn--secondary {
359
- background: transparent;
360
- color: var(--color-text);
361
- border-color: var(--color-border);
362
- }
363
-
364
- .btn--secondary:hover {
365
- background: var(--color-surface-hover);
366
- text-decoration: none;
367
- }
368
-
369
- .btn--ghost {
370
- background: transparent;
371
- color: var(--color-text-dim);
372
- border-color: transparent;
373
- }
374
-
375
- .btn--ghost:hover {
376
- background: var(--color-surface-hover);
377
- }
378
-
379
- .btn--sm {
380
- padding: 2px var(--space-sm);
381
- font-size: 0.75rem;
382
- }
469
+ /* .btn system defined in layout.css */
@@ -312,6 +312,23 @@
312
312
  font-size: 0.9rem;
313
313
  }
314
314
 
315
+ .explorer-filter-select {
316
+ padding: var(--space-xs) var(--space-sm);
317
+ border: 1px solid var(--color-border);
318
+ border-radius: var(--radius-sm);
319
+ background: var(--color-surface);
320
+ color: var(--color-text);
321
+ font-size: 0.875rem;
322
+ font-family: var(--font-sans);
323
+ cursor: pointer;
324
+ min-width: 120px;
325
+ }
326
+
327
+ .explorer-filter-select:focus {
328
+ outline: 2px solid var(--color-accent);
329
+ outline-offset: 1px;
330
+ }
331
+
315
332
  .explorer-create-form {
316
333
  background: var(--color-surface-raised);
317
334
  border: 1px solid var(--color-border);
@@ -321,51 +338,15 @@
321
338
  }
322
339
 
323
340
  .explorer-section-title {
324
- font-size: 0.85rem;
325
- font-weight: 600;
326
- color: var(--color-text-dim);
341
+ font-size: var(--section-label-size);
342
+ font-weight: var(--section-label-weight);
343
+ color: var(--section-label-color);
327
344
  text-transform: uppercase;
328
- letter-spacing: 0.05em;
345
+ letter-spacing: var(--section-label-spacing);
329
346
  margin: var(--space-md) 0 var(--space-sm);
330
347
  }
331
348
 
332
- /* ---- Button system ---- */
333
-
334
- .btn {
335
- display: inline-flex;
336
- align-items: center;
337
- gap: 4px;
338
- padding: var(--space-xs) var(--space-sm);
339
- border-radius: var(--radius-sm);
340
- border: 1px solid transparent;
341
- cursor: pointer;
342
- font-size: 0.875rem;
343
- font-weight: 500;
344
- transition: all 0.15s;
345
- }
346
-
347
- .btn--primary {
348
- background: var(--color-accent);
349
- color: white;
350
- border-color: var(--color-accent);
351
- }
352
-
353
- .btn--ghost {
354
- background: none;
355
- color: var(--color-text-dim);
356
- border-color: var(--color-border);
357
- }
358
-
359
- .btn--sm {
360
- padding: 2px var(--space-xs);
361
- font-size: 0.8rem;
362
- }
363
-
364
- .btn--danger {
365
- background: var(--color-error-bg);
366
- color: var(--color-error);
367
- border-color: var(--color-error);
368
- }
349
+ /* .btn system defined in layout.css */
369
350
 
370
351
  /* ---- Priority badge modifiers ---- */
371
352
 
@@ -42,6 +42,10 @@ a:hover {
42
42
  text-decoration: underline;
43
43
  }
44
44
 
45
+ button, [role="button"], summary, label[for] {
46
+ cursor: pointer;
47
+ }
48
+
45
49
  code, pre, kbd, samp {
46
50
  font-family: var(--font-mono);
47
51
  font-size: 0.875em;
@@ -160,6 +164,38 @@ body.sidebar-visible .main-content::before {
160
164
  letter-spacing: 0.02em;
161
165
  }
162
166
 
167
+ /* --- Sidebar Brand Icon --- */
168
+ .sidebar__brand {
169
+ flex-direction: row;
170
+ align-items: center;
171
+ gap: var(--space-sm);
172
+ }
173
+
174
+ .sidebar__brand-icon {
175
+ display: flex;
176
+ align-items: center;
177
+ color: var(--color-accent);
178
+ flex-shrink: 0;
179
+ }
180
+
181
+ .sidebar__brand-text {
182
+ display: flex;
183
+ flex-direction: column;
184
+ }
185
+
186
+ /* --- Sidebar Nav Icon --- */
187
+ .sidebar__nav-icon {
188
+ display: flex;
189
+ align-items: center;
190
+ flex-shrink: 0;
191
+ opacity: 0.7;
192
+ }
193
+
194
+ .sidebar__nav-link--active .sidebar__nav-icon,
195
+ .sidebar__nav-link[aria-current="page"] .sidebar__nav-icon {
196
+ opacity: 1;
197
+ }
198
+
163
199
  /* --- Sidebar Navigation --- */
164
200
  .sidebar__nav {
165
201
  list-style: none;
@@ -173,7 +209,9 @@ body.sidebar-visible .main-content::before {
173
209
  }
174
210
 
175
211
  .sidebar__nav-link {
176
- display: block;
212
+ display: flex;
213
+ align-items: center;
214
+ gap: var(--space-sm);
177
215
  padding: var(--space-sm) var(--space-lg);
178
216
  font-size: 0.875rem;
179
217
  font-weight: 500;
@@ -267,6 +305,71 @@ body.sidebar-visible .main-content::before {
267
305
  text-align: center;
268
306
  }
269
307
 
308
+ /* --- Button System (single source of truth) --- */
309
+ .btn {
310
+ display: inline-flex;
311
+ align-items: center;
312
+ gap: 4px;
313
+ padding: var(--space-xs) var(--space-md);
314
+ border-radius: var(--radius-sm);
315
+ font-size: 0.875rem;
316
+ font-weight: 500;
317
+ cursor: pointer;
318
+ border: 1px solid transparent;
319
+ transition: background var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast), box-shadow var(--transition-fast);
320
+ text-decoration: none;
321
+ }
322
+
323
+ .btn:focus-visible {
324
+ outline: 2px solid var(--color-accent);
325
+ outline-offset: 2px;
326
+ }
327
+
328
+ .btn--primary {
329
+ background: var(--color-accent);
330
+ color: #fff;
331
+ border-color: var(--color-accent);
332
+ }
333
+
334
+ .btn--primary:hover {
335
+ background: var(--color-accent-hover);
336
+ border-color: var(--color-accent-hover);
337
+ color: #fff;
338
+ text-decoration: none;
339
+ }
340
+
341
+ .btn--secondary {
342
+ background: transparent;
343
+ color: var(--color-text);
344
+ border-color: var(--color-border);
345
+ }
346
+
347
+ .btn--secondary:hover {
348
+ background: var(--color-surface-hover);
349
+ text-decoration: none;
350
+ }
351
+
352
+ .btn--ghost {
353
+ background: transparent;
354
+ color: var(--color-text-dim);
355
+ border-color: transparent;
356
+ }
357
+
358
+ .btn--ghost:hover {
359
+ background: var(--color-surface-hover);
360
+ }
361
+
362
+ .btn--sm {
363
+ padding: 2px var(--space-sm);
364
+ font-size: 0.75rem;
365
+ }
366
+
367
+ .btn--danger {
368
+ background: var(--color-error-bg);
369
+ color: var(--color-error);
370
+ border-color: var(--color-error);
371
+ }
372
+
270
373
  /* --- Card Component --- */
271
374
  .card,
272
375
  article {
@@ -275,6 +378,12 @@ article {
275
378
  background: var(--card-bg);
276
379
  box-shadow: var(--card-shadow);
277
380
  margin-bottom: var(--space-lg);
381
+ transition: box-shadow var(--transition-fast);
382
+ }
383
+
384
+ .card:hover,
385
+ article:hover {
386
+ box-shadow: var(--shadow-md);
278
387
  }
279
388
 
280
389
  .card__header,
@@ -291,6 +400,15 @@ article > header strong {
291
400
  font-weight: 600;
292
401
  }
293
402
 
403
+ /* Reusable section label — same treatment as card headers */
404
+ .section-label {
405
+ font-size: var(--section-label-size);
406
+ font-weight: var(--section-label-weight);
407
+ text-transform: uppercase;
408
+ letter-spacing: var(--section-label-spacing);
409
+ color: var(--section-label-color);
410
+ }
411
+
294
412
  .card__body {
295
413
  padding: var(--card-padding) var(--space-lg);
296
414
  }
@@ -69,6 +69,19 @@
69
69
  --badge-font-size-sm: 0.6875rem;
70
70
  --badge-font-size-base: 0.75rem;
71
71
  --badge-font-size-lg: 0.8125rem;
72
+
73
+ /* Stat card tokens */
74
+ --stat-card-padding: var(--space-md) var(--space-lg);
75
+ --stat-card-value-size: 2rem;
76
+ --stat-card-label-size: 0.6875rem;
77
+ --stat-card-sub-size: 0.8125rem;
78
+ --sidebar-icon-size: 16px;
79
+
80
+ /* Section label tokens */
81
+ --section-label-size: 0.6875rem;
82
+ --section-label-weight: 600;
83
+ --section-label-spacing: 0.08em;
84
+ --section-label-color: var(--color-text-muted);
72
85
  }
73
86
 
74
87
  /* --- Dark Mode (explicit [data-theme="dark"] attribute) --- */
@@ -7,10 +7,30 @@ interface LayoutProps {
7
7
  }
8
8
 
9
9
  const navItems = [
10
- { href: '/', label: 'Command Center', view: 'home' },
11
- { href: '/explorer', label: 'Explorer', view: 'explorer' },
12
- { href: '/timeline', label: 'Timeline', view: 'timeline' },
13
- { href: '/settings', label: 'Settings', view: 'settings' },
10
+ {
11
+ href: '/',
12
+ label: 'Command Center',
13
+ view: 'home',
14
+ icon: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/></svg>',
15
+ },
16
+ {
17
+ href: '/explorer',
18
+ label: 'Explorer',
19
+ view: 'explorer',
20
+ icon: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>',
21
+ },
22
+ {
23
+ href: '/timeline',
24
+ label: 'Timeline',
25
+ view: 'timeline',
26
+ icon: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></svg>',
27
+ },
28
+ {
29
+ href: '/settings',
30
+ label: 'Settings',
31
+ view: 'settings',
32
+ icon: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><line x1="4" y1="21" x2="4" y2="14"/><line x1="4" y1="10" x2="4" y2="3"/><line x1="12" y1="21" x2="12" y2="12"/><line x1="12" y1="8" x2="12" y2="3"/><line x1="20" y1="21" x2="20" y2="16"/><line x1="20" y1="12" x2="20" y2="3"/><line x1="1" y1="14" x2="7" y2="14"/><line x1="9" y1="8" x2="15" y2="8"/><line x1="17" y1="16" x2="23" y2="16"/></svg>',
33
+ },
14
34
  ];
15
35
 
16
36
  export function Layout({ title, children, currentView }: LayoutProps) {
@@ -73,8 +93,13 @@ export function Layout({ title, children, currentView }: LayoutProps) {
73
93
 
74
94
  <nav class="sidebar" aria-label="Main navigation">
75
95
  <div class="sidebar__brand">
76
- <span class="sidebar__brand-name">PBR</span>
77
- <span class="sidebar__brand-subtitle">Dashboard</span>
96
+ <span class="sidebar__brand-icon" aria-hidden="true">
97
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>
98
+ </span>
99
+ <div class="sidebar__brand-text">
100
+ <span class="sidebar__brand-name">PBR</span>
101
+ <span class="sidebar__brand-subtitle">Dashboard</span>
102
+ </div>
78
103
  </div>
79
104
 
80
105
  <ul class="sidebar__nav" role="list">
@@ -88,6 +113,7 @@ export function Layout({ title, children, currentView }: LayoutProps) {
88
113
  class={`sidebar__nav-link${isActive ? ' sidebar__nav-link--active' : ''}`}
89
114
  aria-current={isActive ? 'page' : undefined}
90
115
  >
116
+ <span class="sidebar__nav-icon" aria-hidden="true" dangerouslySetInnerHTML={{ __html: item.icon }} />
91
117
  {item.label}
92
118
  </a>
93
119
  </li>
@@ -3,6 +3,9 @@ interface Phase {
3
3
  name: string;
4
4
  status: string;
5
5
  planCount?: number;
6
+ plansComplete?: number;
7
+ plansTotal?: number;
8
+ lastActivity?: string | null;
6
9
  }
7
10
 
8
11
  interface Plan {
@@ -74,8 +77,15 @@ function PhaseItem({ phase }: { phase: Phase }) {
74
77
  </span>
75
78
  <span class={statusBadgeClass(phase.status)}>{phase.status}</span>
76
79
  <span class="explorer-item__meta">
77
- {phase.planCount != null ? `${phase.planCount} plan${phase.planCount !== 1 ? 's' : ''}` : ''}
80
+ {(phase.plansComplete != null && phase.plansTotal != null)
81
+ ? (phase.plansComplete === 0 && phase.plansTotal === 0
82
+ ? '—'
83
+ : `${phase.plansComplete}/${phase.plansTotal} plans`)
84
+ : (phase.planCount != null
85
+ ? `${phase.planCount} plan${phase.planCount !== 1 ? 's' : ''}`
86
+ : '')}
78
87
  </span>
88
+ <span class="explorer-item__meta">{phase.lastActivity || '—'}</span>
79
89
  </div>
80
90
 
81
91
  {/* Body is only shown when open. The inner div fires hx-get on load (once the body is visible). */}
@@ -19,7 +19,7 @@ interface TodoListFragmentProps {
19
19
 
20
20
  export function TodosTab({ todos }: TodosTabProps) {
21
21
  return (
22
- <div x-data="{ showCreate: false, showDone: false, search: '' }">
22
+ <div x-data="{ showCreate: false, showDone: false, search: '', statusFilter: '', priorityFilter: '', applyFilters() {} }">
23
23
  {/* Search + filters row */}
24
24
  <div class="explorer-toolbar">
25
25
  <input
@@ -29,6 +29,22 @@ export function TodosTab({ todos }: TodosTabProps) {
29
29
  class="explorer-search"
30
30
  aria-label="Filter todos by title"
31
31
  />
32
+ <select class="explorer-filter-select" aria-label="Filter by status"
33
+ x-model="statusFilter"
34
+ x-on:change="applyFilters()">
35
+ <option value="">All statuses</option>
36
+ <option value="pending">Pending</option>
37
+ <option value="in-progress">In Progress</option>
38
+ <option value="done">Done</option>
39
+ </select>
40
+ <select class="explorer-filter-select" aria-label="Filter by priority"
41
+ x-model="priorityFilter"
42
+ x-on:change="applyFilters()">
43
+ <option value="">All priorities</option>
44
+ <option value="high">High</option>
45
+ <option value="medium">Medium</option>
46
+ <option value="low">Low</option>
47
+ </select>
32
48
  <button x-on:click="showCreate = !showCreate" class="btn btn--primary btn--sm">
33
49
  + New Todo
34
50
  </button>
@@ -76,7 +92,7 @@ export function TodoListFragment({ todos }: TodoListFragmentProps) {
76
92
  <li
77
93
  class={`todo-card todo-card--${todo.priority}`}
78
94
  key={todo.id}
79
- x-show={`!search || '${todo.title.toLowerCase()}'.includes(search.toLowerCase())`}
95
+ x-show={`(!search || '${todo.title.toLowerCase()}'.includes(search.toLowerCase())) && (!priorityFilter || priorityFilter === '${todo.priority}') && (!statusFilter || statusFilter === '${todo.status || ''}')`}
80
96
  >
81
97
  <div class="todo-card__main">
82
98
  <span class={`explorer-badge explorer-badge--${todo.priority}`}>{todo.priority}</span>
@@ -41,7 +41,13 @@ export const AttentionPanel: FC<AttentionPanelProps> = ({
41
41
  ))}
42
42
  </ul>
43
43
  ) : (
44
- <p class="attention-panel__clear">All clear — nothing needs attention.</p>
44
+ <div class="empty-state">
45
+ <span class="empty-state__icon" aria-hidden="true">
46
+ <svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>
47
+ </span>
48
+ <p class="empty-state__heading">All clear</p>
49
+ <p class="empty-state__body">No blockers or attention items right now.</p>
50
+ </div>
45
51
  )}
46
52
  </div>
47
53
  );