@sienklogic/plan-build-run 2.18.1 → 2.19.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 (31) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +1 -1
  3. package/dashboard/public/css/layout.css +70 -2
  4. package/dashboard/src/services/roadmap.service.js +19 -5
  5. package/dashboard/src/services/todo.service.js +14 -5
  6. package/dashboard/src/views/partials/dashboard-content.ejs +2 -2
  7. package/dashboard/src/views/partials/layout-bottom.ejs +37 -0
  8. package/dashboard/src/views/partials/layout-top.ejs +1 -0
  9. package/dashboard/src/views/partials/roadmap-content.ejs +26 -1
  10. package/dashboard/src/views/partials/todos-content.ejs +3 -0
  11. package/package.json +1 -1
  12. package/plugins/copilot-pbr/agents/debugger.agent.md +11 -1
  13. package/plugins/copilot-pbr/agents/plan-checker.agent.md +15 -6
  14. package/plugins/copilot-pbr/plugin.json +1 -1
  15. package/plugins/copilot-pbr/references/agent-contracts.md +1 -1
  16. package/plugins/copilot-pbr/skills/health/SKILL.md +9 -0
  17. package/plugins/cursor-pbr/.cursor-plugin/plugin.json +1 -1
  18. package/plugins/cursor-pbr/agents/debugger.md +11 -1
  19. package/plugins/cursor-pbr/agents/plan-checker.md +15 -6
  20. package/plugins/cursor-pbr/references/agent-contracts.md +1 -1
  21. package/plugins/cursor-pbr/skills/health/SKILL.md +9 -0
  22. package/plugins/pbr/.claude-plugin/plugin.json +1 -1
  23. package/plugins/pbr/agents/debugger.md +11 -1
  24. package/plugins/pbr/agents/plan-checker.md +15 -6
  25. package/plugins/pbr/references/agent-contracts.md +1 -1
  26. package/plugins/pbr/scripts/auto-continue.js +8 -2
  27. package/plugins/pbr/scripts/event-handler.js +12 -1
  28. package/plugins/pbr/scripts/package.json +1 -0
  29. package/plugins/pbr/scripts/pre-bash-dispatch.js +30 -0
  30. package/plugins/pbr/scripts/pre-write-dispatch.js +27 -0
  31. package/plugins/pbr/skills/health/SKILL.md +9 -0
package/CHANGELOG.md CHANGED
@@ -5,6 +5,30 @@ 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.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)
9
+
10
+
11
+ ### Features
12
+
13
+ * **dashboard:** add responsive mobile layout with sidebar hamburger menu ([5621739](https://github.com/SienkLogic/plan-build-run/commit/5621739b1b1b85bf5854bf52582908251fdeff13))
14
+ * **tools:** add D10 test plan coverage dimension to plan-checker agent ([a4ff196](https://github.com/SienkLogic/plan-build-run/commit/a4ff19664c723861b262f9d6feccdd9e1ef95221))
15
+ * **tools:** add PreToolUse additionalContext soft warnings for risky operations ([1d39406](https://github.com/SienkLogic/plan-build-run/commit/1d394066071959e4abafdcc1e84d472f05584018))
16
+ * **tools:** add STATE.md backup step before health skill auto-fix regeneration ([43a52dd](https://github.com/SienkLogic/plan-build-run/commit/43a52dd36df9afc2f0aa3ddebfd588904b562bcd))
17
+ * **tools:** require user confirmation before debugger agent applies fixes ([5446654](https://github.com/SienkLogic/plan-build-run/commit/544665487093210c6f6e412f7af79e02d33cf19a))
18
+ * **tools:** use last_assistant_message in Stop/SubagentStop hooks ([ab73122](https://github.com/SienkLogic/plan-build-run/commit/ab731222549b6c251d93de123a3a2475b8d41a13))
19
+
20
+
21
+ ### Bug Fixes
22
+
23
+ * **dashboard:** handle todo files with H1 title and high/medium/low priority ([9edb601](https://github.com/SienkLogic/plan-build-run/commit/9edb601bdeb974c3f1d47f612697516b67d5aa2e))
24
+ * **dashboard:** show completed milestones on roadmap when all phases archived ([656ec04](https://github.com/SienkLogic/plan-build-run/commit/656ec04120931e5092ee608f23022276c5d79381))
25
+ * **tools:** add commonjs package.json to scripts for ESM project compat ([8ca8780](https://github.com/SienkLogic/plan-build-run/commit/8ca878023ce90257ccb9fe0cdabe5a3040ece9e9))
26
+
27
+
28
+ ### Documentation
29
+
30
+ * **tools:** document minimum Claude Code v2.1.47 requirement for Windows hooks ([2ecb231](https://github.com/SienkLogic/plan-build-run/commit/2ecb23172f154e1fe68460c087eb055deea1df94))
31
+
8
32
  ## [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
33
 
10
34
 
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.45+  (`claude --version`)
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(--color-surface-raised);
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.4);
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: match[1].trim(),
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
- // Skip todos missing required frontmatter fields
112
- const title = frontmatter.title;
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 (!title || !priority) continue;
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="grid">
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>
@@ -11,5 +11,6 @@
11
11
  </script>
12
12
  <div class="page-wrapper">
13
13
  <%- include('header') %>
14
+ <div class="sidebar-backdrop" onclick="closeSidebar()"></div>
14
15
  <%- include('sidebar', { activePage: typeof activePage !== 'undefined' ? activePage : '' }) %>
15
16
  <main id="main-content">
@@ -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') %>&ndash;<%= String(ms.endPhase).padStart(2, '0') %>)</small>
20
+ <% } %>
21
+ &mdash;
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sienklogic/plan-build-run",
3
- "version": "2.18.1",
3
+ "version": "2.19.0",
4
4
  "description": "Plan it, Build it, Run it — structured development workflow for Claude Code",
5
5
  "keywords": [
6
6
  "claude-code",
@@ -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
- **Steps**: Verify root cause plan minimal fix predict outcome implement verify check regressions commit update debug file.
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 9 dimensions."
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 9 Verification Dimensions
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 9 Dimensions** — Evaluate each plan against all dimensions. Collect issues.
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: 9 | Issues: 0
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 9 dimensions pass, say PASSED
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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pbr",
3
3
  "displayName": "Plan-Build-Run",
4
- "version": "2.18.1",
4
+ "version": "2.19.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 9 dimensions (D1-D9). Optionally receives CONTEXT.md path.
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.18.1",
4
+ "version": "2.19.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
- **Steps**: Verify root cause plan minimal fix predict outcome implement verify check regressions commit update debug file.
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 9 dimensions."
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 9 Verification Dimensions
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 9 Dimensions** — Evaluate each plan against all dimensions. Collect issues.
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: 9 | Issues: 0
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 9 dimensions pass, say PASSED
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
@@ -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 9 dimensions (D1-D9). Optionally receives CONTEXT.md path.
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.18.1",
3
+ "version": "2.19.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
- **Steps**: Verify root cause plan minimal fix predict outcome implement verify check regressions commit update debug file.
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,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 9 dimensions."
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
6
  tools:
@@ -35,7 +35,7 @@ You receive: (1) plan files to check, (2) phase goal or directory path, (3) opti
35
35
 
36
36
  ---
37
37
 
38
- ## The 9 Verification Dimensions
38
+ ## The 10 Verification Dimensions
39
39
 
40
40
  ### D1: Requirement Coverage
41
41
  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 +131,15 @@ Plans declare `requirement_ids` with bidirectional coverage. Forward: IDs trace
131
131
  | ROADMAP goal not covered (no REQUIREMENTS.md) | WARNING |
132
132
  | Plan missing requirement_ids entirely | INFO |
133
133
 
134
+ ### D10: Test Plan Coverage
135
+ 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>`.
136
+
137
+ | Condition | Severity |
138
+ |-----------|----------|
139
+ | Code task with no test file in `<files>` and no test command in `<verify>` | WARNING |
140
+ | Task creates new module but no corresponding test file planned | WARNING |
141
+ | `<verify>` uses only file-existence checks, no test runner | INFO |
142
+
134
143
  ---
135
144
 
136
145
  ## Verification Process
@@ -138,7 +147,7 @@ Plans declare `requirement_ids` with bidirectional coverage. Forward: IDs trace
138
147
  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
148
  2. **Load Context** — If CONTEXT.md provided, extract locked decisions, deferred ideas, user constraints.
140
149
  3. **Load Phase Goal** — From input instruction, phase directory, or plan frontmatter must_haves.
141
- 4. **Run All 9 Dimensions** — Evaluate each plan against all dimensions. Collect issues.
150
+ 4. **Run All 10 Dimensions** — Evaluate each plan against all dimensions. Collect issues.
142
151
  5. **Cross-Plan Checks** — File conflicts between same-wave plans, circular cross-plan deps, phase goal coverage, duplicate task content.
143
152
  6. **Compile Report** — Produce output in format below.
144
153
 
@@ -148,7 +157,7 @@ Plans declare `requirement_ids` with bidirectional coverage. Forward: IDs trace
148
157
 
149
158
  ```
150
159
  VERIFICATION PASSED
151
- Plans: {count} | Tasks: {count} | Dimensions: 9 | Issues: 0
160
+ Plans: {count} | Tasks: {count} | Dimensions: 10 | Issues: 0
152
161
  ```
153
162
 
154
163
  Or when issues found:
@@ -174,7 +183,7 @@ Plans: {count} | Tasks: {count} | Blockers: {count} | Warnings: {count} | Info:
174
183
  - **Single-task plan**: WARNING on D5. May be too coarse; consider splitting.
175
184
  - **No CONTEXT.md**: Skip D7. Note "D7 skipped: no CONTEXT.md found".
176
185
  - **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.
186
+ - **TDD tasks**: See D10. WARNING if verify lacks a test command.
178
187
 
179
188
  ---
180
189
 
@@ -197,7 +206,7 @@ Plans: {count} | Tasks: {count} | Blockers: {count} | Warnings: {count} | Info:
197
206
  2. DO NOT suggest alternative architectures — focus on plan quality
198
207
  3. DO NOT invent requirements not in the phase goal or must-haves
199
208
  4. DO NOT be lenient on blockers — if it's a blocker, flag it
200
- 5. DO NOT nitpick working plans — if all 9 dimensions pass, say PASSED
209
+ 5. DO NOT nitpick working plans — if all 10 dimensions pass, say PASSED
201
210
  6. DO NOT check code quality — you check PLAN quality
202
211
  7. DO NOT verify that technologies are correct — that's the researcher's job
203
212
  8. DO NOT evaluate the phase goal itself — only whether the plan achieves it
@@ -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 9 dimensions (D1-D9). Optionally receives CONTEXT.md path.
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
- logHook('auto-continue', 'Stop', 'continue', { next: nextCommand });
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);
@@ -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);
@@ -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: