@sienklogic/plan-build-run 2.26.2 → 2.27.1
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/CHANGELOG.md +14 -0
- package/README.md +29 -0
- package/dashboard/public/css/layout.css +7 -283
- package/dashboard/public/css/status-colors.css +7 -0
- package/dashboard/public/css/tokens.css +3 -3
- package/dashboard/public/js/sidebar-toggle.js +9 -31
- package/dashboard/public/js/theme-toggle.js +4 -4
- package/dashboard/src/views/partials/activity-feed.ejs +17 -9
- package/dashboard/src/views/partials/analytics-content.ejs +178 -88
- package/dashboard/src/views/partials/audit-detail-content.ejs +6 -4
- package/dashboard/src/views/partials/audits-content.ejs +28 -26
- package/dashboard/src/views/partials/breadcrumbs.ejs +8 -4
- package/dashboard/src/views/partials/config-content.ejs +98 -95
- package/dashboard/src/views/partials/dashboard-content.ejs +69 -60
- package/dashboard/src/views/partials/dependencies-content.ejs +5 -3
- package/dashboard/src/views/partials/empty-state.ejs +10 -5
- package/dashboard/src/views/partials/footer.ejs +8 -2
- package/dashboard/src/views/partials/head.ejs +2 -1
- package/dashboard/src/views/partials/header.ejs +16 -19
- package/dashboard/src/views/partials/layout-bottom.ejs +5 -40
- package/dashboard/src/views/partials/layout-top.ejs +6 -5
- package/dashboard/src/views/partials/logs-content.ejs +26 -29
- package/dashboard/src/views/partials/milestone-detail-content.ejs +5 -5
- package/dashboard/src/views/partials/milestones-content.ejs +40 -31
- package/dashboard/src/views/partials/note-detail-content.ejs +7 -5
- package/dashboard/src/views/partials/notes-content.ejs +4 -4
- package/dashboard/src/views/partials/phase-content.ejs +6 -8
- package/dashboard/src/views/partials/phase-doc-content.ejs +13 -15
- package/dashboard/src/views/partials/phase-timeline.ejs +22 -15
- package/dashboard/src/views/partials/phases-content.ejs +98 -84
- package/dashboard/src/views/partials/quick-content.ejs +34 -32
- package/dashboard/src/views/partials/quick-detail-content.ejs +20 -19
- package/dashboard/src/views/partials/requirements-content.ejs +6 -6
- package/dashboard/src/views/partials/research-content.ejs +14 -14
- package/dashboard/src/views/partials/research-detail-content.ejs +13 -11
- package/dashboard/src/views/partials/roadmap-content.ejs +145 -128
- package/dashboard/src/views/partials/sidebar.ejs +86 -140
- package/dashboard/src/views/partials/todo-create-content.ejs +51 -46
- package/dashboard/src/views/partials/todo-detail-content.ejs +26 -25
- package/dashboard/src/views/partials/todos-content.ejs +65 -62
- package/dashboard/src/views/partials/todos-done-content.ejs +33 -31
- package/package.json +1 -1
- package/plugins/copilot-pbr/plugin.json +1 -1
- package/plugins/copilot-pbr/skills/build/SKILL.md +12 -0
- package/plugins/copilot-pbr/skills/quick/SKILL.md +12 -0
- package/plugins/copilot-pbr/skills/review/SKILL.md +14 -0
- package/plugins/cursor-pbr/.cursor-plugin/plugin.json +1 -1
- package/plugins/cursor-pbr/README.md +20 -0
- package/plugins/cursor-pbr/skills/build/SKILL.md +12 -0
- package/plugins/cursor-pbr/skills/quick/SKILL.md +12 -0
- package/plugins/cursor-pbr/skills/review/SKILL.md +14 -0
- package/plugins/pbr/.claude-plugin/plugin.json +1 -1
- package/plugins/pbr/scripts/local-llm/metrics.js +121 -33
- package/plugins/pbr/skills/build/SKILL.md +12 -0
- package/plugins/pbr/skills/quick/SKILL.md +12 -0
- package/plugins/pbr/skills/review/SKILL.md +14 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,20 @@ All notable changes to Plan-Build-Run will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [2.27.1](https://github.com/SienkLogic/plan-build-run/compare/plan-build-run-v2.27.0...plan-build-run-v2.27.1) (2026-02-24)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* **tools:** prevent lifetime LLM metrics from plateauing at 200 entries ([2cbdaa4](https://github.com/SienkLogic/plan-build-run/commit/2cbdaa4b4402110cc4bb0f6505d034f2162aa782))
|
|
14
|
+
|
|
15
|
+
## [2.27.0](https://github.com/SienkLogic/plan-build-run/compare/plan-build-run-v2.26.2...plan-build-run-v2.27.0) (2026-02-24)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* **tools:** add local LLM skill-level fallbacks and platform compatibility docs ([d6d1242](https://github.com/SienkLogic/plan-build-run/commit/d6d1242d79eb924525761e0bc6ac65e1a2d51375))
|
|
21
|
+
|
|
8
22
|
## [2.26.2](https://github.com/SienkLogic/plan-build-run/compare/plan-build-run-v2.26.1...plan-build-run-v2.26.2) (2026-02-24)
|
|
9
23
|
|
|
10
24
|
|
package/README.md
CHANGED
|
@@ -304,6 +304,35 @@ Requires a GPU with 6+ GB VRAM for best performance. CPU-only works but adds lat
|
|
|
304
304
|
|
|
305
305
|
---
|
|
306
306
|
|
|
307
|
+
## Platform Compatibility
|
|
308
|
+
|
|
309
|
+
Plan-Build-Run works across three platforms with varying levels of hook support. Hooks are the mechanism that fires validation scripts on every tool call — they power local LLM offloading, commit format enforcement, context budget tracking, and workflow gates.
|
|
310
|
+
|
|
311
|
+
| Feature | Claude Code | Copilot CLI | Cursor IDE |
|
|
312
|
+
|---------|:-----------:|:-----------:|:----------:|
|
|
313
|
+
| Skills (slash commands) | All 26 | All 26 | All 26 |
|
|
314
|
+
| Agents (subagent delegation) | All 12 | All 12 | All 12 |
|
|
315
|
+
| `.planning/` state management | Full | Full | Full |
|
|
316
|
+
| **Hook support** | **Full (14 events)** | **Partial (4 events)** | **Unverified** |
|
|
317
|
+
| Commit format enforcement | Hook-enforced | Hook-enforced | Manual |
|
|
318
|
+
| PLAN/SUMMARY quality classification | Hook + skill fallback | Hook + skill fallback | Skill fallback only |
|
|
319
|
+
| Test failure triage | Automatic (hook) | Automatic (hook) | Not available |
|
|
320
|
+
| Context budget tracking | Automatic (hook) | Not available | Not available |
|
|
321
|
+
| Auto-continue between skills | Automatic (hook) | Not available | Not available |
|
|
322
|
+
| Subagent lifecycle logging | Automatic (hook) | Not available | Not available |
|
|
323
|
+
| **Local LLM offloading** | **Full (8 operations)** | **Mostly (6-7 operations)** | **CLI only** |
|
|
324
|
+
| `pbr-tools.js llm` CLI commands | Full | Full | Full |
|
|
325
|
+
|
|
326
|
+
**Key differences:**
|
|
327
|
+
|
|
328
|
+
- **Claude Code** has full hook support — all local LLM operations fire automatically on every tool call
|
|
329
|
+
- **Copilot CLI** supports `sessionStart`, `preToolUse`, `postToolUse`, and `sessionEnd` — covers most validation hooks but misses lifecycle events (`SubagentStop`, `PreCompact`, `Stop`)
|
|
330
|
+
- **Cursor IDE** hook support is unverified — hooks.json is configured but whether Cursor actually fires them is unknown. Skills include `pbr-tools.js llm` fallback calls for key operations (plan quality, verification quality) so local LLM classification is available even without hooks
|
|
331
|
+
|
|
332
|
+
All platforms share the same scripts via relative paths — no code duplication. See the [Copilot CLI](plugins/copilot-pbr/README.md) and [Cursor IDE](plugins/cursor-pbr/README.md) READMEs for platform-specific details.
|
|
333
|
+
|
|
334
|
+
---
|
|
335
|
+
|
|
307
336
|
## Local Development
|
|
308
337
|
|
|
309
338
|
```bash
|
|
@@ -27,103 +27,6 @@ p { line-height: 1.65; }
|
|
|
27
27
|
|
|
28
28
|
small { font-size: 0.8125rem; color: var(--color-text-dim); }
|
|
29
29
|
|
|
30
|
-
/* --- Page Grid Layout --- */
|
|
31
|
-
.page-wrapper {
|
|
32
|
-
display: grid;
|
|
33
|
-
gap: 0;
|
|
34
|
-
grid-template-columns: var(--size-sidebar) 1fr;
|
|
35
|
-
grid-template-rows: var(--size-header) 1fr auto;
|
|
36
|
-
grid-template-areas:
|
|
37
|
-
"header header"
|
|
38
|
-
"sidebar content"
|
|
39
|
-
"footer footer";
|
|
40
|
-
min-height: 100vh;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/* --- Header --- */
|
|
44
|
-
.page-wrapper > header {
|
|
45
|
-
grid-area: header;
|
|
46
|
-
display: flex;
|
|
47
|
-
align-items: center;
|
|
48
|
-
padding: 0 var(--space-xl);
|
|
49
|
-
border-bottom: 1px solid var(--color-border);
|
|
50
|
-
background: var(--color-surface-raised);
|
|
51
|
-
backdrop-filter: blur(8px);
|
|
52
|
-
position: sticky;
|
|
53
|
-
top: 0;
|
|
54
|
-
z-index: 10;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
.page-wrapper > header nav {
|
|
58
|
-
display: flex;
|
|
59
|
-
justify-content: space-between;
|
|
60
|
-
align-items: center;
|
|
61
|
-
width: 100%;
|
|
62
|
-
margin: 0;
|
|
63
|
-
padding: 0;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
.page-wrapper > header nav strong {
|
|
67
|
-
font-size: 1rem;
|
|
68
|
-
font-weight: 600;
|
|
69
|
-
letter-spacing: -0.02em;
|
|
70
|
-
white-space: nowrap;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
.page-wrapper > header nav ul {
|
|
74
|
-
list-style: none;
|
|
75
|
-
margin: 0;
|
|
76
|
-
padding: 0;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/* --- Sidebar --- */
|
|
80
|
-
.page-wrapper > aside.sidebar {
|
|
81
|
-
grid-area: sidebar;
|
|
82
|
-
padding: var(--space-lg) 0;
|
|
83
|
-
border-right: 1px solid var(--color-border);
|
|
84
|
-
background: var(--color-surface-raised);
|
|
85
|
-
position: sticky;
|
|
86
|
-
top: var(--size-header);
|
|
87
|
-
height: calc(100vh - var(--size-header));
|
|
88
|
-
overflow-y: auto;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
aside.sidebar nav ul {
|
|
92
|
-
list-style: none;
|
|
93
|
-
padding: 0;
|
|
94
|
-
margin: 0;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
aside.sidebar nav li {
|
|
98
|
-
margin: 0;
|
|
99
|
-
padding: 0;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
aside.sidebar nav a {
|
|
103
|
-
display: flex;
|
|
104
|
-
align-items: center;
|
|
105
|
-
padding: 0.6rem var(--space-lg);
|
|
106
|
-
text-decoration: none;
|
|
107
|
-
border-left: 3px solid transparent;
|
|
108
|
-
font-size: 0.9rem;
|
|
109
|
-
font-weight: 500;
|
|
110
|
-
color: var(--color-text-dim);
|
|
111
|
-
transition: all var(--transition-fast);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
aside.sidebar nav a:hover {
|
|
115
|
-
color: var(--pico-color);
|
|
116
|
-
background: var(--color-surface-hover);
|
|
117
|
-
border-left-color: var(--color-border);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
aside.sidebar nav a[aria-current="page"] {
|
|
121
|
-
font-weight: 600;
|
|
122
|
-
color: var(--color-accent);
|
|
123
|
-
border-left-color: var(--color-accent);
|
|
124
|
-
background: var(--color-surface-hover);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
30
|
/* --- Sidebar: Current Phase Card --- */
|
|
128
31
|
.sidebar-current-phase {
|
|
129
32
|
padding: var(--space-md) var(--space-lg);
|
|
@@ -188,59 +91,6 @@ aside.sidebar nav a[aria-current="page"] {
|
|
|
188
91
|
white-space: nowrap;
|
|
189
92
|
}
|
|
190
93
|
|
|
191
|
-
/* --- Sidebar: Section Details --- */
|
|
192
|
-
aside.sidebar details {
|
|
193
|
-
border: none;
|
|
194
|
-
margin: 0;
|
|
195
|
-
padding: 0;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
aside.sidebar details + details {
|
|
199
|
-
margin-top: var(--space-xs);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
aside.sidebar details summary {
|
|
203
|
-
text-transform: uppercase;
|
|
204
|
-
font-size: 0.6875rem;
|
|
205
|
-
font-weight: 600;
|
|
206
|
-
letter-spacing: 0.06em;
|
|
207
|
-
color: var(--color-text-dim);
|
|
208
|
-
padding: var(--space-xs) var(--space-lg);
|
|
209
|
-
cursor: pointer;
|
|
210
|
-
border-left: 3px solid transparent;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
aside.sidebar details[open] summary {
|
|
214
|
-
color: var(--color-accent);
|
|
215
|
-
border-left-color: var(--color-accent);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
aside.sidebar details ul {
|
|
219
|
-
margin: 0;
|
|
220
|
-
padding-bottom: var(--space-xs);
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
/* --- Main Content --- */
|
|
224
|
-
.page-wrapper > main {
|
|
225
|
-
grid-area: content;
|
|
226
|
-
padding: var(--space-xl) var(--space-2xl);
|
|
227
|
-
overflow-y: auto;
|
|
228
|
-
max-width: calc(var(--content-max-width) + var(--space-2xl) * 2);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
/* --- Footer --- */
|
|
232
|
-
.page-wrapper > footer {
|
|
233
|
-
grid-area: footer;
|
|
234
|
-
padding: var(--space-md) var(--space-xl);
|
|
235
|
-
border-top: 1px solid var(--color-border);
|
|
236
|
-
text-align: center;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
.page-wrapper > footer small {
|
|
240
|
-
font-size: 0.75rem;
|
|
241
|
-
color: var(--color-text-dim);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
94
|
/* --- Card Component --- */
|
|
245
95
|
.card,
|
|
246
96
|
article {
|
|
@@ -423,36 +273,6 @@ details li {
|
|
|
423
273
|
margin: var(--space-lg) 0;
|
|
424
274
|
}
|
|
425
275
|
|
|
426
|
-
/* --- Breadcrumbs --- */
|
|
427
|
-
.breadcrumbs {
|
|
428
|
-
display: flex;
|
|
429
|
-
list-style: none;
|
|
430
|
-
padding: 0;
|
|
431
|
-
margin: 0 0 var(--space-md) 0;
|
|
432
|
-
font-size: 0.85rem;
|
|
433
|
-
gap: var(--space-xs);
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
.breadcrumbs li + li::before {
|
|
437
|
-
content: ">";
|
|
438
|
-
margin-right: var(--space-xs);
|
|
439
|
-
color: var(--color-text-dim);
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
.breadcrumbs a {
|
|
443
|
-
color: var(--color-accent);
|
|
444
|
-
text-decoration: none;
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
.breadcrumbs a:hover {
|
|
448
|
-
text-decoration: underline;
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
.breadcrumbs [aria-current="page"] {
|
|
452
|
-
color: var(--color-text-dim);
|
|
453
|
-
font-weight: 500;
|
|
454
|
-
}
|
|
455
|
-
|
|
456
276
|
/* --- Phase Timeline (homepage) --- */
|
|
457
277
|
.phase-timeline {
|
|
458
278
|
list-style: none;
|
|
@@ -586,8 +406,8 @@ main > p:first-of-type > a[href="/"]:hover {
|
|
|
586
406
|
top: 0;
|
|
587
407
|
z-index: 1000;
|
|
588
408
|
padding: var(--space-sm) var(--space-md);
|
|
589
|
-
background: var(--
|
|
590
|
-
color: var(--
|
|
409
|
+
background: var(--tblr-primary);
|
|
410
|
+
color: var(--tblr-primary-fg, #fff);
|
|
591
411
|
text-decoration: none;
|
|
592
412
|
font-weight: 600;
|
|
593
413
|
}
|
|
@@ -600,24 +420,13 @@ main > p:first-of-type > a[href="/"]:hover {
|
|
|
600
420
|
|
|
601
421
|
/* --- Focus Visible --- */
|
|
602
422
|
:focus-visible {
|
|
603
|
-
outline: 2px solid var(--
|
|
423
|
+
outline: 2px solid var(--tblr-primary);
|
|
604
424
|
outline-offset: 2px;
|
|
605
425
|
}
|
|
606
426
|
|
|
607
|
-
/* --- Empty State --- */
|
|
608
|
-
.empty-state {
|
|
609
|
-
text-align: center;
|
|
610
|
-
padding: var(--space-2xl) var(--space-lg);
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
.empty-state h3 {
|
|
614
|
-
color: var(--color-text-dim);
|
|
615
|
-
font-weight: 500;
|
|
616
|
-
}
|
|
617
|
-
|
|
618
427
|
/* --- Error Card --- */
|
|
619
428
|
.error-card {
|
|
620
|
-
border-left: 4px solid var(--
|
|
429
|
+
border-left: 4px solid var(--tblr-danger);
|
|
621
430
|
padding: var(--space-lg);
|
|
622
431
|
margin: var(--space-lg) 0;
|
|
623
432
|
background: var(--color-surface-raised);
|
|
@@ -659,7 +468,7 @@ main > p:first-of-type > a[href="/"]:hover {
|
|
|
659
468
|
/* --- Bar Chart --- */
|
|
660
469
|
.bar-chart-row { display: flex; align-items: center; gap: var(--space-sm); margin-bottom: var(--space-xs); }
|
|
661
470
|
.bar-chart-label { min-width: 160px; font-size: 0.875rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
662
|
-
.bar-chart-bar { height: 1.5rem; border-radius: var(--radius-sm); background: var(--
|
|
471
|
+
.bar-chart-bar { height: 1.5rem; border-radius: var(--radius-sm); background: var(--tblr-primary); color: var(--tblr-primary-fg, #fff); font-size: 0.75rem; display: flex; align-items: center; padding-left: var(--space-sm); min-width: 2rem; transition: width var(--transition-base); }
|
|
663
472
|
|
|
664
473
|
/* --- Loading Bar --- */
|
|
665
474
|
.loading-bar {
|
|
@@ -674,7 +483,7 @@ main > p:first-of-type > a[href="/"]:hover {
|
|
|
674
483
|
|
|
675
484
|
.htmx-request .loading-bar {
|
|
676
485
|
display: block;
|
|
677
|
-
background: var(--
|
|
486
|
+
background: var(--tblr-primary);
|
|
678
487
|
animation: loading-shimmer 1.2s ease-in-out infinite;
|
|
679
488
|
}
|
|
680
489
|
|
|
@@ -683,93 +492,12 @@ main > p:first-of-type > a[href="/"]:hover {
|
|
|
683
492
|
100% { transform: translateX(100%); }
|
|
684
493
|
}
|
|
685
494
|
|
|
686
|
-
/* --- Sidebar Backdrop (hidden by default, shown on mobile) --- */
|
|
687
|
-
.sidebar-backdrop {
|
|
688
|
-
display: none;
|
|
689
|
-
}
|
|
690
|
-
|
|
691
|
-
/* --- Mobile hamburger toggle --- */
|
|
692
|
-
.sidebar-toggle {
|
|
693
|
-
display: none;
|
|
694
|
-
background: none;
|
|
695
|
-
border: 1px solid var(--color-border);
|
|
696
|
-
border-radius: var(--radius-sm);
|
|
697
|
-
color: var(--pico-color);
|
|
698
|
-
font-size: 1.25rem;
|
|
699
|
-
padding: 0.25rem 0.5rem;
|
|
700
|
-
cursor: pointer;
|
|
701
|
-
line-height: 1;
|
|
702
|
-
}
|
|
703
|
-
|
|
704
495
|
/* ============================================
|
|
705
496
|
Responsive Breakpoints
|
|
706
497
|
============================================ */
|
|
707
498
|
|
|
708
|
-
/*
|
|
709
|
-
@media (max-width: 1024px) {
|
|
710
|
-
:root {
|
|
711
|
-
--size-sidebar: 180px;
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
.page-wrapper > main {
|
|
715
|
-
padding: var(--space-lg) var(--space-xl);
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
/* Mobile: sidebar overlays content */
|
|
499
|
+
/* Mobile: compact typography */
|
|
720
500
|
@media (max-width: 768px) {
|
|
721
|
-
.page-wrapper {
|
|
722
|
-
grid-template-columns: 1fr;
|
|
723
|
-
grid-template-rows: var(--size-header) 1fr auto;
|
|
724
|
-
grid-template-areas:
|
|
725
|
-
"header"
|
|
726
|
-
"content"
|
|
727
|
-
"footer";
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
.sidebar-toggle {
|
|
731
|
-
display: block;
|
|
732
|
-
}
|
|
733
|
-
|
|
734
|
-
.page-wrapper > aside.sidebar {
|
|
735
|
-
position: fixed;
|
|
736
|
-
top: var(--size-header);
|
|
737
|
-
left: 0;
|
|
738
|
-
width: 260px;
|
|
739
|
-
height: calc(100vh - var(--size-header));
|
|
740
|
-
z-index: 20;
|
|
741
|
-
transform: translateX(-100%);
|
|
742
|
-
transition: var(--transition-transform);
|
|
743
|
-
display: block;
|
|
744
|
-
border-right: 1px solid var(--color-border);
|
|
745
|
-
border-bottom: none;
|
|
746
|
-
padding: var(--space-lg) 0;
|
|
747
|
-
overflow-y: auto;
|
|
748
|
-
background: var(--pico-background-color, var(--color-dark-surface));
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
.page-wrapper > aside.sidebar.open {
|
|
752
|
-
transform: translateX(0);
|
|
753
|
-
box-shadow: 4px 0 24px var(--overlay-bg);
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
.sidebar-backdrop {
|
|
757
|
-
display: none;
|
|
758
|
-
position: fixed;
|
|
759
|
-
inset: 0;
|
|
760
|
-
top: var(--size-header);
|
|
761
|
-
background: var(--overlay-bg-heavy);
|
|
762
|
-
z-index: 19;
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
.sidebar-backdrop.open {
|
|
766
|
-
display: block;
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
.page-wrapper > main {
|
|
770
|
-
padding: var(--space-lg) var(--space-md);
|
|
771
|
-
}
|
|
772
|
-
|
|
773
501
|
h1 { font-size: 1.4rem; }
|
|
774
502
|
h2 { font-size: 1.15rem; }
|
|
775
503
|
|
|
@@ -810,10 +538,6 @@ main > p:first-of-type > a[href="/"]:hover {
|
|
|
810
538
|
font-size: 14px;
|
|
811
539
|
}
|
|
812
540
|
|
|
813
|
-
.page-wrapper > main {
|
|
814
|
-
padding: var(--space-md);
|
|
815
|
-
}
|
|
816
|
-
|
|
817
541
|
article > header {
|
|
818
542
|
padding: var(--space-sm) var(--space-md);
|
|
819
543
|
}
|
|
@@ -97,6 +97,13 @@
|
|
|
97
97
|
border-color: rgba(129, 140, 248, 0.2);
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
/* Tabler .badge compatibility shim */
|
|
101
|
+
.badge.status-badge {
|
|
102
|
+
font-size: var(--badge-font-size-base);
|
|
103
|
+
font-weight: 600;
|
|
104
|
+
letter-spacing: 0.02em;
|
|
105
|
+
}
|
|
106
|
+
|
|
100
107
|
/* Size variants */
|
|
101
108
|
.status-badge--sm {
|
|
102
109
|
padding: var(--badge-padding-sm);
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
--color-border: rgba(0, 0, 0, 0.1);
|
|
14
14
|
--color-text-dim: rgba(0, 0, 0, 0.5);
|
|
15
15
|
--color-text: #1a1a2e;
|
|
16
|
-
--color-accent: var(--
|
|
16
|
+
--color-accent: var(--tblr-primary, #0054a6);
|
|
17
17
|
|
|
18
18
|
/* Spacing */
|
|
19
19
|
--space-xs: 0.25rem;
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
/* --- Dark Mode (explicit attribute) --- */
|
|
76
|
-
[data-theme="dark"] {
|
|
76
|
+
[data-bs-theme="dark"] {
|
|
77
77
|
--color-surface: #13131a;
|
|
78
78
|
--color-surface-raised: rgba(255, 255, 255, 0.03);
|
|
79
79
|
--color-surface-hover: rgba(255, 255, 255, 0.06);
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
|
|
85
85
|
/* --- Dark Mode (system preference, unless light forced) --- */
|
|
86
86
|
@media (prefers-color-scheme: dark) {
|
|
87
|
-
:root:not([data-theme="light"]) {
|
|
87
|
+
:root:not([data-bs-theme="light"]) {
|
|
88
88
|
--color-surface: #13131a;
|
|
89
89
|
--color-surface-raised: rgba(255, 255, 255, 0.03);
|
|
90
90
|
--color-surface-hover: rgba(255, 255, 255, 0.06);
|
|
@@ -1,34 +1,12 @@
|
|
|
1
|
-
//
|
|
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.
|
|
2
5
|
document.addEventListener('DOMContentLoaded', function() {
|
|
3
|
-
var toggle = document.
|
|
4
|
-
var
|
|
5
|
-
if (!toggle || !
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
var backdrop = document.createElement('div');
|
|
9
|
-
backdrop.className = 'sidebar-backdrop';
|
|
10
|
-
document.body.appendChild(backdrop);
|
|
11
|
-
|
|
12
|
-
function closeSidebar() {
|
|
13
|
-
sidebar.classList.remove('open');
|
|
14
|
-
backdrop.classList.remove('open');
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function toggleSidebar() {
|
|
18
|
-
sidebar.classList.toggle('open');
|
|
19
|
-
backdrop.classList.toggle('open');
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
toggle.addEventListener('click', toggleSidebar);
|
|
23
|
-
backdrop.addEventListener('click', closeSidebar);
|
|
24
|
-
|
|
25
|
-
// Close sidebar when a nav link is clicked (mobile)
|
|
26
|
-
var navLinks = sidebar.querySelectorAll('a');
|
|
27
|
-
navLinks.forEach(function(link) {
|
|
28
|
-
link.addEventListener('click', function() {
|
|
29
|
-
if (window.innerWidth <= 768) {
|
|
30
|
-
closeSidebar();
|
|
31
|
-
}
|
|
32
|
-
});
|
|
6
|
+
var toggle = document.getElementById('sidebar-toggle');
|
|
7
|
+
var sidebarMenu = document.getElementById('sidebar-menu');
|
|
8
|
+
if (!toggle || !sidebarMenu) return;
|
|
9
|
+
toggle.addEventListener('click', function() {
|
|
10
|
+
sidebarMenu.classList.toggle('show');
|
|
33
11
|
});
|
|
34
12
|
});
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
/* theme-toggle.js — Toggle light/dark theme via data-theme attribute + localStorage */
|
|
1
|
+
/* theme-toggle.js — Toggle light/dark theme via data-bs-theme attribute + localStorage */
|
|
2
2
|
(function () {
|
|
3
3
|
'use strict';
|
|
4
4
|
|
|
5
5
|
var STORAGE_KEY = 'pbr-theme';
|
|
6
6
|
|
|
7
7
|
function getEffectiveTheme() {
|
|
8
|
-
var explicit = document.documentElement.dataset.
|
|
8
|
+
var explicit = document.documentElement.dataset.bsTheme;
|
|
9
9
|
if (explicit === 'light' || explicit === 'dark') return explicit;
|
|
10
10
|
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
|
11
11
|
}
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
// Apply stored theme (also done in layout-top inline script for flash prevention)
|
|
24
24
|
var stored = localStorage.getItem(STORAGE_KEY);
|
|
25
25
|
if (stored) {
|
|
26
|
-
document.documentElement.dataset.
|
|
26
|
+
document.documentElement.dataset.bsTheme = stored;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
updateIcon(btn, getEffectiveTheme());
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
btn.addEventListener('click', function () {
|
|
32
32
|
var current = getEffectiveTheme();
|
|
33
33
|
var next = current === 'dark' ? 'light' : 'dark';
|
|
34
|
-
document.documentElement.dataset.
|
|
34
|
+
document.documentElement.dataset.bsTheme = next;
|
|
35
35
|
localStorage.setItem(STORAGE_KEY, next);
|
|
36
36
|
updateIcon(btn, next);
|
|
37
37
|
});
|
|
@@ -1,19 +1,27 @@
|
|
|
1
1
|
<% if (!recentActivity || recentActivity.length === 0) { %>
|
|
2
|
-
|
|
2
|
+
<%- include('empty-state', { title: 'No recent activity' }) %>
|
|
3
3
|
<% } else { %>
|
|
4
|
-
<
|
|
4
|
+
<div class="list-group list-group-flush">
|
|
5
5
|
<% recentActivity.forEach(function(item) { %>
|
|
6
6
|
<%
|
|
7
7
|
// Format path: strip .planning/ prefix for brevity
|
|
8
|
-
var displayPath = item.path.replace(/^\.planning\//, '');
|
|
8
|
+
var displayPath = (item.path || item.description || String(item)).replace(/^\.planning\//, '');
|
|
9
9
|
// Format timestamp: show just date+time, no timezone
|
|
10
|
-
var ts = item.timestamp || '';
|
|
10
|
+
var ts = item.timestamp || item.time || item.date || '';
|
|
11
11
|
var dateOnly = ts.replace(/\s+[-+]\d{4}$/, '').replace(/:\d{2}$/, '');
|
|
12
12
|
%>
|
|
13
|
-
<
|
|
14
|
-
<
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
<div class="list-group-item">
|
|
14
|
+
<div class="row align-items-center">
|
|
15
|
+
<div class="col text-truncate">
|
|
16
|
+
<span class="text-truncate small"><%= displayPath %></span>
|
|
17
|
+
</div>
|
|
18
|
+
<% if (dateOnly) { %>
|
|
19
|
+
<div class="col-auto">
|
|
20
|
+
<time class="text-muted small" datetime="<%= ts %>"><%= dateOnly %></time>
|
|
21
|
+
</div>
|
|
22
|
+
<% } %>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
17
25
|
<% }); %>
|
|
18
|
-
</
|
|
26
|
+
</div>
|
|
19
27
|
<% } %>
|