@sienklogic/plan-build-run 2.19.0 → 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 CHANGED
@@ -5,6 +5,13 @@ 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
+
8
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)
9
16
 
10
17
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sienklogic/plan-build-run",
3
- "version": "2.19.0",
3
+ "version": "2.20.0",
4
4
  "description": "Plan it, Build it, Run it — structured development workflow for Claude Code",
5
5
  "keywords": [
6
6
  "claude-code",
@@ -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.19.0",
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",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pbr",
3
3
  "displayName": "Plan-Build-Run",
4
- "version": "2.19.0",
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",
@@ -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": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pbr",
3
- "version": "2.19.0",
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",
@@ -3,6 +3,7 @@ name: plan-checker
3
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
@@ -3,6 +3,7 @@ name: verifier
3
3
  description: "Goal-backward phase verification. Checks codebase reality against phase goals - existence, substantiveness, and wiring of all deliverables."
4
4
  model: sonnet
5
5
  memory: none
6
+ isolation: worktree
6
7
  tools:
7
8
  - Read
8
9
  - Bash
@@ -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": [
@@ -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 };
@@ -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
@@ -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.