@sienklogic/plan-build-run 2.0.0 → 2.0.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.
Files changed (225) hide show
  1. package/CHANGELOG.md +56 -56
  2. package/CLAUDE.md +149 -149
  3. package/LICENSE +21 -21
  4. package/README.md +247 -247
  5. package/dashboard/bin/cli.js +25 -25
  6. package/dashboard/package.json +34 -34
  7. package/dashboard/public/css/layout.css +406 -406
  8. package/dashboard/public/css/status-colors.css +98 -98
  9. package/dashboard/public/js/htmx-title.js +5 -5
  10. package/dashboard/public/js/sidebar-toggle.js +20 -20
  11. package/dashboard/src/app.js +78 -78
  12. package/dashboard/src/middleware/errorHandler.js +52 -52
  13. package/dashboard/src/middleware/notFoundHandler.js +9 -9
  14. package/dashboard/src/repositories/planning.repository.js +128 -128
  15. package/dashboard/src/routes/events.routes.js +40 -40
  16. package/dashboard/src/routes/index.routes.js +31 -31
  17. package/dashboard/src/routes/pages.routes.js +245 -195
  18. package/dashboard/src/server.js +42 -42
  19. package/dashboard/src/services/dashboard.service.js +222 -222
  20. package/dashboard/src/services/phase.service.js +220 -167
  21. package/dashboard/src/services/project.service.js +57 -57
  22. package/dashboard/src/services/roadmap.service.js +171 -171
  23. package/dashboard/src/services/sse.service.js +58 -58
  24. package/dashboard/src/services/todo.service.js +254 -254
  25. package/dashboard/src/services/watcher.service.js +48 -48
  26. package/dashboard/src/views/coming-soon.ejs +11 -11
  27. package/dashboard/src/views/error.ejs +13 -13
  28. package/dashboard/src/views/index.ejs +5 -5
  29. package/dashboard/src/views/layout.ejs +1 -1
  30. package/dashboard/src/views/partials/dashboard-content.ejs +77 -77
  31. package/dashboard/src/views/partials/footer.ejs +3 -3
  32. package/dashboard/src/views/partials/head.ejs +21 -21
  33. package/dashboard/src/views/partials/header.ejs +12 -12
  34. package/dashboard/src/views/partials/layout-bottom.ejs +15 -15
  35. package/dashboard/src/views/partials/layout-top.ejs +8 -8
  36. package/dashboard/src/views/partials/phase-content.ejs +188 -181
  37. package/dashboard/src/views/partials/phase-doc-content.ejs +38 -0
  38. package/dashboard/src/views/partials/phases-content.ejs +117 -117
  39. package/dashboard/src/views/partials/roadmap-content.ejs +142 -142
  40. package/dashboard/src/views/partials/sidebar.ejs +38 -38
  41. package/dashboard/src/views/partials/todo-create-content.ejs +53 -53
  42. package/dashboard/src/views/partials/todo-detail-content.ejs +38 -38
  43. package/dashboard/src/views/partials/todos-content.ejs +53 -53
  44. package/dashboard/src/views/phase-detail.ejs +5 -5
  45. package/dashboard/src/views/phase-doc.ejs +5 -0
  46. package/dashboard/src/views/phases.ejs +5 -5
  47. package/dashboard/src/views/roadmap.ejs +5 -5
  48. package/dashboard/src/views/todo-create.ejs +5 -5
  49. package/dashboard/src/views/todo-detail.ejs +5 -5
  50. package/dashboard/src/views/todos.ejs +5 -5
  51. package/package.json +57 -57
  52. package/plugins/pbr/.claude-plugin/plugin.json +13 -13
  53. package/plugins/pbr/UI-CONSISTENCY-GAPS.md +61 -61
  54. package/plugins/pbr/agents/codebase-mapper.md +279 -271
  55. package/plugins/pbr/agents/debugger.md +281 -281
  56. package/plugins/pbr/agents/executor.md +428 -407
  57. package/plugins/pbr/agents/general.md +164 -164
  58. package/plugins/pbr/agents/integration-checker.md +169 -141
  59. package/plugins/pbr/agents/plan-checker.md +296 -280
  60. package/plugins/pbr/agents/planner.md +358 -358
  61. package/plugins/pbr/agents/researcher.md +363 -363
  62. package/plugins/pbr/agents/synthesizer.md +230 -230
  63. package/plugins/pbr/agents/verifier.md +489 -454
  64. package/plugins/pbr/commands/begin.md +5 -5
  65. package/plugins/pbr/commands/build.md +5 -5
  66. package/plugins/pbr/commands/config.md +5 -5
  67. package/plugins/pbr/commands/continue.md +5 -5
  68. package/plugins/pbr/commands/debug.md +5 -5
  69. package/plugins/pbr/commands/discuss.md +5 -5
  70. package/plugins/pbr/commands/explore.md +5 -5
  71. package/plugins/pbr/commands/health.md +5 -5
  72. package/plugins/pbr/commands/help.md +5 -5
  73. package/plugins/pbr/commands/import.md +5 -5
  74. package/plugins/pbr/commands/milestone.md +5 -5
  75. package/plugins/pbr/commands/note.md +5 -5
  76. package/plugins/pbr/commands/pause.md +5 -5
  77. package/plugins/pbr/commands/plan.md +5 -5
  78. package/plugins/pbr/commands/quick.md +5 -5
  79. package/plugins/pbr/commands/resume.md +5 -5
  80. package/plugins/pbr/commands/review.md +5 -5
  81. package/plugins/pbr/commands/scan.md +5 -5
  82. package/plugins/pbr/commands/setup.md +5 -5
  83. package/plugins/pbr/commands/status.md +5 -5
  84. package/plugins/pbr/commands/todo.md +5 -5
  85. package/plugins/pbr/contexts/dev.md +27 -27
  86. package/plugins/pbr/contexts/research.md +28 -28
  87. package/plugins/pbr/contexts/review.md +36 -36
  88. package/plugins/pbr/hooks/hooks.json +183 -183
  89. package/plugins/pbr/references/agent-anti-patterns.md +24 -24
  90. package/plugins/pbr/references/agent-interactions.md +134 -134
  91. package/plugins/pbr/references/agent-teams.md +54 -54
  92. package/plugins/pbr/references/checkpoints.md +157 -157
  93. package/plugins/pbr/references/common-bug-patterns.md +13 -13
  94. package/plugins/pbr/references/config-reference.md +441 -0
  95. package/plugins/pbr/references/continuation-format.md +212 -212
  96. package/plugins/pbr/references/deviation-rules.md +112 -112
  97. package/plugins/pbr/references/git-integration.md +226 -226
  98. package/plugins/pbr/references/integration-patterns.md +117 -117
  99. package/plugins/pbr/references/model-profiles.md +99 -99
  100. package/plugins/pbr/references/model-selection.md +31 -31
  101. package/plugins/pbr/references/pbr-rules.md +193 -193
  102. package/plugins/pbr/references/plan-authoring.md +181 -181
  103. package/plugins/pbr/references/plan-format.md +287 -283
  104. package/plugins/pbr/references/planning-config.md +213 -213
  105. package/plugins/pbr/references/questioning.md +214 -214
  106. package/plugins/pbr/references/reading-verification.md +127 -127
  107. package/plugins/pbr/references/stub-patterns.md +160 -160
  108. package/plugins/pbr/references/subagent-coordination.md +119 -119
  109. package/plugins/pbr/references/ui-formatting.md +461 -399
  110. package/plugins/pbr/references/verification-patterns.md +198 -198
  111. package/plugins/pbr/references/wave-execution.md +95 -95
  112. package/plugins/pbr/scripts/auto-continue.js +80 -80
  113. package/plugins/pbr/scripts/check-dangerous-commands.js +136 -136
  114. package/plugins/pbr/scripts/check-doc-sprawl.js +102 -102
  115. package/plugins/pbr/scripts/check-phase-boundary.js +196 -196
  116. package/plugins/pbr/scripts/check-plan-format.js +270 -270
  117. package/plugins/pbr/scripts/check-roadmap-sync.js +322 -252
  118. package/plugins/pbr/scripts/check-skill-workflow.js +262 -262
  119. package/plugins/pbr/scripts/check-state-sync.js +476 -476
  120. package/plugins/pbr/scripts/check-subagent-output.js +144 -144
  121. package/plugins/pbr/scripts/config-schema.json +251 -251
  122. package/plugins/pbr/scripts/context-budget-check.js +287 -287
  123. package/plugins/pbr/scripts/event-handler.js +151 -151
  124. package/plugins/pbr/scripts/event-logger.js +92 -92
  125. package/plugins/pbr/scripts/hook-logger.js +80 -76
  126. package/plugins/pbr/scripts/hooks-schema.json +79 -79
  127. package/plugins/pbr/scripts/log-subagent.js +164 -152
  128. package/plugins/pbr/scripts/log-tool-failure.js +88 -88
  129. package/plugins/pbr/scripts/pbr-tools.js +1378 -1301
  130. package/plugins/pbr/scripts/post-write-dispatch.js +66 -66
  131. package/plugins/pbr/scripts/post-write-quality.js +207 -207
  132. package/plugins/pbr/scripts/pre-bash-dispatch.js +86 -56
  133. package/plugins/pbr/scripts/pre-write-dispatch.js +97 -62
  134. package/plugins/pbr/scripts/progress-tracker.js +281 -228
  135. package/plugins/pbr/scripts/run-hook.js +92 -0
  136. package/plugins/pbr/scripts/session-cleanup.js +254 -254
  137. package/plugins/pbr/scripts/status-line.js +288 -285
  138. package/plugins/pbr/scripts/suggest-compact.js +119 -119
  139. package/plugins/pbr/scripts/task-completed.js +45 -45
  140. package/plugins/pbr/scripts/track-context-budget.js +149 -119
  141. package/plugins/pbr/scripts/validate-commit.js +200 -200
  142. package/plugins/pbr/scripts/validate-plugin-structure.js +183 -172
  143. package/plugins/pbr/scripts/validate-task.js +106 -0
  144. package/plugins/pbr/skills/begin/SKILL.md +594 -545
  145. package/plugins/pbr/skills/begin/templates/PROJECT.md.tmpl +33 -33
  146. package/plugins/pbr/skills/begin/templates/REQUIREMENTS.md.tmpl +18 -18
  147. package/plugins/pbr/skills/begin/templates/STATE.md.tmpl +49 -49
  148. package/plugins/pbr/skills/begin/templates/config.json.tmpl +64 -63
  149. package/plugins/pbr/skills/begin/templates/researcher-prompt.md.tmpl +19 -19
  150. package/plugins/pbr/skills/begin/templates/roadmap-prompt.md.tmpl +30 -30
  151. package/plugins/pbr/skills/begin/templates/synthesis-prompt.md.tmpl +16 -16
  152. package/plugins/pbr/skills/build/SKILL.md +943 -962
  153. package/plugins/pbr/skills/config/SKILL.md +256 -241
  154. package/plugins/pbr/skills/continue/SKILL.md +164 -127
  155. package/plugins/pbr/skills/debug/SKILL.md +515 -489
  156. package/plugins/pbr/skills/debug/templates/continuation-prompt.md.tmpl +16 -16
  157. package/plugins/pbr/skills/debug/templates/initial-investigation-prompt.md.tmpl +27 -27
  158. package/plugins/pbr/skills/discuss/SKILL.md +347 -338
  159. package/plugins/pbr/skills/discuss/templates/CONTEXT.md.tmpl +61 -61
  160. package/plugins/pbr/skills/discuss/templates/decision-categories.md +9 -9
  161. package/plugins/pbr/skills/explore/SKILL.md +378 -362
  162. package/plugins/pbr/skills/health/SKILL.md +221 -186
  163. package/plugins/pbr/skills/health/templates/check-pattern.md.tmpl +30 -30
  164. package/plugins/pbr/skills/health/templates/output-format.md.tmpl +63 -63
  165. package/plugins/pbr/skills/help/SKILL.md +155 -140
  166. package/plugins/pbr/skills/import/SKILL.md +504 -490
  167. package/plugins/pbr/skills/milestone/SKILL.md +704 -673
  168. package/plugins/pbr/skills/milestone/templates/audit-report.md.tmpl +48 -48
  169. package/plugins/pbr/skills/milestone/templates/stats-file.md.tmpl +30 -30
  170. package/plugins/pbr/skills/note/SKILL.md +231 -212
  171. package/plugins/pbr/skills/pause/SKILL.md +249 -235
  172. package/plugins/pbr/skills/pause/templates/continue-here.md.tmpl +71 -71
  173. package/plugins/pbr/skills/plan/SKILL.md +685 -628
  174. package/plugins/pbr/skills/plan/decimal-phase-calc.md +98 -98
  175. package/plugins/pbr/skills/plan/templates/checker-prompt.md.tmpl +21 -21
  176. package/plugins/pbr/skills/plan/templates/gap-closure-prompt.md.tmpl +32 -32
  177. package/plugins/pbr/skills/plan/templates/planner-prompt.md.tmpl +38 -38
  178. package/plugins/pbr/skills/plan/templates/researcher-prompt.md.tmpl +19 -19
  179. package/plugins/pbr/skills/plan/templates/revision-prompt.md.tmpl +23 -23
  180. package/plugins/pbr/skills/quick/SKILL.md +354 -335
  181. package/plugins/pbr/skills/resume/SKILL.md +402 -388
  182. package/plugins/pbr/skills/review/SKILL.md +686 -652
  183. package/plugins/pbr/skills/review/templates/debugger-prompt.md.tmpl +60 -60
  184. package/plugins/pbr/skills/review/templates/gap-planner-prompt.md.tmpl +40 -40
  185. package/plugins/pbr/skills/review/templates/verifier-prompt.md.tmpl +115 -115
  186. package/plugins/pbr/skills/scan/SKILL.md +304 -269
  187. package/plugins/pbr/skills/scan/templates/mapper-prompt.md.tmpl +201 -201
  188. package/plugins/pbr/skills/setup/SKILL.md +253 -227
  189. package/plugins/pbr/skills/shared/commit-planning-docs.md +35 -35
  190. package/plugins/pbr/skills/shared/config-loading.md +102 -102
  191. package/plugins/pbr/skills/shared/context-budget.md +40 -40
  192. package/plugins/pbr/skills/shared/context-loader-task.md +86 -86
  193. package/plugins/pbr/skills/shared/digest-select.md +79 -79
  194. package/plugins/pbr/skills/shared/domain-probes.md +125 -125
  195. package/plugins/pbr/skills/shared/error-reporting.md +79 -79
  196. package/plugins/pbr/skills/shared/gate-prompts.md +388 -388
  197. package/plugins/pbr/skills/shared/phase-argument-parsing.md +45 -45
  198. package/plugins/pbr/skills/shared/progress-display.md +53 -53
  199. package/plugins/pbr/skills/shared/revision-loop.md +81 -81
  200. package/plugins/pbr/skills/shared/state-loading.md +62 -62
  201. package/plugins/pbr/skills/shared/state-update.md +161 -161
  202. package/plugins/pbr/skills/shared/universal-anti-patterns.md +33 -33
  203. package/plugins/pbr/skills/status/SKILL.md +367 -353
  204. package/plugins/pbr/skills/todo/SKILL.md +198 -181
  205. package/plugins/pbr/templates/CONTEXT.md.tmpl +52 -52
  206. package/plugins/pbr/templates/INTEGRATION-REPORT.md.tmpl +151 -151
  207. package/plugins/pbr/templates/RESEARCH-SUMMARY.md.tmpl +97 -97
  208. package/plugins/pbr/templates/ROADMAP.md.tmpl +40 -40
  209. package/plugins/pbr/templates/SUMMARY.md.tmpl +81 -81
  210. package/plugins/pbr/templates/VERIFICATION-DETAIL.md.tmpl +116 -116
  211. package/plugins/pbr/templates/codebase/ARCHITECTURE.md.tmpl +98 -98
  212. package/plugins/pbr/templates/codebase/CONCERNS.md.tmpl +93 -93
  213. package/plugins/pbr/templates/codebase/CONVENTIONS.md.tmpl +104 -104
  214. package/plugins/pbr/templates/codebase/INTEGRATIONS.md.tmpl +78 -78
  215. package/plugins/pbr/templates/codebase/STACK.md.tmpl +78 -78
  216. package/plugins/pbr/templates/codebase/STRUCTURE.md.tmpl +80 -80
  217. package/plugins/pbr/templates/codebase/TESTING.md.tmpl +107 -107
  218. package/plugins/pbr/templates/continue-here.md.tmpl +73 -73
  219. package/plugins/pbr/templates/prompt-partials/phase-project-context.md.tmpl +37 -37
  220. package/plugins/pbr/templates/research/ARCHITECTURE.md.tmpl +124 -124
  221. package/plugins/pbr/templates/research/STACK.md.tmpl +71 -71
  222. package/plugins/pbr/templates/research/SUMMARY.md.tmpl +112 -112
  223. package/plugins/pbr/templates/research-outputs/phase-research.md.tmpl +81 -81
  224. package/plugins/pbr/templates/research-outputs/project-research.md.tmpl +99 -99
  225. package/plugins/pbr/templates/research-outputs/synthesis.md.tmpl +36 -36
@@ -1,142 +1,142 @@
1
- <h1>Project Roadmap</h1>
2
-
3
- <% if (phases.length === 0) { %>
4
- <article>
5
- <p>No phases found. Add a ROADMAP.md file to your .planning/ directory to see the roadmap here.</p>
6
- </article>
7
- <% } else { %>
8
-
9
- <%
10
- // Group phases by milestone
11
- const msGroups = (typeof milestones !== 'undefined' && milestones.length > 0)
12
- ? milestones.map(m => ({
13
- ...m,
14
- phases: phases.filter(p => p.id >= m.startPhase && p.id <= m.endPhase)
15
- })).filter(g => g.phases.length > 0)
16
- : [{ name: 'All Phases', goal: '', startPhase: 1, endPhase: 9999, phases: phases }];
17
-
18
- const coveredIds = new Set(msGroups.flatMap(g => g.phases.map(p => p.id)));
19
- const ungroupedPhases = phases.filter(p => !coveredIds.has(p.id));
20
- %>
21
-
22
- <!-- Overall Progress -->
23
- <article>
24
- <header><strong>Overall Progress</strong></header>
25
- <%
26
- const totalComplete = phases.filter(p => p.status === 'complete').length;
27
- const totalPhases = phases.length;
28
- const pct = totalPhases > 0 ? Math.round((totalComplete / totalPhases) * 100) : 0;
29
- %>
30
- <progress value="<%= totalComplete %>" max="<%= totalPhases %>"></progress>
31
- <p><%= pct %>% complete (<%= totalComplete %> of <%= totalPhases %> phases)</p>
32
- </article>
33
-
34
- <% msGroups.forEach(function(group) { %>
35
- <article>
36
- <header>
37
- <strong><%= group.name %></strong>
38
- <% if (group.startPhase && group.endPhase < 9999) { %>
39
- <small>(Phases <%= String(group.startPhase).padStart(2, '0') %>&ndash;<%= String(group.endPhase).padStart(2, '0') %>)</small>
40
- <% } %>
41
- &mdash;
42
- <%
43
- const gc = group.phases.filter(p => p.status === 'complete').length;
44
- const gt = group.phases.length;
45
- %>
46
- <span class="status-badge" data-status="<%= gc === gt ? 'complete' : (gc > 0 ? 'in-progress' : 'not-started') %>">
47
- <%= gc %>/<%= gt %>
48
- </span>
49
- </header>
50
- <% if (group.goal) { %>
51
- <p><small><%= group.goal %></small></p>
52
- <% } %>
53
- <div class="table-wrap">
54
- <table>
55
- <thead>
56
- <tr>
57
- <th scope="col">Phase</th>
58
- <th scope="col">Name</th>
59
- <th scope="col">Plans</th>
60
- <th scope="col">Status</th>
61
- <th scope="col">Depends On</th>
62
- </tr>
63
- </thead>
64
- <tbody>
65
- <% group.phases.forEach(function(phase) { %>
66
- <tr>
67
- <td><%= String(phase.id).padStart(2, '0') %></td>
68
- <td>
69
- <a href="/phases/<%= String(phase.id).padStart(2, '0') %>">
70
- <%= phase.name %>
71
- </a>
72
- </td>
73
- <td><%= phase.planCount %></td>
74
- <td>
75
- <span class="status-badge" data-status="<%= phase.status %>">
76
- <%= phase.status.replace('-', ' ') %>
77
- </span>
78
- </td>
79
- <td>
80
- <% if (phase.dependencies && phase.dependencies.length > 0) { %>
81
- <% phase.dependencies.forEach(function(dep, idx) { %>
82
- <a href="/phases/<%= String(dep).padStart(2, '0') %>"><%= String(dep).padStart(2, '0') %></a><% if (idx < phase.dependencies.length - 1) { %>, <% } %>
83
- <% }); %>
84
- <% } else { %>
85
- <small>None</small>
86
- <% } %>
87
- </td>
88
- </tr>
89
- <% }); %>
90
- </tbody>
91
- </table>
92
- </div>
93
- </article>
94
- <% }); %>
95
-
96
- <% if (ungroupedPhases.length > 0) { %>
97
- <article>
98
- <header><strong>Other Phases</strong></header>
99
- <div class="table-wrap">
100
- <table>
101
- <thead>
102
- <tr>
103
- <th scope="col">Phase</th>
104
- <th scope="col">Name</th>
105
- <th scope="col">Plans</th>
106
- <th scope="col">Status</th>
107
- <th scope="col">Depends On</th>
108
- </tr>
109
- </thead>
110
- <tbody>
111
- <% ungroupedPhases.forEach(function(phase) { %>
112
- <tr>
113
- <td><%= String(phase.id).padStart(2, '0') %></td>
114
- <td>
115
- <a href="/phases/<%= String(phase.id).padStart(2, '0') %>">
116
- <%= phase.name %>
117
- </a>
118
- </td>
119
- <td><%= phase.planCount %></td>
120
- <td>
121
- <span class="status-badge" data-status="<%= phase.status %>">
122
- <%= phase.status.replace('-', ' ') %>
123
- </span>
124
- </td>
125
- <td>
126
- <% if (phase.dependencies && phase.dependencies.length > 0) { %>
127
- <% phase.dependencies.forEach(function(dep, idx) { %>
128
- <a href="/phases/<%= String(dep).padStart(2, '0') %>"><%= String(dep).padStart(2, '0') %></a><% if (idx < phase.dependencies.length - 1) { %>, <% } %>
129
- <% }); %>
130
- <% } else { %>
131
- <small>None</small>
132
- <% } %>
133
- </td>
134
- </tr>
135
- <% }); %>
136
- </tbody>
137
- </table>
138
- </div>
139
- </article>
140
- <% } %>
141
-
142
- <% } %>
1
+ <h1>Project Roadmap</h1>
2
+
3
+ <% if (phases.length === 0) { %>
4
+ <article>
5
+ <p>No phases found. Add a ROADMAP.md file to your .planning/ directory to see the roadmap here.</p>
6
+ </article>
7
+ <% } else { %>
8
+
9
+ <%
10
+ // Group phases by milestone
11
+ const msGroups = (typeof milestones !== 'undefined' && milestones.length > 0)
12
+ ? milestones.map(m => ({
13
+ ...m,
14
+ phases: phases.filter(p => p.id >= m.startPhase && p.id <= m.endPhase)
15
+ })).filter(g => g.phases.length > 0)
16
+ : [{ name: 'All Phases', goal: '', startPhase: 1, endPhase: 9999, phases: phases }];
17
+
18
+ const coveredIds = new Set(msGroups.flatMap(g => g.phases.map(p => p.id)));
19
+ const ungroupedPhases = phases.filter(p => !coveredIds.has(p.id));
20
+ %>
21
+
22
+ <!-- Overall Progress -->
23
+ <article>
24
+ <header><strong>Overall Progress</strong></header>
25
+ <%
26
+ const totalComplete = phases.filter(p => p.status === 'complete').length;
27
+ const totalPhases = phases.length;
28
+ const pct = totalPhases > 0 ? Math.round((totalComplete / totalPhases) * 100) : 0;
29
+ %>
30
+ <progress value="<%= totalComplete %>" max="<%= totalPhases %>"></progress>
31
+ <p><%= pct %>% complete (<%= totalComplete %> of <%= totalPhases %> phases)</p>
32
+ </article>
33
+
34
+ <% msGroups.forEach(function(group) { %>
35
+ <article>
36
+ <header>
37
+ <strong><%= group.name %></strong>
38
+ <% if (group.startPhase && group.endPhase < 9999) { %>
39
+ <small>(Phases <%= String(group.startPhase).padStart(2, '0') %>&ndash;<%= String(group.endPhase).padStart(2, '0') %>)</small>
40
+ <% } %>
41
+ &mdash;
42
+ <%
43
+ const gc = group.phases.filter(p => p.status === 'complete').length;
44
+ const gt = group.phases.length;
45
+ %>
46
+ <span class="status-badge" data-status="<%= gc === gt ? 'complete' : (gc > 0 ? 'in-progress' : 'not-started') %>">
47
+ <%= gc %>/<%= gt %>
48
+ </span>
49
+ </header>
50
+ <% if (group.goal) { %>
51
+ <p><small><%= group.goal %></small></p>
52
+ <% } %>
53
+ <div class="table-wrap">
54
+ <table>
55
+ <thead>
56
+ <tr>
57
+ <th scope="col">Phase</th>
58
+ <th scope="col">Name</th>
59
+ <th scope="col">Plans</th>
60
+ <th scope="col">Status</th>
61
+ <th scope="col">Depends On</th>
62
+ </tr>
63
+ </thead>
64
+ <tbody>
65
+ <% group.phases.forEach(function(phase) { %>
66
+ <tr>
67
+ <td><%= String(phase.id).padStart(2, '0') %></td>
68
+ <td>
69
+ <a href="/phases/<%= String(phase.id).padStart(2, '0') %>">
70
+ <%= phase.name %>
71
+ </a>
72
+ </td>
73
+ <td><%= phase.planCount %></td>
74
+ <td>
75
+ <span class="status-badge" data-status="<%= phase.status %>">
76
+ <%= phase.status.replace('-', ' ') %>
77
+ </span>
78
+ </td>
79
+ <td>
80
+ <% if (phase.dependencies && phase.dependencies.length > 0) { %>
81
+ <% phase.dependencies.forEach(function(dep, idx) { %>
82
+ <a href="/phases/<%= String(dep).padStart(2, '0') %>"><%= String(dep).padStart(2, '0') %></a><% if (idx < phase.dependencies.length - 1) { %>, <% } %>
83
+ <% }); %>
84
+ <% } else { %>
85
+ <small>None</small>
86
+ <% } %>
87
+ </td>
88
+ </tr>
89
+ <% }); %>
90
+ </tbody>
91
+ </table>
92
+ </div>
93
+ </article>
94
+ <% }); %>
95
+
96
+ <% if (ungroupedPhases.length > 0) { %>
97
+ <article>
98
+ <header><strong>Other Phases</strong></header>
99
+ <div class="table-wrap">
100
+ <table>
101
+ <thead>
102
+ <tr>
103
+ <th scope="col">Phase</th>
104
+ <th scope="col">Name</th>
105
+ <th scope="col">Plans</th>
106
+ <th scope="col">Status</th>
107
+ <th scope="col">Depends On</th>
108
+ </tr>
109
+ </thead>
110
+ <tbody>
111
+ <% ungroupedPhases.forEach(function(phase) { %>
112
+ <tr>
113
+ <td><%= String(phase.id).padStart(2, '0') %></td>
114
+ <td>
115
+ <a href="/phases/<%= String(phase.id).padStart(2, '0') %>">
116
+ <%= phase.name %>
117
+ </a>
118
+ </td>
119
+ <td><%= phase.planCount %></td>
120
+ <td>
121
+ <span class="status-badge" data-status="<%= phase.status %>">
122
+ <%= phase.status.replace('-', ' ') %>
123
+ </span>
124
+ </td>
125
+ <td>
126
+ <% if (phase.dependencies && phase.dependencies.length > 0) { %>
127
+ <% phase.dependencies.forEach(function(dep, idx) { %>
128
+ <a href="/phases/<%= String(dep).padStart(2, '0') %>"><%= String(dep).padStart(2, '0') %></a><% if (idx < phase.dependencies.length - 1) { %>, <% } %>
129
+ <% }); %>
130
+ <% } else { %>
131
+ <small>None</small>
132
+ <% } %>
133
+ </td>
134
+ </tr>
135
+ <% }); %>
136
+ </tbody>
137
+ </table>
138
+ </div>
139
+ </article>
140
+ <% } %>
141
+
142
+ <% } %>
@@ -1,38 +1,38 @@
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
- </ul>
37
- </nav>
38
- </aside>
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
+ </ul>
37
+ </nav>
38
+ </aside>
@@ -1,53 +1,53 @@
1
- <h1>Create Todo</h1>
2
-
3
- <p><a href="/todos">&larr; Back to Todos</a></p>
4
-
5
- <article>
6
- <form method="POST" action="/todos"
7
- hx-post="/todos"
8
- hx-target="#main-content">
9
- <label>
10
- Title
11
- <input
12
- type="text"
13
- name="title"
14
- placeholder="Todo title"
15
- required
16
- maxlength="200"
17
- />
18
- </label>
19
-
20
- <label>
21
- Priority
22
- <select name="priority" required>
23
- <option value="">Select priority...</option>
24
- <option value="P0">P0 - Critical</option>
25
- <option value="P1">P1 - High</option>
26
- <option value="P2">P2 - Medium</option>
27
- <option value="PX">PX - Low</option>
28
- </select>
29
- </label>
30
-
31
- <label>
32
- Phase (optional)
33
- <input
34
- type="text"
35
- name="phase"
36
- placeholder="e.g., 09-todo-write-operations"
37
- />
38
- <small>Format: 01-phase-name</small>
39
- </label>
40
-
41
- <label>
42
- Description
43
- <textarea
44
- name="description"
45
- rows="10"
46
- required
47
- placeholder="Markdown content..."
48
- ></textarea>
49
- </label>
50
-
51
- <button type="submit">Create Todo</button>
52
- </form>
53
- </article>
1
+ <h1>Create Todo</h1>
2
+
3
+ <p><a href="/todos">&larr; Back to Todos</a></p>
4
+
5
+ <article>
6
+ <form method="POST" action="/todos"
7
+ hx-post="/todos"
8
+ hx-target="#main-content">
9
+ <label>
10
+ Title
11
+ <input
12
+ type="text"
13
+ name="title"
14
+ placeholder="Todo title"
15
+ required
16
+ maxlength="200"
17
+ />
18
+ </label>
19
+
20
+ <label>
21
+ Priority
22
+ <select name="priority" required>
23
+ <option value="">Select priority...</option>
24
+ <option value="P0">P0 - Critical</option>
25
+ <option value="P1">P1 - High</option>
26
+ <option value="P2">P2 - Medium</option>
27
+ <option value="PX">PX - Low</option>
28
+ </select>
29
+ </label>
30
+
31
+ <label>
32
+ Phase (optional)
33
+ <input
34
+ type="text"
35
+ name="phase"
36
+ placeholder="e.g., 09-todo-write-operations"
37
+ />
38
+ <small>Format: 01-phase-name</small>
39
+ </label>
40
+
41
+ <label>
42
+ Description
43
+ <textarea
44
+ name="description"
45
+ rows="10"
46
+ required
47
+ placeholder="Markdown content..."
48
+ ></textarea>
49
+ </label>
50
+
51
+ <button type="submit">Create Todo</button>
52
+ </form>
53
+ </article>
@@ -1,38 +1,38 @@
1
- <h1><%= title %></h1>
2
-
3
- <p><a href="/todos">&larr; Back to Todos</a></p>
4
-
5
- <article>
6
- <header>
7
- <strong>Todo <%= id %></strong>
8
- &nbsp;
9
- <span class="status-badge" data-priority="<%= priority %>">
10
- <%= priority %>
11
- </span>
12
- &nbsp;
13
- <span class="status-badge" data-status="<%= status %>">
14
- <%= status %>
15
- </span>
16
- </header>
17
-
18
- <% if (phase) { %>
19
- <p><strong>Phase:</strong> <%= phase %></p>
20
- <% } %>
21
- <% if (created) { %>
22
- <p><strong>Created:</strong> <%= created %></p>
23
- <% } %>
24
-
25
- <hr>
26
-
27
- <%- html %>
28
-
29
- <% if (status === 'pending') { %>
30
- <hr>
31
- <form method="POST" action="/todos/<%= id %>/done"
32
- hx-post="/todos/<%= id %>/done"
33
- hx-target="#main-content"
34
- style="display:inline;">
35
- <button type="submit" class="secondary">Mark as Done</button>
36
- </form>
37
- <% } %>
38
- </article>
1
+ <h1><%= title %></h1>
2
+
3
+ <p><a href="/todos">&larr; Back to Todos</a></p>
4
+
5
+ <article>
6
+ <header>
7
+ <strong>Todo <%= id %></strong>
8
+ &nbsp;
9
+ <span class="status-badge" data-priority="<%= priority %>">
10
+ <%= priority %>
11
+ </span>
12
+ &nbsp;
13
+ <span class="status-badge" data-status="<%= status %>">
14
+ <%= status %>
15
+ </span>
16
+ </header>
17
+
18
+ <% if (phase) { %>
19
+ <p><strong>Phase:</strong> <%= phase %></p>
20
+ <% } %>
21
+ <% if (created) { %>
22
+ <p><strong>Created:</strong> <%= created %></p>
23
+ <% } %>
24
+
25
+ <hr>
26
+
27
+ <%- html %>
28
+
29
+ <% if (status === 'pending') { %>
30
+ <hr>
31
+ <form method="POST" action="/todos/<%= id %>/done"
32
+ hx-post="/todos/<%= id %>/done"
33
+ hx-target="#main-content"
34
+ style="display:inline;">
35
+ <button type="submit" class="secondary">Mark as Done</button>
36
+ </form>
37
+ <% } %>
38
+ </article>
@@ -1,53 +1,53 @@
1
- <h1>Todos</h1>
2
-
3
- <p><a href="/todos/new" role="button"
4
- hx-get="/todos/new"
5
- hx-target="#main-content"
6
- hx-push-url="true">Create Todo</a></p>
7
-
8
- <% if (todos.length > 0) { %>
9
- <article>
10
- <div class="table-wrap">
11
- <table>
12
- <thead>
13
- <tr>
14
- <th scope="col">ID</th>
15
- <th scope="col">Title</th>
16
- <th scope="col">Priority</th>
17
- <th scope="col">Phase</th>
18
- <th scope="col">Status</th>
19
- <th scope="col">Created</th>
20
- </tr>
21
- </thead>
22
- <tbody>
23
- <% todos.forEach(function(todo) { %>
24
- <tr>
25
- <td><%= todo.id %></td>
26
- <td>
27
- <a href="/todos/<%= todo.id %>">
28
- <%= todo.title %>
29
- </a>
30
- </td>
31
- <td>
32
- <span class="status-badge" data-priority="<%= todo.priority %>">
33
- <%= todo.priority %>
34
- </span>
35
- </td>
36
- <td><%= todo.phase %></td>
37
- <td>
38
- <span class="status-badge" data-status="<%= todo.status %>">
39
- <%= todo.status %>
40
- </span>
41
- </td>
42
- <td><%= todo.created %></td>
43
- </tr>
44
- <% }); %>
45
- </tbody>
46
- </table>
47
- </div>
48
- </article>
49
- <% } 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>
53
- <% } %>
1
+ <h1>Todos</h1>
2
+
3
+ <p><a href="/todos/new" role="button"
4
+ hx-get="/todos/new"
5
+ hx-target="#main-content"
6
+ hx-push-url="true">Create Todo</a></p>
7
+
8
+ <% if (todos.length > 0) { %>
9
+ <article>
10
+ <div class="table-wrap">
11
+ <table>
12
+ <thead>
13
+ <tr>
14
+ <th scope="col">ID</th>
15
+ <th scope="col">Title</th>
16
+ <th scope="col">Priority</th>
17
+ <th scope="col">Phase</th>
18
+ <th scope="col">Status</th>
19
+ <th scope="col">Created</th>
20
+ </tr>
21
+ </thead>
22
+ <tbody>
23
+ <% todos.forEach(function(todo) { %>
24
+ <tr>
25
+ <td><%= todo.id %></td>
26
+ <td>
27
+ <a href="/todos/<%= todo.id %>">
28
+ <%= todo.title %>
29
+ </a>
30
+ </td>
31
+ <td>
32
+ <span class="status-badge" data-priority="<%= todo.priority %>">
33
+ <%= todo.priority %>
34
+ </span>
35
+ </td>
36
+ <td><%= todo.phase %></td>
37
+ <td>
38
+ <span class="status-badge" data-status="<%= todo.status %>">
39
+ <%= todo.status %>
40
+ </span>
41
+ </td>
42
+ <td><%= todo.created %></td>
43
+ </tr>
44
+ <% }); %>
45
+ </tbody>
46
+ </table>
47
+ </div>
48
+ </article>
49
+ <% } 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>
53
+ <% } %>