@sienklogic/plan-build-run 2.18.1 → 2.20.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.
- package/CHANGELOG.md +31 -0
- package/README.md +1 -1
- package/dashboard/public/css/layout.css +70 -2
- package/dashboard/src/services/roadmap.service.js +19 -5
- package/dashboard/src/services/todo.service.js +14 -5
- package/dashboard/src/views/partials/dashboard-content.ejs +2 -2
- package/dashboard/src/views/partials/layout-bottom.ejs +37 -0
- package/dashboard/src/views/partials/layout-top.ejs +1 -0
- package/dashboard/src/views/partials/roadmap-content.ejs +26 -1
- package/dashboard/src/views/partials/todos-content.ejs +3 -0
- package/package.json +1 -1
- package/plugins/copilot-pbr/agents/debugger.agent.md +11 -1
- package/plugins/copilot-pbr/agents/plan-checker.agent.md +15 -6
- package/plugins/copilot-pbr/hooks/hooks.json +13 -0
- package/plugins/copilot-pbr/plugin.json +1 -1
- package/plugins/copilot-pbr/references/agent-contracts.md +1 -1
- package/plugins/copilot-pbr/skills/health/SKILL.md +9 -0
- package/plugins/cursor-pbr/.cursor-plugin/plugin.json +1 -1
- package/plugins/cursor-pbr/agents/debugger.md +11 -1
- package/plugins/cursor-pbr/agents/plan-checker.md +15 -6
- package/plugins/cursor-pbr/hooks/hooks.json +11 -0
- package/plugins/cursor-pbr/references/agent-contracts.md +1 -1
- package/plugins/cursor-pbr/skills/health/SKILL.md +9 -0
- package/plugins/pbr/.claude-plugin/plugin.json +1 -1
- package/plugins/pbr/agents/debugger.md +11 -1
- package/plugins/pbr/agents/plan-checker.md +16 -6
- package/plugins/pbr/agents/verifier.md +1 -0
- package/plugins/pbr/hooks/hooks.json +11 -0
- package/plugins/pbr/references/agent-contracts.md +1 -1
- package/plugins/pbr/scripts/auto-continue.js +8 -2
- package/plugins/pbr/scripts/check-config-change.js +130 -0
- package/plugins/pbr/scripts/event-handler.js +12 -1
- package/plugins/pbr/scripts/hooks-schema.json +1 -0
- package/plugins/pbr/scripts/package.json +1 -0
- package/plugins/pbr/scripts/pre-bash-dispatch.js +30 -0
- package/plugins/pbr/scripts/pre-write-dispatch.js +27 -0
- package/plugins/pbr/skills/health/SKILL.md +9 -0
- package/plugins/pbr/skills/help/SKILL.md +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,37 @@ All notable changes to Plan-Build-Run will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [2.20.0](https://github.com/SienkLogic/plan-build-run/compare/plan-build-run-v2.19.0...plan-build-run-v2.20.0) (2026-02-23)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* **tools:** add worktree isolation, ConfigChange hook, and claude agents docs ([d704f34](https://github.com/SienkLogic/plan-build-run/commit/d704f340c636fa41f988d27a661a1e1918b04c87))
|
|
14
|
+
|
|
15
|
+
## [2.19.0](https://github.com/SienkLogic/plan-build-run/compare/plan-build-run-v2.18.1...plan-build-run-v2.19.0) (2026-02-22)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* **dashboard:** add responsive mobile layout with sidebar hamburger menu ([5621739](https://github.com/SienkLogic/plan-build-run/commit/5621739b1b1b85bf5854bf52582908251fdeff13))
|
|
21
|
+
* **tools:** add D10 test plan coverage dimension to plan-checker agent ([a4ff196](https://github.com/SienkLogic/plan-build-run/commit/a4ff19664c723861b262f9d6feccdd9e1ef95221))
|
|
22
|
+
* **tools:** add PreToolUse additionalContext soft warnings for risky operations ([1d39406](https://github.com/SienkLogic/plan-build-run/commit/1d394066071959e4abafdcc1e84d472f05584018))
|
|
23
|
+
* **tools:** add STATE.md backup step before health skill auto-fix regeneration ([43a52dd](https://github.com/SienkLogic/plan-build-run/commit/43a52dd36df9afc2f0aa3ddebfd588904b562bcd))
|
|
24
|
+
* **tools:** require user confirmation before debugger agent applies fixes ([5446654](https://github.com/SienkLogic/plan-build-run/commit/544665487093210c6f6e412f7af79e02d33cf19a))
|
|
25
|
+
* **tools:** use last_assistant_message in Stop/SubagentStop hooks ([ab73122](https://github.com/SienkLogic/plan-build-run/commit/ab731222549b6c251d93de123a3a2475b8d41a13))
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
### Bug Fixes
|
|
29
|
+
|
|
30
|
+
* **dashboard:** handle todo files with H1 title and high/medium/low priority ([9edb601](https://github.com/SienkLogic/plan-build-run/commit/9edb601bdeb974c3f1d47f612697516b67d5aa2e))
|
|
31
|
+
* **dashboard:** show completed milestones on roadmap when all phases archived ([656ec04](https://github.com/SienkLogic/plan-build-run/commit/656ec04120931e5092ee608f23022276c5d79381))
|
|
32
|
+
* **tools:** add commonjs package.json to scripts for ESM project compat ([8ca8780](https://github.com/SienkLogic/plan-build-run/commit/8ca878023ce90257ccb9fe0cdabe5a3040ece9e9))
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
### Documentation
|
|
36
|
+
|
|
37
|
+
* **tools:** document minimum Claude Code v2.1.47 requirement for Windows hooks ([2ecb231](https://github.com/SienkLogic/plan-build-run/commit/2ecb23172f154e1fe68460c087eb055deea1df94))
|
|
38
|
+
|
|
8
39
|
## [2.18.1](https://github.com/SienkLogic/plan-build-run/compare/plan-build-run-v2.18.0...plan-build-run-v2.18.1) (2026-02-22)
|
|
9
40
|
|
|
10
41
|
|
package/README.md
CHANGED
|
@@ -61,7 +61,7 @@ Works on every Claude Code plan. Use `depth: quick` on Free/Pro, `depth: standar
|
|
|
61
61
|
|
|
62
62
|
### Prerequisites
|
|
63
63
|
|
|
64
|
-
- [Claude Code](https://docs.anthropic.com/en/docs/claude-code) 2.1.
|
|
64
|
+
- [Claude Code](https://docs.anthropic.com/en/docs/claude-code) 2.1.47+ (`claude --version`)
|
|
65
65
|
- Node.js 18+
|
|
66
66
|
|
|
67
67
|
### Install
|
|
@@ -500,10 +500,25 @@ main > p:first-of-type > a[href="/"]:hover {
|
|
|
500
500
|
font-size: 0.875rem;
|
|
501
501
|
}
|
|
502
502
|
|
|
503
|
+
/* --- Hero Stats Grid --- */
|
|
504
|
+
.hero-stats {
|
|
505
|
+
display: grid;
|
|
506
|
+
grid-template-columns: repeat(4, 1fr);
|
|
507
|
+
gap: var(--space-md);
|
|
508
|
+
}
|
|
509
|
+
|
|
503
510
|
/* --- Stat Values --- */
|
|
504
511
|
.stat-value { font-size: 2rem; font-weight: 700; line-height: 1.2; }
|
|
505
512
|
.stat-unit { font-size: 0.875rem; color: var(--color-dim); margin-left: 0.25rem; }
|
|
506
513
|
|
|
514
|
+
/* --- Quick Actions --- */
|
|
515
|
+
.quick-actions {
|
|
516
|
+
display: flex;
|
|
517
|
+
flex-wrap: wrap;
|
|
518
|
+
gap: var(--space-sm);
|
|
519
|
+
margin-bottom: var(--space-lg);
|
|
520
|
+
}
|
|
521
|
+
|
|
507
522
|
/* --- Bar Chart --- */
|
|
508
523
|
.bar-chart-row { display: flex; align-items: center; gap: var(--space-sm); margin-bottom: var(--space-xs); }
|
|
509
524
|
.bar-chart-label { min-width: 160px; font-size: 0.875rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
@@ -531,6 +546,11 @@ main > p:first-of-type > a[href="/"]:hover {
|
|
|
531
546
|
100% { transform: translateX(100%); }
|
|
532
547
|
}
|
|
533
548
|
|
|
549
|
+
/* --- Sidebar Backdrop (hidden by default, shown on mobile) --- */
|
|
550
|
+
.sidebar-backdrop {
|
|
551
|
+
display: none;
|
|
552
|
+
}
|
|
553
|
+
|
|
534
554
|
/* --- Mobile hamburger toggle --- */
|
|
535
555
|
.sidebar-toggle {
|
|
536
556
|
display: none;
|
|
@@ -588,11 +608,12 @@ main > p:first-of-type > a[href="/"]:hover {
|
|
|
588
608
|
border-bottom: none;
|
|
589
609
|
padding: var(--space-lg) 0;
|
|
590
610
|
overflow-y: auto;
|
|
591
|
-
background: var(--
|
|
611
|
+
background: var(--pico-background-color, #1a1a2e);
|
|
592
612
|
}
|
|
593
613
|
|
|
594
614
|
.page-wrapper > aside.sidebar.open {
|
|
595
615
|
transform: translateX(0);
|
|
616
|
+
box-shadow: 4px 0 24px rgba(0, 0, 0, 0.3);
|
|
596
617
|
}
|
|
597
618
|
|
|
598
619
|
.sidebar-backdrop {
|
|
@@ -600,7 +621,7 @@ main > p:first-of-type > a[href="/"]:hover {
|
|
|
600
621
|
position: fixed;
|
|
601
622
|
inset: 0;
|
|
602
623
|
top: var(--size-header);
|
|
603
|
-
background: rgba(0, 0, 0, 0.
|
|
624
|
+
background: rgba(0, 0, 0, 0.7);
|
|
604
625
|
z-index: 19;
|
|
605
626
|
}
|
|
606
627
|
|
|
@@ -615,9 +636,35 @@ main > p:first-of-type > a[href="/"]:hover {
|
|
|
615
636
|
h1 { font-size: 1.4rem; }
|
|
616
637
|
h2 { font-size: 1.15rem; }
|
|
617
638
|
|
|
639
|
+
/* Tables: ensure horizontal scroll on mobile */
|
|
618
640
|
table {
|
|
619
641
|
font-size: 0.8125rem;
|
|
620
642
|
}
|
|
643
|
+
|
|
644
|
+
.table-wrap {
|
|
645
|
+
margin: 0 calc(-1 * var(--space-md));
|
|
646
|
+
padding: 0 var(--space-md);
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
/* Hero stat cards: 2-column grid on mobile */
|
|
650
|
+
.hero-stats {
|
|
651
|
+
grid-template-columns: repeat(2, 1fr);
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
.hero-stats .stat-value {
|
|
655
|
+
font-size: 1.5rem;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
/* Bar chart: narrower labels */
|
|
659
|
+
.bar-chart-label {
|
|
660
|
+
min-width: 100px;
|
|
661
|
+
font-size: 0.75rem;
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
/* Filter form: compact on mobile */
|
|
665
|
+
.grid[style*="grid-template-columns: 1fr 1fr 2fr"] {
|
|
666
|
+
grid-template-columns: 1fr 1fr !important;
|
|
667
|
+
}
|
|
621
668
|
}
|
|
622
669
|
|
|
623
670
|
/* Small mobile */
|
|
@@ -633,4 +680,25 @@ main > p:first-of-type > a[href="/"]:hover {
|
|
|
633
680
|
article > header {
|
|
634
681
|
padding: var(--space-sm) var(--space-md);
|
|
635
682
|
}
|
|
683
|
+
|
|
684
|
+
/* Stack hero stats to single column on very small screens */
|
|
685
|
+
.hero-stats {
|
|
686
|
+
grid-template-columns: 1fr;
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
/* Bar chart: even narrower labels */
|
|
690
|
+
.bar-chart-label {
|
|
691
|
+
min-width: 80px;
|
|
692
|
+
font-size: 0.7rem;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
/* Quick action buttons: full width stack */
|
|
696
|
+
.quick-actions {
|
|
697
|
+
flex-direction: column;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
.quick-actions a[role="button"] {
|
|
701
|
+
width: 100%;
|
|
702
|
+
text-align: center;
|
|
703
|
+
}
|
|
636
704
|
}
|
|
@@ -94,15 +94,33 @@ function extractMilestones(roadmapContent) {
|
|
|
94
94
|
// Parse explicit milestones: "## Milestone: Name\n\n**Goal:** ...\n**Phases:** N - M"
|
|
95
95
|
const milestoneRegex = /## Milestone:\s*(.+)\n+\*\*Goal:?\*\*:?\s*(.+)\n\*\*Phases:?\*\*:?\s*(\d+)\s*-\s*(\d+)/g;
|
|
96
96
|
const explicit = [];
|
|
97
|
+
const seenNames = new Set();
|
|
97
98
|
for (const match of roadmapContent.matchAll(milestoneRegex)) {
|
|
99
|
+
const name = match[1].trim();
|
|
100
|
+
seenNames.add(name);
|
|
98
101
|
explicit.push({
|
|
99
|
-
name
|
|
102
|
+
name,
|
|
100
103
|
goal: match[2].trim(),
|
|
101
104
|
startPhase: parseInt(match[3], 10),
|
|
102
105
|
endPhase: parseInt(match[4], 10)
|
|
103
106
|
});
|
|
104
107
|
}
|
|
105
108
|
|
|
109
|
+
// Parse completed/collapsed milestones: "## Milestone: Name -- COMPLETED\n\nPhases N-M completed..."
|
|
110
|
+
const completedRegex = /## Milestone:\s*(.+?)\s*--\s*COMPLETED\n+Phases\s+(\d+)-(\d+)\s+completed[^\n]*/g;
|
|
111
|
+
for (const match of roadmapContent.matchAll(completedRegex)) {
|
|
112
|
+
const name = match[1].trim();
|
|
113
|
+
if (seenNames.has(name)) continue; // avoid duplicates
|
|
114
|
+
seenNames.add(name);
|
|
115
|
+
explicit.push({
|
|
116
|
+
name: name + ' (Completed)',
|
|
117
|
+
goal: 'Completed',
|
|
118
|
+
startPhase: parseInt(match[2], 10),
|
|
119
|
+
endPhase: parseInt(match[3], 10),
|
|
120
|
+
completed: true
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
106
124
|
// Sort explicit milestones by start phase
|
|
107
125
|
explicit.sort((a, b) => a.startPhase - b.startPhase);
|
|
108
126
|
|
|
@@ -215,10 +233,6 @@ export async function generateDependencyMermaid(projectDir) {
|
|
|
215
233
|
export async function getRoadmapData(projectDir) {
|
|
216
234
|
const { phases: basePhases } = await parseRoadmapFile(projectDir);
|
|
217
235
|
|
|
218
|
-
if (basePhases.length === 0) {
|
|
219
|
-
return { phases: [], milestones: [] };
|
|
220
|
-
}
|
|
221
|
-
|
|
222
236
|
// Read raw ROADMAP.md for dependencies and milestones
|
|
223
237
|
let dependencyMap = new Map();
|
|
224
238
|
let milestones = [];
|
|
@@ -3,7 +3,7 @@ import { join } from 'node:path';
|
|
|
3
3
|
import matter from 'gray-matter';
|
|
4
4
|
import { readMarkdownFile } from '../repositories/planning.repository.js';
|
|
5
5
|
|
|
6
|
-
const PRIORITY_ORDER = { P0: 0, P1: 1, P2: 2, PX: 3 };
|
|
6
|
+
const PRIORITY_ORDER = { P0: 0, P1: 1, P2: 2, PX: 3, high: 0, medium: 1, low: 2 };
|
|
7
7
|
|
|
8
8
|
class WriteQueue {
|
|
9
9
|
constructor() {
|
|
@@ -105,13 +105,22 @@ export async function listPendingTodos(projectDir, filters = {}) {
|
|
|
105
105
|
for (let i = 0; i < results.length; i++) {
|
|
106
106
|
if (results[i].status !== 'fulfilled') continue;
|
|
107
107
|
|
|
108
|
-
const { frontmatter } = results[i].value;
|
|
108
|
+
const { frontmatter, rawContent } = results[i].value;
|
|
109
109
|
const { filename, fileId } = mdFiles[i];
|
|
110
110
|
|
|
111
|
-
//
|
|
112
|
-
|
|
111
|
+
// Derive title: frontmatter > H1 heading in raw markdown > filename slug
|
|
112
|
+
let title = frontmatter.title;
|
|
113
|
+
if (!title && rawContent) {
|
|
114
|
+
const h1Match = rawContent.match(/^#\s+(.+)$/m);
|
|
115
|
+
if (h1Match) title = h1Match[1].trim();
|
|
116
|
+
}
|
|
117
|
+
if (!title) {
|
|
118
|
+
// Extract from filename: "003-some-slug.md" -> "Some slug"
|
|
119
|
+
const slugMatch = filename.match(/^\d{3}-(.+)\.md$/);
|
|
120
|
+
title = slugMatch ? slugMatch[1].replace(/-/g, ' ').replace(/^\w/, c => c.toUpperCase()) : 'Untitled';
|
|
121
|
+
}
|
|
113
122
|
const priority = frontmatter.priority;
|
|
114
|
-
if (!
|
|
123
|
+
if (!priority) continue;
|
|
115
124
|
|
|
116
125
|
todos.push({
|
|
117
126
|
id: frontmatter.id || fileId,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<h1><%= projectName %></h1>
|
|
3
3
|
|
|
4
4
|
<!-- Hero Stat Row -->
|
|
5
|
-
<div class="
|
|
5
|
+
<div class="hero-stats">
|
|
6
6
|
<!-- Current Phase -->
|
|
7
7
|
<article>
|
|
8
8
|
<header><strong>Current Phase</strong></header>
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
</div>
|
|
55
55
|
|
|
56
56
|
<!-- Quick Actions -->
|
|
57
|
-
<div>
|
|
57
|
+
<div class="quick-actions">
|
|
58
58
|
<% var phaseId = String(currentPhase.id).padStart(2, '0'); %>
|
|
59
59
|
<a role="button" class="outline"
|
|
60
60
|
href="/phases/<%= phaseId %>"
|
|
@@ -2,5 +2,42 @@
|
|
|
2
2
|
<%- include('footer') %>
|
|
3
3
|
</div>
|
|
4
4
|
<script src="/js/sse-client.js"></script>
|
|
5
|
+
<script>
|
|
6
|
+
(function() {
|
|
7
|
+
var sidebar = document.querySelector('.sidebar');
|
|
8
|
+
var backdrop = document.querySelector('.sidebar-backdrop');
|
|
9
|
+
var toggle = document.querySelector('.sidebar-toggle');
|
|
10
|
+
|
|
11
|
+
function openSidebar() {
|
|
12
|
+
sidebar.classList.add('open');
|
|
13
|
+
backdrop.classList.add('open');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function closeSidebar() {
|
|
17
|
+
sidebar.classList.remove('open');
|
|
18
|
+
backdrop.classList.remove('open');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Expose for onclick handler on backdrop
|
|
22
|
+
window.closeSidebar = closeSidebar;
|
|
23
|
+
|
|
24
|
+
if (toggle) {
|
|
25
|
+
toggle.addEventListener('click', function() {
|
|
26
|
+
if (sidebar.classList.contains('open')) { closeSidebar(); } else { openSidebar(); }
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (backdrop) {
|
|
31
|
+
backdrop.addEventListener('click', closeSidebar);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Auto-close sidebar on nav link click (mobile)
|
|
35
|
+
document.querySelectorAll('.sidebar nav a').forEach(function(link) {
|
|
36
|
+
link.addEventListener('click', function() {
|
|
37
|
+
if (window.innerWidth <= 768) closeSidebar();
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
})();
|
|
41
|
+
</script>
|
|
5
42
|
</body>
|
|
6
43
|
</html>
|
|
@@ -1,10 +1,35 @@
|
|
|
1
1
|
<%- include('breadcrumbs', { breadcrumbs: typeof breadcrumbs !== 'undefined' ? breadcrumbs : [] }) %>
|
|
2
2
|
<h1>Project Roadmap</h1>
|
|
3
3
|
|
|
4
|
-
<% if (phases.length === 0) { %>
|
|
4
|
+
<% if (phases.length === 0 && (typeof milestones === 'undefined' || milestones.length === 0)) { %>
|
|
5
5
|
<article>
|
|
6
6
|
<p>No phases found. Add a ROADMAP.md file to your .planning/ directory to see the roadmap here.</p>
|
|
7
7
|
</article>
|
|
8
|
+
<% } else if (phases.length === 0 && typeof milestones !== 'undefined' && milestones.length > 0) { %>
|
|
9
|
+
<!-- All milestones completed — show summary -->
|
|
10
|
+
<article>
|
|
11
|
+
<header><strong>All Milestones Completed</strong></header>
|
|
12
|
+
<p>All phases have been archived into milestones.</p>
|
|
13
|
+
</article>
|
|
14
|
+
<% milestones.forEach(function(ms) { %>
|
|
15
|
+
<article>
|
|
16
|
+
<header>
|
|
17
|
+
<strong><%= ms.name %></strong>
|
|
18
|
+
<% if (ms.startPhase && ms.endPhase) { %>
|
|
19
|
+
<small>(Phases <%= String(ms.startPhase).padStart(2, '0') %>–<%= String(ms.endPhase).padStart(2, '0') %>)</small>
|
|
20
|
+
<% } %>
|
|
21
|
+
—
|
|
22
|
+
<span class="status-badge" data-status="complete">complete</span>
|
|
23
|
+
</header>
|
|
24
|
+
<% if (ms.goal && ms.goal !== 'Completed') { %>
|
|
25
|
+
<p><small><%= ms.goal %></small></p>
|
|
26
|
+
<% } %>
|
|
27
|
+
<p><a href="/milestones"
|
|
28
|
+
hx-get="/milestones"
|
|
29
|
+
hx-target="#main-content"
|
|
30
|
+
hx-push-url="true">View in Milestones</a></p>
|
|
31
|
+
</article>
|
|
32
|
+
<% }); %>
|
|
8
33
|
<% } else { %>
|
|
9
34
|
|
|
10
35
|
<%
|
|
@@ -14,6 +14,9 @@
|
|
|
14
14
|
Priority
|
|
15
15
|
<select name="priority" onchange="this.form.requestSubmit()">
|
|
16
16
|
<option value="">All</option>
|
|
17
|
+
<option value="high"<%= f.priority === 'high' ? ' selected' : '' %>>High</option>
|
|
18
|
+
<option value="medium"<%= f.priority === 'medium' ? ' selected' : '' %>>Medium</option>
|
|
19
|
+
<option value="low"<%= f.priority === 'low' ? ' selected' : '' %>>Low</option>
|
|
17
20
|
<option value="P0"<%= f.priority === 'P0' ? ' selected' : '' %>>P0</option>
|
|
18
21
|
<option value="P1"<%= f.priority === 'P1' ? ' selected' : '' %>>P1</option>
|
|
19
22
|
<option value="P2"<%= f.priority === 'P2' ? ' selected' : '' %>>P2</option>
|
package/package.json
CHANGED
|
@@ -119,7 +119,16 @@ When you need human input, emit a checkpoint block. Always include `Debug file:`
|
|
|
119
119
|
|
|
120
120
|
**CRITICAL — DO NOT SKIP steps 5-8. Uncommitted fixes and unupdated debug files cause state corruption on resume.**
|
|
121
121
|
|
|
122
|
-
**
|
|
122
|
+
**CRITICAL — NEVER apply fixes without user approval.** After identifying the root cause and planning the fix, you MUST present your findings and proposed changes to the user, then wait for explicit confirmation before writing any code. Set debug status to `self-verified` while awaiting approval. Only proceed to `fixing` after the user approves.
|
|
123
|
+
|
|
124
|
+
Present to the user:
|
|
125
|
+
1. Root cause and mechanism
|
|
126
|
+
2. Proposed fix (files to change, what changes)
|
|
127
|
+
3. Predicted outcome and risk assessment
|
|
128
|
+
|
|
129
|
+
Then emit a `DECISION` checkpoint asking the user to approve, modify, or reject the fix.
|
|
130
|
+
|
|
131
|
+
**Steps**: Verify root cause → plan minimal fix → predict outcome → **present to user and wait for approval** → implement → verify → check regressions → commit → update debug file.
|
|
123
132
|
|
|
124
133
|
**Guidelines**: Minimal change (root cause, not symptoms). One atomic commit. No refactoring or features. Test the fix.
|
|
125
134
|
|
|
@@ -156,6 +165,7 @@ Reference: `references/common-bug-patterns.md` — covers off-by-one, null/undef
|
|
|
156
165
|
6. DO NOT assume first hypothesis is correct or fight contradicting evidence
|
|
157
166
|
7. DO NOT spend too long on one hypothesis — if inconclusive, move on
|
|
158
167
|
8. DO NOT trust error messages at face value — may be a deeper symptom
|
|
168
|
+
9. DO NOT apply fixes without explicit user approval — present findings first, wait for confirmation
|
|
159
169
|
|
|
160
170
|
## Context Budget
|
|
161
171
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: plan-checker
|
|
3
|
-
description: "Verifies plans will achieve phase goals before execution. Goal-backward analysis of plan quality across
|
|
3
|
+
description: "Verifies plans will achieve phase goals before execution. Goal-backward analysis of plan quality across 10 dimensions."
|
|
4
4
|
tools: ["read", "search"]
|
|
5
5
|
infer: true
|
|
6
6
|
target: "github-copilot"
|
|
@@ -31,7 +31,7 @@ You receive: (1) plan files to check, (2) phase goal or directory path, (3) opti
|
|
|
31
31
|
|
|
32
32
|
---
|
|
33
33
|
|
|
34
|
-
## The
|
|
34
|
+
## The 10 Verification Dimensions
|
|
35
35
|
|
|
36
36
|
### D1: Requirement Coverage
|
|
37
37
|
Plan tasks must cover all must-haves from frontmatter (`truths`, `artifacts`, `key_links`). Each must-have needs at least one task's `<done>` mapping.
|
|
@@ -127,6 +127,15 @@ Plans declare `requirement_ids` with bidirectional coverage. Forward: IDs trace
|
|
|
127
127
|
| ROADMAP goal not covered (no REQUIREMENTS.md) | WARNING |
|
|
128
128
|
| Plan missing requirement_ids entirely | INFO |
|
|
129
129
|
|
|
130
|
+
### D10: Test Plan Coverage
|
|
131
|
+
Code-producing tasks should include test expectations. Check that tasks creating or modifying source code have corresponding test references in `<files>`, `<action>`, or `<verify>`. Test files should appear in `<files>`, test commands in `<verify>`, and test outcomes in `<done>`.
|
|
132
|
+
|
|
133
|
+
| Condition | Severity |
|
|
134
|
+
|-----------|----------|
|
|
135
|
+
| Code task with no test file in `<files>` and no test command in `<verify>` | WARNING |
|
|
136
|
+
| Task creates new module but no corresponding test file planned | WARNING |
|
|
137
|
+
| `<verify>` uses only file-existence checks, no test runner | INFO |
|
|
138
|
+
|
|
130
139
|
---
|
|
131
140
|
|
|
132
141
|
## Verification Process
|
|
@@ -134,7 +143,7 @@ Plans declare `requirement_ids` with bidirectional coverage. Forward: IDs trace
|
|
|
134
143
|
1. **Load Plans** — Read all plan files. Parse YAML frontmatter and XML tasks. Use `node ${CLAUDE_PLUGIN_ROOT}/scripts/pbr-tools.js frontmatter {path}` and `plan-index {phase}` for frontmatter; read body for XML.
|
|
135
144
|
2. **Load Context** — If CONTEXT.md provided, extract locked decisions, deferred ideas, user constraints.
|
|
136
145
|
3. **Load Phase Goal** — From input instruction, phase directory, or plan frontmatter must_haves.
|
|
137
|
-
4. **Run All
|
|
146
|
+
4. **Run All 10 Dimensions** — Evaluate each plan against all dimensions. Collect issues.
|
|
138
147
|
5. **Cross-Plan Checks** — File conflicts between same-wave plans, circular cross-plan deps, phase goal coverage, duplicate task content.
|
|
139
148
|
6. **Compile Report** — Produce output in format below.
|
|
140
149
|
|
|
@@ -144,7 +153,7 @@ Plans declare `requirement_ids` with bidirectional coverage. Forward: IDs trace
|
|
|
144
153
|
|
|
145
154
|
```
|
|
146
155
|
VERIFICATION PASSED
|
|
147
|
-
Plans: {count} | Tasks: {count} | Dimensions:
|
|
156
|
+
Plans: {count} | Tasks: {count} | Dimensions: 10 | Issues: 0
|
|
148
157
|
```
|
|
149
158
|
|
|
150
159
|
Or when issues found:
|
|
@@ -170,7 +179,7 @@ Plans: {count} | Tasks: {count} | Blockers: {count} | Warnings: {count} | Info:
|
|
|
170
179
|
- **Single-task plan**: WARNING on D5. May be too coarse; consider splitting.
|
|
171
180
|
- **No CONTEXT.md**: Skip D7. Note "D7 skipped: no CONTEXT.md found".
|
|
172
181
|
- **Checkpoint tasks**: `human-verify` → verify describes what to look at. `decision` → lists options. `human-action` → describes action.
|
|
173
|
-
- **TDD tasks**: WARNING if verify lacks a test command.
|
|
182
|
+
- **TDD tasks**: See D10. WARNING if verify lacks a test command.
|
|
174
183
|
|
|
175
184
|
---
|
|
176
185
|
|
|
@@ -193,7 +202,7 @@ Plans: {count} | Tasks: {count} | Blockers: {count} | Warnings: {count} | Info:
|
|
|
193
202
|
2. DO NOT suggest alternative architectures — focus on plan quality
|
|
194
203
|
3. DO NOT invent requirements not in the phase goal or must-haves
|
|
195
204
|
4. DO NOT be lenient on blockers — if it's a blocker, flag it
|
|
196
|
-
5. DO NOT nitpick working plans — if all
|
|
205
|
+
5. DO NOT nitpick working plans — if all 10 dimensions pass, say PASSED
|
|
197
206
|
6. DO NOT check code quality — you check PLAN quality
|
|
198
207
|
7. DO NOT verify that technologies are correct — that's the researcher's job
|
|
199
208
|
8. DO NOT evaluate the phase goal itself — only whether the plan achieves it
|
|
@@ -139,6 +139,19 @@
|
|
|
139
139
|
]
|
|
140
140
|
}
|
|
141
141
|
],
|
|
142
|
+
"configChange": [
|
|
143
|
+
{
|
|
144
|
+
"hooks": [
|
|
145
|
+
{
|
|
146
|
+
"type": "command",
|
|
147
|
+
"bash": "node \"$(cd \"$(dirname \"$0\")\" && pwd)/../../pbr/scripts/run-hook.js\" check-config-change.js",
|
|
148
|
+
"powershell": "node (Join-Path (Split-Path -Parent $PSScriptRoot) 'pbr\\scripts\\run-hook.js') check-config-change.js",
|
|
149
|
+
"cwd": ".",
|
|
150
|
+
"timeoutSec": 15
|
|
151
|
+
}
|
|
152
|
+
]
|
|
153
|
+
}
|
|
154
|
+
],
|
|
142
155
|
"sessionEnd": [
|
|
143
156
|
{
|
|
144
157
|
"hooks": [
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pbr",
|
|
3
3
|
"displayName": "Plan-Build-Run",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.20.0",
|
|
5
5
|
"description": "Plan-Build-Run — Structured development workflow for GitHub Copilot CLI. Solves context rot through disciplined agent delegation, structured planning, atomic execution, and goal-backward verification.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "SienkLogic",
|
|
@@ -117,7 +117,7 @@ requirement_ids: []
|
|
|
117
117
|
|
|
118
118
|
### Expected Input
|
|
119
119
|
|
|
120
|
-
Plan-Checker reads plan frontmatter + XML tasks and evaluates across
|
|
120
|
+
Plan-Checker reads plan frontmatter + XML tasks and evaluates across 10 dimensions (D1-D10). Optionally receives CONTEXT.md path.
|
|
121
121
|
|
|
122
122
|
### Output Format
|
|
123
123
|
|
|
@@ -168,6 +168,15 @@ After running all 10 checks and collecting results, if any of the following auto
|
|
|
168
168
|
|
|
169
169
|
After displaying health check results, if any auto-fixable issues were detected:
|
|
170
170
|
|
|
171
|
+
**CRITICAL — Before ANY auto-fix that modifies or regenerates STATE.md (frontmatter regeneration, phase_slug correction, or line compaction), you MUST create a timestamped backup first. DO NOT SKIP THIS STEP.**
|
|
172
|
+
|
|
173
|
+
```
|
|
174
|
+
mkdir -p .planning/backups
|
|
175
|
+
cp .planning/STATE.md .planning/backups/STATE-$(date +%Y%m%dT%H%M%S).md
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
This ensures the user can recover the original STATE.md if the fix produces incorrect results.
|
|
179
|
+
|
|
171
180
|
1. Count the auto-fixable issues and present:
|
|
172
181
|
|
|
173
182
|
Use AskUserQuestion:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pbr",
|
|
3
3
|
"displayName": "Plan-Build-Run",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.20.0",
|
|
5
5
|
"description": "Plan-Build-Run — Structured development workflow for Cursor. Solves context rot through disciplined subagent delegation, structured planning, atomic execution, and goal-backward verification.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "SienkLogic",
|
|
@@ -118,7 +118,16 @@ When you need human input, emit a checkpoint block. Always include `Debug file:`
|
|
|
118
118
|
|
|
119
119
|
**CRITICAL — DO NOT SKIP steps 5-8. Uncommitted fixes and unupdated debug files cause state corruption on resume.**
|
|
120
120
|
|
|
121
|
-
**
|
|
121
|
+
**CRITICAL — NEVER apply fixes without user approval.** After identifying the root cause and planning the fix, you MUST present your findings and proposed changes to the user, then wait for explicit confirmation before writing any code. Set debug status to `self-verified` while awaiting approval. Only proceed to `fixing` after the user approves.
|
|
122
|
+
|
|
123
|
+
Present to the user:
|
|
124
|
+
1. Root cause and mechanism
|
|
125
|
+
2. Proposed fix (files to change, what changes)
|
|
126
|
+
3. Predicted outcome and risk assessment
|
|
127
|
+
|
|
128
|
+
Then emit a `DECISION` checkpoint asking the user to approve, modify, or reject the fix.
|
|
129
|
+
|
|
130
|
+
**Steps**: Verify root cause → plan minimal fix → predict outcome → **present to user and wait for approval** → implement → verify → check regressions → commit → update debug file.
|
|
122
131
|
|
|
123
132
|
**Guidelines**: Minimal change (root cause, not symptoms). One atomic commit. No refactoring or features. Test the fix.
|
|
124
133
|
|
|
@@ -155,6 +164,7 @@ Reference: `references/common-bug-patterns.md` — covers off-by-one, null/undef
|
|
|
155
164
|
6. DO NOT assume first hypothesis is correct or fight contradicting evidence
|
|
156
165
|
7. DO NOT spend too long on one hypothesis — if inconclusive, move on
|
|
157
166
|
8. DO NOT trust error messages at face value — may be a deeper symptom
|
|
167
|
+
9. DO NOT apply fixes without explicit user approval — present findings first, wait for confirmation
|
|
158
168
|
|
|
159
169
|
## Context Budget
|
|
160
170
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: plan-checker
|
|
3
|
-
description: "Verifies plans will achieve phase goals before execution. Goal-backward analysis of plan quality across
|
|
3
|
+
description: "Verifies plans will achieve phase goals before execution. Goal-backward analysis of plan quality across 10 dimensions."
|
|
4
4
|
model: sonnet
|
|
5
5
|
readonly: true
|
|
6
6
|
---
|
|
@@ -30,7 +30,7 @@ You receive: (1) plan files to check, (2) phase goal or directory path, (3) opti
|
|
|
30
30
|
|
|
31
31
|
---
|
|
32
32
|
|
|
33
|
-
## The
|
|
33
|
+
## The 10 Verification Dimensions
|
|
34
34
|
|
|
35
35
|
### D1: Requirement Coverage
|
|
36
36
|
Plan tasks must cover all must-haves from frontmatter (`truths`, `artifacts`, `key_links`). Each must-have needs at least one task's `<done>` mapping.
|
|
@@ -126,6 +126,15 @@ Plans declare `requirement_ids` with bidirectional coverage. Forward: IDs trace
|
|
|
126
126
|
| ROADMAP goal not covered (no REQUIREMENTS.md) | WARNING |
|
|
127
127
|
| Plan missing requirement_ids entirely | INFO |
|
|
128
128
|
|
|
129
|
+
### D10: Test Plan Coverage
|
|
130
|
+
Code-producing tasks should include test expectations. Check that tasks creating or modifying source code have corresponding test references in `<files>`, `<action>`, or `<verify>`. Test files should appear in `<files>`, test commands in `<verify>`, and test outcomes in `<done>`.
|
|
131
|
+
|
|
132
|
+
| Condition | Severity |
|
|
133
|
+
|-----------|----------|
|
|
134
|
+
| Code task with no test file in `<files>` and no test command in `<verify>` | WARNING |
|
|
135
|
+
| Task creates new module but no corresponding test file planned | WARNING |
|
|
136
|
+
| `<verify>` uses only file-existence checks, no test runner | INFO |
|
|
137
|
+
|
|
129
138
|
---
|
|
130
139
|
|
|
131
140
|
## Verification Process
|
|
@@ -133,7 +142,7 @@ Plans declare `requirement_ids` with bidirectional coverage. Forward: IDs trace
|
|
|
133
142
|
1. **Load Plans** — Read all plan files. Parse YAML frontmatter and XML tasks. Use `node ${CLAUDE_PLUGIN_ROOT}/scripts/pbr-tools.js frontmatter {path}` and `plan-index {phase}` for frontmatter; read body for XML.
|
|
134
143
|
2. **Load Context** — If CONTEXT.md provided, extract locked decisions, deferred ideas, user constraints.
|
|
135
144
|
3. **Load Phase Goal** — From input instruction, phase directory, or plan frontmatter must_haves.
|
|
136
|
-
4. **Run All
|
|
145
|
+
4. **Run All 10 Dimensions** — Evaluate each plan against all dimensions. Collect issues.
|
|
137
146
|
5. **Cross-Plan Checks** — File conflicts between same-wave plans, circular cross-plan deps, phase goal coverage, duplicate task content.
|
|
138
147
|
6. **Compile Report** — Produce output in format below.
|
|
139
148
|
|
|
@@ -143,7 +152,7 @@ Plans declare `requirement_ids` with bidirectional coverage. Forward: IDs trace
|
|
|
143
152
|
|
|
144
153
|
```
|
|
145
154
|
VERIFICATION PASSED
|
|
146
|
-
Plans: {count} | Tasks: {count} | Dimensions:
|
|
155
|
+
Plans: {count} | Tasks: {count} | Dimensions: 10 | Issues: 0
|
|
147
156
|
```
|
|
148
157
|
|
|
149
158
|
Or when issues found:
|
|
@@ -169,7 +178,7 @@ Plans: {count} | Tasks: {count} | Blockers: {count} | Warnings: {count} | Info:
|
|
|
169
178
|
- **Single-task plan**: WARNING on D5. May be too coarse; consider splitting.
|
|
170
179
|
- **No CONTEXT.md**: Skip D7. Note "D7 skipped: no CONTEXT.md found".
|
|
171
180
|
- **Checkpoint tasks**: `human-verify` → verify describes what to look at. `decision` → lists options. `human-action` → describes action.
|
|
172
|
-
- **TDD tasks**: WARNING if verify lacks a test command.
|
|
181
|
+
- **TDD tasks**: See D10. WARNING if verify lacks a test command.
|
|
173
182
|
|
|
174
183
|
---
|
|
175
184
|
|
|
@@ -192,7 +201,7 @@ Plans: {count} | Tasks: {count} | Blockers: {count} | Warnings: {count} | Info:
|
|
|
192
201
|
2. DO NOT suggest alternative architectures — focus on plan quality
|
|
193
202
|
3. DO NOT invent requirements not in the phase goal or must-haves
|
|
194
203
|
4. DO NOT be lenient on blockers — if it's a blocker, flag it
|
|
195
|
-
5. DO NOT nitpick working plans — if all
|
|
204
|
+
5. DO NOT nitpick working plans — if all 10 dimensions pass, say PASSED
|
|
196
205
|
6. DO NOT check code quality — you check PLAN quality
|
|
197
206
|
7. DO NOT verify that technologies are correct — that's the researcher's job
|
|
198
207
|
8. DO NOT evaluate the phase goal itself — only whether the plan achieves it
|
|
@@ -196,6 +196,17 @@
|
|
|
196
196
|
]
|
|
197
197
|
}
|
|
198
198
|
],
|
|
199
|
+
"ConfigChange": [
|
|
200
|
+
{
|
|
201
|
+
"hooks": [
|
|
202
|
+
{
|
|
203
|
+
"type": "command",
|
|
204
|
+
"command": "node -e \"var r=process.env.CLAUDE_PLUGIN_ROOT||'',m=r.match(/^\\/([a-zA-Z])\\/(.*)/);if(m)r=m[1]+String.fromCharCode(58)+String.fromCharCode(92)+m[2];require(require('path').resolve(r,'..','pbr','scripts','run-hook.js'))\" check-config-change.js",
|
|
205
|
+
"statusMessage": "Validating configuration..."
|
|
206
|
+
}
|
|
207
|
+
]
|
|
208
|
+
}
|
|
209
|
+
],
|
|
199
210
|
"SessionEnd": [
|
|
200
211
|
{
|
|
201
212
|
"hooks": [
|
|
@@ -117,7 +117,7 @@ requirement_ids: []
|
|
|
117
117
|
|
|
118
118
|
### Expected Input
|
|
119
119
|
|
|
120
|
-
Plan-Checker reads plan frontmatter + XML tasks and evaluates across
|
|
120
|
+
Plan-Checker reads plan frontmatter + XML tasks and evaluates across 10 dimensions (D1-D10). Optionally receives CONTEXT.md path.
|
|
121
121
|
|
|
122
122
|
### Output Format
|
|
123
123
|
|
|
@@ -168,6 +168,15 @@ After running all 10 checks and collecting results, if any of the following auto
|
|
|
168
168
|
|
|
169
169
|
After displaying health check results, if any auto-fixable issues were detected:
|
|
170
170
|
|
|
171
|
+
**CRITICAL — Before ANY auto-fix that modifies or regenerates STATE.md (frontmatter regeneration, phase_slug correction, or line compaction), you MUST create a timestamped backup first. DO NOT SKIP THIS STEP.**
|
|
172
|
+
|
|
173
|
+
```
|
|
174
|
+
mkdir -p .planning/backups
|
|
175
|
+
cp .planning/STATE.md .planning/backups/STATE-$(date +%Y%m%dT%H%M%S).md
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
This ensures the user can recover the original STATE.md if the fix produces incorrect results.
|
|
179
|
+
|
|
171
180
|
1. Count the auto-fixable issues and present:
|
|
172
181
|
|
|
173
182
|
Use AskUserQuestion:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pbr",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.20.0",
|
|
4
4
|
"description": "Plan-Build-Run — Structured development workflow for Claude Code. Solves context rot through disciplined subagent delegation, structured planning, atomic execution, and goal-backward verification.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "SienkLogic",
|
|
@@ -125,7 +125,16 @@ When you need human input, emit a checkpoint block. Always include `Debug file:`
|
|
|
125
125
|
|
|
126
126
|
**CRITICAL — DO NOT SKIP steps 5-8. Uncommitted fixes and unupdated debug files cause state corruption on resume.**
|
|
127
127
|
|
|
128
|
-
**
|
|
128
|
+
**CRITICAL — NEVER apply fixes without user approval.** After identifying the root cause and planning the fix, you MUST present your findings and proposed changes to the user, then wait for explicit confirmation before writing any code. Set debug status to `self-verified` while awaiting approval. Only proceed to `fixing` after the user approves.
|
|
129
|
+
|
|
130
|
+
Present to the user:
|
|
131
|
+
1. Root cause and mechanism
|
|
132
|
+
2. Proposed fix (files to change, what changes)
|
|
133
|
+
3. Predicted outcome and risk assessment
|
|
134
|
+
|
|
135
|
+
Then emit a `DECISION` checkpoint asking the user to approve, modify, or reject the fix.
|
|
136
|
+
|
|
137
|
+
**Steps**: Verify root cause → plan minimal fix → predict outcome → **present to user and wait for approval** → implement → verify → check regressions → commit → update debug file.
|
|
129
138
|
|
|
130
139
|
**Guidelines**: Minimal change (root cause, not symptoms). One atomic commit. No refactoring or features. Test the fix.
|
|
131
140
|
|
|
@@ -162,6 +171,7 @@ Reference: `references/common-bug-patterns.md` — covers off-by-one, null/undef
|
|
|
162
171
|
6. DO NOT assume first hypothesis is correct or fight contradicting evidence
|
|
163
172
|
7. DO NOT spend too long on one hypothesis — if inconclusive, move on
|
|
164
173
|
8. DO NOT trust error messages at face value — may be a deeper symptom
|
|
174
|
+
9. DO NOT apply fixes without explicit user approval — present findings first, wait for confirmation
|
|
165
175
|
|
|
166
176
|
## Context Budget
|
|
167
177
|
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: plan-checker
|
|
3
|
-
description: "Verifies plans will achieve phase goals before execution. Goal-backward analysis of plan quality across
|
|
3
|
+
description: "Verifies plans will achieve phase goals before execution. Goal-backward analysis of plan quality across 10 dimensions."
|
|
4
4
|
model: sonnet
|
|
5
5
|
memory: none
|
|
6
|
+
isolation: worktree
|
|
6
7
|
tools:
|
|
7
8
|
- Read
|
|
8
9
|
- Bash
|
|
@@ -35,7 +36,7 @@ You receive: (1) plan files to check, (2) phase goal or directory path, (3) opti
|
|
|
35
36
|
|
|
36
37
|
---
|
|
37
38
|
|
|
38
|
-
## The
|
|
39
|
+
## The 10 Verification Dimensions
|
|
39
40
|
|
|
40
41
|
### D1: Requirement Coverage
|
|
41
42
|
Plan tasks must cover all must-haves from frontmatter (`truths`, `artifacts`, `key_links`). Each must-have needs at least one task's `<done>` mapping.
|
|
@@ -131,6 +132,15 @@ Plans declare `requirement_ids` with bidirectional coverage. Forward: IDs trace
|
|
|
131
132
|
| ROADMAP goal not covered (no REQUIREMENTS.md) | WARNING |
|
|
132
133
|
| Plan missing requirement_ids entirely | INFO |
|
|
133
134
|
|
|
135
|
+
### D10: Test Plan Coverage
|
|
136
|
+
Code-producing tasks should include test expectations. Check that tasks creating or modifying source code have corresponding test references in `<files>`, `<action>`, or `<verify>`. Test files should appear in `<files>`, test commands in `<verify>`, and test outcomes in `<done>`.
|
|
137
|
+
|
|
138
|
+
| Condition | Severity |
|
|
139
|
+
|-----------|----------|
|
|
140
|
+
| Code task with no test file in `<files>` and no test command in `<verify>` | WARNING |
|
|
141
|
+
| Task creates new module but no corresponding test file planned | WARNING |
|
|
142
|
+
| `<verify>` uses only file-existence checks, no test runner | INFO |
|
|
143
|
+
|
|
134
144
|
---
|
|
135
145
|
|
|
136
146
|
## Verification Process
|
|
@@ -138,7 +148,7 @@ Plans declare `requirement_ids` with bidirectional coverage. Forward: IDs trace
|
|
|
138
148
|
1. **Load Plans** — Read all plan files. Parse YAML frontmatter and XML tasks. Use `node ${CLAUDE_PLUGIN_ROOT}/scripts/pbr-tools.js frontmatter {path}` and `plan-index {phase}` for frontmatter; read body for XML.
|
|
139
149
|
2. **Load Context** — If CONTEXT.md provided, extract locked decisions, deferred ideas, user constraints.
|
|
140
150
|
3. **Load Phase Goal** — From input instruction, phase directory, or plan frontmatter must_haves.
|
|
141
|
-
4. **Run All
|
|
151
|
+
4. **Run All 10 Dimensions** — Evaluate each plan against all dimensions. Collect issues.
|
|
142
152
|
5. **Cross-Plan Checks** — File conflicts between same-wave plans, circular cross-plan deps, phase goal coverage, duplicate task content.
|
|
143
153
|
6. **Compile Report** — Produce output in format below.
|
|
144
154
|
|
|
@@ -148,7 +158,7 @@ Plans declare `requirement_ids` with bidirectional coverage. Forward: IDs trace
|
|
|
148
158
|
|
|
149
159
|
```
|
|
150
160
|
VERIFICATION PASSED
|
|
151
|
-
Plans: {count} | Tasks: {count} | Dimensions:
|
|
161
|
+
Plans: {count} | Tasks: {count} | Dimensions: 10 | Issues: 0
|
|
152
162
|
```
|
|
153
163
|
|
|
154
164
|
Or when issues found:
|
|
@@ -174,7 +184,7 @@ Plans: {count} | Tasks: {count} | Blockers: {count} | Warnings: {count} | Info:
|
|
|
174
184
|
- **Single-task plan**: WARNING on D5. May be too coarse; consider splitting.
|
|
175
185
|
- **No CONTEXT.md**: Skip D7. Note "D7 skipped: no CONTEXT.md found".
|
|
176
186
|
- **Checkpoint tasks**: `human-verify` → verify describes what to look at. `decision` → lists options. `human-action` → describes action.
|
|
177
|
-
- **TDD tasks**: WARNING if verify lacks a test command.
|
|
187
|
+
- **TDD tasks**: See D10. WARNING if verify lacks a test command.
|
|
178
188
|
|
|
179
189
|
---
|
|
180
190
|
|
|
@@ -197,7 +207,7 @@ Plans: {count} | Tasks: {count} | Blockers: {count} | Warnings: {count} | Info:
|
|
|
197
207
|
2. DO NOT suggest alternative architectures — focus on plan quality
|
|
198
208
|
3. DO NOT invent requirements not in the phase goal or must-haves
|
|
199
209
|
4. DO NOT be lenient on blockers — if it's a blocker, flag it
|
|
200
|
-
5. DO NOT nitpick working plans — if all
|
|
210
|
+
5. DO NOT nitpick working plans — if all 10 dimensions pass, say PASSED
|
|
201
211
|
6. DO NOT check code quality — you check PLAN quality
|
|
202
212
|
7. DO NOT verify that technologies are correct — that's the researcher's job
|
|
203
213
|
8. DO NOT evaluate the phase goal itself — only whether the plan achieves it
|
|
@@ -192,6 +192,17 @@
|
|
|
192
192
|
]
|
|
193
193
|
}
|
|
194
194
|
],
|
|
195
|
+
"ConfigChange": [
|
|
196
|
+
{
|
|
197
|
+
"hooks": [
|
|
198
|
+
{
|
|
199
|
+
"type": "command",
|
|
200
|
+
"command": "node -e \"var r=process.env.CLAUDE_PLUGIN_ROOT||'',m=r.match(/^\\/([a-zA-Z])\\/(.*)/);if(m)r=m[1]+String.fromCharCode(58)+String.fromCharCode(92)+m[2];require(require('path').resolve(r,'scripts','run-hook.js'))\" check-config-change.js",
|
|
201
|
+
"statusMessage": "Validating configuration..."
|
|
202
|
+
}
|
|
203
|
+
]
|
|
204
|
+
}
|
|
205
|
+
],
|
|
195
206
|
"SessionEnd": [
|
|
196
207
|
{
|
|
197
208
|
"hooks": [
|
|
@@ -117,7 +117,7 @@ requirement_ids: []
|
|
|
117
117
|
|
|
118
118
|
### Expected Input
|
|
119
119
|
|
|
120
|
-
Plan-Checker reads plan frontmatter + XML tasks and evaluates across
|
|
120
|
+
Plan-Checker reads plan frontmatter + XML tasks and evaluates across 10 dimensions (D1-D10). Optionally receives CONTEXT.md path.
|
|
121
121
|
|
|
122
122
|
### Output Format
|
|
123
123
|
|
|
@@ -91,13 +91,19 @@ function main() {
|
|
|
91
91
|
process.exit(0);
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
|
|
94
|
+
// Extract last_assistant_message for richer continuation context
|
|
95
|
+
const lastMsg = hookInput.last_assistant_message || '';
|
|
96
|
+
const msgSuffix = lastMsg
|
|
97
|
+
? ` (last message excerpt: ${lastMsg.slice(0, 200)})`
|
|
98
|
+
: '';
|
|
99
|
+
|
|
100
|
+
logHook('auto-continue', 'Stop', 'continue', { next: nextCommand, hasLastMsg: !!lastMsg });
|
|
95
101
|
|
|
96
102
|
// Block the stop and inject the next command as Claude's continuation reason.
|
|
97
103
|
// Claude Code Stop hooks use { decision: "block", reason: "..." } to keep going.
|
|
98
104
|
const output = {
|
|
99
105
|
decision: 'block',
|
|
100
|
-
reason: `Auto-continue: execute ${nextCommand}`
|
|
106
|
+
reason: `Auto-continue: execute ${nextCommand}${msgSuffix}`
|
|
101
107
|
};
|
|
102
108
|
process.stdout.write(JSON.stringify(output));
|
|
103
109
|
process.exit(0);
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ConfigChange hook: Validates config.json changes and warns about inconsistencies.
|
|
5
|
+
*
|
|
6
|
+
* Fires when Claude Code detects configuration file changes (v2.1.49+).
|
|
7
|
+
* Checks .planning/config.json for:
|
|
8
|
+
* - Required top-level keys
|
|
9
|
+
* - Semantic conflicts (e.g., parallel agents enabled with max=1)
|
|
10
|
+
* - Version field presence
|
|
11
|
+
*
|
|
12
|
+
* Exit codes:
|
|
13
|
+
* 0 = always (advisory hook, never blocks)
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const fs = require('fs');
|
|
17
|
+
const path = require('path');
|
|
18
|
+
const { logHook } = require('./hook-logger');
|
|
19
|
+
const { logEvent } = require('./event-logger');
|
|
20
|
+
|
|
21
|
+
function readStdin() {
|
|
22
|
+
return new Promise((resolve) => {
|
|
23
|
+
let input = '';
|
|
24
|
+
process.stdin.setEncoding('utf8');
|
|
25
|
+
process.stdin.on('data', (chunk) => { input += chunk; });
|
|
26
|
+
process.stdin.on('end', () => {
|
|
27
|
+
try {
|
|
28
|
+
resolve(JSON.parse(input));
|
|
29
|
+
} catch (_e) {
|
|
30
|
+
resolve({});
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function findPlanningDir() {
|
|
37
|
+
let dir = process.cwd();
|
|
38
|
+
const root = path.parse(dir).root;
|
|
39
|
+
while (dir !== root) {
|
|
40
|
+
const candidate = path.join(dir, '.planning');
|
|
41
|
+
if (fs.existsSync(candidate)) return candidate;
|
|
42
|
+
dir = path.dirname(dir);
|
|
43
|
+
}
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function validateConfig(configPath) {
|
|
48
|
+
const warnings = [];
|
|
49
|
+
|
|
50
|
+
let config;
|
|
51
|
+
try {
|
|
52
|
+
const raw = fs.readFileSync(configPath, 'utf8');
|
|
53
|
+
config = JSON.parse(raw);
|
|
54
|
+
} catch (e) {
|
|
55
|
+
warnings.push(`config.json parse error: ${e.message}`);
|
|
56
|
+
return warnings;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Check required top-level keys
|
|
60
|
+
const requiredKeys = ['version', 'features', 'models', 'gates'];
|
|
61
|
+
for (const key of requiredKeys) {
|
|
62
|
+
if (!(key in config)) {
|
|
63
|
+
warnings.push(`Missing required key: ${key}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Check version
|
|
68
|
+
if (config.version && config.version < 2) {
|
|
69
|
+
warnings.push(`Config version ${config.version} is outdated — expected version 2+`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Check semantic conflicts
|
|
73
|
+
if (config.parallelization) {
|
|
74
|
+
const p = config.parallelization;
|
|
75
|
+
if (p.enabled && p.max_concurrent_agents === 1) {
|
|
76
|
+
warnings.push('Semantic conflict: parallelization.enabled=true but max_concurrent_agents=1');
|
|
77
|
+
}
|
|
78
|
+
if (!p.enabled && (p.plan_level || p.task_level)) {
|
|
79
|
+
warnings.push('Semantic conflict: parallelization.enabled=false but plan_level/task_level are true');
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Check model values
|
|
84
|
+
if (config.models) {
|
|
85
|
+
const validModels = ['sonnet', 'opus', 'haiku', 'inherit'];
|
|
86
|
+
for (const [role, model] of Object.entries(config.models)) {
|
|
87
|
+
if (!validModels.includes(model)) {
|
|
88
|
+
warnings.push(`Invalid model "${model}" for ${role} — expected: ${validModels.join(', ')}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return warnings;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async function main() {
|
|
97
|
+
await readStdin();
|
|
98
|
+
const startTime = Date.now();
|
|
99
|
+
|
|
100
|
+
const planningDir = findPlanningDir();
|
|
101
|
+
if (!planningDir) {
|
|
102
|
+
logHook('check-config-change', 'ConfigChange', 'skip', { reason: 'no .planning dir' }, startTime);
|
|
103
|
+
process.exit(0);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const configPath = path.join(planningDir, 'config.json');
|
|
107
|
+
if (!fs.existsSync(configPath)) {
|
|
108
|
+
logHook('check-config-change', 'ConfigChange', 'skip', { reason: 'no config.json' }, startTime);
|
|
109
|
+
process.exit(0);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const warnings = validateConfig(configPath);
|
|
113
|
+
|
|
114
|
+
if (warnings.length > 0) {
|
|
115
|
+
const msg = `⚠️ Config validation (${warnings.length} issue${warnings.length > 1 ? 's' : ''}):\n${warnings.map(w => ` - ${w}`).join('\n')}`;
|
|
116
|
+
|
|
117
|
+
logHook('check-config-change', 'ConfigChange', 'warn', { warnings }, startTime);
|
|
118
|
+
logEvent('workflow', 'config-change', { warnings });
|
|
119
|
+
|
|
120
|
+
process.stdout.write(JSON.stringify({ additionalContext: msg }));
|
|
121
|
+
} else {
|
|
122
|
+
logHook('check-config-change', 'ConfigChange', 'ok', {}, startTime);
|
|
123
|
+
logEvent('workflow', 'config-change', { status: 'valid' });
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
process.exit(0);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (require.main === module || process.argv[1] === __filename) main();
|
|
130
|
+
module.exports = { validateConfig, findPlanningDir };
|
|
@@ -140,8 +140,19 @@ function main() {
|
|
|
140
140
|
|
|
141
141
|
writeAutoVerifySignal(planningDir, stateInfo.phase);
|
|
142
142
|
|
|
143
|
+
// Extract last_assistant_message for verification context hints
|
|
144
|
+
const lastMsg = data.last_assistant_message || '';
|
|
145
|
+
let verifyHint = '';
|
|
146
|
+
if (lastMsg) {
|
|
147
|
+
// Look for error/failure indicators that might inform verification priority
|
|
148
|
+
const lowerMsg = lastMsg.toLowerCase();
|
|
149
|
+
if (lowerMsg.includes('error') || lowerMsg.includes('failed') || lowerMsg.includes('warning')) {
|
|
150
|
+
verifyHint = ' Note: executor output mentions errors/warnings — verification should pay close attention.';
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
143
154
|
const output = {
|
|
144
|
-
additionalContext: `Executor complete. Auto-verification queued for Phase ${stateInfo.phase}
|
|
155
|
+
additionalContext: `Executor complete. Auto-verification queued for Phase ${stateInfo.phase}.${verifyHint}`
|
|
145
156
|
};
|
|
146
157
|
process.stdout.write(JSON.stringify(output));
|
|
147
158
|
process.exit(0);
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"SubagentStart": { "$ref": "#/definitions/hookEntryList" },
|
|
19
19
|
"SubagentStop": { "$ref": "#/definitions/hookEntryList" },
|
|
20
20
|
"TaskCompleted": { "$ref": "#/definitions/hookEntryList" },
|
|
21
|
+
"ConfigChange": { "$ref": "#/definitions/hookEntryList" },
|
|
21
22
|
"SessionEnd": { "$ref": "#/definitions/hookEntryList" }
|
|
22
23
|
},
|
|
23
24
|
"additionalProperties": false
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type": "commonjs"}
|
|
@@ -75,6 +75,36 @@ function main() {
|
|
|
75
75
|
process.exit(commitResult.exitCode);
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
// Soft warnings for risky-but-allowed commands
|
|
79
|
+
const command = data.tool_input?.command || '';
|
|
80
|
+
if (command) {
|
|
81
|
+
const warnings = [];
|
|
82
|
+
|
|
83
|
+
// Warn about npm publish / deploy commands
|
|
84
|
+
if (/\bnpm\s+publish\b/.test(command)) {
|
|
85
|
+
warnings.push('npm publish detected — ensure version is correct before publishing');
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Warn about touching production config files
|
|
89
|
+
if (/\b(production|prod)\b.*\.(json|ya?ml|env|conf|cfg)\b/i.test(command) ||
|
|
90
|
+
/\.(json|ya?ml|env|conf|cfg)\b.*\b(production|prod)\b/i.test(command)) {
|
|
91
|
+
warnings.push('command references production config files');
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Warn about database operations
|
|
95
|
+
if (/\b(DROP|TRUNCATE|DELETE\s+FROM|ALTER\s+TABLE)\b/i.test(command)) {
|
|
96
|
+
warnings.push('destructive database operation detected — verify target');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (warnings.length > 0) {
|
|
100
|
+
process.stdout.write(JSON.stringify({
|
|
101
|
+
decision: 'allow',
|
|
102
|
+
additionalContext: `[pbr] Advisory: ${warnings.join('; ')}.`
|
|
103
|
+
}));
|
|
104
|
+
process.exit(0);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
78
108
|
process.exit(0);
|
|
79
109
|
} catch (_e) {
|
|
80
110
|
// Don't block on errors
|
|
@@ -99,6 +99,33 @@ function main() {
|
|
|
99
99
|
process.exit(sprawlResult.exitCode || 0);
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
// Soft warning: writing outside current phase directory
|
|
103
|
+
// (only when all hard checks passed and we're in a phase)
|
|
104
|
+
const filePath = data.tool_input?.file_path || data.tool_input?.path || '';
|
|
105
|
+
if (filePath) {
|
|
106
|
+
const normalized = filePath.replace(/\\/g, '/');
|
|
107
|
+
// Warn about writes to other phase directories (not blocked, just advisory)
|
|
108
|
+
const phaseMatch = normalized.match(/\.planning\/phases\/(\d+)-/);
|
|
109
|
+
if (phaseMatch) {
|
|
110
|
+
const fs = require('fs');
|
|
111
|
+
const path = require('path');
|
|
112
|
+
const statePath = path.join(process.cwd(), '.planning', 'STATE.md');
|
|
113
|
+
try {
|
|
114
|
+
const stateContent = fs.readFileSync(statePath, 'utf8');
|
|
115
|
+
const currentPhase = stateContent.match(/Phase:\s*(\d+)\s+of/);
|
|
116
|
+
if (currentPhase && parseInt(phaseMatch[1], 10) !== parseInt(currentPhase[1], 10)) {
|
|
117
|
+
process.stdout.write(JSON.stringify({
|
|
118
|
+
decision: 'allow',
|
|
119
|
+
additionalContext: `[pbr] Advisory: writing to phase ${phaseMatch[1]} but current phase is ${currentPhase[1]}. Ensure this cross-phase write is intentional.`
|
|
120
|
+
}));
|
|
121
|
+
process.exit(0);
|
|
122
|
+
}
|
|
123
|
+
} catch (_e) {
|
|
124
|
+
// No STATE.md — skip warning
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
102
129
|
process.exit(0);
|
|
103
130
|
} catch (_e) {
|
|
104
131
|
// Don't block on errors
|
|
@@ -171,6 +171,15 @@ After running all 10 checks and collecting results, if any of the following auto
|
|
|
171
171
|
|
|
172
172
|
After displaying health check results, if any auto-fixable issues were detected:
|
|
173
173
|
|
|
174
|
+
**CRITICAL — Before ANY auto-fix that modifies or regenerates STATE.md (frontmatter regeneration, phase_slug correction, or line compaction), you MUST create a timestamped backup first. DO NOT SKIP THIS STEP.**
|
|
175
|
+
|
|
176
|
+
```
|
|
177
|
+
mkdir -p .planning/backups
|
|
178
|
+
cp .planning/STATE.md .planning/backups/STATE-$(date +%Y%m%dT%H%M%S).md
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
This ensures the user can recover the original STATE.md if the fix produces incorrect results.
|
|
182
|
+
|
|
174
183
|
1. Count the auto-fixable issues and present:
|
|
175
184
|
|
|
176
185
|
Use AskUserQuestion:
|
|
@@ -138,6 +138,7 @@ Display the following reference to the user:
|
|
|
138
138
|
- **Depth**: `quick` (skip research, ~50% cheaper) | `standard` | `comprehensive` (~2x cost)
|
|
139
139
|
- **State files**: `.planning/STATE.md` (position), `.planning/ROADMAP.md` (phases), `.planning/config.json` (settings)
|
|
140
140
|
- **Configure**: `/pbr:config` to change depth, models, gates, parallelization
|
|
141
|
+
- **List agents**: Run `claude agents` in your terminal to see all registered PBR agents and verify loading
|
|
141
142
|
- **Tip**: Use `/pbr:quick` for creative/visual work where structured planning adds overhead without benefit.
|
|
142
143
|
- **PR hygiene**: When creating PRs from a Plan-Build-Run project, `.planning/` commits can be filtered using phase branching (`git.branching: phase`) which squash-merges code-only changes to main.
|
|
143
144
|
- **Seeds**: `/pbr:explore` can create seed files (`.planning/seeds/`) with trigger conditions. Seeds auto-inject into planning when their trigger phase is reached.
|