@sienklogic/plan-build-run 2.15.0 → 2.16.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 (44) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/dashboard/package.json +3 -1
  3. package/dashboard/public/css/layout.css +237 -82
  4. package/dashboard/public/css/tokens.css +59 -0
  5. package/dashboard/public/js/sidebar-toggle.js +21 -7
  6. package/dashboard/public/js/sse-client.js +99 -0
  7. package/dashboard/public/js/theme-toggle.js +46 -0
  8. package/dashboard/src/app.js +4 -0
  9. package/dashboard/src/middleware/current-phase.js +24 -0
  10. package/dashboard/src/routes/events.routes.js +5 -0
  11. package/dashboard/src/routes/index.routes.js +2 -1
  12. package/dashboard/src/routes/pages.routes.js +94 -6
  13. package/dashboard/src/services/analytics.service.js +143 -0
  14. package/dashboard/src/services/milestone.service.js +50 -4
  15. package/dashboard/src/services/roadmap.service.js +73 -0
  16. package/dashboard/src/services/todo.service.js +11 -2
  17. package/dashboard/src/services/watcher.service.js +1 -1
  18. package/dashboard/src/utils/cache.js +55 -0
  19. package/dashboard/src/views/analytics.ejs +5 -0
  20. package/dashboard/src/views/dependencies.ejs +5 -0
  21. package/dashboard/src/views/error.ejs +16 -9
  22. package/dashboard/src/views/partials/analytics-content.ejs +71 -0
  23. package/dashboard/src/views/partials/breadcrumbs.ejs +14 -0
  24. package/dashboard/src/views/partials/dashboard-content.ejs +1 -0
  25. package/dashboard/src/views/partials/dependencies-content.ejs +16 -0
  26. package/dashboard/src/views/partials/empty-state.ejs +7 -0
  27. package/dashboard/src/views/partials/head.ejs +4 -1
  28. package/dashboard/src/views/partials/header.ejs +9 -0
  29. package/dashboard/src/views/partials/layout-bottom.ejs +1 -10
  30. package/dashboard/src/views/partials/layout-top.ejs +7 -0
  31. package/dashboard/src/views/partials/milestone-detail-content.ejs +1 -0
  32. package/dashboard/src/views/partials/milestones-content.ejs +55 -19
  33. package/dashboard/src/views/partials/phase-content.ejs +1 -0
  34. package/dashboard/src/views/partials/phase-doc-content.ejs +1 -1
  35. package/dashboard/src/views/partials/phases-content.ejs +1 -0
  36. package/dashboard/src/views/partials/roadmap-content.ejs +1 -0
  37. package/dashboard/src/views/partials/sidebar.ejs +88 -43
  38. package/dashboard/src/views/partials/todo-create-content.ejs +1 -0
  39. package/dashboard/src/views/partials/todo-detail-content.ejs +5 -1
  40. package/dashboard/src/views/partials/todos-content.ejs +44 -3
  41. package/package.json +1 -1
  42. package/plugins/copilot-pbr/plugin.json +1 -1
  43. package/plugins/cursor-pbr/.cursor-plugin/plugin.json +1 -1
  44. package/plugins/pbr/.claude-plugin/plugin.json +1 -1
@@ -1,46 +1,91 @@
1
1
  <aside class="sidebar">
2
- <nav>
3
- <ul>
4
- <li>
5
- <a href="/"
6
- hx-get="/"
7
- hx-target="#main-content"
8
- hx-push-url="true"<%= typeof activePage !== 'undefined' && activePage === 'dashboard' ? ' aria-current="page"' : '' %>>
9
- Dashboard
10
- </a>
11
- </li>
12
- <li>
13
- <a href="/phases"
14
- hx-get="/phases"
15
- hx-target="#main-content"
16
- hx-push-url="true"<%= typeof activePage !== 'undefined' && activePage === 'phases' ? ' aria-current="page"' : '' %>>
17
- Phases
18
- </a>
19
- </li>
20
- <li>
21
- <a href="/todos"
22
- hx-get="/todos"
23
- hx-target="#main-content"
24
- hx-push-url="true"<%= typeof activePage !== 'undefined' && activePage === 'todos' ? ' aria-current="page"' : '' %>>
25
- Todos
26
- </a>
27
- </li>
28
- <li>
29
- <a href="/roadmap"
30
- hx-get="/roadmap"
31
- hx-target="#main-content"
32
- hx-push-url="true"<%= typeof activePage !== 'undefined' && activePage === 'roadmap' ? ' aria-current="page"' : '' %>>
33
- Roadmap
34
- </a>
35
- </li>
36
- <li>
37
- <a href="/milestones"
38
- hx-get="/milestones"
39
- hx-target="#main-content"
40
- hx-push-url="true"<%= typeof activePage !== 'undefined' && activePage === 'milestones' ? ' aria-current="page"' : '' %>>
41
- Milestones
42
- </a>
43
- </li>
44
- </ul>
2
+ <% if (typeof currentPhase !== 'undefined' && currentPhase) { %>
3
+ <div class="sidebar-current-phase">
4
+ <small>Current Phase</small>
5
+ <a href="/phases/<%= currentPhase.number %>"
6
+ hx-get="/phases/<%= currentPhase.number %>"
7
+ hx-target="#main-content"
8
+ hx-push-url="true">
9
+ <strong>Phase <%= currentPhase.number %></strong>
10
+ <span><%= currentPhase.name %></span>
11
+ <span class="phase-status"><%= currentPhase.status %></span>
12
+ </a>
13
+ </div>
14
+ <% } %>
15
+
16
+ <nav aria-label="Main navigation">
17
+ <details open>
18
+ <summary>Overview</summary>
19
+ <ul>
20
+ <li>
21
+ <a href="/"
22
+ hx-get="/"
23
+ hx-target="#main-content"
24
+ hx-push-url="true"<%= typeof activePage !== 'undefined' && activePage === 'dashboard' ? ' aria-current="page"' : '' %>>
25
+ Dashboard
26
+ </a>
27
+ </li>
28
+ <li>
29
+ <a href="/roadmap"
30
+ hx-get="/roadmap"
31
+ hx-target="#main-content"
32
+ hx-push-url="true"<%= typeof activePage !== 'undefined' && activePage === 'roadmap' ? ' aria-current="page"' : '' %>>
33
+ Roadmap
34
+ </a>
35
+ </li>
36
+ <li>
37
+ <a href="/dependencies"
38
+ hx-get="/dependencies"
39
+ hx-target="#main-content"
40
+ hx-push-url="true"<%= typeof activePage !== 'undefined' && activePage === 'dependencies' ? ' aria-current="page"' : '' %>>
41
+ Dependencies
42
+ </a>
43
+ </li>
44
+ <li>
45
+ <a href="/analytics"
46
+ hx-get="/analytics"
47
+ hx-target="#main-content"
48
+ hx-push-url="true"<%= typeof activePage !== 'undefined' && activePage === 'analytics' ? ' aria-current="page"' : '' %>>
49
+ Analytics
50
+ </a>
51
+ </li>
52
+ </ul>
53
+ </details>
54
+
55
+ <details open>
56
+ <summary>Work</summary>
57
+ <ul>
58
+ <li>
59
+ <a href="/phases"
60
+ hx-get="/phases"
61
+ hx-target="#main-content"
62
+ hx-push-url="true"<%= typeof activePage !== 'undefined' && activePage === 'phases' ? ' aria-current="page"' : '' %>>
63
+ Phases
64
+ </a>
65
+ </li>
66
+ <li>
67
+ <a href="/todos"
68
+ hx-get="/todos"
69
+ hx-target="#main-content"
70
+ hx-push-url="true"<%= typeof activePage !== 'undefined' && activePage === 'todos' ? ' aria-current="page"' : '' %>>
71
+ Todos
72
+ </a>
73
+ </li>
74
+ </ul>
75
+ </details>
76
+
77
+ <details open>
78
+ <summary>History</summary>
79
+ <ul>
80
+ <li>
81
+ <a href="/milestones"
82
+ hx-get="/milestones"
83
+ hx-target="#main-content"
84
+ hx-push-url="true"<%= typeof activePage !== 'undefined' && activePage === 'milestones' ? ' aria-current="page"' : '' %>>
85
+ Milestones
86
+ </a>
87
+ </li>
88
+ </ul>
89
+ </details>
45
90
  </nav>
46
91
  </aside>
@@ -1,3 +1,4 @@
1
+ <%- include('breadcrumbs', { breadcrumbs: typeof breadcrumbs !== 'undefined' ? breadcrumbs : [] }) %>
1
2
  <h1>Create Todo</h1>
2
3
 
3
4
  <p><a href="/todos">&larr; Back to Todos</a></p>
@@ -1,3 +1,4 @@
1
+ <%- include('breadcrumbs', { breadcrumbs: typeof breadcrumbs !== 'undefined' ? breadcrumbs : [] }) %>
1
2
  <h1><%= title %></h1>
2
3
 
3
4
  <p><a href="/todos">&larr; Back to Todos</a></p>
@@ -30,9 +31,12 @@
30
31
  <hr>
31
32
  <form method="POST" action="/todos/<%= id %>/done"
32
33
  hx-post="/todos/<%= id %>/done"
33
- hx-target="#main-content"
34
+ hx-target="closest article"
35
+ hx-swap="outerHTML"
36
+ hx-indicator="#done-spinner"
34
37
  style="display:inline;">
35
38
  <button type="submit" class="secondary">Mark as Done</button>
39
+ <span id="done-spinner" class="htmx-indicator" aria-busy="true"></span>
36
40
  </form>
37
41
  <% } %>
38
42
  </article>
@@ -1,3 +1,4 @@
1
+ <%- include('breadcrumbs', { breadcrumbs: typeof breadcrumbs !== 'undefined' ? breadcrumbs : [] }) %>
1
2
  <h1>Todos</h1>
2
3
 
3
4
  <p><a href="/todos/new" role="button"
@@ -5,7 +6,49 @@
5
6
  hx-target="#main-content"
6
7
  hx-push-url="true">Create Todo</a></p>
7
8
 
9
+ <% const f = typeof filters !== 'undefined' ? filters : { priority: '', status: '', q: '' }; %>
10
+ <article>
11
+ <form hx-get="/todos" hx-target="#main-content" hx-push-url="true">
12
+ <div class="grid">
13
+ <label>
14
+ Priority
15
+ <select name="priority" onchange="this.form.requestSubmit()">
16
+ <option value="">All</option>
17
+ <option value="P0"<%= f.priority === 'P0' ? ' selected' : '' %>>P0</option>
18
+ <option value="P1"<%= f.priority === 'P1' ? ' selected' : '' %>>P1</option>
19
+ <option value="P2"<%= f.priority === 'P2' ? ' selected' : '' %>>P2</option>
20
+ <option value="PX"<%= f.priority === 'PX' ? ' selected' : '' %>>PX</option>
21
+ </select>
22
+ </label>
23
+ <label>
24
+ Status
25
+ <select name="status" onchange="this.form.requestSubmit()">
26
+ <option value="">All</option>
27
+ <option value="pending"<%= f.status === 'pending' ? ' selected' : '' %>>pending</option>
28
+ </select>
29
+ </label>
30
+ <label>
31
+ Search
32
+ <input type="search" name="q" value="<%= f.q %>" placeholder="Search titles..."
33
+ hx-get="/todos" hx-target="#main-content" hx-push-url="true"
34
+ hx-trigger="keyup changed delay:300ms, search" hx-include="closest form">
35
+ </label>
36
+ </div>
37
+ </form>
38
+ </article>
39
+
8
40
  <% if (todos.length > 0) { %>
41
+ <p>
42
+ <button class="secondary"
43
+ hx-post="/todos/bulk-complete?priority=<%= encodeURIComponent(f.priority) %>&status=<%= encodeURIComponent(f.status) %>&q=<%= encodeURIComponent(f.q) %>"
44
+ hx-target="#main-content"
45
+ hx-swap="outerHTML"
46
+ hx-indicator="#bulk-spinner"
47
+ hx-confirm="Complete all <%= todos.length %> visible todo(s)?">
48
+ Complete All Visible (<%= todos.length %>)
49
+ </button>
50
+ <span id="bulk-spinner" class="htmx-indicator" aria-busy="true"></span>
51
+ </p>
9
52
  <article>
10
53
  <div class="table-wrap">
11
54
  <table>
@@ -47,7 +90,5 @@
47
90
  </div>
48
91
  </article>
49
92
  <% } else { %>
50
- <article>
51
- <p>No pending todos found. Add a todo file to <code>.planning/todos/pending/</code> to see it here.</p>
52
- </article>
93
+ <%- include('empty-state', { icon: '📋', title: 'No todos found', action: '<p><a href="/todos/new" role="button" hx-get="/todos/new" hx-target="#main-content" hx-push-url="true">Create Todo</a></p>' }) %>
53
94
  <% } %>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sienklogic/plan-build-run",
3
- "version": "2.15.0",
3
+ "version": "2.16.0",
4
4
  "description": "Plan it, Build it, Run it — structured development workflow for Claude Code",
5
5
  "keywords": [
6
6
  "claude-code",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pbr",
3
3
  "displayName": "Plan-Build-Run",
4
- "version": "2.15.0",
4
+ "version": "2.16.0",
5
5
  "description": "Plan-Build-Run — Structured development workflow for GitHub Copilot CLI. Solves context rot through disciplined agent delegation, structured planning, atomic execution, and goal-backward verification.",
6
6
  "author": {
7
7
  "name": "SienkLogic",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pbr",
3
3
  "displayName": "Plan-Build-Run",
4
- "version": "2.15.0",
4
+ "version": "2.16.0",
5
5
  "description": "Plan-Build-Run — Structured development workflow for Cursor. Solves context rot through disciplined subagent delegation, structured planning, atomic execution, and goal-backward verification.",
6
6
  "author": {
7
7
  "name": "SienkLogic",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pbr",
3
- "version": "2.15.0",
3
+ "version": "2.16.0",
4
4
  "description": "Plan-Build-Run — Structured development workflow for Claude Code. Solves context rot through disciplined subagent delegation, structured planning, atomic execution, and goal-backward verification.",
5
5
  "author": {
6
6
  "name": "SienkLogic",