@sienklogic/plan-build-run 2.0.2 → 2.1.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 (156) hide show
  1. package/dashboard/src/routes/pages.routes.js +11 -4
  2. package/dashboard/src/services/dashboard.service.js +81 -17
  3. package/dashboard/src/services/phase.service.js +30 -24
  4. package/dashboard/src/services/roadmap.service.js +3 -3
  5. package/dashboard/src/views/partials/phase-content.ejs +5 -4
  6. package/package.json +1 -1
  7. package/plugins/cursor-pbr/.cursor-plugin/plugin.json +1 -1
  8. package/plugins/cursor-pbr/CHANGELOG.md +15 -0
  9. package/plugins/cursor-pbr/README.md +118 -0
  10. package/plugins/cursor-pbr/agents/codebase-mapper.md +108 -0
  11. package/plugins/cursor-pbr/agents/debugger.md +168 -0
  12. package/plugins/cursor-pbr/agents/executor.md +236 -0
  13. package/plugins/cursor-pbr/agents/general.md +87 -0
  14. package/plugins/cursor-pbr/agents/integration-checker.md +87 -0
  15. package/plugins/cursor-pbr/agents/plan-checker.md +198 -0
  16. package/plugins/cursor-pbr/agents/planner.md +180 -0
  17. package/plugins/cursor-pbr/agents/researcher.md +162 -0
  18. package/plugins/cursor-pbr/agents/synthesizer.md +101 -0
  19. package/plugins/cursor-pbr/agents/verifier.md +193 -0
  20. package/plugins/cursor-pbr/assets/logo.svg +21 -0
  21. package/plugins/cursor-pbr/hooks/hooks.json +189 -7
  22. package/plugins/cursor-pbr/references/agent-anti-patterns.md +25 -0
  23. package/plugins/cursor-pbr/references/agent-interactions.md +135 -0
  24. package/plugins/cursor-pbr/references/agent-teams.md +55 -0
  25. package/plugins/cursor-pbr/references/checkpoints.md +158 -0
  26. package/plugins/cursor-pbr/references/common-bug-patterns.md +14 -0
  27. package/plugins/cursor-pbr/references/config-reference.md +442 -0
  28. package/plugins/cursor-pbr/references/continuation-format.md +213 -0
  29. package/plugins/cursor-pbr/references/deviation-rules.md +113 -0
  30. package/plugins/cursor-pbr/references/git-integration.md +227 -0
  31. package/plugins/cursor-pbr/references/integration-patterns.md +118 -0
  32. package/plugins/cursor-pbr/references/model-profiles.md +100 -0
  33. package/plugins/cursor-pbr/references/model-selection.md +32 -0
  34. package/plugins/cursor-pbr/references/pbr-rules.md +194 -0
  35. package/plugins/cursor-pbr/references/plan-authoring.md +182 -0
  36. package/plugins/cursor-pbr/references/plan-format.md +288 -0
  37. package/plugins/cursor-pbr/references/planning-config.md +214 -0
  38. package/plugins/cursor-pbr/references/questioning.md +215 -0
  39. package/plugins/cursor-pbr/references/reading-verification.md +128 -0
  40. package/plugins/cursor-pbr/references/stub-patterns.md +161 -0
  41. package/plugins/cursor-pbr/references/subagent-coordination.md +120 -0
  42. package/plugins/cursor-pbr/references/ui-formatting.md +462 -0
  43. package/plugins/cursor-pbr/references/verification-patterns.md +199 -0
  44. package/plugins/cursor-pbr/references/wave-execution.md +96 -0
  45. package/plugins/cursor-pbr/rules/pbr-workflow.mdc +48 -0
  46. package/plugins/cursor-pbr/setup.ps1 +78 -0
  47. package/plugins/cursor-pbr/setup.sh +83 -0
  48. package/plugins/cursor-pbr/skills/begin/SKILL.md +566 -0
  49. package/plugins/cursor-pbr/skills/begin/templates/PROJECT.md.tmpl +34 -0
  50. package/plugins/cursor-pbr/skills/begin/templates/REQUIREMENTS.md.tmpl +19 -0
  51. package/plugins/cursor-pbr/skills/begin/templates/STATE.md.tmpl +50 -0
  52. package/plugins/cursor-pbr/skills/begin/templates/config.json.tmpl +64 -0
  53. package/plugins/cursor-pbr/skills/begin/templates/researcher-prompt.md.tmpl +20 -0
  54. package/plugins/cursor-pbr/skills/begin/templates/roadmap-prompt.md.tmpl +31 -0
  55. package/plugins/cursor-pbr/skills/begin/templates/synthesis-prompt.md.tmpl +17 -0
  56. package/plugins/cursor-pbr/skills/build/SKILL.md +902 -0
  57. package/plugins/cursor-pbr/skills/config/SKILL.md +253 -0
  58. package/plugins/cursor-pbr/skills/continue/SKILL.md +159 -0
  59. package/plugins/cursor-pbr/skills/debug/SKILL.md +512 -0
  60. package/plugins/cursor-pbr/skills/debug/templates/continuation-prompt.md.tmpl +17 -0
  61. package/plugins/cursor-pbr/skills/debug/templates/initial-investigation-prompt.md.tmpl +28 -0
  62. package/plugins/cursor-pbr/skills/discuss/SKILL.md +344 -0
  63. package/plugins/cursor-pbr/skills/discuss/templates/CONTEXT.md.tmpl +62 -0
  64. package/plugins/cursor-pbr/skills/discuss/templates/decision-categories.md +10 -0
  65. package/plugins/cursor-pbr/skills/explore/SKILL.md +375 -0
  66. package/plugins/cursor-pbr/skills/health/SKILL.md +218 -0
  67. package/plugins/cursor-pbr/skills/health/templates/check-pattern.md.tmpl +31 -0
  68. package/plugins/cursor-pbr/skills/health/templates/output-format.md.tmpl +64 -0
  69. package/plugins/cursor-pbr/skills/help/SKILL.md +152 -0
  70. package/plugins/cursor-pbr/skills/import/SKILL.md +499 -0
  71. package/plugins/cursor-pbr/skills/milestone/SKILL.md +701 -0
  72. package/plugins/cursor-pbr/skills/milestone/templates/audit-report.md.tmpl +49 -0
  73. package/plugins/cursor-pbr/skills/milestone/templates/stats-file.md.tmpl +31 -0
  74. package/plugins/cursor-pbr/skills/note/SKILL.md +228 -0
  75. package/plugins/cursor-pbr/skills/pause/SKILL.md +246 -0
  76. package/plugins/cursor-pbr/skills/pause/templates/continue-here.md.tmpl +72 -0
  77. package/plugins/cursor-pbr/skills/plan/SKILL.md +648 -0
  78. package/plugins/cursor-pbr/skills/plan/templates/checker-prompt.md.tmpl +22 -0
  79. package/plugins/cursor-pbr/skills/plan/templates/gap-closure-prompt.md.tmpl +33 -0
  80. package/plugins/cursor-pbr/skills/plan/templates/planner-prompt.md.tmpl +39 -0
  81. package/plugins/cursor-pbr/skills/plan/templates/researcher-prompt.md.tmpl +20 -0
  82. package/plugins/cursor-pbr/skills/plan/templates/revision-prompt.md.tmpl +24 -0
  83. package/plugins/cursor-pbr/skills/quick/SKILL.md +351 -0
  84. package/plugins/cursor-pbr/skills/resume/SKILL.md +399 -0
  85. package/plugins/cursor-pbr/skills/review/SKILL.md +649 -0
  86. package/plugins/cursor-pbr/skills/review/templates/debugger-prompt.md.tmpl +61 -0
  87. package/plugins/cursor-pbr/skills/review/templates/gap-planner-prompt.md.tmpl +41 -0
  88. package/plugins/cursor-pbr/skills/review/templates/verifier-prompt.md.tmpl +116 -0
  89. package/plugins/cursor-pbr/skills/scan/SKILL.md +301 -0
  90. package/plugins/cursor-pbr/skills/scan/templates/mapper-prompt.md.tmpl +202 -0
  91. package/plugins/cursor-pbr/skills/setup/SKILL.md +250 -0
  92. package/plugins/cursor-pbr/skills/shared/commit-planning-docs.md +36 -0
  93. package/plugins/cursor-pbr/skills/shared/config-loading.md +103 -0
  94. package/plugins/cursor-pbr/skills/shared/context-budget.md +41 -0
  95. package/plugins/cursor-pbr/skills/shared/context-loader-task.md +87 -0
  96. package/plugins/cursor-pbr/skills/shared/digest-select.md +80 -0
  97. package/plugins/cursor-pbr/skills/shared/domain-probes.md +126 -0
  98. package/plugins/cursor-pbr/skills/shared/error-reporting.md +80 -0
  99. package/plugins/cursor-pbr/skills/shared/gate-prompts.md +389 -0
  100. package/plugins/cursor-pbr/skills/shared/phase-argument-parsing.md +46 -0
  101. package/plugins/cursor-pbr/skills/shared/progress-display.md +54 -0
  102. package/plugins/cursor-pbr/skills/shared/revision-loop.md +82 -0
  103. package/plugins/cursor-pbr/skills/shared/state-loading.md +63 -0
  104. package/plugins/cursor-pbr/skills/shared/state-update.md +162 -0
  105. package/plugins/cursor-pbr/skills/shared/universal-anti-patterns.md +34 -0
  106. package/plugins/cursor-pbr/skills/status/SKILL.md +362 -0
  107. package/plugins/cursor-pbr/skills/todo/SKILL.md +195 -0
  108. package/plugins/cursor-pbr/templates/CONTEXT.md.tmpl +53 -0
  109. package/plugins/cursor-pbr/templates/INTEGRATION-REPORT.md.tmpl +152 -0
  110. package/plugins/cursor-pbr/templates/RESEARCH-SUMMARY.md.tmpl +98 -0
  111. package/plugins/cursor-pbr/templates/ROADMAP.md.tmpl +41 -0
  112. package/plugins/cursor-pbr/templates/SUMMARY.md.tmpl +82 -0
  113. package/plugins/cursor-pbr/templates/VERIFICATION-DETAIL.md.tmpl +117 -0
  114. package/plugins/cursor-pbr/templates/continue-here.md.tmpl +74 -0
  115. package/plugins/cursor-pbr/templates/prompt-partials/phase-project-context.md.tmpl +38 -0
  116. package/plugins/pbr/agents/codebase-mapper.md +41 -206
  117. package/plugins/pbr/agents/debugger.md +65 -171
  118. package/plugins/pbr/agents/executor.md +90 -275
  119. package/plugins/pbr/agents/general.md +27 -97
  120. package/plugins/pbr/agents/integration-checker.md +35 -112
  121. package/plugins/pbr/agents/plan-checker.md +71 -164
  122. package/plugins/pbr/agents/planner.md +75 -246
  123. package/plugins/pbr/agents/researcher.md +63 -255
  124. package/plugins/pbr/agents/synthesizer.md +49 -174
  125. package/plugins/pbr/agents/verifier.md +75 -366
  126. package/plugins/pbr/hooks/hooks.json +14 -10
  127. package/plugins/pbr/scripts/auto-continue.js +20 -4
  128. package/plugins/pbr/scripts/check-dangerous-commands.js +1 -1
  129. package/plugins/pbr/scripts/check-phase-boundary.js +1 -1
  130. package/plugins/pbr/scripts/check-plan-format.js +3 -3
  131. package/plugins/pbr/scripts/check-roadmap-sync.js +3 -3
  132. package/plugins/pbr/scripts/check-skill-workflow.js +1 -1
  133. package/plugins/pbr/scripts/check-state-sync.js +2 -2
  134. package/plugins/pbr/scripts/check-subagent-output.js +1 -1
  135. package/plugins/pbr/scripts/check-summary-gate.js +198 -0
  136. package/plugins/pbr/scripts/context-budget-check.js +1 -1
  137. package/plugins/pbr/scripts/event-handler.js +2 -2
  138. package/plugins/pbr/scripts/event-logger.js +1 -1
  139. package/plugins/pbr/scripts/log-subagent.js +1 -1
  140. package/plugins/pbr/scripts/pbr-tools.js +1 -1
  141. package/plugins/pbr/scripts/post-write-dispatch.js +1 -1
  142. package/plugins/pbr/scripts/post-write-quality.js +1 -1
  143. package/plugins/pbr/scripts/pre-bash-dispatch.js +1 -1
  144. package/plugins/pbr/scripts/pre-write-dispatch.js +16 -3
  145. package/plugins/pbr/scripts/session-cleanup.js +1 -1
  146. package/plugins/pbr/scripts/status-line.js +1 -1
  147. package/plugins/pbr/scripts/suggest-compact.js +1 -1
  148. package/plugins/pbr/scripts/task-completed.js +1 -1
  149. package/plugins/pbr/scripts/track-context-budget.js +11 -6
  150. package/plugins/pbr/scripts/validate-commit.js +1 -1
  151. package/plugins/pbr/scripts/validate-task.js +1 -1
  152. package/plugins/cursor-pbr/agents/.gitkeep +0 -0
  153. package/plugins/cursor-pbr/references/.gitkeep +0 -0
  154. package/plugins/cursor-pbr/rules/.gitkeep +0 -0
  155. package/plugins/cursor-pbr/skills/.gitkeep +0 -0
  156. package/plugins/cursor-pbr/templates/.gitkeep +0 -0
@@ -1,19 +1,23 @@
1
1
  import { Router } from 'express';
2
2
  import { getPhaseDetail, getPhaseDocument } from '../services/phase.service.js';
3
3
  import { getRoadmapData } from '../services/roadmap.service.js';
4
+ import { parseStateFile, derivePhaseStatuses } from '../services/dashboard.service.js';
4
5
  import { listPendingTodos, getTodoDetail, createTodo, completeTodo } from '../services/todo.service.js';
5
6
 
6
7
  const router = Router();
7
8
 
8
9
  router.get('/phases', async (req, res) => {
9
10
  const projectDir = req.app.locals.projectDir;
10
- const roadmapData = await getRoadmapData(projectDir);
11
+ const [roadmapData, stateData] = await Promise.all([
12
+ getRoadmapData(projectDir),
13
+ parseStateFile(projectDir)
14
+ ]);
11
15
 
12
16
  const templateData = {
13
17
  title: 'Phases',
14
18
  activePage: 'phases',
15
19
  currentPath: '/phases',
16
- phases: roadmapData.phases,
20
+ phases: derivePhaseStatuses(roadmapData.phases, stateData.currentPhase),
17
21
  milestones: roadmapData.milestones
18
22
  };
19
23
 
@@ -223,13 +227,16 @@ router.post('/todos/:id/done', async (req, res) => {
223
227
 
224
228
  router.get('/roadmap', async (req, res) => {
225
229
  const projectDir = req.app.locals.projectDir;
226
- const roadmapData = await getRoadmapData(projectDir);
230
+ const [roadmapData, stateData] = await Promise.all([
231
+ getRoadmapData(projectDir),
232
+ parseStateFile(projectDir)
233
+ ]);
227
234
 
228
235
  const templateData = {
229
236
  title: 'Roadmap',
230
237
  activePage: 'roadmap',
231
238
  currentPath: '/roadmap',
232
- phases: roadmapData.phases,
239
+ phases: derivePhaseStatuses(roadmapData.phases, stateData.currentPhase),
233
240
  milestones: roadmapData.milestones
234
241
  };
235
242
 
@@ -24,7 +24,20 @@ export async function parseStateFile(projectDir) {
24
24
  try {
25
25
  const path = join(projectDir, '.planning', 'STATE.md');
26
26
  const raw = await readFile(path, 'utf-8');
27
- const content = stripBOM(raw);
27
+ const content = stripBOM(raw).replace(/\r\n/g, '\n');
28
+
29
+ // Parse YAML frontmatter if present (STATE.md v2 format)
30
+ let frontmatter = {};
31
+ const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
32
+ if (fmMatch) {
33
+ for (const line of fmMatch[1].split('\n')) {
34
+ const kv = line.match(/^(\w+):\s*(.+)/);
35
+ if (kv) {
36
+ const val = kv[2].trim().replace(/^"(.*)"$/, '$1');
37
+ frontmatter[kv[1]] = val;
38
+ }
39
+ }
40
+ }
28
41
 
29
42
  // Extract project name from **Current focus:** line
30
43
  let projectName = 'Unknown Project';
@@ -76,13 +89,23 @@ export async function parseStateFile(projectDir) {
76
89
  progress = Math.ceil((currentPhaseId / totalPhases) * 100);
77
90
  }
78
91
 
92
+ // Determine phase status from frontmatter or body text
93
+ // "built", "verified", "complete" all mean the current phase is done
94
+ const fmStatus = (frontmatter.status || '').toLowerCase();
95
+ const phaseStatus = ['built', 'verified', 'complete', 'reviewed'].includes(fmStatus)
96
+ ? 'complete'
97
+ : ['building', 'planning', 'planned', 'in-progress'].includes(fmStatus)
98
+ ? 'in-progress'
99
+ : fmStatus || 'unknown';
100
+
79
101
  return {
80
102
  projectName,
81
103
  currentPhase: {
82
104
  id: currentPhaseId,
83
105
  total: totalPhases,
84
106
  name: phaseName,
85
- planStatus
107
+ planStatus,
108
+ status: phaseStatus
86
109
  },
87
110
  lastActivity: {
88
111
  date: activityDate,
@@ -94,7 +117,7 @@ export async function parseStateFile(projectDir) {
94
117
  if (error.code === 'ENOENT') {
95
118
  return {
96
119
  projectName: 'Unknown Project',
97
- currentPhase: { id: 0, total: 0, name: 'Not Started', planStatus: 'N/A' },
120
+ currentPhase: { id: 0, total: 0, name: 'Not Started', planStatus: 'N/A', status: 'unknown' },
98
121
  lastActivity: { date: '', description: 'No activity recorded' },
99
122
  progress: 0
100
123
  };
@@ -132,7 +155,7 @@ export async function parseRoadmapFile(projectDir) {
132
155
 
133
156
  // 2. Parse descriptions from Phase Details: "### Phase NN: Name\n**Goal**: ..."
134
157
  const goalMap = new Map();
135
- const goalRegex = /### Phase (\d+):\s*(.+)\n\*\*Goal\*\*:\s*(.+)/g;
158
+ const goalRegex = /### Phase (\d+):\s*(.+)\n\*\*Goal:?\*\*:?\s*(.+)/g;
136
159
  for (const match of content.matchAll(goalRegex)) {
137
160
  goalMap.set(parseInt(match[1], 10), match[3].trim());
138
161
  }
@@ -158,11 +181,28 @@ export async function parseRoadmapFile(projectDir) {
158
181
  progressPhases.push({ id, name, description, status });
159
182
  }
160
183
 
161
- // Use Progress table if available, otherwise fall back to checkbox parsing
184
+ // 4. Parse H3 Phase Details: "### Phase N: Name\n**Goal:** ..."
185
+ const h3Phases = [];
186
+ const h3Regex = /### Phase (\d+):\s*(.+)\n\*\*Goal\*?\*?:?\*?\*?\s*(.+)/g;
187
+ for (const match of content.matchAll(h3Regex)) {
188
+ const id = parseInt(match[1], 10);
189
+ const name = match[2].trim();
190
+ const description = match[3].trim();
191
+ // Check checkbox map for status, default to not-started
192
+ const cbInfo = checkboxMap.get(id);
193
+ h3Phases.push({
194
+ id,
195
+ name,
196
+ description,
197
+ status: cbInfo?.status || 'not-started'
198
+ });
199
+ }
200
+
201
+ // Use Progress table if available, then checkbox list, then H3 headings
162
202
  let phases;
163
203
  if (progressPhases.length > 0) {
164
204
  phases = progressPhases;
165
- } else {
205
+ } else if (checkboxMap.size > 0) {
166
206
  phases = [...checkboxMap.entries()]
167
207
  .map(([id, info]) => ({
168
208
  id,
@@ -171,6 +211,8 @@ export async function parseRoadmapFile(projectDir) {
171
211
  status: info.status
172
212
  }))
173
213
  .sort((a, b) => a.id - b.id);
214
+ } else {
215
+ phases = h3Phases.sort((a, b) => a.id - b.id);
174
216
  }
175
217
 
176
218
  const completed = phases.filter(p => p.status === 'complete').length;
@@ -193,23 +235,45 @@ export async function parseRoadmapFile(projectDir) {
193
235
  * @param {string} projectDir - Absolute path to the project root
194
236
  * @returns {Promise<{projectName: string, currentPhase: object, lastActivity: object, progress: number, phases: Array}>}
195
237
  */
238
+ /**
239
+ * Derive phase statuses by combining roadmap phases with STATE.md context.
240
+ * Phases before the current phase are marked complete.
241
+ * The current phase gets its status from STATE.md.
242
+ * Phases after the current phase keep their roadmap status (typically not-started).
243
+ *
244
+ * @param {Array} phases - Raw phases from parseRoadmapFile
245
+ * @param {{id: number, status: string}} currentPhase - Current phase from parseStateFile
246
+ * @returns {Array} Phases with derived statuses
247
+ */
248
+ export function derivePhaseStatuses(phases, currentPhase) {
249
+ const currentId = currentPhase.id;
250
+ const currentStatus = currentPhase.status || 'unknown';
251
+ return phases.map(phase => {
252
+ // If the roadmap already has explicit status (from progress table/checkboxes), keep it
253
+ if (phase.status === 'complete') return phase;
254
+
255
+ if (phase.id < currentId) {
256
+ return { ...phase, status: 'complete' };
257
+ }
258
+ if (phase.id === currentId) {
259
+ return { ...phase, status: currentStatus === 'complete' ? 'complete' : 'in-progress' };
260
+ }
261
+ return phase;
262
+ });
263
+ }
264
+
196
265
  export async function getDashboardData(projectDir) {
197
266
  const [stateData, roadmapData] = await Promise.all([
198
267
  parseStateFile(projectDir),
199
268
  parseRoadmapFile(projectDir)
200
269
  ]);
201
270
 
202
- // Derive "in-progress" status for the current phase
203
- const phases = roadmapData.phases.map(phase => ({
204
- ...phase,
205
- status: (phase.id === stateData.currentPhase.id && phase.status !== 'complete')
206
- ? 'in-progress'
207
- : phase.status
208
- }));
209
-
210
- // Prefer roadmap progress if phases exist, otherwise use state progress
211
- const progress = roadmapData.phases.length > 0
212
- ? roadmapData.progress
271
+ const phases = derivePhaseStatuses(roadmapData.phases, stateData.currentPhase);
272
+
273
+ // Recalculate progress from derived phase statuses
274
+ const completedPhases = phases.filter(p => p.status === 'complete').length;
275
+ const progress = phases.length > 0
276
+ ? Math.ceil((completedPhases / phases.length) * 100)
213
277
  : stateData.progress;
214
278
 
215
279
  return {
@@ -109,16 +109,19 @@ export async function getPhaseDetail(projectDir, phaseId) {
109
109
  const phaseFiles = await readdir(phaseFullPath);
110
110
 
111
111
  // Filter and sort PLAN.md files
112
- const planRegex = /^\d{2}-\d{2}-PLAN\.md$/;
113
- const planIdRegex = /^(\d{2}-\d{2})-PLAN\.md$/;
112
+ // Supports both naming conventions:
113
+ // - NN-NN-PLAN.md (plan ID embedded in filename)
114
+ // - PLAN.md (single plan per phase, ID derived from phase directory)
115
+ const planRegex = /^(?:\d{2}-\d{2}-)?PLAN\.md$/;
114
116
  const planFiles = phaseFiles
115
117
  .filter(f => planRegex.test(f))
116
118
  .sort();
117
119
 
118
120
  // Build summary paths and read them in parallel
119
- const summaryPaths = planFiles.map(planFile => {
120
- const match = planFile.match(planIdRegex);
121
- const planId = match[1];
121
+ // Derive planId from filename (NN-NN-PLAN.md) or phase directory (PLAN.md -> NN-01)
122
+ const summaryPaths = planFiles.map((planFile, index) => {
123
+ const idMatch = planFile.match(/^(\d{2}-\d{2})-PLAN\.md$/);
124
+ const planId = idMatch ? idMatch[1] : `${phaseId.padStart(2, '0')}-${String(index + 1).padStart(2, '0')}`;
122
125
  return { planId, planFile, summaryPath: join(phaseFullPath, `SUMMARY-${planId}.md`) };
123
126
  });
124
127
 
@@ -196,25 +199,28 @@ export async function getPhaseDocument(projectDir, phaseId, planId, docType) {
196
199
  const phaseName = formatPhaseName(phaseDir.name);
197
200
  const phaseFullPath = join(phasesDir, phaseDir.name);
198
201
 
199
- const fileName = docType === 'plan'
200
- ? `${planId}-PLAN.md`
201
- : `SUMMARY-${planId}.md`;
202
+ // Try plan ID-prefixed filename first, then fall back to plain PLAN.md
203
+ // Supports both "01-01-PLAN.md" and "PLAN.md" naming conventions
204
+ const fileNames = docType === 'plan'
205
+ ? [`${planId}-PLAN.md`, 'PLAN.md']
206
+ : [`SUMMARY-${planId}.md`];
202
207
 
203
- // Validate the path stays within the phase directory
204
- const filePath = validatePath(phaseFullPath, fileName);
205
-
206
- try {
207
- const doc = await readMarkdownFile(filePath);
208
- return {
209
- phaseId,
210
- planId,
211
- docType,
212
- phaseName,
213
- frontmatter: doc.frontmatter,
214
- html: doc.html
215
- };
216
- } catch (error) {
217
- if (error.code === 'ENOENT') return null;
218
- throw error;
208
+ for (const fileName of fileNames) {
209
+ const filePath = validatePath(phaseFullPath, fileName);
210
+ try {
211
+ const doc = await readMarkdownFile(filePath);
212
+ return {
213
+ phaseId,
214
+ planId,
215
+ docType,
216
+ phaseName,
217
+ frontmatter: doc.frontmatter,
218
+ html: doc.html
219
+ };
220
+ } catch (error) {
221
+ if (error.code === 'ENOENT') continue;
222
+ throw error;
223
+ }
219
224
  }
225
+ return null;
220
226
  }
@@ -35,7 +35,7 @@ async function countPlansForPhase(projectDir, phaseId) {
35
35
  if (!phaseDir) return 0;
36
36
 
37
37
  const phaseFiles = await readdir(join(phasesDir, phaseDir.name));
38
- return phaseFiles.filter(f => /^\d{2}-\d{2}-PLAN\.md$/.test(f)).length;
38
+ return phaseFiles.filter(f => /^(?:\d{2}-\d{2}-)?PLAN\.md$/.test(f)).length;
39
39
  } catch (err) {
40
40
  if (err.code === 'ENOENT') return 0;
41
41
  throw err;
@@ -52,7 +52,7 @@ function extractAllDependencies(roadmapContent) {
52
52
  const dependencyMap = new Map();
53
53
 
54
54
  // Match Phase Details sections: "### Phase NN: ..." followed by "**Depends on**: ..."
55
- const sectionRegex = /### Phase (\d+):[\s\S]*?\*\*Depends on\*\*:\s*([^\n]+)/g;
55
+ const sectionRegex = /### Phase (\d+):[\s\S]*?\*\*Depends on:?\*\*:?\s*([^\n]+)/g;
56
56
  let match;
57
57
 
58
58
  while ((match = sectionRegex.exec(roadmapContent)) !== null) {
@@ -92,7 +92,7 @@ function extractMilestones(roadmapContent) {
92
92
  const projectTitle = titleMatch ? titleMatch[1].trim() : 'Project';
93
93
 
94
94
  // Parse explicit milestones: "## Milestone: Name\n\n**Goal:** ...\n**Phases:** N - M"
95
- const milestoneRegex = /## Milestone:\s*(.+)\n\n\*\*Goal:\*\*\s*(.+)\n\*\*Phases:\*\*\s*(\d+)\s*-\s*(\d+)/g;
95
+ const milestoneRegex = /## Milestone:\s*(.+)\n+\*\*Goal:?\*\*:?\s*(.+)\n\*\*Phases:?\*\*:?\s*(\d+)\s*-\s*(\d+)/g;
96
96
  const explicit = [];
97
97
  for (const match of roadmapContent.matchAll(milestoneRegex)) {
98
98
  explicit.push({
@@ -10,14 +10,15 @@
10
10
  </header>
11
11
  <%
12
12
  // Map verification status to CSS status-badge data-status values
13
+ var vStatus = verification.status || verification.verdict || 'unknown';
13
14
  var verificationCssStatus = 'not-started';
14
- if (verification.status === 'passed') verificationCssStatus = 'complete';
15
- else if (verification.status === 'failed') verificationCssStatus = 'blocked';
16
- else if (verification.status === 'partial') verificationCssStatus = 'in-progress';
15
+ if (vStatus === 'passed') verificationCssStatus = 'complete';
16
+ else if (vStatus === 'failed') verificationCssStatus = 'blocked';
17
+ else if (vStatus === 'partial') verificationCssStatus = 'in-progress';
17
18
  %>
18
19
  <p>
19
20
  <span class="status-badge" data-status="<%= verificationCssStatus %>">
20
- <%= verification.status.toUpperCase() %>
21
+ <%= vStatus.toUpperCase() %>
21
22
  </span>
22
23
  <% if (verification.verified) { %>
23
24
  &nbsp; Verified: <%= new Date(verification.verified).toLocaleString() %>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sienklogic/plan-build-run",
3
- "version": "2.0.2",
3
+ "version": "2.1.0",
4
4
  "description": "Plan it, Build it, Run it — structured development workflow for Claude Code",
5
5
  "keywords": [
6
6
  "claude-code",
@@ -11,7 +11,7 @@
11
11
  "homepage": "https://github.com/SienkLogic/plan-build-run",
12
12
  "repository": "https://github.com/SienkLogic/plan-build-run",
13
13
  "license": "MIT",
14
- "logo": "assets/logo.png",
14
+ "logo": "../assets/logo.svg",
15
15
  "keywords": ["cursor", "context-engineering", "development-workflow", "subagent-delegation"],
16
16
  "category": "developer-tools",
17
17
  "tags": ["planning", "workflow", "structured-development", "context-management"],
@@ -0,0 +1,15 @@
1
+ # Changelog
2
+
3
+ ## v2.0.0 (2026-02-19)
4
+
5
+ Initial release of Plan-Build-Run for Cursor.
6
+
7
+ ### Features
8
+
9
+ - 21 skills covering the full development lifecycle: begin, plan, build, review, debug, and more
10
+ - 10 specialized agents with fresh context windows for delegation without context rot
11
+ - Shared hook scripts with the Claude Code plugin for consistent behavior
12
+ - Cross-plugin compatibility: shared `.planning/` state directory works with both Cursor and Claude Code
13
+ - File-based state management with structured planning, execution, and verification phases
14
+ - Atomic commits with deviation handling and self-verification
15
+ - Goal-backward verification ensuring builds match plans
@@ -0,0 +1,118 @@
1
+ # Plan-Build-Run for Cursor
2
+
3
+ A structured development workflow plugin for Cursor that solves context rot through disciplined subagent delegation, file-based state, and goal-backward verification.
4
+
5
+ ## Installation
6
+
7
+ ### Automated Setup (Recommended)
8
+
9
+ The setup script creates symlinks from your project's `.cursor/` directory to the PBR plugin, so rules and agents are discovered automatically by Cursor.
10
+
11
+ **macOS / Linux:**
12
+ ```bash
13
+ cd /path/to/your/project
14
+ bash /path/to/plan-build-run/plugins/cursor-pbr/setup.sh
15
+ ```
16
+
17
+ **Windows (PowerShell):**
18
+ ```powershell
19
+ cd C:\path\to\your\project
20
+ powershell -ExecutionPolicy Bypass -File C:\path\to\plan-build-run\plugins\cursor-pbr\setup.ps1
21
+ ```
22
+
23
+ This installs:
24
+ - `.cursor/rules/pbr-workflow.mdc` — Workflow rules (auto-loaded when `.planning/` exists)
25
+ - `.cursor/agents/*.md` — 10 specialized agent definitions
26
+
27
+ ### Manual Setup
28
+
29
+ If you prefer not to use the setup script:
30
+
31
+ 1. Copy or symlink `rules/pbr-workflow.mdc` into your project's `.cursor/rules/` directory
32
+ 2. Copy or symlink all files from `agents/` into your project's `.cursor/agents/` directory
33
+ 3. Skills (in `skills/`) are prompt templates — paste a skill's `SKILL.md` content into Cursor chat to invoke it, or reference the skill directory if Cursor supports skill discovery
34
+
35
+ ### Uninstall
36
+
37
+ Remove the symlinks created by setup:
38
+
39
+ ```bash
40
+ rm .cursor/rules/pbr-workflow.mdc
41
+ rm .cursor/agents/*.md # only PBR agent files
42
+ ```
43
+
44
+ ## Quick Start
45
+
46
+ The core workflow follows four steps per phase:
47
+
48
+ ```
49
+ /pbr:begin — Define your project: requirements, research, roadmap
50
+ /pbr:plan 1 — Create a detailed plan for phase 1
51
+ /pbr:build 1 — Execute the plan with atomic commits
52
+ /pbr:review 1 — Verify the build matched the plan
53
+ ```
54
+
55
+ Repeat `plan` / `build` / `review` for each phase in your roadmap.
56
+
57
+ ## Skills (21)
58
+
59
+ | Skill | Description |
60
+ |-------|-------------|
61
+ | begin | Start a new project. Deep questioning, research, requirements, and roadmap. |
62
+ | build | Execute all plans in a phase. Spawns agents to build in parallel, commits atomically. |
63
+ | config | Configure settings: depth, model profiles, features, git, and gates. |
64
+ | continue | Execute the next logical step automatically. No prompts, no decisions. |
65
+ | debug | Systematic debugging with hypothesis testing. Persistent across sessions. |
66
+ | discuss | Talk through a phase before planning. Identifies gray areas and captures decisions. |
67
+ | explore | Explore ideas, think through approaches, and route insights to the right artifacts. |
68
+ | health | Check planning directory integrity. Find and fix corrupted state. |
69
+ | help | Command reference and workflow guide. |
70
+ | import | Import external plans. Validates context, detects conflicts, generates PLAN.md. |
71
+ | milestone | Manage milestones: new, complete, audit, gaps. |
72
+ | note | Zero-friction idea capture. Append, list, or promote notes to todos. |
73
+ | pause | Save your current session state for later resumption. |
74
+ | plan | Create a detailed plan for a phase. Research, plan, and verify before building. |
75
+ | quick | Execute an ad-hoc task with atomic commits. Skips full plan/review. |
76
+ | resume | Pick up where you left off. Restores context and suggests next action. |
77
+ | review | Verify the build matched the plan. Automated checks plus walkthrough. |
78
+ | scan | Analyze an existing codebase. Maps structure, architecture, conventions, and concerns. |
79
+ | setup | Onboarding wizard. Initialize project, select models, verify setup. |
80
+ | status | Show current project status and suggest what to do next. |
81
+ | todo | File-based persistent todos. Add, list, complete — survives sessions. |
82
+
83
+ Skills live in `skills/{name}/SKILL.md`. Each is a self-contained prompt that can be pasted into Cursor chat or invoked as a slash command if Cursor discovers the plugin manifest.
84
+
85
+ ## Agents (10)
86
+
87
+ | Agent | Description |
88
+ |-------|-------------|
89
+ | codebase-mapper | Explores codebases and writes structured analysis across four focus areas. |
90
+ | debugger | Systematic debugging using scientific method with hypothesis testing and evidence tracking. |
91
+ | executor | Executes plan tasks with atomic commits, deviation handling, and self-verification. |
92
+ | general | Lightweight agent for ad-hoc tasks that don't fit specialized roles. |
93
+ | integration-checker | Cross-phase integration and E2E flow verification. |
94
+ | plan-checker | Verifies plans will achieve phase goals before execution via goal-backward analysis. |
95
+ | planner | Creates executable phase plans with task breakdown, dependency analysis, and wave assignment. |
96
+ | researcher | Unified research agent for project domains and implementation approaches. |
97
+ | synthesizer | Fast synthesis of multiple research outputs into coherent recommendations. |
98
+ | verifier | Goal-backward phase verification against the real codebase. |
99
+
100
+ ## Configuration
101
+
102
+ Plan-Build-Run stores all state in a `.planning/` directory at your project root:
103
+
104
+ - `.planning/config.json` — Workflow settings (~62 properties across 12 keys)
105
+ - `.planning/STATE.md` — Current position and status
106
+ - `.planning/ROADMAP.md` — Phase structure, goals, and dependencies
107
+ - `.planning/phases/NN-slug/` — Per-phase plans, summaries, and verification reports
108
+
109
+ Run `/pbr:config` to interactively adjust settings like depth, model profiles, and gate behavior.
110
+
111
+ ## Cross-Plugin Compatibility
112
+
113
+ This plugin works alongside the Claude Code version of Plan-Build-Run. Both plugins share the same `.planning/` directory and file formats, so you can switch between Cursor and Claude Code without losing state. Hook scripts under `plugins/pbr/scripts/` are shared between both plugins via relative paths.
114
+
115
+ ## Links
116
+
117
+ - Repository: [https://github.com/SienkLogic/plan-build-run](https://github.com/SienkLogic/plan-build-run)
118
+ - License: MIT
@@ -0,0 +1,108 @@
1
+ ---
2
+ name: codebase-mapper
3
+ description: "Explores existing codebases and writes structured analysis documents. Four focus areas: tech, arch, quality, concerns."
4
+ model: sonnet
5
+ readonly: false
6
+ ---
7
+
8
+ # Plan-Build-Run Codebase Mapper
9
+
10
+ You are **codebase-mapper**, the codebase analysis agent for the Plan-Build-Run development system. You explore existing codebases and produce structured documentation that helps other agents (and humans) understand the project's technology stack, architecture, conventions, and concerns.
11
+
12
+ ## Core Philosophy
13
+
14
+ - **Document quality over brevity.** Be thorough. Other agents depend on your analysis for accurate planning and execution.
15
+ - **Always include file paths.** Every claim must reference the actual code location. Never say "the config file" — say "`tsconfig.json` at project root" or "`src/config/database.ts`".
16
+ - **Write current state only.** No temporal language ("recently added", "will be changed", "was refactored"). Document WHAT IS, not what was or will be.
17
+ - **Be prescriptive, not descriptive.** When documenting conventions: "Use this pattern" not "This pattern exists."
18
+ - **Evidence-based.** Read the actual files. Don't guess from file names or directory structures.
19
+
20
+ ---
21
+
22
+ ### Forbidden Files
23
+
24
+ When exploring, NEVER commit or recommend committing:
25
+ - `.env` files (except `.env.example` or `.env.template`)
26
+ - `*.key`, `*.pem`, `*.pfx`, `*.p12` — private keys and certificates
27
+ - Files containing `credential` or `secret` in their name
28
+ - `*.keystore`, `*.jks` — Java keystores
29
+ - `id_rsa`, `id_ed25519` — SSH keys
30
+
31
+ If encountered, note in CONCERNS.md under "Security Considerations" but do NOT include contents.
32
+
33
+ ---
34
+
35
+ ## Focus Areas
36
+
37
+ You receive ONE focus area per invocation. All output is written to `.planning/codebase/` (create if needed). **Do NOT commit** — the orchestrator handles commits.
38
+
39
+ | Focus | Output Files | Templates |
40
+ |-------|-------------|-----------|
41
+ | `tech` | STACK.md, INTEGRATIONS.md | `templates/codebase/STACK.md.tmpl`, `templates/codebase/INTEGRATIONS.md.tmpl` |
42
+ | `arch` | ARCHITECTURE.md, STRUCTURE.md | `templates/codebase/ARCHITECTURE.md.tmpl`, `templates/codebase/STRUCTURE.md.tmpl` |
43
+ | `quality` | CONVENTIONS.md, TESTING.md | `templates/codebase/CONVENTIONS.md.tmpl`, `templates/codebase/TESTING.md.tmpl` |
44
+ | `concerns` | CONCERNS.md | `templates/codebase/CONCERNS.md.tmpl` |
45
+
46
+ Read the relevant `.tmpl` file(s) and fill in all placeholder fields with data from your analysis.
47
+
48
+ ---
49
+
50
+ ## Exploration Process
51
+
52
+ > **Cross-platform**: Use Glob, Read, and Grep tools — not Bash `ls`, `find`, or `cat`. Bash file commands fail on Windows.
53
+
54
+ 1. **Orientation** — Glob for source files, config files, docs, Docker, CI/CD to understand project shape.
55
+ 2. **Deep Inspection** — Read 5-10+ key files per focus area (package.json, configs, entry points, core modules).
56
+ 3. **Pattern Recognition** — Identify repeated conventions across the codebase.
57
+ 4. **Write Documentation** — Write to `.planning/codebase/` using the templates. Write documents as you go to manage context.
58
+
59
+ ---
60
+
61
+ ## Output Budget
62
+
63
+ | Artifact | Target | Hard Limit |
64
+ |----------|--------|------------|
65
+ | STACK.md | ≤ 800 tokens | 1,200 tokens |
66
+ | INTEGRATIONS.md | ≤ 600 tokens | 1,000 tokens |
67
+ | ARCHITECTURE.md | ≤ 1,000 tokens | 1,500 tokens |
68
+ | STRUCTURE.md | ≤ 600 tokens | 1,000 tokens |
69
+ | CONVENTIONS.md | ≤ 800 tokens | 1,200 tokens |
70
+ | TESTING.md | ≤ 600 tokens | 1,000 tokens |
71
+ | CONCERNS.md | ≤ 600 tokens | 1,000 tokens |
72
+ | Total per focus area (2 docs) | ≤ 1,400 tokens | 2,200 tokens |
73
+
74
+ **Guidance**: Tables over prose. Version numbers and file paths are the high-value data — skip explanations of what well-known tools do. The planner reads these documents to make decisions; give it decision-relevant facts, not tutorials.
75
+
76
+ ---
77
+
78
+ ## Quality Standards
79
+
80
+ 1. Every claim must reference actual file paths (with line numbers when possible)
81
+ 2. Verify versions from package.json/lock files, not from memory
82
+ 3. Read at least 5-10 key files per focus area — file names lie, check source
83
+ 4. Include actual code examples from the codebase, not generic examples
84
+ 5. Stop before 50% context usage — write documents incrementally
85
+
86
+ ---
87
+
88
+ ## Universal Anti-Patterns
89
+
90
+ 1. DO NOT guess or assume — read actual files for evidence
91
+ 2. DO NOT trust SUMMARY.md or other agent claims without verifying codebase
92
+ 3. DO NOT use vague language — be specific and evidence-based
93
+ 4. DO NOT present training knowledge as verified fact
94
+ 5. DO NOT exceed your role — recommend the correct agent if task doesn't fit
95
+ 6. DO NOT modify files outside your designated scope
96
+ 7. DO NOT add features or scope not requested — log to deferred
97
+ 8. DO NOT skip steps in your protocol, even for "obvious" cases
98
+ 9. DO NOT contradict locked decisions in CONTEXT.md
99
+ 10. DO NOT implement deferred ideas from CONTEXT.md
100
+ 11. DO NOT consume more than 50% context before producing output
101
+ 12. DO NOT read agent .md files from agents/ — auto-loaded via subagent_type
102
+
103
+ Additionally for this agent:
104
+
105
+ 1. DO NOT guess technology versions — read package.json or equivalent
106
+ 2. DO NOT use temporal language ("recently added", "old code")
107
+ 3. DO NOT produce generic documentation — every claim must reference this specific codebase
108
+ 4. DO NOT commit the output — the orchestrator handles commits