@sienklogic/plan-build-run 2.0.2 → 2.2.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 (166) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +25 -6
  3. package/dashboard/src/routes/pages.routes.js +11 -4
  4. package/dashboard/src/services/dashboard.service.js +81 -17
  5. package/dashboard/src/services/phase.service.js +30 -24
  6. package/dashboard/src/services/roadmap.service.js +3 -3
  7. package/dashboard/src/views/partials/phase-content.ejs +5 -4
  8. package/package.json +1 -1
  9. package/plugins/cursor-pbr/.cursor-plugin/plugin.json +1 -1
  10. package/plugins/cursor-pbr/CHANGELOG.md +15 -0
  11. package/plugins/cursor-pbr/README.md +118 -0
  12. package/plugins/cursor-pbr/agents/codebase-mapper.md +108 -0
  13. package/plugins/cursor-pbr/agents/debugger.md +168 -0
  14. package/plugins/cursor-pbr/agents/executor.md +236 -0
  15. package/plugins/cursor-pbr/agents/general.md +87 -0
  16. package/plugins/cursor-pbr/agents/integration-checker.md +87 -0
  17. package/plugins/cursor-pbr/agents/plan-checker.md +198 -0
  18. package/plugins/cursor-pbr/agents/planner.md +180 -0
  19. package/plugins/cursor-pbr/agents/researcher.md +162 -0
  20. package/plugins/cursor-pbr/agents/synthesizer.md +101 -0
  21. package/plugins/cursor-pbr/agents/verifier.md +193 -0
  22. package/plugins/cursor-pbr/assets/logo.svg +21 -0
  23. package/plugins/cursor-pbr/hooks/hooks.json +189 -7
  24. package/plugins/cursor-pbr/references/agent-anti-patterns.md +25 -0
  25. package/plugins/cursor-pbr/references/agent-interactions.md +135 -0
  26. package/plugins/cursor-pbr/references/agent-teams.md +55 -0
  27. package/plugins/cursor-pbr/references/checkpoints.md +158 -0
  28. package/plugins/cursor-pbr/references/common-bug-patterns.md +14 -0
  29. package/plugins/cursor-pbr/references/config-reference.md +442 -0
  30. package/plugins/cursor-pbr/references/continuation-format.md +213 -0
  31. package/plugins/cursor-pbr/references/deviation-rules.md +113 -0
  32. package/plugins/cursor-pbr/references/git-integration.md +227 -0
  33. package/plugins/cursor-pbr/references/integration-patterns.md +118 -0
  34. package/plugins/cursor-pbr/references/model-profiles.md +100 -0
  35. package/plugins/cursor-pbr/references/model-selection.md +32 -0
  36. package/plugins/cursor-pbr/references/pbr-rules.md +194 -0
  37. package/plugins/cursor-pbr/references/plan-authoring.md +182 -0
  38. package/plugins/cursor-pbr/references/plan-format.md +288 -0
  39. package/plugins/cursor-pbr/references/planning-config.md +214 -0
  40. package/plugins/cursor-pbr/references/questioning.md +215 -0
  41. package/plugins/cursor-pbr/references/reading-verification.md +128 -0
  42. package/plugins/cursor-pbr/references/stub-patterns.md +161 -0
  43. package/plugins/cursor-pbr/references/subagent-coordination.md +120 -0
  44. package/plugins/cursor-pbr/references/ui-formatting.md +462 -0
  45. package/plugins/cursor-pbr/references/verification-patterns.md +199 -0
  46. package/plugins/cursor-pbr/references/wave-execution.md +96 -0
  47. package/plugins/cursor-pbr/rules/pbr-workflow.mdc +48 -0
  48. package/plugins/cursor-pbr/setup.ps1 +78 -0
  49. package/plugins/cursor-pbr/setup.sh +83 -0
  50. package/plugins/cursor-pbr/skills/begin/SKILL.md +566 -0
  51. package/plugins/cursor-pbr/skills/begin/templates/PROJECT.md.tmpl +34 -0
  52. package/plugins/cursor-pbr/skills/begin/templates/REQUIREMENTS.md.tmpl +19 -0
  53. package/plugins/cursor-pbr/skills/begin/templates/STATE.md.tmpl +50 -0
  54. package/plugins/cursor-pbr/skills/begin/templates/config.json.tmpl +64 -0
  55. package/plugins/cursor-pbr/skills/begin/templates/researcher-prompt.md.tmpl +20 -0
  56. package/plugins/cursor-pbr/skills/begin/templates/roadmap-prompt.md.tmpl +31 -0
  57. package/plugins/cursor-pbr/skills/begin/templates/synthesis-prompt.md.tmpl +17 -0
  58. package/plugins/cursor-pbr/skills/build/SKILL.md +902 -0
  59. package/plugins/cursor-pbr/skills/config/SKILL.md +253 -0
  60. package/plugins/cursor-pbr/skills/continue/SKILL.md +159 -0
  61. package/plugins/cursor-pbr/skills/debug/SKILL.md +512 -0
  62. package/plugins/cursor-pbr/skills/debug/templates/continuation-prompt.md.tmpl +17 -0
  63. package/plugins/cursor-pbr/skills/debug/templates/initial-investigation-prompt.md.tmpl +28 -0
  64. package/plugins/cursor-pbr/skills/discuss/SKILL.md +344 -0
  65. package/plugins/cursor-pbr/skills/discuss/templates/CONTEXT.md.tmpl +62 -0
  66. package/plugins/cursor-pbr/skills/discuss/templates/decision-categories.md +10 -0
  67. package/plugins/cursor-pbr/skills/explore/SKILL.md +375 -0
  68. package/plugins/cursor-pbr/skills/health/SKILL.md +218 -0
  69. package/plugins/cursor-pbr/skills/health/templates/check-pattern.md.tmpl +31 -0
  70. package/plugins/cursor-pbr/skills/health/templates/output-format.md.tmpl +64 -0
  71. package/plugins/cursor-pbr/skills/help/SKILL.md +152 -0
  72. package/plugins/cursor-pbr/skills/import/SKILL.md +499 -0
  73. package/plugins/cursor-pbr/skills/milestone/SKILL.md +701 -0
  74. package/plugins/cursor-pbr/skills/milestone/templates/audit-report.md.tmpl +49 -0
  75. package/plugins/cursor-pbr/skills/milestone/templates/stats-file.md.tmpl +31 -0
  76. package/plugins/cursor-pbr/skills/note/SKILL.md +228 -0
  77. package/plugins/cursor-pbr/skills/pause/SKILL.md +246 -0
  78. package/plugins/cursor-pbr/skills/pause/templates/continue-here.md.tmpl +72 -0
  79. package/plugins/cursor-pbr/skills/plan/SKILL.md +648 -0
  80. package/plugins/cursor-pbr/skills/plan/templates/checker-prompt.md.tmpl +22 -0
  81. package/plugins/cursor-pbr/skills/plan/templates/gap-closure-prompt.md.tmpl +33 -0
  82. package/plugins/cursor-pbr/skills/plan/templates/planner-prompt.md.tmpl +39 -0
  83. package/plugins/cursor-pbr/skills/plan/templates/researcher-prompt.md.tmpl +20 -0
  84. package/plugins/cursor-pbr/skills/plan/templates/revision-prompt.md.tmpl +24 -0
  85. package/plugins/cursor-pbr/skills/quick/SKILL.md +351 -0
  86. package/plugins/cursor-pbr/skills/resume/SKILL.md +399 -0
  87. package/plugins/cursor-pbr/skills/review/SKILL.md +649 -0
  88. package/plugins/cursor-pbr/skills/review/templates/debugger-prompt.md.tmpl +61 -0
  89. package/plugins/cursor-pbr/skills/review/templates/gap-planner-prompt.md.tmpl +41 -0
  90. package/plugins/cursor-pbr/skills/review/templates/verifier-prompt.md.tmpl +116 -0
  91. package/plugins/cursor-pbr/skills/scan/SKILL.md +301 -0
  92. package/plugins/cursor-pbr/skills/scan/templates/mapper-prompt.md.tmpl +202 -0
  93. package/plugins/cursor-pbr/skills/setup/SKILL.md +250 -0
  94. package/plugins/cursor-pbr/skills/shared/commit-planning-docs.md +36 -0
  95. package/plugins/cursor-pbr/skills/shared/config-loading.md +103 -0
  96. package/plugins/cursor-pbr/skills/shared/context-budget.md +41 -0
  97. package/plugins/cursor-pbr/skills/shared/context-loader-task.md +87 -0
  98. package/plugins/cursor-pbr/skills/shared/digest-select.md +80 -0
  99. package/plugins/cursor-pbr/skills/shared/domain-probes.md +126 -0
  100. package/plugins/cursor-pbr/skills/shared/error-reporting.md +80 -0
  101. package/plugins/cursor-pbr/skills/shared/gate-prompts.md +389 -0
  102. package/plugins/cursor-pbr/skills/shared/phase-argument-parsing.md +46 -0
  103. package/plugins/cursor-pbr/skills/shared/progress-display.md +54 -0
  104. package/plugins/cursor-pbr/skills/shared/revision-loop.md +82 -0
  105. package/plugins/cursor-pbr/skills/shared/state-loading.md +63 -0
  106. package/plugins/cursor-pbr/skills/shared/state-update.md +162 -0
  107. package/plugins/cursor-pbr/skills/shared/universal-anti-patterns.md +34 -0
  108. package/plugins/cursor-pbr/skills/status/SKILL.md +362 -0
  109. package/plugins/cursor-pbr/skills/todo/SKILL.md +195 -0
  110. package/plugins/cursor-pbr/templates/CONTEXT.md.tmpl +53 -0
  111. package/plugins/cursor-pbr/templates/INTEGRATION-REPORT.md.tmpl +152 -0
  112. package/plugins/cursor-pbr/templates/RESEARCH-SUMMARY.md.tmpl +98 -0
  113. package/plugins/cursor-pbr/templates/ROADMAP.md.tmpl +41 -0
  114. package/plugins/cursor-pbr/templates/SUMMARY.md.tmpl +82 -0
  115. package/plugins/cursor-pbr/templates/VERIFICATION-DETAIL.md.tmpl +117 -0
  116. package/plugins/cursor-pbr/templates/continue-here.md.tmpl +74 -0
  117. package/plugins/cursor-pbr/templates/prompt-partials/phase-project-context.md.tmpl +38 -0
  118. package/plugins/pbr/agents/codebase-mapper.md +41 -206
  119. package/plugins/pbr/agents/debugger.md +65 -171
  120. package/plugins/pbr/agents/executor.md +90 -275
  121. package/plugins/pbr/agents/general.md +27 -97
  122. package/plugins/pbr/agents/integration-checker.md +35 -112
  123. package/plugins/pbr/agents/plan-checker.md +71 -164
  124. package/plugins/pbr/agents/planner.md +76 -245
  125. package/plugins/pbr/agents/researcher.md +63 -255
  126. package/plugins/pbr/agents/synthesizer.md +49 -174
  127. package/plugins/pbr/agents/verifier.md +75 -366
  128. package/plugins/pbr/hooks/hooks.json +14 -10
  129. package/plugins/pbr/references/ui-formatting.md +1 -1
  130. package/plugins/pbr/scripts/auto-continue.js +20 -4
  131. package/plugins/pbr/scripts/check-dangerous-commands.js +1 -1
  132. package/plugins/pbr/scripts/check-phase-boundary.js +1 -1
  133. package/plugins/pbr/scripts/check-plan-format.js +3 -3
  134. package/plugins/pbr/scripts/check-roadmap-sync.js +3 -3
  135. package/plugins/pbr/scripts/check-skill-workflow.js +1 -1
  136. package/plugins/pbr/scripts/check-state-sync.js +2 -2
  137. package/plugins/pbr/scripts/check-subagent-output.js +1 -1
  138. package/plugins/pbr/scripts/check-summary-gate.js +198 -0
  139. package/plugins/pbr/scripts/context-budget-check.js +1 -1
  140. package/plugins/pbr/scripts/event-handler.js +2 -2
  141. package/plugins/pbr/scripts/event-logger.js +1 -1
  142. package/plugins/pbr/scripts/log-subagent.js +1 -1
  143. package/plugins/pbr/scripts/pbr-tools.js +1 -1
  144. package/plugins/pbr/scripts/post-write-dispatch.js +1 -1
  145. package/plugins/pbr/scripts/post-write-quality.js +1 -1
  146. package/plugins/pbr/scripts/pre-bash-dispatch.js +1 -1
  147. package/plugins/pbr/scripts/pre-write-dispatch.js +16 -3
  148. package/plugins/pbr/scripts/session-cleanup.js +1 -1
  149. package/plugins/pbr/scripts/status-line.js +1 -1
  150. package/plugins/pbr/scripts/suggest-compact.js +1 -1
  151. package/plugins/pbr/scripts/task-completed.js +1 -1
  152. package/plugins/pbr/scripts/track-context-budget.js +11 -6
  153. package/plugins/pbr/scripts/validate-commit.js +1 -1
  154. package/plugins/pbr/scripts/validate-task.js +1 -1
  155. package/plugins/pbr/skills/begin/SKILL.md +4 -2
  156. package/plugins/pbr/skills/begin/templates/roadmap-prompt.md.tmpl +2 -0
  157. package/plugins/pbr/skills/build/SKILL.md +6 -4
  158. package/plugins/pbr/skills/continue/SKILL.md +2 -1
  159. package/plugins/pbr/skills/review/SKILL.md +4 -3
  160. package/plugins/pbr/skills/status/SKILL.md +5 -2
  161. package/plugins/pbr/templates/ROADMAP.md.tmpl +6 -1
  162. package/plugins/cursor-pbr/agents/.gitkeep +0 -0
  163. package/plugins/cursor-pbr/references/.gitkeep +0 -0
  164. package/plugins/cursor-pbr/rules/.gitkeep +0 -0
  165. package/plugins/cursor-pbr/skills/.gitkeep +0 -0
  166. package/plugins/cursor-pbr/templates/.gitkeep +0 -0
package/CHANGELOG.md CHANGED
@@ -7,6 +7,36 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.2.0] - 2026-02-19
11
+
12
+ ### Added
13
+ - Milestone integration into workflow lifecycle — milestones are now created automatically during `/pbr:begin` roadmap generation
14
+ - Planner agent generates milestone-grouped roadmaps (single milestone for standard projects, multiple for 8+ phase comprehensive projects)
15
+ - Milestone-aware boundary detection in `/pbr:build` and `/pbr:review` — reads ROADMAP.md phase ranges instead of just "last phase overall"
16
+ - Between-milestones state handling in `/pbr:continue`
17
+ - Audit report detection in `/pbr:status` — suggests the correct next action based on whether an audit exists and its result
18
+
19
+ ### Fixed
20
+ - "Skip audit" option in build/review completion banners now correctly says "archive milestone after audit passes" (consistent with milestone anti-pattern rules)
21
+ - `auto_advance` hard-stop message at milestone boundaries now explains why it paused
22
+
23
+ ## [2.1.0] - 2026-02-19
24
+
25
+ ### Added
26
+ - **Cursor IDE plugin** (`plugins/cursor-pbr/`) — complete port with 21 skills, 10 agents, and `.mdc` workflow rules
27
+ - Cross-plugin compatibility: shared `.planning/` state between Claude Code and Cursor plugins
28
+ - Setup scripts (`setup.sh` for macOS/Linux, `setup.ps1` for Windows) for easy Cursor plugin installation
29
+ - Summary gate hook (`check-summary-gate.js`) — enforces SUMMARY file before phase state can advance
30
+ - Cross-plugin compatibility test suite (7 tests)
31
+ - Cursor plugin validation test suite (92 tests)
32
+ - Companion web dashboard improvements: service and route enhancements
33
+
34
+ ### Changed
35
+ - Agent definitions optimized — 48% average size reduction across all 10 agents
36
+ - Hook scripts improved with better error handling and dispatch logic
37
+ - Test count increased from 758 to 1008 across 42 suites
38
+ - Removed `.gitkeep` placeholder files from `cursor-pbr/` (replaced by real content)
39
+
10
40
  ## [2.0.0] - 2026-02-17
11
41
 
12
42
  ### Added
package/README.md CHANGED
@@ -3,11 +3,11 @@
3
3
  </p>
4
4
 
5
5
  <p align="center">
6
- <strong>Context-engineered development workflow for Claude Code.</strong>
6
+ <strong>Context-engineered development workflow for Claude Code and Cursor.</strong>
7
7
  <br />
8
8
  Build ambitious multi-phase software without quality degradation.
9
9
  <br />
10
- Works with any Claude Code plan. Shines on Max.
10
+ Works with any Claude Code plan. Shines on Max. Now available for Cursor IDE.
11
11
  <br />
12
12
  <br />
13
13
  <a href="#why-plan-build-run">Why Plan-Build-Run?</a> &bull;
@@ -21,10 +21,11 @@
21
21
  <p align="center">
22
22
  <a href="https://github.com/SienkLogic/plan-build-run/actions"><img src="https://img.shields.io/github/actions/workflow/status/SienkLogic/plan-build-run/ci.yml?style=for-the-badge&label=CI&logo=github" alt="CI Status" /></a>
23
23
  <img src="https://img.shields.io/badge/Claude_Code-Plugin-7C3AED?style=for-the-badge&logo=anthropic&logoColor=white" alt="Claude Code Plugin" />
24
+ <img src="https://img.shields.io/badge/Cursor-Plugin-00A67E?style=for-the-badge&logo=cursor&logoColor=white" alt="Cursor Plugin" />
24
25
  <img src="https://img.shields.io/badge/Node.js-18%2B-339933?style=for-the-badge&logo=node.js&logoColor=white" alt="Node.js 18+" />
25
26
  <a href="LICENSE"><img src="https://img.shields.io/github/license/SienkLogic/plan-build-run?style=for-the-badge" alt="License" /></a>
26
27
  <a href="https://www.npmjs.com/package/@sienklogic/plan-build-run"><img src="https://img.shields.io/npm/v/@sienklogic/plan-build-run?style=for-the-badge&logo=npm&logoColor=white" alt="npm" /></a>
27
- <img src="https://img.shields.io/badge/Tests-780_passing-brightgreen?style=for-the-badge" alt="780 Tests" />
28
+ <img src="https://img.shields.io/badge/Tests-1008_passing-brightgreen?style=for-the-badge" alt="1008 Tests" />
28
29
  </p>
29
30
 
30
31
  ---
@@ -87,6 +88,24 @@ All `/pbr:*` commands are now available globally.
87
88
 
88
89
  </details>
89
90
 
91
+ ### Install for Cursor IDE
92
+
93
+ Plan-Build-Run also works in Cursor. The setup script symlinks rules and agents into your project's `.cursor/` directory.
94
+
95
+ **macOS / Linux:**
96
+ ```bash
97
+ cd /path/to/your/project
98
+ bash /path/to/plan-build-run/plugins/cursor-pbr/setup.sh
99
+ ```
100
+
101
+ **Windows (PowerShell):**
102
+ ```powershell
103
+ cd C:\path\to\your\project
104
+ powershell -ExecutionPolicy Bypass -File C:\path\to\plan-build-run\plugins\cursor-pbr\setup.ps1
105
+ ```
106
+
107
+ Both plugins share the same `.planning/` directory — start a project in Claude Code, continue in Cursor, or vice versa. See [`plugins/cursor-pbr/README.md`](plugins/cursor-pbr/README.md) for full details.
108
+
90
109
  ### Dashboard (Optional)
91
110
 
92
111
  Plan-Build-Run ships with a companion web dashboard for browsing your project's planning state in a browser. To set it up:
@@ -212,7 +231,7 @@ git clone https://github.com/SienkLogic/plan-build-run.git
212
231
  cd plan-build-run
213
232
  npm install
214
233
 
215
- # Run tests (758 tests, 36 suites)
234
+ # Run tests (1008 tests, 42 suites)
216
235
  npm test
217
236
 
218
237
  # Lint
@@ -236,8 +255,8 @@ CI runs on Node 18/20/22 across Windows, macOS, and Linux. See [CONTRIBUTING.md]
236
255
  | Skills (slash commands) | 21 |
237
256
  | Specialized agents | 10 |
238
257
  | Hook scripts | 28 |
239
- | Tests | 758 |
240
- | Test suites | 36 |
258
+ | Tests | 1008 |
259
+ | Test suites | 42 |
241
260
  | Config toggles | 12 top-level keys |
242
261
 
243
262
  ---
@@ -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.2.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