@sienklogic/plan-build-run 2.33.1 → 2.37.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 (140) hide show
  1. package/CHANGELOG.md +678 -0
  2. package/dashboard/public/css/command-center.css +152 -65
  3. package/dashboard/public/css/explorer.css +70 -41
  4. package/dashboard/public/css/layout.css +163 -2
  5. package/dashboard/public/css/settings.css +108 -110
  6. package/dashboard/public/css/timeline.css +2 -1
  7. package/dashboard/public/css/tokens.css +13 -0
  8. package/dashboard/public/js/sidebar-toggle.js +21 -7
  9. package/dashboard/src/components/Layout.tsx +51 -7
  10. package/dashboard/src/components/explorer/tabs/MilestonesTab.tsx +18 -2
  11. package/dashboard/src/components/explorer/tabs/PhasesTab.tsx +11 -1
  12. package/dashboard/src/components/explorer/tabs/TodosTab.tsx +25 -6
  13. package/dashboard/src/components/partials/AttentionPanel.tsx +7 -1
  14. package/dashboard/src/components/partials/CurrentPhaseCard.tsx +26 -24
  15. package/dashboard/src/components/partials/QuickActions.tsx +21 -11
  16. package/dashboard/src/components/partials/StatCardGrid.tsx +67 -0
  17. package/dashboard/src/components/partials/StatusHeader.tsx +2 -1
  18. package/dashboard/src/components/settings/LogEntryList.tsx +43 -5
  19. package/dashboard/src/routes/command-center.routes.tsx +8 -7
  20. package/dashboard/src/routes/index.routes.tsx +32 -29
  21. package/package.json +2 -2
  22. package/plugins/copilot-pbr/agents/audit.agent.md +128 -16
  23. package/plugins/copilot-pbr/agents/codebase-mapper.agent.md +48 -1
  24. package/plugins/copilot-pbr/agents/debugger.agent.md +47 -1
  25. package/plugins/copilot-pbr/agents/executor.agent.md +152 -8
  26. package/plugins/copilot-pbr/agents/general.agent.md +46 -1
  27. package/plugins/copilot-pbr/agents/integration-checker.agent.md +52 -2
  28. package/plugins/copilot-pbr/agents/plan-checker.agent.md +50 -2
  29. package/plugins/copilot-pbr/agents/planner.agent.md +54 -1
  30. package/plugins/copilot-pbr/agents/researcher.agent.md +47 -2
  31. package/plugins/copilot-pbr/agents/synthesizer.agent.md +49 -1
  32. package/plugins/copilot-pbr/agents/verifier.agent.md +86 -2
  33. package/plugins/copilot-pbr/hooks/hooks.json +11 -0
  34. package/plugins/copilot-pbr/plugin.json +1 -1
  35. package/plugins/copilot-pbr/references/agent-contracts.md +27 -0
  36. package/plugins/copilot-pbr/references/checkpoints.md +32 -1
  37. package/plugins/copilot-pbr/references/context-quality-tiers.md +45 -0
  38. package/plugins/copilot-pbr/references/pbr-tools-cli.md +115 -0
  39. package/plugins/copilot-pbr/references/questioning.md +21 -1
  40. package/plugins/copilot-pbr/references/verification-patterns.md +52 -1
  41. package/plugins/copilot-pbr/skills/audit/SKILL.md +19 -3
  42. package/plugins/copilot-pbr/skills/begin/SKILL.md +57 -4
  43. package/plugins/copilot-pbr/skills/build/SKILL.md +39 -2
  44. package/plugins/copilot-pbr/skills/debug/SKILL.md +12 -1
  45. package/plugins/copilot-pbr/skills/explore/SKILL.md +13 -2
  46. package/plugins/copilot-pbr/skills/import/SKILL.md +26 -1
  47. package/plugins/copilot-pbr/skills/milestone/SKILL.md +15 -3
  48. package/plugins/copilot-pbr/skills/plan/SKILL.md +50 -0
  49. package/plugins/copilot-pbr/skills/quick/SKILL.md +21 -0
  50. package/plugins/copilot-pbr/skills/review/SKILL.md +45 -0
  51. package/plugins/copilot-pbr/skills/scan/SKILL.md +20 -0
  52. package/plugins/copilot-pbr/templates/SUMMARY-complex.md.tmpl +95 -0
  53. package/plugins/copilot-pbr/templates/SUMMARY-minimal.md.tmpl +48 -0
  54. package/plugins/cursor-pbr/.cursor-plugin/plugin.json +1 -1
  55. package/plugins/cursor-pbr/agents/audit.md +51 -5
  56. package/plugins/cursor-pbr/agents/codebase-mapper.md +48 -1
  57. package/plugins/cursor-pbr/agents/debugger.md +47 -1
  58. package/plugins/cursor-pbr/agents/executor.md +152 -8
  59. package/plugins/cursor-pbr/agents/general.md +46 -1
  60. package/plugins/cursor-pbr/agents/integration-checker.md +51 -1
  61. package/plugins/cursor-pbr/agents/plan-checker.md +49 -1
  62. package/plugins/cursor-pbr/agents/planner.md +54 -1
  63. package/plugins/cursor-pbr/agents/researcher.md +46 -1
  64. package/plugins/cursor-pbr/agents/synthesizer.md +49 -1
  65. package/plugins/cursor-pbr/agents/verifier.md +85 -1
  66. package/plugins/cursor-pbr/hooks/hooks.json +9 -0
  67. package/plugins/cursor-pbr/references/agent-contracts.md +27 -0
  68. package/plugins/cursor-pbr/references/checkpoints.md +32 -1
  69. package/plugins/cursor-pbr/references/context-quality-tiers.md +45 -0
  70. package/plugins/cursor-pbr/references/pbr-tools-cli.md +115 -0
  71. package/plugins/cursor-pbr/references/questioning.md +21 -1
  72. package/plugins/cursor-pbr/references/verification-patterns.md +52 -1
  73. package/plugins/cursor-pbr/skills/audit/SKILL.md +19 -3
  74. package/plugins/cursor-pbr/skills/begin/SKILL.md +57 -4
  75. package/plugins/cursor-pbr/skills/build/SKILL.md +37 -2
  76. package/plugins/cursor-pbr/skills/debug/SKILL.md +12 -1
  77. package/plugins/cursor-pbr/skills/explore/SKILL.md +13 -2
  78. package/plugins/cursor-pbr/skills/import/SKILL.md +26 -1
  79. package/plugins/cursor-pbr/skills/milestone/SKILL.md +15 -3
  80. package/plugins/cursor-pbr/skills/plan/SKILL.md +50 -0
  81. package/plugins/cursor-pbr/skills/quick/SKILL.md +21 -0
  82. package/plugins/cursor-pbr/skills/review/SKILL.md +45 -0
  83. package/plugins/cursor-pbr/skills/scan/SKILL.md +20 -0
  84. package/plugins/cursor-pbr/templates/SUMMARY-complex.md.tmpl +95 -0
  85. package/plugins/cursor-pbr/templates/SUMMARY-minimal.md.tmpl +48 -0
  86. package/plugins/pbr/.claude-plugin/plugin.json +1 -1
  87. package/plugins/pbr/agents/audit.md +44 -0
  88. package/plugins/pbr/agents/codebase-mapper.md +47 -0
  89. package/plugins/pbr/agents/debugger.md +46 -0
  90. package/plugins/pbr/agents/executor.md +150 -6
  91. package/plugins/pbr/agents/general.md +45 -0
  92. package/plugins/pbr/agents/integration-checker.md +50 -0
  93. package/plugins/pbr/agents/plan-checker.md +48 -0
  94. package/plugins/pbr/agents/planner.md +51 -0
  95. package/plugins/pbr/agents/researcher.md +45 -0
  96. package/plugins/pbr/agents/synthesizer.md +48 -0
  97. package/plugins/pbr/agents/verifier.md +84 -0
  98. package/plugins/pbr/hooks/hooks.json +9 -0
  99. package/plugins/pbr/references/agent-contracts.md +27 -0
  100. package/plugins/pbr/references/checkpoints.md +32 -0
  101. package/plugins/pbr/references/context-quality-tiers.md +45 -0
  102. package/plugins/pbr/references/pbr-tools-cli.md +115 -0
  103. package/plugins/pbr/references/questioning.md +21 -0
  104. package/plugins/pbr/references/verification-patterns.md +52 -0
  105. package/plugins/pbr/scripts/check-plan-format.js +15 -3
  106. package/plugins/pbr/scripts/check-state-sync.js +26 -7
  107. package/plugins/pbr/scripts/check-subagent-output.js +30 -2
  108. package/plugins/pbr/scripts/config-schema.json +11 -1
  109. package/plugins/pbr/scripts/context-bridge.js +259 -0
  110. package/plugins/pbr/scripts/context-budget-check.js +2 -2
  111. package/plugins/pbr/scripts/lib/config.js +178 -0
  112. package/plugins/pbr/scripts/lib/core.js +578 -0
  113. package/plugins/pbr/scripts/lib/history.js +73 -0
  114. package/plugins/pbr/scripts/lib/init.js +166 -0
  115. package/plugins/pbr/scripts/lib/phase.js +364 -0
  116. package/plugins/pbr/scripts/lib/roadmap.js +175 -0
  117. package/plugins/pbr/scripts/lib/state.js +397 -0
  118. package/plugins/pbr/scripts/pbr-tools.js +346 -1235
  119. package/plugins/pbr/scripts/post-write-dispatch.js +5 -4
  120. package/plugins/pbr/scripts/post-write-quality.js +3 -3
  121. package/plugins/pbr/scripts/pre-write-dispatch.js +1 -1
  122. package/plugins/pbr/scripts/progress-tracker.js +1 -1
  123. package/plugins/pbr/scripts/suggest-compact.js +1 -1
  124. package/plugins/pbr/scripts/track-context-budget.js +53 -2
  125. package/plugins/pbr/scripts/validate-task.js +20 -28
  126. package/plugins/pbr/skills/audit/SKILL.md +19 -3
  127. package/plugins/pbr/skills/begin/SKILL.md +48 -2
  128. package/plugins/pbr/skills/build/SKILL.md +39 -2
  129. package/plugins/pbr/skills/debug/SKILL.md +12 -1
  130. package/plugins/pbr/skills/debug/templates/continuation-prompt.md.tmpl +12 -1
  131. package/plugins/pbr/skills/debug/templates/initial-investigation-prompt.md.tmpl +12 -5
  132. package/plugins/pbr/skills/explore/SKILL.md +13 -2
  133. package/plugins/pbr/skills/import/SKILL.md +26 -1
  134. package/plugins/pbr/skills/milestone/SKILL.md +15 -3
  135. package/plugins/pbr/skills/plan/SKILL.md +52 -2
  136. package/plugins/pbr/skills/quick/SKILL.md +21 -0
  137. package/plugins/pbr/skills/review/SKILL.md +46 -0
  138. package/plugins/pbr/skills/scan/SKILL.md +20 -0
  139. package/plugins/pbr/templates/SUMMARY-complex.md.tmpl +95 -0
  140. package/plugins/pbr/templates/SUMMARY-minimal.md.tmpl +48 -0
@@ -3,17 +3,17 @@
3
3
  /* Tab bar */
4
4
  .settings-tabs {
5
5
  display: flex;
6
- gap: var(--size-2);
7
- border-bottom: 2px solid var(--surface-3, #e2e8f0);
8
- margin-bottom: var(--size-5);
6
+ gap: var(--space-sm);
7
+ border-bottom: 2px solid var(--color-border);
8
+ margin-bottom: var(--space-md);
9
9
  padding-bottom: 0;
10
10
  }
11
11
 
12
12
  /* Mode toggle (Form / Raw JSON) */
13
13
  .config-mode-toggle {
14
14
  display: flex;
15
- gap: var(--size-2);
16
- margin-bottom: var(--size-4);
15
+ gap: var(--space-sm);
16
+ margin-bottom: var(--space-md);
17
17
  }
18
18
 
19
19
  /* Tab buttons — shared by settings-tabs and config-mode-toggle */
@@ -21,44 +21,44 @@
21
21
  background: none;
22
22
  border: none;
23
23
  border-bottom: 2px solid transparent;
24
- padding: var(--size-2) var(--size-4);
25
- font-size: var(--font-size-1);
24
+ padding: var(--space-sm) var(--space-md);
25
+ font-size: 0.875rem;
26
26
  font-weight: 500;
27
- color: var(--text-2, #64748b);
27
+ color: var(--color-text-dim);
28
28
  cursor: pointer;
29
29
  transition: color 0.15s ease, border-color 0.15s ease;
30
30
  margin-bottom: -2px;
31
31
  }
32
32
 
33
33
  .tab-btn:hover {
34
- color: var(--text-1, #1e293b);
34
+ color: var(--color-text);
35
35
  }
36
36
 
37
37
  .tab-btn.active {
38
- color: var(--link, #2563eb);
39
- border-bottom-color: var(--link, #2563eb);
38
+ color: var(--color-accent);
39
+ border-bottom-color: var(--color-accent);
40
40
  }
41
41
 
42
42
  /* Config section card */
43
43
  .config-section {
44
- border: 1px solid var(--surface-3, #e2e8f0);
45
- border-radius: var(--radius-2);
46
- padding: var(--size-4);
47
- margin-bottom: var(--size-4);
48
- background: var(--surface-1, #f8fafc);
44
+ border: 1px solid var(--color-border);
45
+ border-radius: var(--radius-sm);
46
+ padding: var(--space-md);
47
+ margin-bottom: var(--space-md);
48
+ background: var(--color-surface);
49
49
  }
50
50
 
51
51
  .config-section--nested {
52
- margin-top: var(--size-4);
53
- background: var(--surface-2, #f1f5f9);
52
+ margin-top: var(--space-md);
53
+ background: var(--color-surface-raised);
54
54
  }
55
55
 
56
56
  /* Section heading */
57
57
  .config-section__title {
58
- font-size: var(--font-size-1);
58
+ font-size: 0.875rem;
59
59
  font-weight: 600;
60
- color: var(--text-1, #1e293b);
61
- margin: 0 0 var(--size-3) 0;
60
+ color: var(--color-text);
61
+ margin: 0 0 var(--space-sm) 0;
62
62
  text-transform: uppercase;
63
63
  letter-spacing: 0.05em;
64
64
  }
@@ -67,10 +67,10 @@
67
67
  .config-field {
68
68
  display: flex;
69
69
  align-items: center;
70
- gap: var(--size-3);
71
- padding: var(--size-1) 0;
72
- font-size: var(--font-size-1);
73
- color: var(--text-1, #1e293b);
70
+ gap: var(--space-sm);
71
+ padding: var(--space-xs) 0;
72
+ font-size: 0.875rem;
73
+ color: var(--color-text);
74
74
  cursor: pointer;
75
75
  }
76
76
 
@@ -80,20 +80,20 @@
80
80
 
81
81
  .config-field__label {
82
82
  min-width: 12rem;
83
- color: var(--text-2, #64748b);
84
- font-size: var(--font-size-0);
83
+ color: var(--color-text-dim);
84
+ font-size: 0.8125rem;
85
85
  }
86
86
 
87
87
  .config-field input[type='text'],
88
88
  .config-field input[type='number'],
89
89
  .config-field select {
90
90
  flex: 1;
91
- padding: var(--size-1) var(--size-2);
92
- border: 1px solid var(--surface-3, #e2e8f0);
93
- border-radius: var(--radius-1);
94
- font-size: var(--font-size-0);
95
- background: var(--surface-1, #fff);
96
- color: var(--text-1, #1e293b);
91
+ padding: var(--space-xs) var(--space-sm);
92
+ border: 1px solid var(--color-border);
93
+ border-radius: var(--radius-sm);
94
+ font-size: 0.8125rem;
95
+ background: var(--color-surface);
96
+ color: var(--color-text);
97
97
  }
98
98
 
99
99
  .config-field input[readonly] {
@@ -104,20 +104,20 @@
104
104
  .config-field input[type='checkbox'] {
105
105
  width: 1rem;
106
106
  height: 1rem;
107
- accent-color: var(--link, #2563eb);
107
+ accent-color: var(--color-accent);
108
108
  cursor: pointer;
109
109
  }
110
110
 
111
111
  /* Raw JSON textarea */
112
112
  .config-raw-json {
113
113
  width: 100%;
114
- font-family: var(--font-mono, 'JetBrains Mono', monospace);
115
- font-size: var(--font-size-0);
116
- padding: var(--size-3);
117
- border: 1px solid var(--surface-3, #e2e8f0);
118
- border-radius: var(--radius-2);
119
- background: var(--surface-1, #f8fafc);
120
- color: var(--text-1, #1e293b);
114
+ font-family: var(--font-mono);
115
+ font-size: 0.8125rem;
116
+ padding: var(--space-sm);
117
+ border: 1px solid var(--color-border);
118
+ border-radius: var(--radius-sm);
119
+ background: var(--color-surface);
120
+ color: var(--color-text);
121
121
  resize: vertical;
122
122
  box-sizing: border-box;
123
123
  }
@@ -126,30 +126,30 @@
126
126
  .config-actions {
127
127
  display: flex;
128
128
  justify-content: flex-end;
129
- margin-bottom: var(--size-3);
129
+ margin-bottom: var(--space-sm);
130
130
  }
131
131
 
132
132
  /* Inline feedback */
133
133
  .config-feedback {
134
134
  min-height: 1.5rem;
135
- margin-top: var(--size-2);
136
- font-size: var(--font-size-0);
135
+ margin-top: var(--space-sm);
136
+ font-size: 0.8125rem;
137
137
  }
138
138
 
139
139
  .feedback--success {
140
- color: var(--green-7, #15803d);
140
+ color: var(--status-complete);
141
141
  font-weight: 500;
142
142
  }
143
143
 
144
144
  .feedback--error {
145
- color: var(--red-7, #b91c1c);
145
+ color: var(--status-blocked);
146
146
  font-weight: 500;
147
147
  }
148
148
 
149
149
  /* Empty state */
150
150
  .config-empty {
151
- font-size: var(--font-size-0);
152
- color: var(--text-2, #64748b);
151
+ font-size: 0.8125rem;
152
+ color: var(--color-text-dim);
153
153
  font-style: italic;
154
154
  margin: 0;
155
155
  }
@@ -158,52 +158,33 @@
158
158
  .btn--primary {
159
159
  display: inline-flex;
160
160
  align-items: center;
161
- gap: var(--size-2);
162
- padding: var(--size-2) var(--size-5);
163
- background: var(--link, #2563eb);
161
+ gap: var(--space-sm);
162
+ padding: var(--space-sm) var(--space-md);
163
+ background: var(--color-accent);
164
164
  color: #fff;
165
165
  border: none;
166
- border-radius: var(--radius-2);
167
- font-size: var(--font-size-1);
166
+ border-radius: var(--radius-sm);
167
+ font-size: 0.875rem;
168
168
  font-weight: 500;
169
169
  cursor: pointer;
170
170
  transition: background 0.15s ease;
171
171
  }
172
172
 
173
173
  .btn--primary:hover {
174
- background: var(--blue-7, #1d4ed8);
175
- }
176
-
177
- /* Dark theme overrides */
178
- [data-theme='dark'] .config-section {
179
- background: var(--surface-2, #1e2535);
180
- border-color: var(--surface-3, #2d3748);
181
- }
182
-
183
- [data-theme='dark'] .config-section--nested {
184
- background: var(--surface-1, #161e2d);
185
- }
186
-
187
- [data-theme='dark'] .config-raw-json,
188
- [data-theme='dark'] .config-field input[type='text'],
189
- [data-theme='dark'] .config-field input[type='number'],
190
- [data-theme='dark'] .config-field select {
191
- background: var(--surface-2, #1e2535);
192
- border-color: var(--surface-3, #2d3748);
193
- color: var(--text-1, #e2e8f0);
174
+ background: var(--color-accent-hover);
194
175
  }
195
176
 
196
177
  /* ── Log Viewer ─────────────────────────────────────── */
197
178
  .log-viewer-layout {
198
179
  display: grid;
199
180
  grid-template-columns: 220px 1fr;
200
- gap: var(--size-4);
201
- height: calc(100vh - var(--size-12));
181
+ gap: var(--space-md);
182
+ height: calc(100vh - var(--space-2xl));
202
183
  }
203
184
 
204
185
  .log-file-sidebar {
205
- border-right: 1px solid var(--surface-3);
206
- padding-right: var(--size-3);
186
+ border-right: 1px solid var(--color-border);
187
+ padding-right: var(--space-sm);
207
188
  overflow-y: auto;
208
189
  }
209
190
 
@@ -215,57 +196,74 @@
215
196
 
216
197
  .log-file-item {
217
198
  display: block;
218
- padding: var(--size-2) var(--size-3);
219
- border-radius: var(--radius-2);
199
+ padding: var(--space-sm);
200
+ border-radius: var(--radius-sm);
220
201
  text-decoration: none;
221
- color: var(--text-2);
222
- font-size: var(--font-size-0);
202
+ color: var(--color-text-dim);
203
+ font-size: 0.8125rem;
223
204
  margin-block: 2px;
224
205
  }
225
206
 
226
- .log-file-item:hover { background: var(--surface-2); }
227
- .log-file-item--active { background: var(--surface-3); color: var(--text-1); font-weight: 500; }
207
+ .log-file-item:hover { background: var(--color-surface-raised); }
208
+ .log-file-item--active { background: var(--color-border); color: var(--color-text); font-weight: 500; }
228
209
 
229
210
  .log-file-name { display: block; font-family: var(--font-mono); font-size: 0.75rem; }
230
- .log-file-size { color: var(--text-2); }
231
- .log-file-date { color: var(--text-2); }
211
+ .log-file-size { color: var(--color-text-dim); }
212
+ .log-file-date { color: var(--color-text-dim); }
232
213
 
233
- .log-main { overflow-y: auto; padding-right: var(--size-2); }
214
+ .log-main { overflow-y: auto; padding-right: var(--space-sm); }
234
215
 
235
216
  .log-filters {
236
217
  display: flex;
237
- gap: var(--size-3);
218
+ gap: var(--space-sm);
238
219
  align-items: center;
239
- margin-bottom: var(--size-3);
240
- padding: var(--size-2) var(--size-3);
241
- background: var(--surface-2);
242
- border-radius: var(--radius-2);
220
+ margin-bottom: var(--space-sm);
221
+ padding: var(--space-sm);
222
+ background: var(--color-surface-raised);
223
+ border-radius: var(--radius-sm);
243
224
  }
244
225
 
245
226
  .log-table {
246
227
  width: 100%;
247
228
  border-collapse: collapse;
248
- font-size: var(--font-size-0);
229
+ font-size: 0.8125rem;
249
230
  }
250
231
 
251
232
  .log-table th,
252
233
  .log-table td {
253
234
  text-align: left;
254
- padding: var(--size-1) var(--size-2);
255
- border-bottom: 1px solid var(--surface-3);
235
+ padding: var(--space-xs) var(--space-sm);
236
+ border-bottom: 1px solid var(--color-border);
256
237
  }
257
238
 
258
- .log-table th { color: var(--text-2); font-weight: 500; }
239
+ .log-table th { color: var(--color-text-dim); font-weight: 500; }
240
+
241
+ .log-table th:first-child,
242
+ .log-table td:first-child {
243
+ width: 80px;
244
+ }
245
+
246
+ .log-table th:nth-child(2),
247
+ .log-table td:nth-child(2) {
248
+ width: 170px;
249
+ white-space: nowrap;
250
+ }
251
+
252
+ .log-table td:nth-child(3) {
253
+ font-family: var(--font-mono);
254
+ font-size: 0.8rem;
255
+ word-break: break-all;
256
+ }
259
257
 
260
258
  .log-badge {
261
259
  display: inline-block;
262
260
  padding: 1px 6px;
263
- border-radius: var(--radius-round);
261
+ border-radius: 999px;
264
262
  font-size: 0.7rem;
265
263
  font-weight: 600;
266
264
  text-transform: uppercase;
267
- background: var(--surface-3);
268
- color: var(--text-2);
265
+ background: var(--color-border);
266
+ color: var(--color-text-dim);
269
267
  }
270
268
 
271
269
  .log-badge--error { background: var(--red-2); color: var(--red-9); }
@@ -277,29 +275,29 @@
277
275
 
278
276
  .log-pagination {
279
277
  display: flex;
280
- gap: var(--size-2);
278
+ gap: var(--space-sm);
281
279
  align-items: center;
282
- padding: var(--size-2) 0;
280
+ padding: var(--space-sm) 0;
283
281
  }
284
282
 
285
283
  .log-tail-indicator {
286
284
  display: flex;
287
285
  align-items: center;
288
- gap: var(--size-2);
289
- font-size: var(--font-size-0);
290
- color: var(--text-2);
291
- margin-bottom: var(--size-2);
286
+ gap: var(--space-sm);
287
+ font-size: 0.8125rem;
288
+ color: var(--color-text-dim);
289
+ margin-bottom: var(--space-sm);
292
290
  }
293
291
 
294
292
  .tail-dot {
295
293
  width: 8px;
296
294
  height: 8px;
297
295
  border-radius: 50%;
298
- background: var(--surface-3);
296
+ background: var(--color-border);
299
297
  }
300
298
 
301
299
  .tail-dot--active {
302
- background: var(--green-6);
300
+ background: var(--status-complete);
303
301
  animation: pulse 1.5s ease-in-out infinite;
304
302
  }
305
303
 
@@ -308,7 +306,7 @@
308
306
  50% { opacity: 0.4; }
309
307
  }
310
308
 
311
- .log-tail-entries { font-family: var(--font-mono); font-size: 0.75rem; color: var(--text-2); }
312
- .log-tail-row { padding: 2px 0; border-bottom: 1px solid var(--surface-2); }
313
- .log-empty, .log-prompt { color: var(--text-2); padding: var(--size-4); }
314
- .log-summary { color: var(--text-2); font-size: var(--font-size-0); margin-bottom: var(--size-2); }
309
+ .log-tail-entries { font-family: var(--font-mono); font-size: 0.75rem; color: var(--color-text-dim); }
310
+ .log-tail-row { padding: 2px 0; border-bottom: 1px solid var(--color-surface-raised); }
311
+ .log-empty, .log-prompt { color: var(--color-text-dim); padding: var(--space-md); }
312
+ .log-summary { color: var(--color-text-dim); font-size: 0.8125rem; margin-bottom: var(--space-sm); }
@@ -46,7 +46,7 @@
46
46
 
47
47
  .timeline__event {
48
48
  display: grid;
49
- grid-template-columns: 1rem 10rem 9rem 1fr auto;
49
+ grid-template-columns: 1rem auto 5rem 1fr auto;
50
50
  align-items: start;
51
51
  gap: var(--space-sm);
52
52
  padding: var(--space-sm) 0;
@@ -91,6 +91,7 @@
91
91
 
92
92
  .timeline__event-title {
93
93
  font-size: 0.9rem;
94
+ overflow-wrap: anywhere;
94
95
  }
95
96
 
96
97
  .timeline__event-author {
@@ -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) --- */
@@ -1,12 +1,26 @@
1
- // sidebar-toggle.js — Tabler vertical navbar toggle shim
2
- // Tabler's Bootstrap JS handles collapse via data-bs-toggle="collapse".
3
- // This file remains for the header button (#sidebar-toggle) which triggers
4
- // the .navbar-vertical collapse on mobile.
5
1
  document.addEventListener('DOMContentLoaded', function() {
6
2
  var toggle = document.getElementById('sidebar-toggle');
7
- var sidebarMenu = document.getElementById('sidebar-menu');
8
- if (!toggle || !sidebarMenu) return;
3
+ var sidebar = document.querySelector('.sidebar');
4
+ if (!toggle || !sidebar) return;
5
+
9
6
  toggle.addEventListener('click', function() {
10
- sidebarMenu.classList.toggle('show');
7
+ sidebar.classList.toggle('sidebar--open');
8
+ document.body.classList.toggle('sidebar-visible');
9
+ });
10
+
11
+ // Close sidebar when a nav link is clicked (mobile)
12
+ sidebar.querySelectorAll('.sidebar__nav-link').forEach(function(link) {
13
+ link.addEventListener('click', function() {
14
+ sidebar.classList.remove('sidebar--open');
15
+ document.body.classList.remove('sidebar-visible');
16
+ });
17
+ });
18
+
19
+ // Close sidebar when clicking the backdrop
20
+ document.addEventListener('click', function(e) {
21
+ if (!sidebar.classList.contains('sidebar--open')) return;
22
+ if (sidebar.contains(e.target) || toggle.contains(e.target)) return;
23
+ sidebar.classList.remove('sidebar--open');
24
+ document.body.classList.remove('sidebar-visible');
11
25
  });
12
26
  });
@@ -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) {
@@ -50,15 +70,36 @@ export function Layout({ title, children, currentView }: LayoutProps) {
50
70
  })();
51
71
  </script>`}
52
72
  <script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js" defer></script>
53
- {html`<script>document.addEventListener('DOMContentLoaded', function() { mermaid.initialize({ startOnLoad: false, theme: 'neutral' }); });</script>`}
73
+ {html`<script>
74
+ document.addEventListener('DOMContentLoaded', function() {
75
+ function initMermaid() {
76
+ var isDark = document.documentElement.getAttribute('data-theme') === 'dark' ||
77
+ (!document.documentElement.getAttribute('data-theme') && window.matchMedia('(prefers-color-scheme: dark)').matches);
78
+ mermaid.initialize({ startOnLoad: false, theme: isDark ? 'dark' : 'neutral' });
79
+ }
80
+ initMermaid();
81
+ new MutationObserver(function(mutations) {
82
+ mutations.forEach(function(m) { if (m.attributeName === 'data-theme') initMermaid(); });
83
+ }).observe(document.documentElement, { attributes: true });
84
+ });
85
+ </script>`}
54
86
  </head>
55
87
  <body>
56
88
  <a href="#main-content" class="skip-link">Skip to content</a>
57
89
 
90
+ <button id="sidebar-toggle" class="sidebar__toggle" type="button" aria-label="Toggle navigation">
91
+ <span aria-hidden="true">☰</span>
92
+ </button>
93
+
58
94
  <nav class="sidebar" aria-label="Main navigation">
59
95
  <div class="sidebar__brand">
60
- <span class="sidebar__brand-name">PBR</span>
61
- <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>
62
103
  </div>
63
104
 
64
105
  <ul class="sidebar__nav" role="list">
@@ -72,6 +113,7 @@ export function Layout({ title, children, currentView }: LayoutProps) {
72
113
  class={`sidebar__nav-link${isActive ? ' sidebar__nav-link--active' : ''}`}
73
114
  aria-current={isActive ? 'page' : undefined}
74
115
  >
116
+ <span class="sidebar__nav-icon" aria-hidden="true" dangerouslySetInnerHTML={{ __html: item.icon }} />
75
117
  {item.label}
76
118
  </a>
77
119
  </li>
@@ -88,6 +130,7 @@ export function Layout({ title, children, currentView }: LayoutProps) {
88
130
  </nav>
89
131
 
90
132
  <main id="main-content" class="main-content">
133
+ <div class="loading-bar" aria-hidden="true"></div>
91
134
  {children}
92
135
  </main>
93
136
 
@@ -98,6 +141,7 @@ export function Layout({ title, children, currentView }: LayoutProps) {
98
141
  {/* Local scripts */}
99
142
  <script src="/js/theme-toggle.js"></script>
100
143
  <script src="/js/sse-client.js" defer></script>
144
+ <script src="/js/sidebar-toggle.js" defer></script>
101
145
  </body>
102
146
  </html>
103
147
  );
@@ -1,6 +1,10 @@
1
1
  interface Milestone {
2
2
  version: string;
3
3
  name?: string;
4
+ goal?: string;
5
+ startPhase?: string | number;
6
+ endPhase?: string | number;
7
+ completed?: boolean;
4
8
  date?: string;
5
9
  duration?: string;
6
10
  }
@@ -27,9 +31,21 @@ export function MilestonesTab({ active, archived }: MilestonesTabProps) {
27
31
  {active.length === 0 && <p class="explorer__loading">No active milestones.</p>}
28
32
  <div class="explorer-list">
29
33
  {active.map((ms) => (
30
- <div class="explorer-item" key={ms.version}>
34
+ <div class="explorer-item" key={ms.name || ms.version}>
31
35
  <div class="explorer-item__header">
32
- <span class="explorer-item__title">v{ms.version}</span>
36
+ <span class="explorer-item__title">
37
+ {ms.name || `v${ms.version}`}
38
+ </span>
39
+ {ms.startPhase != null && ms.endPhase != null && (
40
+ <span class="explorer-item__meta">
41
+ Phase {ms.startPhase}–{ms.endPhase}
42
+ </span>
43
+ )}
44
+ {ms.goal && (
45
+ <span class="explorer-item__meta" style="flex:1; text-align:right; white-space:normal;">
46
+ {ms.goal}
47
+ </span>
48
+ )}
33
49
  <span class="explorer-badge explorer-badge--building">active</span>
34
50
  </div>
35
51
  </div>
@@ -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). */}