@sienklogic/plan-build-run 2.19.1 → 2.19.2

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 (116) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/CLAUDE.md +29 -16
  3. package/README.md +3 -3
  4. package/dashboard/server/index.js +10 -1
  5. package/dashboard/server/routes/agents.js +23 -2
  6. package/dashboard/server/routes/health.js +7 -4
  7. package/dashboard/server/routes/telemetry.js +20 -1
  8. package/dashboard/server/services/planning-reader.js +3 -17
  9. package/package.json +1 -1
  10. package/plan-build-run/bin/config-schema.json +23 -145
  11. package/plugins/pbr/.claude-plugin/plugin.json +1 -1
  12. package/plugins/pbr/agents/advisor-researcher.md +1 -0
  13. package/plugins/pbr/agents/debugger.md +0 -4
  14. package/plugins/pbr/agents/researcher.md +0 -4
  15. package/plugins/pbr/agents/synthesizer.md +0 -4
  16. package/plugins/pbr/dist/check-config-change.js +0 -7
  17. package/plugins/pbr/dist/check-cross-plugin-sync.js +1 -1
  18. package/plugins/pbr/dist/check-plan-format.js +0 -32
  19. package/plugins/pbr/dist/check-roadmap-sync.js +15 -11
  20. package/plugins/pbr/dist/check-subagent-output.js +4 -60
  21. package/plugins/pbr/dist/check-summary-gate.js +3 -14
  22. package/plugins/pbr/dist/feedback-loop.js +12 -29
  23. package/plugins/pbr/dist/hook-server.js +58 -6
  24. package/plugins/pbr/dist/milestone-learnings.js +6 -56
  25. package/plugins/pbr/dist/pbr-tools.js +8 -91
  26. package/plugins/pbr/dist/post-bash-triage.js +5 -63
  27. package/plugins/pbr/dist/post-hoc.js +3 -52
  28. package/plugins/pbr/dist/post-write-dispatch.js +0 -36
  29. package/plugins/pbr/dist/pre-bash-dispatch.js +1 -7
  30. package/plugins/pbr/dist/pre-task-dispatch.js +0 -28
  31. package/plugins/pbr/dist/progress-tracker.js +2 -27
  32. package/plugins/pbr/dist/session-cleanup.js +1 -31
  33. package/plugins/pbr/dist/status-line.js +13 -11
  34. package/plugins/pbr/dist/suggest-compact.js +2 -10
  35. package/plugins/pbr/dist/validate-commit.js +8 -64
  36. package/plugins/pbr/dist/validate-task.js +0 -30
  37. package/plugins/pbr/references/config-reference.md +0 -96
  38. package/plugins/pbr/scripts/audit-checks/si-agent-hook-config-checks.js +2 -72
  39. package/plugins/pbr/scripts/audit-checks/workflow-compliance.js +5 -41
  40. package/plugins/pbr/scripts/check-config-change.js +0 -7
  41. package/plugins/pbr/scripts/check-cross-plugin-sync.js +1 -1
  42. package/plugins/pbr/scripts/check-plan-format.js +0 -32
  43. package/plugins/pbr/scripts/check-roadmap-sync.js +15 -11
  44. package/plugins/pbr/scripts/check-subagent-output.js +4 -60
  45. package/plugins/pbr/scripts/check-summary-gate.js +3 -14
  46. package/plugins/pbr/scripts/config-schema.json +16 -129
  47. package/plugins/pbr/scripts/feedback-loop.js +12 -29
  48. package/plugins/pbr/scripts/hook-server.js +58 -6
  49. package/plugins/pbr/scripts/lib/config.js +4 -11
  50. package/plugins/pbr/scripts/lib/contextual-help.js +5 -29
  51. package/plugins/pbr/scripts/lib/format-validators.js +1 -26
  52. package/plugins/pbr/scripts/lib/frontmatter.js +4 -4
  53. package/plugins/pbr/scripts/lib/gates/rich-agent-context.js +13 -19
  54. package/plugins/pbr/scripts/lib/health.js +4 -5
  55. package/plugins/pbr/scripts/lib/help.js +3 -54
  56. package/plugins/pbr/scripts/lib/phase.js +2 -4
  57. package/plugins/pbr/scripts/lib/pre-commit-checks.js +1 -1
  58. package/plugins/pbr/scripts/lib/pre-research.js +10 -17
  59. package/plugins/pbr/scripts/lib/roadmap.js +11 -35
  60. package/plugins/pbr/scripts/lib/smart-next-task.js +11 -20
  61. package/plugins/pbr/scripts/lib/spot-check.js +3 -106
  62. package/plugins/pbr/scripts/lib/state.js +25 -130
  63. package/plugins/pbr/scripts/lib/verify.js +56 -46
  64. package/plugins/pbr/scripts/milestone-learnings.js +6 -56
  65. package/plugins/pbr/scripts/pbr-tools.js +8 -91
  66. package/plugins/pbr/scripts/post-bash-triage.js +5 -63
  67. package/plugins/pbr/scripts/post-hoc.js +3 -52
  68. package/plugins/pbr/scripts/post-write-dispatch.js +0 -36
  69. package/plugins/pbr/scripts/pre-bash-dispatch.js +1 -7
  70. package/plugins/pbr/scripts/pre-task-dispatch.js +0 -28
  71. package/plugins/pbr/scripts/progress-tracker.js +2 -27
  72. package/plugins/pbr/scripts/session-cleanup.js +1 -31
  73. package/plugins/pbr/scripts/status-line.js +13 -11
  74. package/plugins/pbr/scripts/suggest-compact.js +2 -10
  75. package/plugins/pbr/scripts/test/state.test.js +5 -13
  76. package/plugins/pbr/scripts/validate-commit.js +8 -64
  77. package/plugins/pbr/scripts/validate-task.js +0 -30
  78. package/plugins/pbr/skills/begin/SKILL.md +1 -0
  79. package/plugins/pbr/skills/begin/templates/config.json.tmpl +0 -4
  80. package/plugins/pbr/skills/build/SKILL.md +6 -6
  81. package/plugins/pbr/skills/config/SKILL.md +1 -0
  82. package/plugins/pbr/skills/help/SKILL.md +1 -0
  83. package/plugins/pbr/skills/pause/SKILL.md +1 -0
  84. package/plugins/pbr/skills/profile-user/SKILL.md +1 -0
  85. package/plugins/pbr/skills/quick/SKILL.md +2 -1
  86. package/plugins/pbr/skills/resume/SKILL.md +1 -0
  87. package/plugins/pbr/skills/scan/SKILL.md +1 -0
  88. package/plugins/pbr/skills/setup/SKILL.md +1 -0
  89. package/plugins/pbr/skills/shared/state-update.md +2 -2
  90. package/plugins/pbr/skills/status/SKILL.md +1 -0
  91. package/plugins/pbr/references/behavioral-contexts.md +0 -53
  92. package/plugins/pbr/scripts/lib/autonomy.js +0 -91
  93. package/plugins/pbr/scripts/lib/circuit-state.js +0 -133
  94. package/plugins/pbr/scripts/lib/completion.js +0 -377
  95. package/plugins/pbr/scripts/lib/hypothesis-runner.js +0 -127
  96. package/plugins/pbr/scripts/lib/local-llm/client.js +0 -237
  97. package/plugins/pbr/scripts/lib/local-llm/health.js +0 -12
  98. package/plugins/pbr/scripts/lib/local-llm/index.js +0 -89
  99. package/plugins/pbr/scripts/lib/local-llm/metrics.js +0 -20
  100. package/plugins/pbr/scripts/lib/local-llm/operations/classify-artifact.js +0 -4
  101. package/plugins/pbr/scripts/lib/local-llm/operations/classify-commit.js +0 -4
  102. package/plugins/pbr/scripts/lib/local-llm/operations/classify-error.js +0 -4
  103. package/plugins/pbr/scripts/lib/local-llm/operations/classify-file-intent.js +0 -4
  104. package/plugins/pbr/scripts/lib/local-llm/operations/score-source.js +0 -72
  105. package/plugins/pbr/scripts/lib/local-llm/operations/summarize-context.js +0 -62
  106. package/plugins/pbr/scripts/lib/local-llm/operations/triage-test-output.js +0 -12
  107. package/plugins/pbr/scripts/lib/local-llm/operations/validate-task.js +0 -4
  108. package/plugins/pbr/scripts/lib/local-llm/router.js +0 -101
  109. package/plugins/pbr/scripts/lib/local-llm/shadow.js +0 -60
  110. package/plugins/pbr/scripts/lib/local-llm/threshold-tuner.js +0 -118
  111. package/plugins/pbr/scripts/lib/team-composer.js +0 -87
  112. package/plugins/pbr/scripts/lib/team-coordinator.js +0 -153
  113. package/plugins/pbr/scripts/lib/template.js +0 -222
  114. package/plugins/pbr/scripts/lib/test-cache.js +0 -54
  115. package/plugins/pbr/scripts/lib/trust-gate.js +0 -84
  116. package/plugins/pbr/scripts/lib/wiring-check.js +0 -196
@@ -84,119 +84,30 @@ function parseStateMd(content) {
84
84
  progress: null,
85
85
  status: null,
86
86
  line_count: normalized.split('\n').length,
87
- format: 'legacy' // 'legacy' or 'frontmatter'
87
+ format: 'frontmatter'
88
88
  };
89
89
 
90
90
  // Check for YAML frontmatter (version 2 format)
91
91
  const frontmatter = parseYamlFrontmatter(normalized);
92
- if (frontmatter.version === 2 || frontmatter.current_phase !== undefined) {
93
- result.format = 'frontmatter';
94
- result.current_phase = frontmatter.current_phase || null;
95
- result.phase_name = frontmatter.phase_slug || frontmatter.phase_name || null;
96
- result.status = frontmatter.status || null;
97
- result.progress = frontmatter.progress_percent !== undefined ? frontmatter.progress_percent : null;
98
- result.plans_total = frontmatter.plans_total || null;
99
- result.plans_complete = frontmatter.plans_complete || null;
100
- result.last_activity = frontmatter.last_activity || null;
101
- result.last_command = frontmatter.last_command || null;
102
- result.blockers = frontmatter.blockers || [];
103
- result.velocity = frontmatter.velocity || null;
104
- result.session_last = frontmatter.session_last || null;
105
- result.session_stopped_at = frontmatter.session_stopped_at || null;
106
- result.session_resume = frontmatter.session_resume || null;
92
+ result.format = 'frontmatter';
93
+ result.current_phase = frontmatter.current_phase || null;
94
+ result.phase_name = frontmatter.phase_slug || frontmatter.phase_name || null;
95
+ result.status = frontmatter.status || null;
96
+ result.progress = frontmatter.progress_percent !== undefined ? frontmatter.progress_percent : null;
97
+ result.plans_total = frontmatter.plans_total || null;
98
+ result.plans_complete = frontmatter.plans_complete || null;
99
+ result.last_activity = frontmatter.last_activity || null;
100
+ result.last_command = frontmatter.last_command || null;
101
+ result.blockers = frontmatter.blockers || [];
102
+ result.velocity = frontmatter.velocity || null;
103
+ result.session_last = frontmatter.session_last || null;
104
+ result.session_stopped_at = frontmatter.session_stopped_at || null;
105
+ result.session_resume = frontmatter.session_resume || null;
107
106
  return result;
108
- }
109
-
110
- // Legacy regex-based parsing (version 1 format, no frontmatter)
111
- // DEPRECATED (2026-02): v1 STATE.md format (no YAML frontmatter) is deprecated.
112
- // New projects should use v2 (frontmatter) format, generated by /pbr:setup.
113
- // v1 support will be removed in a future major version.
114
- process.stderr.write('[pbr] WARNING: STATE.md uses legacy v1 format. Run /pbr:setup to migrate to v2 format.\n');
115
-
116
- // Extract "Phase: N of M"
117
- const phaseMatch = normalized.match(/Phase:\s*(\d+)\s+of\s+(\d+)/);
118
- if (phaseMatch) {
119
- result.current_phase = parseInt(phaseMatch[1], 10);
120
- result.total_phases = parseInt(phaseMatch[2], 10);
121
- }
122
-
123
- // Extract phase name (line after "Phase:")
124
- const nameMatch = normalized.match(/--\s+(.+?)(?:\n|$)/);
125
- if (nameMatch) {
126
- result.phase_name = nameMatch[1].trim();
127
- }
128
-
129
- // Extract progress percentage
130
- const progressMatch = normalized.match(/(\d+)%/);
131
- if (progressMatch) {
132
- result.progress = parseInt(progressMatch[1], 10);
133
- }
134
-
135
- // Extract plan status
136
- const statusMatch = normalized.match(/Status:\s*(.+?)(?:\n|$)/i);
137
- if (statusMatch) {
138
- result.status = statusMatch[1].trim();
139
- }
140
-
141
- return result;
142
107
  }
143
108
 
144
109
  // --- Mutation helpers ---
145
110
 
146
- /**
147
- * Update a field in legacy (non-frontmatter) STATE.md content.
148
- * Pure function: content in, content out.
149
- */
150
- function updateLegacyStateField(content, field, value) {
151
- const lines = content.replace(/\r\n/g, '\n').split('\n');
152
-
153
- switch (field) {
154
- case 'current_phase': {
155
- const idx = lines.findIndex(l => /Phase:\s*\d+\s+of\s+\d+/.test(l));
156
- if (idx !== -1) {
157
- lines[idx] = lines[idx].replace(/(Phase:\s*)\d+/, (_, prefix) => `${prefix}${value}`);
158
- }
159
- break;
160
- }
161
- case 'status': {
162
- const idx = lines.findIndex(l => /^Status:/i.test(l));
163
- if (idx !== -1) {
164
- lines[idx] = `Status: ${value}`;
165
- } else {
166
- const phaseIdx = lines.findIndex(l => /Phase:/.test(l));
167
- if (phaseIdx !== -1) {
168
- lines.splice(phaseIdx + 1, 0, `Status: ${value}`);
169
- } else {
170
- lines.push(`Status: ${value}`);
171
- }
172
- }
173
- break;
174
- }
175
- case 'plans_complete': {
176
- const idx = lines.findIndex(l => /Plan:\s*\d+\s+of\s+\d+/.test(l));
177
- if (idx !== -1) {
178
- lines[idx] = lines[idx].replace(/(Plan:\s*)\d+/, (_, prefix) => `${prefix}${value}`);
179
- }
180
- break;
181
- }
182
- case 'last_activity': {
183
- const idx = lines.findIndex(l => /^Last Activity:/i.test(l));
184
- if (idx !== -1) {
185
- lines[idx] = `Last Activity: ${value}`;
186
- } else {
187
- const statusIdx = lines.findIndex(l => /^Status:/i.test(l));
188
- if (statusIdx !== -1) {
189
- lines.splice(statusIdx + 1, 0, `Last Activity: ${value}`);
190
- } else {
191
- lines.push(`Last Activity: ${value}`);
192
- }
193
- }
194
- break;
195
- }
196
- }
197
-
198
- return lines.join('\n');
199
- }
200
111
 
201
112
  /**
202
113
  * Update a field in YAML frontmatter content.
@@ -428,7 +339,7 @@ function stateCheckProgress(planningDir) {
428
339
 
429
340
  /**
430
341
  * Atomically update a field in STATE.md using lockedFileUpdate.
431
- * Supports both legacy and frontmatter (v2) formats.
342
+ * Updates frontmatter (v2) format STATE.md.
432
343
  *
433
344
  * @param {string} field - One of: current_phase, status, plans_complete, last_activity,
434
345
  * progress_percent, phase_slug, total_phases, last_command, blockers
@@ -468,13 +379,9 @@ function stateUpdate(field, value, planningDir) {
468
379
  }
469
380
 
470
381
  const result = lockedFileUpdate(statePath, (content) => {
471
- const fm = parseYamlFrontmatter(content);
472
- if (fm.version === 2 || fm.current_phase !== undefined) {
473
- let updated = updateFrontmatterField(content, field, value);
474
- updated = syncBodyLine(updated, field, value);
475
- return updated;
476
- }
477
- return updateLegacyStateField(content, field, value);
382
+ let updated = updateFrontmatterField(content, field, value);
383
+ updated = syncBodyLine(updated, field, value);
384
+ return updated;
478
385
  });
479
386
 
480
387
  if (result.success) {
@@ -501,19 +408,13 @@ function statePatch(jsonStr, planningDir) {
501
408
 
502
409
  const result = lockedFileUpdate(statePath, (content) => {
503
410
  let updated = content;
504
- const fm = parseYamlFrontmatter(updated);
505
- const isFrontmatter = fm.version === 2 || fm.current_phase !== undefined;
506
411
  for (const [field, value] of Object.entries(fields)) {
507
412
  let val = String(value);
508
413
  if (field === 'last_activity' && val === 'now') {
509
414
  val = new Date().toISOString().slice(0, 19).replace('T', ' ');
510
415
  }
511
- if (isFrontmatter) {
512
- updated = updateFrontmatterField(updated, field, val);
513
- updated = syncBodyLine(updated, field, val);
514
- } else {
515
- updated = updateLegacyStateField(updated, field, val);
516
- }
416
+ updated = updateFrontmatterField(updated, field, val);
417
+ updated = syncBodyLine(updated, field, val);
517
418
  }
518
419
  return updated;
519
420
  });
@@ -546,15 +447,10 @@ function stateAdvancePlan(planningDir) {
546
447
  resultData = { previous_plan: current, current_plan: next, total_plans: total, progress_percent: progressPct };
547
448
 
548
449
  let updated = content;
549
- const fm = parseYamlFrontmatter(content);
550
- if (fm.version === 2 || fm.current_phase !== undefined) {
551
- updated = updateFrontmatterField(updated, 'plans_complete', String(next));
552
- updated = syncBodyLine(updated, 'plans_complete', String(next));
553
- updated = updateFrontmatterField(updated, 'progress_percent', String(progressPct));
554
- updated = syncBodyLine(updated, 'progress_percent', String(progressPct));
555
- } else {
556
- updated = updateLegacyStateField(updated, 'plans_complete', String(next));
557
- }
450
+ updated = updateFrontmatterField(updated, 'plans_complete', String(next));
451
+ updated = syncBodyLine(updated, 'plans_complete', String(next));
452
+ updated = updateFrontmatterField(updated, 'progress_percent', String(progressPct));
453
+ updated = syncBodyLine(updated, 'progress_percent', String(progressPct));
558
454
  return updated;
559
455
  });
560
456
 
@@ -1158,7 +1054,6 @@ function stateBackup(planningDir) {
1158
1054
 
1159
1055
  module.exports = {
1160
1056
  parseStateMd,
1161
- updateLegacyStateField,
1162
1057
  updateFrontmatterField,
1163
1058
  syncBodyLine,
1164
1059
  buildProgressBar,
@@ -183,7 +183,7 @@ function cmdVerifyPhaseCompleteness(cwd, phase, raw) {
183
183
 
184
184
  // List plans and summaries
185
185
  let files;
186
- try { files = fs.readdirSync(phaseDir); } catch { output({ error: 'Cannot read phase directory' }, raw); return; }
186
+ try { files = fs.readdirSync(phaseDir); } catch (err) { if (process.env.PBR_DEBUG) console.error(`[verify] Cannot read phase directory ${phaseDir}: ${err.message}`); output({ error: 'Cannot read phase directory' }, raw); return; }
187
187
 
188
188
  const plans = files.filter(f => f.match(/-PLAN\.md$/i));
189
189
  const summaries = files.filter(f => f.match(/-SUMMARY\.md$/i));
@@ -409,7 +409,8 @@ function cmdVerifyKeyLinks(cwd, planFilePath, raw) {
409
409
  check.detail = `Pattern "${link.pattern}" not found in source or target`;
410
410
  }
411
411
  }
412
- } catch {
412
+ } catch (err) {
413
+ if (process.env.PBR_DEBUG) console.error(`[verify] Invalid regex pattern ${link.pattern}: ${err.message}`);
413
414
  check.detail = `Invalid regex pattern: ${link.pattern}`;
414
415
  }
415
416
  } else {
@@ -466,7 +467,7 @@ function cmdValidateConsistency(cwd, raw) {
466
467
  const dm = dir.match(/^(\d+[A-Z]?(?:\.\d+)*)/i);
467
468
  if (dm) diskPhases.add(dm[1]);
468
469
  }
469
- } catch {}
470
+ } catch (err) { if (process.env.PBR_DEBUG) console.error(`[verify] Failed to read phases directory: ${err.message}`); }
470
471
 
471
472
  // Check: phases in ROADMAP but not on disk
472
473
  for (const p of roadmapPhases) {
@@ -528,7 +529,7 @@ function cmdValidateConsistency(cwd, raw) {
528
529
  }
529
530
  }
530
531
  }
531
- } catch {}
532
+ } catch (err) { if (process.env.PBR_DEBUG) console.error(`[verify] Failed to check plan numbering: ${err.message}`); }
532
533
 
533
534
  // Check: frontmatter in plans has required fields
534
535
  try {
@@ -548,7 +549,7 @@ function cmdValidateConsistency(cwd, raw) {
548
549
  }
549
550
  }
550
551
  }
551
- } catch {}
552
+ } catch (err) { if (process.env.PBR_DEBUG) console.error(`[verify] Failed to check plan frontmatter: ${err.message}`); }
552
553
 
553
554
  const passed = errors.length === 0;
554
555
  output({ passed, errors, warnings, warning_count: warnings.length }, raw, passed ? 'passed' : 'failed');
@@ -678,7 +679,7 @@ function cmdValidateHealth(cwd, options, raw) {
678
679
  if (m) diskPhases.add(m[1]);
679
680
  }
680
681
  }
681
- } catch {}
682
+ } catch (err) { if (process.env.PBR_DEBUG) console.error(`[verify] Failed to read phases for state validation: ${err.message}`); }
682
683
  // Check for invalid references
683
684
  for (const ref of phaseRefs) {
684
685
  const normalizedRef = String(parseInt(ref, 10)).padStart(2, '0');
@@ -720,7 +721,7 @@ function cmdValidateHealth(cwd, options, raw) {
720
721
  addIssue('warning', 'W008', 'config.json: workflow.nyquist_validation absent (defaults to enabled but agents may skip)', 'Run /pbr:health --repair to add key', true);
721
722
  if (!repairs.includes('addNyquistKey')) repairs.push('addNyquistKey');
722
723
  }
723
- } catch {}
724
+ } catch (err) { if (process.env.PBR_DEBUG) console.error(`[verify] Failed to check nyquist key: ${err.message}`); }
724
725
  }
725
726
 
726
727
  // ─── Check 6: Phase directory naming (NN-name format) ─────────────────────
@@ -731,7 +732,7 @@ function cmdValidateHealth(cwd, options, raw) {
731
732
  addIssue('warning', 'W005', `Phase directory "${e.name}" doesn't follow NN-name format`, 'Rename to match pattern (e.g., 01-setup)');
732
733
  }
733
734
  }
734
- } catch {}
735
+ } catch (err) { if (process.env.PBR_DEBUG) console.error(`[verify] Failed to check phase directory naming: ${err.message}`); }
735
736
 
736
737
  // ─── Check 7: Orphaned plans (PLAN without SUMMARY) ───────────────────────
737
738
  try {
@@ -750,7 +751,7 @@ function cmdValidateHealth(cwd, options, raw) {
750
751
  }
751
752
  }
752
753
  }
753
- } catch {}
754
+ } catch (err) { if (process.env.PBR_DEBUG) console.error(`[verify] Failed to check orphaned plans: ${err.message}`); }
754
755
 
755
756
  // ─── Check 7b: Nyquist VALIDATION.md consistency ────────────────────────
756
757
  try {
@@ -768,7 +769,7 @@ function cmdValidateHealth(cwd, options, raw) {
768
769
  }
769
770
  }
770
771
  }
771
- } catch {}
772
+ } catch (err) { if (process.env.PBR_DEBUG) console.error(`[verify] Failed to check nyquist validation: ${err.message}`); }
772
773
 
773
774
  // ─── Check 8: Run existing consistency checks ─────────────────────────────
774
775
  // Inline subset of cmdValidateConsistency
@@ -790,7 +791,7 @@ function cmdValidateHealth(cwd, options, raw) {
790
791
  if (dm) diskPhases.add(dm[1]);
791
792
  }
792
793
  }
793
- } catch {}
794
+ } catch (err) { if (process.env.PBR_DEBUG) console.error(`[verify] Failed to read phases for roadmap check: ${err.message}`); }
794
795
 
795
796
  // Phases in ROADMAP but not on disk
796
797
  for (const p of roadmapPhases) {
@@ -909,20 +910,20 @@ function cmdValidateHealth(cwd, options, raw) {
909
910
  } else {
910
911
  feature_status.multi_phase_awareness = { enabled: false, status: 'disabled' };
911
912
  }
912
- } catch (_e) { /* config parse errors handled in Check 5 */ }
913
+ } catch (err) { if (process.env.PBR_DEBUG) console.error(`[verify] Config parse error (handled in Check 5): ${err.message}`); }
913
914
  }
914
915
 
915
916
  // ─── Check 11: Phase 05 feature status ────────────────────────────────────
916
917
  {
917
918
  let p05Config = {};
918
- try { p05Config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (_) {}
919
+ try { p05Config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (err) { if (process.env.PBR_DEBUG) console.error(`[verify] Failed to parse config for phase05: ${err.message}`); }
919
920
  var phase05_features = checkPhase05Features(planningDir, p05Config);
920
921
  }
921
922
 
922
923
  // ─── Check 12: Trust tracking health ──────────────────────────────────────
923
924
  {
924
925
  let config = {};
925
- try { config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (_) {}
926
+ try { config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (err) { if (process.env.PBR_DEBUG) console.error(`[verify] Failed to parse config for trust: ${err.message}`); }
926
927
 
927
928
  if (config.features && config.features.trust_tracking === false) {
928
929
  addIssue('info', 'I-TRUST-DISABLED', 'trust_tracking is disabled in config', 'Enable features.trust_tracking in config.json if desired');
@@ -941,7 +942,8 @@ function cmdValidateHealth(cwd, options, raw) {
941
942
  }
942
943
  }
943
944
  addIssue('info', 'I-TRUST-HEALTHY', `trust_tracking: healthy — ${agents.length} agents, ${totalOutcomes} outcomes tracked`, '');
944
- } catch (_) {
945
+ } catch (err) {
946
+ if (process.env.PBR_DEBUG) console.error(`[verify] Failed to parse agent-scores.json: ${err.message}`);
945
947
  addIssue('info', 'I-TRUST-DEGRADED', 'trust_tracking: degraded — agent-scores.json exists but is malformed', 'Delete .planning/trust/agent-scores.json to reset');
946
948
  }
947
949
  }
@@ -957,7 +959,8 @@ function cmdValidateHealth(cwd, options, raw) {
957
959
  try {
958
960
  JSON.parse(fs.readFileSync(trustFile, 'utf-8'));
959
961
  addIssue('info', 'I-CONFIDENCE-HEALTHY', 'confidence_calibration: healthy — trust data available for calibration', '');
960
- } catch (_) {
962
+ } catch (err) {
963
+ if (process.env.PBR_DEBUG) console.error(`[verify] Failed to parse trust data for confidence: ${err.message}`);
961
964
  addIssue('info', 'I-CONFIDENCE-DEGRADED', 'confidence_calibration: degraded — trust data malformed', 'Delete .planning/trust/agent-scores.json to reset');
962
965
  }
963
966
  }
@@ -971,12 +974,12 @@ function cmdValidateHealth(cwd, options, raw) {
971
974
  const guardHealth = graph.guardHealthCheck(planningDir);
972
975
  feature_status.architecture_graph = graphHealth;
973
976
  feature_status.architecture_guard = guardHealth;
974
- } catch (_e) { /* graph module not available skip */ }
977
+ } catch (err) { if (process.env.PBR_DEBUG) console.error(`[verify] Graph module not available: ${err.message}`); }
975
978
 
976
979
  // ─── Check 14: Phase 15 DX feature health ────────────────────────────────
977
980
  {
978
981
  let p15Config = {};
979
- try { p15Config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (_) {}
982
+ try { p15Config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (err) { if (process.env.PBR_DEBUG) console.error(`[verify] Failed to parse config for phase15: ${err.message}`); }
980
983
  const p15Features = (p15Config && p15Config.features) || {};
981
984
 
982
985
  const checkDxFeature = (featureName, modulePath, exportName) => {
@@ -1004,17 +1007,17 @@ function cmdValidateHealth(cwd, options, raw) {
1004
1007
 
1005
1008
  feature_status.progress_visualization = checkDxFeature(
1006
1009
  'progress_visualization',
1007
- path.join(__dirname, 'progress-visualization.cjs'),
1010
+ path.join(__dirname, 'progress-visualization.js'),
1008
1011
  'getProgressData'
1009
1012
  );
1010
1013
  feature_status.contextual_help = checkDxFeature(
1011
1014
  'contextual_help',
1012
- path.join(__dirname, 'contextual-help.cjs'),
1015
+ path.join(__dirname, 'contextual-help.js'),
1013
1016
  'getContextualHelp'
1014
1017
  );
1015
1018
  feature_status.team_onboarding = checkDxFeature(
1016
1019
  'team_onboarding',
1017
- path.join(__dirname, 'onboarding-generator.cjs'),
1020
+ path.join(__dirname, 'onboarding-generator.js'),
1018
1021
  'generateOnboardingGuide'
1019
1022
  );
1020
1023
  }
@@ -1022,7 +1025,7 @@ function cmdValidateHealth(cwd, options, raw) {
1022
1025
  // ─── Check 15: Phase 14 Quality & Safety feature health ───────────────────
1023
1026
  {
1024
1027
  let p14Config = {};
1025
- try { p14Config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (_) {}
1028
+ try { p14Config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (err) { if (process.env.PBR_DEBUG) console.error(`[verify] Failed to parse config for phase14: ${err.message}`); }
1026
1029
 
1027
1030
  const p14Features = p14Config.features || {};
1028
1031
 
@@ -1040,7 +1043,8 @@ function cmdValidateHealth(cwd, options, raw) {
1040
1043
  }
1041
1044
  addIssue('warning', `W-${featureName.toUpperCase()}-DEGRADED`, `${featureName}: degraded (module validation failed)`, `Check ${modulePath} exports`);
1042
1045
  return { enabled: true, status: 'degraded' };
1043
- } catch (_e) {
1046
+ } catch (err) {
1047
+ if (process.env.PBR_DEBUG) console.error(`[verify] Feature ${featureName} module load failed: ${err.message}`);
1044
1048
  addIssue('warning', `W-${featureName.toUpperCase()}-DEGRADED`, `${featureName}: degraded (module load failed)`, `Ensure ${modulePath} exists and is valid`);
1045
1049
  return { enabled: true, status: 'degraded' };
1046
1050
  }
@@ -1048,7 +1052,7 @@ function cmdValidateHealth(cwd, options, raw) {
1048
1052
 
1049
1053
  // regression_prevention: default true
1050
1054
  const rpEnabled = p14Features.regression_prevention !== false;
1051
- const rpModPath = path.join(__dirname, 'test-selection.cjs');
1055
+ const rpModPath = path.join(__dirname, 'test-selection.js');
1052
1056
  const rpHealth = checkFeatureHealth(
1053
1057
  'regression_prevention',
1054
1058
  rpEnabled,
@@ -1062,7 +1066,7 @@ function cmdValidateHealth(cwd, options, raw) {
1062
1066
 
1063
1067
  // security_scanning: default true
1064
1068
  const ssEnabled = p14Features.security_scanning !== false;
1065
- const ssModPath = path.join(__dirname, 'security-scan.cjs');
1069
+ const ssModPath = path.join(__dirname, 'security-scan.js');
1066
1070
  const ssHealth = checkFeatureHealth(
1067
1071
  'security_scanning',
1068
1072
  ssEnabled,
@@ -1074,7 +1078,7 @@ function cmdValidateHealth(cwd, options, raw) {
1074
1078
  const ssMod = require(ssModPath);
1075
1079
  const ruleCount = ssMod.SECURITY_RULES.length;
1076
1080
  addIssue('info', 'I-SS-HEALTHY', `security_scanning: healthy (${ruleCount} rules loaded)`, '');
1077
- } catch (_) {}
1081
+ } catch (err) { if (process.env.PBR_DEBUG) console.error(`[verify] Failed to load security rules: ${err.message}`); }
1078
1082
  }
1079
1083
  feature_status.security_scanning = ssHealth;
1080
1084
  }
@@ -1082,7 +1086,7 @@ function cmdValidateHealth(cwd, options, raw) {
1082
1086
  // ─── Check 16: Phase 11 Spec-Driven Development feature health ───────────
1083
1087
  {
1084
1088
  let p11Config = {};
1085
- try { p11Config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (_) {}
1089
+ try { p11Config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (err) { if (process.env.PBR_DEBUG) console.error(`[verify] Failed to parse config for phase11: ${err.message}`); }
1086
1090
  const p11Features = p11Config.features || {};
1087
1091
 
1088
1092
  const checkSpecFeatureHealth = (featureName, defaultEnabled, modulePath, exportName) => {
@@ -1096,29 +1100,30 @@ function cmdValidateHealth(cwd, options, raw) {
1096
1100
  return { status: 'healthy', enabled: true, details: `${exportName} loaded` };
1097
1101
  }
1098
1102
  return { status: 'degraded', enabled: true, details: `${exportName} not a function` };
1099
- } catch (_e) {
1100
- return { status: 'degraded', enabled: true, details: `Cannot load module: ${_e.message}` };
1103
+ } catch (err) {
1104
+ if (process.env.PBR_DEBUG) console.error(`[verify] Cannot load spec module: ${err.message}`);
1105
+ return { status: 'degraded', enabled: true, details: `Cannot load module: ${err.message}` };
1101
1106
  }
1102
1107
  };
1103
1108
 
1104
1109
  feature_status.machine_executable_plans = checkSpecFeatureHealth(
1105
- 'machine_executable_plans', false, path.join(__dirname, 'spec-engine.cjs'), 'parsePlanToSpec'
1110
+ 'machine_executable_plans', false, path.join(__dirname, 'spec-engine.js'), 'parsePlanToSpec'
1106
1111
  );
1107
1112
  feature_status.spec_diffing = checkSpecFeatureHealth(
1108
- 'spec_diffing', true, path.join(__dirname, 'spec-diff.cjs'), 'diffSpecs'
1113
+ 'spec_diffing', true, path.join(__dirname, 'spec-diff.js'), 'diffSpecs'
1109
1114
  );
1110
1115
  feature_status.reverse_spec = checkSpecFeatureHealth(
1111
- 'reverse_spec', true, path.join(__dirname, 'reverse-spec.cjs'), 'generateReverseSpec'
1116
+ 'reverse_spec', true, path.join(__dirname, 'reverse-spec.js'), 'generateReverseSpec'
1112
1117
  );
1113
1118
  feature_status.predictive_impact = checkSpecFeatureHealth(
1114
- 'predictive_impact', true, path.join(__dirname, 'impact-analysis.cjs'), 'analyzeImpact'
1119
+ 'predictive_impact', true, path.join(__dirname, 'impact-analysis.js'), 'analyzeImpact'
1115
1120
  );
1116
1121
  }
1117
1122
 
1118
1123
  // ─── Check 17: Phase 16 cross-project intelligence feature health ────────
1119
1124
  {
1120
1125
  let p16Config = {};
1121
- try { p16Config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (_) {}
1126
+ try { p16Config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (err) { if (process.env.PBR_DEBUG) console.error(`[verify] Failed to parse config for phase16: ${err.message}`); }
1122
1127
  const p16Features = p16Config.features || {};
1123
1128
 
1124
1129
  // Helper: check if a feature is enabled (default true unless explicitly false)
@@ -1138,7 +1143,7 @@ function cmdValidateHealth(cwd, options, raw) {
1138
1143
  const patternsDir = require('path').join(require('os').homedir(), '.claude', 'patterns');
1139
1144
  return fs.existsSync(patternsDir) &&
1140
1145
  fs.readdirSync(patternsDir).some(f => f.endsWith('.json'));
1141
- } catch (_) { return false; }
1146
+ } catch (err) { if (process.env.PBR_DEBUG) console.error(`[verify] Failed to check patterns dir: ${err.message}`); return false; }
1142
1147
  }
1143
1148
  );
1144
1149
 
@@ -1155,7 +1160,7 @@ function cmdValidateHealth(cwd, options, raw) {
1155
1160
  try {
1156
1161
  const learningsPath = require('path').join(require('os').homedir(), '.claude', 'learnings.jsonl');
1157
1162
  return fs.existsSync(learningsPath);
1158
- } catch (_) { return false; }
1163
+ } catch (err) { if (process.env.PBR_DEBUG) console.error(`[verify] Failed to check learnings path: ${err.message}`); return false; }
1159
1164
  }
1160
1165
  );
1161
1166
  }
@@ -1163,7 +1168,7 @@ function cmdValidateHealth(cwd, options, raw) {
1163
1168
  // ─── Check 18: Phase 3 (zero-friction) feature status ────────────────────
1164
1169
  {
1165
1170
  let p3Config = {};
1166
- try { p3Config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (_) {}
1171
+ try { p3Config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (err) { if (process.env.PBR_DEBUG) console.error(`[verify] Failed to parse config for phase3: ${err.message}`); }
1167
1172
  const p3Features = p3Config.features || {};
1168
1173
 
1169
1174
  const zfqEnabled = p3Features.zero_friction_quick !== false;
@@ -1176,7 +1181,7 @@ function cmdValidateHealth(cwd, options, raw) {
1176
1181
  // ─── Check 19: Phase 4 (NL routing) feature status ───────────────────────
1177
1182
  {
1178
1183
  let p4Config = {};
1179
- try { p4Config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (_) {}
1184
+ try { p4Config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (err) { if (process.env.PBR_DEBUG) console.error(`[verify] Failed to parse config for phase4: ${err.message}`); }
1180
1185
  const p4Features = p4Config.features || {};
1181
1186
  const pluginRoot = path.resolve(__dirname, '..', '..', '..', 'plugins', 'pbr');
1182
1187
 
@@ -1188,7 +1193,8 @@ function cmdValidateHealth(cwd, options, raw) {
1188
1193
  try {
1189
1194
  require(path.join(pluginRoot, 'scripts', 'lib', 'alternatives.js'));
1190
1195
  feature_status.natural_language_routing = { enabled: true, status: 'healthy' };
1191
- } catch (_e) {
1196
+ } catch (err) {
1197
+ if (process.env.PBR_DEBUG) console.error(`[verify] Failed to load alternatives.js: ${err.message}`);
1192
1198
  feature_status.natural_language_routing = { enabled: true, status: 'degraded' };
1193
1199
  }
1194
1200
  }
@@ -1204,7 +1210,7 @@ function cmdValidateHealth(cwd, options, raw) {
1204
1210
  // ─── Check 20: Phase 6 (convention memory) feature status ────────────────
1205
1211
  {
1206
1212
  let p6Config = {};
1207
- try { p6Config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (_) {}
1213
+ try { p6Config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (err) { if (process.env.PBR_DEBUG) console.error(`[verify] Failed to parse config for phase6: ${err.message}`); }
1208
1214
  const p6Features = p6Config.features || {};
1209
1215
  const pluginRoot = path.resolve(__dirname, '..', '..', '..', 'plugins', 'pbr');
1210
1216
 
@@ -1216,7 +1222,8 @@ function cmdValidateHealth(cwd, options, raw) {
1216
1222
  try {
1217
1223
  require(path.join(pluginRoot, 'scripts', 'lib', 'convention-detector.js'));
1218
1224
  feature_status.convention_memory = { enabled: true, status: 'healthy' };
1219
- } catch (_e) {
1225
+ } catch (err) {
1226
+ if (process.env.PBR_DEBUG) console.error(`[verify] Failed to load convention-detector.js: ${err.message}`);
1220
1227
  feature_status.convention_memory = { enabled: true, status: 'degraded' };
1221
1228
  }
1222
1229
  }
@@ -1229,7 +1236,8 @@ function cmdValidateHealth(cwd, options, raw) {
1229
1236
  try {
1230
1237
  require(path.join(pluginRoot, 'scripts', 'lib', 'snapshot-manager.js'));
1231
1238
  feature_status.mental_model_snapshots = { enabled: true, status: 'healthy' };
1232
- } catch (_e) {
1239
+ } catch (err) {
1240
+ if (process.env.PBR_DEBUG) console.error(`[verify] Failed to load snapshot-manager.js: ${err.message}`);
1233
1241
  feature_status.mental_model_snapshots = { enabled: true, status: 'degraded' };
1234
1242
  }
1235
1243
  }
@@ -1238,7 +1246,7 @@ function cmdValidateHealth(cwd, options, raw) {
1238
1246
  // ─── Check 21: Phase 9 (proactive intelligence) feature status ───────────
1239
1247
  {
1240
1248
  let p9Config = {};
1241
- try { p9Config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (_) {}
1249
+ try { p9Config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (err) { if (process.env.PBR_DEBUG) console.error(`[verify] Failed to parse config for phase9: ${err.message}`); }
1242
1250
  const scriptsDir = path.resolve(__dirname, '..', '..', '..', 'plugins', 'pbr', 'scripts');
1243
1251
  const { checkFeatureHealth: checkPhase9FeatureHealth } = require('./health');
1244
1252
  const phase9Features = [
@@ -1274,7 +1282,8 @@ function cmdValidateHealth(cwd, options, raw) {
1274
1282
  enabled: metricsResult.enabled,
1275
1283
  status: metricsResult.status,
1276
1284
  };
1277
- } catch (_e) {
1285
+ } catch (err) {
1286
+ if (process.env.PBR_DEBUG) console.error(`[verify] Failed to load health-checks.js: ${err.message}`);
1278
1287
  // health-checks.js not available — mark all as degraded
1279
1288
  feature_status.post_hoc_artifacts = { enabled: true, status: 'degraded' };
1280
1289
  feature_status.agent_feedback_loop = { enabled: true, status: 'degraded' };
@@ -1285,7 +1294,7 @@ function cmdValidateHealth(cwd, options, raw) {
1285
1294
  // ─── Check 23: Phase 13 (multi-agent) feature status ─────────────────────
1286
1295
  {
1287
1296
  let p13Config = {};
1288
- try { p13Config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (_) {}
1297
+ try { p13Config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (err) { if (process.env.PBR_DEBUG) console.error(`[verify] Failed to parse config for phase13: ${err.message}`); }
1289
1298
  const { checkMultiAgentHealth } = require('./health');
1290
1299
  const multiAgentResults = checkMultiAgentHealth(p13Config);
1291
1300
  for (const result of multiAgentResults) {
@@ -1407,7 +1416,8 @@ function checkFeatureModuleHealth(featureName, planningDir, pluginRoot, modulePa
1407
1416
  if (fs.existsSync(configPath)) {
1408
1417
  config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
1409
1418
  }
1410
- } catch (_e) {
1419
+ } catch (err) {
1420
+ if (process.env.PBR_DEBUG) console.error(`[verify] Config unreadable for feature health: ${err.message}`);
1411
1421
  // Config unreadable — treat as defaults
1412
1422
  }
1413
1423