@sienklogic/plan-build-run 2.56.0 → 2.56.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.
- package/CHANGELOG.md +14 -0
- package/README.md +76 -28
- package/package.json +1 -1
- package/plugins/codex-pbr/references/pbr-tools-cli.md +2 -2
- package/plugins/codex-pbr/skills/audit/SKILL.md +2 -2
- package/plugins/codex-pbr/skills/explore/SKILL.md +28 -1
- package/plugins/codex-pbr/skills/health/SKILL.md +1 -1
- package/plugins/codex-pbr/skills/shared/context-loader-task.md +1 -0
- package/plugins/codex-pbr/skills/shared/state-update.md +1 -1
- package/plugins/codex-pbr/skills/shared/universal-anti-patterns.md +1 -0
- package/plugins/copilot-pbr/plugin.json +1 -1
- package/plugins/copilot-pbr/references/pbr-tools-cli.md +2 -2
- package/plugins/copilot-pbr/skills/audit/SKILL.md +2 -2
- package/plugins/copilot-pbr/skills/begin/templates/STATE.md.tmpl +0 -1
- package/plugins/copilot-pbr/skills/explore/SKILL.md +28 -1
- package/plugins/copilot-pbr/skills/health/SKILL.md +1 -1
- package/plugins/copilot-pbr/skills/shared/context-loader-task.md +1 -0
- package/plugins/copilot-pbr/skills/shared/state-update.md +1 -1
- package/plugins/copilot-pbr/skills/shared/universal-anti-patterns.md +1 -0
- package/plugins/cursor-pbr/.cursor-plugin/plugin.json +1 -1
- package/plugins/cursor-pbr/references/pbr-tools-cli.md +2 -2
- package/plugins/cursor-pbr/skills/audit/SKILL.md +2 -2
- package/plugins/cursor-pbr/skills/begin/templates/STATE.md.tmpl +0 -1
- package/plugins/cursor-pbr/skills/explore/SKILL.md +28 -1
- package/plugins/cursor-pbr/skills/health/SKILL.md +1 -1
- package/plugins/cursor-pbr/skills/shared/context-loader-task.md +1 -0
- package/plugins/cursor-pbr/skills/shared/state-update.md +1 -1
- package/plugins/cursor-pbr/skills/shared/universal-anti-patterns.md +1 -0
- package/plugins/pbr/.claude-plugin/plugin.json +1 -1
- package/plugins/pbr/references/pbr-tools-cli.md +2 -2
- package/plugins/pbr/scripts/check-plan-format.js +5 -6
- package/plugins/pbr/scripts/check-state-sync.js +0 -5
- package/plugins/pbr/scripts/enforce-pbr-workflow.js +31 -5
- package/plugins/pbr/scripts/lib/state.js +1 -3
- package/plugins/pbr/scripts/pbr-tools.js +1 -1
- package/plugins/pbr/scripts/status-line.js +3 -4
- package/plugins/pbr/skills/audit/SKILL.md +2 -2
- package/plugins/pbr/skills/begin/templates/STATE.md.tmpl +0 -1
- package/plugins/pbr/skills/explore/SKILL.md +28 -1
- package/plugins/pbr/skills/health/SKILL.md +1 -1
- package/plugins/pbr/skills/shared/context-loader-task.md +1 -0
- package/plugins/pbr/skills/shared/state-update.md +1 -1
- package/plugins/pbr/skills/shared/universal-anti-patterns.md +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,20 @@ 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.56.2](https://github.com/SienkLogic/plan-build-run/compare/plan-build-run-v2.56.1...plan-build-run-v2.56.2) (2026-03-03)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* **tools:** block non-PBR agent types by default with [native] bypass ([0256189](https://github.com/SienkLogic/plan-build-run/commit/02561890e49dba88df03d3977f9a8597740bd389))
|
|
14
|
+
|
|
15
|
+
## [2.56.1](https://github.com/SienkLogic/plan-build-run/compare/plan-build-run-v2.56.0...plan-build-run-v2.56.1) (2026-03-03)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Documentation
|
|
19
|
+
|
|
20
|
+
* **quick-020:** comprehensively update documentation for v2.56.0 ([82f9177](https://github.com/SienkLogic/plan-build-run/commit/82f917792dd573192c4ce69df8633f13b1050b0a))
|
|
21
|
+
|
|
8
22
|
## [2.56.0](https://github.com/SienkLogic/plan-build-run/compare/plan-build-run-v2.55.0...plan-build-run-v2.56.0) (2026-03-02)
|
|
9
23
|
|
|
10
24
|
|
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
<p align="center">
|
|
6
|
-
<strong>Context-engineered development workflow for Claude Code, Cursor,
|
|
6
|
+
<strong>Context-engineered development workflow for Claude Code, Cursor, GitHub Copilot CLI, OpenAI Codex, and Google Jules.</strong>
|
|
7
7
|
<br />
|
|
8
8
|
Build ambitious multi-phase software without quality degradation.
|
|
9
9
|
<br />
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
<img src="https://img.shields.io/badge/Node.js-18%2B-339933?style=for-the-badge&logo=node.js&logoColor=white" alt="Node.js 18+" />
|
|
28
28
|
<a href="LICENSE"><img src="https://img.shields.io/github/license/SienkLogic/plan-build-run?style=for-the-badge" alt="License" /></a>
|
|
29
29
|
<a href="https://www.npmjs.com/package/@sienklogic/plan-build-run"><img src="https://img.shields.io/npm/v/@sienklogic/plan-build-run?style=for-the-badge&logo=npm&logoColor=white" alt="npm" /></a>
|
|
30
|
-
<img src="https://img.shields.io/badge/Tests-
|
|
30
|
+
<img src="https://img.shields.io/badge/Tests-9283_passing-brightgreen?style=for-the-badge" alt="9283 Tests" />
|
|
31
31
|
</p>
|
|
32
32
|
|
|
33
33
|
---
|
|
@@ -132,6 +132,48 @@ All three plugins share the same `.planning/` directory — start in any tool, c
|
|
|
132
132
|
|
|
133
133
|
</details>
|
|
134
134
|
|
|
135
|
+
<details>
|
|
136
|
+
<summary><strong>Install for OpenAI Codex CLI</strong></summary>
|
|
137
|
+
|
|
138
|
+
Plan-Build-Run also works in OpenAI Codex CLI. Skills and agents are available via the `plugins/codex-pbr/` plugin. No hooks (Codex CLI does not support lifecycle hooks).
|
|
139
|
+
|
|
140
|
+
**macOS / Linux:**
|
|
141
|
+
```bash
|
|
142
|
+
cd /path/to/your/project
|
|
143
|
+
bash /path/to/plan-build-run/plugins/codex-pbr/setup.sh
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**Windows (PowerShell):**
|
|
147
|
+
```powershell
|
|
148
|
+
cd C:\path\to\your\project
|
|
149
|
+
powershell -ExecutionPolicy Bypass -File C:\path\to\plan-build-run\plugins\codex-pbr\setup.ps1
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
All five plugins share the same `.planning/` directory. See [`plugins/codex-pbr/README.md`](plugins/codex-pbr/README.md) for full details.
|
|
153
|
+
|
|
154
|
+
</details>
|
|
155
|
+
|
|
156
|
+
<details>
|
|
157
|
+
<summary><strong>Install for Google Jules</strong></summary>
|
|
158
|
+
|
|
159
|
+
Plan-Build-Run also works in Google Jules. Skills and agents are available via the `plugins/jules-pbr/` plugin. No hooks (Jules does not support lifecycle hooks).
|
|
160
|
+
|
|
161
|
+
**macOS / Linux:**
|
|
162
|
+
```bash
|
|
163
|
+
cd /path/to/your/project
|
|
164
|
+
bash /path/to/plan-build-run/plugins/jules-pbr/setup.sh
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
**Windows (PowerShell):**
|
|
168
|
+
```powershell
|
|
169
|
+
cd C:\path\to\your\project
|
|
170
|
+
powershell -ExecutionPolicy Bypass -File C:\path\to\plan-build-run\plugins\jules-pbr\setup.ps1
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
All five plugins share the same `.planning/` directory. See [`plugins/jules-pbr/README.md`](plugins/jules-pbr/README.md) for full details.
|
|
174
|
+
|
|
175
|
+
</details>
|
|
176
|
+
|
|
135
177
|
<details>
|
|
136
178
|
<summary><strong>Dashboard (Optional)</strong></summary>
|
|
137
179
|
|
|
@@ -219,7 +261,7 @@ Set `depth: quick` in `/pbr:config` to reduce agent spawns across all workflows.
|
|
|
219
261
|
| `/pbr:build <N>` | Build a phase: parallel execution in waves, atomic commits | 2-4 (quick: 1-2) |
|
|
220
262
|
| `/pbr:review <N>` | Verify a phase: automated 3-layer checks + conversational UAT | 1 |
|
|
221
263
|
|
|
222
|
-
See **[Commands](https://github.com/SienkLogic/plan-build-run/wiki/Commands)** for all
|
|
264
|
+
See **[Commands](https://github.com/SienkLogic/plan-build-run/wiki/Commands)** for all 27 commands with flags, cost-by-depth tables, and detailed descriptions.
|
|
223
265
|
|
|
224
266
|
---
|
|
225
267
|
|
|
@@ -292,8 +334,8 @@ Requires a GPU with 6+ GB VRAM for best performance. CPU-only works but adds lat
|
|
|
292
334
|
| Topic | Description |
|
|
293
335
|
|-------|-------------|
|
|
294
336
|
| **[Agents](https://github.com/SienkLogic/plan-build-run/wiki/Agents)** | 12 specialized agents with configurable model profiles and file-based communication |
|
|
295
|
-
| **[Configuration](https://github.com/SienkLogic/plan-build-run/wiki/Configuration)** |
|
|
296
|
-
| **[Hooks](https://github.com/SienkLogic/plan-build-run/wiki/Hooks)** |
|
|
337
|
+
| **[Configuration](https://github.com/SienkLogic/plan-build-run/wiki/Configuration)** | 12 config keys, depth/model profiles, 14+ feature toggles, local LLM settings |
|
|
338
|
+
| **[Hooks](https://github.com/SienkLogic/plan-build-run/wiki/Hooks)** | 41 hook scripts that enforce discipline at zero token cost |
|
|
297
339
|
| **[Local LLM](https://github.com/SienkLogic/plan-build-run/wiki/Configuration#local_llm)** | Offload hook-level inference to Ollama for token savings with automatic fallback |
|
|
298
340
|
| **[Project Structure](https://github.com/SienkLogic/plan-build-run/wiki/Project-Structure)** | The `.planning/` directory layout, key files, and file ownership |
|
|
299
341
|
| **[Dashboard](https://github.com/SienkLogic/plan-build-run/wiki/Dashboard)** | Web UI with live updates for browsing project state |
|
|
@@ -306,28 +348,29 @@ Requires a GPU with 6+ GB VRAM for best performance. CPU-only works but adds lat
|
|
|
306
348
|
|
|
307
349
|
## Platform Compatibility
|
|
308
350
|
|
|
309
|
-
Plan-Build-Run works across
|
|
310
|
-
|
|
311
|
-
| Feature | Claude Code | Copilot CLI | Cursor IDE |
|
|
312
|
-
|
|
313
|
-
| Skills (slash commands) | All
|
|
314
|
-
| Agents (subagent delegation) | All 12 | All 12 | All 12 |
|
|
315
|
-
| `.planning/` state management | Full | Full | Full |
|
|
316
|
-
| **Hook support** | **Full (14 events)** | **Partial (4 events)** | **Unverified** |
|
|
317
|
-
| Commit format enforcement | Hook-enforced | Hook-enforced | Manual |
|
|
318
|
-
| PLAN/SUMMARY quality classification | Hook + skill fallback | Hook + skill fallback | Skill fallback only |
|
|
319
|
-
| Test failure triage | Automatic (hook) | Automatic (hook) | Not available |
|
|
320
|
-
| Context budget tracking | Automatic (hook) | Not available | Not available |
|
|
321
|
-
| Auto-continue between skills | Automatic (hook) | Not available | Not available |
|
|
322
|
-
| Subagent lifecycle logging | Automatic (hook) | Not available | Not available |
|
|
323
|
-
| **Local LLM offloading** | **Full (8 operations)** | **Mostly (6-7 operations)** | **CLI only** |
|
|
324
|
-
| `pbr-tools.js llm` CLI commands | Full | Full | Full |
|
|
351
|
+
Plan-Build-Run works across five platforms with varying levels of hook support. Hooks are the mechanism that fires validation scripts on every tool call — they power local LLM offloading, commit format enforcement, context budget tracking, and workflow gates.
|
|
352
|
+
|
|
353
|
+
| Feature | Claude Code | Copilot CLI | Cursor IDE | Codex CLI | Jules |
|
|
354
|
+
|---------|:-----------:|:-----------:|:----------:|:---------:|:-----:|
|
|
355
|
+
| Skills (slash commands) | All 27 | All 27 | All 27 | All 27 | All 27 |
|
|
356
|
+
| Agents (subagent delegation) | All 12 | All 12 | All 12 | All 12 | All 12 |
|
|
357
|
+
| `.planning/` state management | Full | Full | Full | Full | Full |
|
|
358
|
+
| **Hook support** | **Full (14 events)** | **Partial (4 events)** | **Unverified** | **None** | **None** |
|
|
359
|
+
| Commit format enforcement | Hook-enforced | Hook-enforced | Manual | Manual | Manual |
|
|
360
|
+
| PLAN/SUMMARY quality classification | Hook + skill fallback | Hook + skill fallback | Skill fallback only | Skill fallback only | Skill fallback only |
|
|
361
|
+
| Test failure triage | Automatic (hook) | Automatic (hook) | Not available | Not available | Not available |
|
|
362
|
+
| Context budget tracking | Automatic (hook) | Not available | Not available | Not available | Not available |
|
|
363
|
+
| Auto-continue between skills | Automatic (hook) | Not available | Not available | Not available | Not available |
|
|
364
|
+
| Subagent lifecycle logging | Automatic (hook) | Not available | Not available | Not available | Not available |
|
|
365
|
+
| **Local LLM offloading** | **Full (8 operations)** | **Mostly (6-7 operations)** | **CLI only** | **CLI only** | **CLI only** |
|
|
366
|
+
| `pbr-tools.js llm` CLI commands | Full | Full | Full | Full | Full |
|
|
325
367
|
|
|
326
368
|
**Key differences:**
|
|
327
369
|
|
|
328
370
|
- **Claude Code** has full hook support — all local LLM operations fire automatically on every tool call
|
|
329
371
|
- **Copilot CLI** supports `sessionStart`, `preToolUse`, `postToolUse`, and `sessionEnd` — covers most validation hooks but misses lifecycle events (`SubagentStop`, `PreCompact`, `Stop`)
|
|
330
372
|
- **Cursor IDE** hook support is unverified — hooks.json is configured but whether Cursor actually fires them is unknown. Skills include `pbr-tools.js llm` fallback calls for key operations (plan quality, verification quality) so local LLM classification is available even without hooks
|
|
373
|
+
- **OpenAI Codex CLI** and **Google Jules** do not support hooks. All skills and agents are available via `plugins/codex-pbr/` and `plugins/jules-pbr/` respectively. Agent definitions use AGENTS.md format.
|
|
331
374
|
|
|
332
375
|
All platforms share the same scripts via relative paths — no code duplication. See the [Copilot CLI](plugins/copilot-pbr/README.md) and [Cursor IDE](plugins/cursor-pbr/README.md) READMEs for platform-specific details.
|
|
333
376
|
|
|
@@ -341,7 +384,7 @@ git clone https://github.com/SienkLogic/plan-build-run.git
|
|
|
341
384
|
cd plan-build-run
|
|
342
385
|
npm install
|
|
343
386
|
|
|
344
|
-
# Run tests (
|
|
387
|
+
# Run tests (9283 tests, 281 suites)
|
|
345
388
|
npm test
|
|
346
389
|
|
|
347
390
|
# Lint
|
|
@@ -362,14 +405,19 @@ CI runs on Node 18/20/22 across Windows, macOS, and Linux. See [CONTRIBUTING.md]
|
|
|
362
405
|
|
|
363
406
|
| Metric | Count |
|
|
364
407
|
|--------|-------|
|
|
365
|
-
| Skills (slash commands) |
|
|
408
|
+
| Skills (slash commands) | 27 |
|
|
366
409
|
| Specialized agents | 12 |
|
|
367
|
-
| Hook scripts |
|
|
410
|
+
| Hook scripts | 41 |
|
|
368
411
|
| Local LLM operations | 8 |
|
|
369
|
-
| Supported platforms |
|
|
370
|
-
| Tests |
|
|
371
|
-
| Test suites |
|
|
372
|
-
| Config keys |
|
|
412
|
+
| Supported platforms | 5 (Claude Code, Cursor, Copilot CLI, Codex, Jules) |
|
|
413
|
+
| Tests | 9283 |
|
|
414
|
+
| Test suites | 281 |
|
|
415
|
+
| Config keys | 12 top-level (62+ properties) |
|
|
416
|
+
| Feature toggles | 14 |
|
|
417
|
+
| Lib modules | 19 |
|
|
418
|
+
| Shared fragments | 12 |
|
|
419
|
+
| Templates | 10 |
|
|
420
|
+
| References | 19 |
|
|
373
421
|
|
|
374
422
|
---
|
|
375
423
|
|
package/package.json
CHANGED
|
@@ -361,7 +361,7 @@ All phases with status and completion data.
|
|
|
361
361
|
node ${CLAUDE_PLUGIN_ROOT}/scripts/pbr-tools.js init progress
|
|
362
362
|
```
|
|
363
363
|
|
|
364
|
-
**Output:** `current_phase`, `
|
|
364
|
+
**Output:** `current_phase`, `phase_count`, `status`, `phases` array, `total_plans`, `completed_plans`, `percentage`.
|
|
365
365
|
|
|
366
366
|
---
|
|
367
367
|
|
|
@@ -375,7 +375,7 @@ Multi-field atomic STATE.md update. Updates all fields in a single pass.
|
|
|
375
375
|
node ${CLAUDE_PLUGIN_ROOT}/scripts/pbr-tools.js state patch '{"status":"executing","last_activity":"now"}'
|
|
376
376
|
```
|
|
377
377
|
|
|
378
|
-
**Valid fields:** `current_phase`, `status`, `plans_complete`, `last_activity`, `progress_percent`, `phase_slug`, `
|
|
378
|
+
**Valid fields:** `current_phase`, `status`, `plans_complete`, `last_activity`, `progress_percent`, `phase_slug`, `last_command`, `blockers`
|
|
379
379
|
|
|
380
380
|
**Output:** `{ "success": true, "updated": ["status", "last_activity"] }`
|
|
381
381
|
|
|
@@ -153,11 +153,11 @@ Task({
|
|
|
153
153
|
})
|
|
154
154
|
```
|
|
155
155
|
|
|
156
|
-
Also spawn a git analysis agent
|
|
156
|
+
Also spawn a git analysis agent:
|
|
157
157
|
|
|
158
158
|
```
|
|
159
159
|
Task({
|
|
160
|
-
subagent_type: "
|
|
160
|
+
subagent_type: "pbr:general",
|
|
161
161
|
model: "haiku",
|
|
162
162
|
prompt: "Run these git commands in {project_dir}:
|
|
163
163
|
1. git log --since='{from}' --until='{to}' --format='%h|%s|%an|%ai' --all
|
|
@@ -21,7 +21,9 @@ Then proceed to Step 1.
|
|
|
21
21
|
|
|
22
22
|
You are running the **explore** skill. Your job is to help the user think through ideas that might become a todo, requirement, phase, decision, or nothing yet. This is Socratic conversation, not requirements gathering. No phase number is needed.
|
|
23
23
|
|
|
24
|
-
This skill runs **inline** (no Task delegation), with optional Task() spawns for context loading and mid-conversation research.
|
|
24
|
+
This skill runs **inline** (no Task delegation), with optional Task() spawns for context loading, upfront research, and mid-conversation research.
|
|
25
|
+
|
|
26
|
+
**CRITICAL: Agent type rule** — When spawning ANY research or analysis Task(), ALWAYS use `subagent_type: "pbr:researcher"`. NEVER use `general-purpose`, `Explore`, or other non-PBR agent types. The PreToolUse hook will block non-PBR agents.
|
|
25
27
|
|
|
26
28
|
---
|
|
27
29
|
|
|
@@ -103,6 +105,31 @@ Reference `skills/shared/domain-probes.md` for technology-specific follow-up que
|
|
|
103
105
|
|
|
104
106
|
---
|
|
105
107
|
|
|
108
|
+
## Upfront Research Delegation
|
|
109
|
+
|
|
110
|
+
When the user's initial request is research-heavy (e.g., "explore best practices for X", "research how other projects do Y", "compare approaches to Z"), delegate immediately to `pbr:researcher` agents rather than doing inline research.
|
|
111
|
+
|
|
112
|
+
**Detection**: If `$ARGUMENTS` contains words like "research", "compare", "explore examples", "best practices", "how do others", or describes gathering external information — this is an upfront research task.
|
|
113
|
+
|
|
114
|
+
**Pattern**: Spawn one or more `pbr:researcher` agents in parallel, then synthesize their findings inline:
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
Task({
|
|
118
|
+
subagent_type: "pbr:researcher",
|
|
119
|
+
prompt: "<research_assignment>
|
|
120
|
+
Topic: {specific research question from user's request}
|
|
121
|
+
Output: Return findings as structured markdown in your response.
|
|
122
|
+
Mode: external-research
|
|
123
|
+
|
|
124
|
+
{detailed research instructions}
|
|
125
|
+
</research_assignment>"
|
|
126
|
+
})
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
After researchers complete, synthesize findings inline and continue the Socratic conversation with the user about what was discovered.
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
106
133
|
## Mid-Conversation Research
|
|
107
134
|
|
|
108
135
|
When a knowledge gap emerges during the conversation — you're unsure about a library, pattern, or approach — surface it explicitly.
|
|
@@ -172,7 +172,7 @@ After running all 10 checks and collecting results, if any of the following auto
|
|
|
172
172
|
|
|
173
173
|
| Pattern | Detection | Fix Action |
|
|
174
174
|
|---------|-----------|------------|
|
|
175
|
-
| Missing STATE.md frontmatter | Check 5 finds STATE.md without `---` block | Regenerate frontmatter from ROADMAP.md phase data (current_phase,
|
|
175
|
+
| Missing STATE.md frontmatter | Check 5 finds STATE.md without `---` block | Regenerate frontmatter from ROADMAP.md phase data (current_phase, phase_slug, status) |
|
|
176
176
|
| STATE.md phase_slug mismatch | Check 5/7 finds phase_slug doesn't match current phase directory name | Correct phase_slug to match the actual directory name in `.planning/phases/` |
|
|
177
177
|
| Missing config.json | Check 1/2 finds no `.planning/config.json` | Create with default config template (same as `$pbr-setup` defaults) |
|
|
178
178
|
| Orphaned .active-skill file | Check 10 or general scan finds `.planning/.active-skill` older than 1 hour | Delete the stale `.active-skill` file |
|
|
@@ -44,6 +44,7 @@ Task({
|
|
|
44
44
|
2. **Budget: ~500 tokens.** The briefing must be concise. The subagent reads full files in its own context; the orchestrator receives only the summary.
|
|
45
45
|
3. **No suggestions.** The briefing reports state, it does not recommend actions. The skill logic decides what to do.
|
|
46
46
|
4. **Read-only.** The briefing task must not write any files.
|
|
47
|
+
5. **No subagent_type needed.** This is the ONE exception to the "always use `pbr:*` agents" rule. Bare `Task()` without `subagent_type` is intentional here — these are lightweight read-only briefings that don't need agent-specific prompts. Do NOT generalize this pattern to other Task() calls — all research, execution, and analysis Task() calls MUST use `subagent_type: "pbr:{agent}"`.
|
|
47
48
|
|
|
48
49
|
### Using the Briefing
|
|
49
50
|
|
|
@@ -53,7 +53,7 @@ Progress: [{progress_bar}] {percent}%
|
|
|
53
53
|
Phase 3 of 10 = 20% → [████░░░░░░░░░░░░░░░░] 20%
|
|
54
54
|
Phase 7 of 10 = 70% → [██████████████░░░░░░] 70%
|
|
55
55
|
```
|
|
56
|
-
Calculation: `filled = Math.round((completed_phases /
|
|
56
|
+
Calculation: `filled = Math.round((completed_phases / phase_count) * 20)` where `phase_count` is derived from ROADMAP.md (available via `stateLoad` as `phase_count`)
|
|
57
57
|
|
|
58
58
|
### 3. Accumulated Context (lines 16-25)
|
|
59
59
|
```
|
|
@@ -26,6 +26,7 @@ These rules prevent context rot -- quality degradation as the context window fil
|
|
|
26
26
|
## Task/Subagent Rules (apply to every skill)
|
|
27
27
|
|
|
28
28
|
10. **Never** invoke `Skill()` inside a `Task()` subagent -- the Skill tool is not available in subagent contexts. Agents spawned by `Task()` cannot resolve `$pbr-*` skill prefixes, so `Skill({ skill: "pbr:plan" })` will silently fail. Instead, chain skills at the orchestrator level (return control to the orchestrator, then call `Skill()` from there). For subagent work, use `subagent_type: "pbr:{agent}"` which auto-loads agent definitions.
|
|
29
|
+
11. **NEVER** use non-PBR agent types (`general-purpose`, `Explore`, `Plan`, `Bash`, `feature-dev`, etc.) -- ALWAYS use `subagent_type: "pbr:{agent}"` (e.g., `pbr:researcher`, `pbr:executor`, `pbr:general`). PBR agents have project-aware prompts, audit logging, and workflow context. Generic agents bypass all of this. A PreToolUse hook **blocks** non-PBR agent spawns by default. Exceptions: (a) bare `Task()` with no `subagent_type` for lightweight read-only briefings (see context-loader-task pattern), (b) if the user says "use native agents", add `[native]` to the Task description to bypass the block for that call.
|
|
29
30
|
|
|
30
31
|
## Behavioral Rules (apply to every skill)
|
|
31
32
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pbr",
|
|
3
3
|
"displayName": "Plan-Build-Run",
|
|
4
|
-
"version": "2.56.
|
|
4
|
+
"version": "2.56.2",
|
|
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",
|
|
@@ -361,7 +361,7 @@ All phases with status and completion data.
|
|
|
361
361
|
node ${CLAUDE_PLUGIN_ROOT}/scripts/pbr-tools.js init progress
|
|
362
362
|
```
|
|
363
363
|
|
|
364
|
-
**Output:** `current_phase`, `
|
|
364
|
+
**Output:** `current_phase`, `phase_count`, `status`, `phases` array, `total_plans`, `completed_plans`, `percentage`.
|
|
365
365
|
|
|
366
366
|
---
|
|
367
367
|
|
|
@@ -375,7 +375,7 @@ Multi-field atomic STATE.md update. Updates all fields in a single pass.
|
|
|
375
375
|
node ${CLAUDE_PLUGIN_ROOT}/scripts/pbr-tools.js state patch '{"status":"executing","last_activity":"now"}'
|
|
376
376
|
```
|
|
377
377
|
|
|
378
|
-
**Valid fields:** `current_phase`, `status`, `plans_complete`, `last_activity`, `progress_percent`, `phase_slug`, `
|
|
378
|
+
**Valid fields:** `current_phase`, `status`, `plans_complete`, `last_activity`, `progress_percent`, `phase_slug`, `last_command`, `blockers`
|
|
379
379
|
|
|
380
380
|
**Output:** `{ "success": true, "updated": ["status", "last_activity"] }`
|
|
381
381
|
|
|
@@ -153,11 +153,11 @@ Task({
|
|
|
153
153
|
})
|
|
154
154
|
```
|
|
155
155
|
|
|
156
|
-
Also spawn a git analysis agent
|
|
156
|
+
Also spawn a git analysis agent:
|
|
157
157
|
|
|
158
158
|
```
|
|
159
159
|
Task({
|
|
160
|
-
subagent_type: "
|
|
160
|
+
subagent_type: "pbr:general",
|
|
161
161
|
model: "haiku",
|
|
162
162
|
prompt: "Run these git commands in {project_dir}:
|
|
163
163
|
1. git log --since='{from}' --until='{to}' --format='%h|%s|%an|%ai' --all
|
|
@@ -21,7 +21,9 @@ Then proceed to Step 1.
|
|
|
21
21
|
|
|
22
22
|
You are running the **explore** skill. Your job is to help the user think through ideas that might become a todo, requirement, phase, decision, or nothing yet. This is Socratic conversation, not requirements gathering. No phase number is needed.
|
|
23
23
|
|
|
24
|
-
This skill runs **inline** (no Task delegation), with optional Task() spawns for context loading and mid-conversation research.
|
|
24
|
+
This skill runs **inline** (no Task delegation), with optional Task() spawns for context loading, upfront research, and mid-conversation research.
|
|
25
|
+
|
|
26
|
+
**CRITICAL: Agent type rule** — When spawning ANY research or analysis Task(), ALWAYS use `subagent_type: "pbr:researcher"`. NEVER use `general-purpose`, `Explore`, or other non-PBR agent types. The PreToolUse hook will block non-PBR agents.
|
|
25
27
|
|
|
26
28
|
---
|
|
27
29
|
|
|
@@ -103,6 +105,31 @@ Reference `skills/shared/domain-probes.md` for technology-specific follow-up que
|
|
|
103
105
|
|
|
104
106
|
---
|
|
105
107
|
|
|
108
|
+
## Upfront Research Delegation
|
|
109
|
+
|
|
110
|
+
When the user's initial request is research-heavy (e.g., "explore best practices for X", "research how other projects do Y", "compare approaches to Z"), delegate immediately to `pbr:researcher` agents rather than doing inline research.
|
|
111
|
+
|
|
112
|
+
**Detection**: If `$ARGUMENTS` contains words like "research", "compare", "explore examples", "best practices", "how do others", or describes gathering external information — this is an upfront research task.
|
|
113
|
+
|
|
114
|
+
**Pattern**: Spawn one or more `pbr:researcher` agents in parallel, then synthesize their findings inline:
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
Task({
|
|
118
|
+
subagent_type: "pbr:researcher",
|
|
119
|
+
prompt: "<research_assignment>
|
|
120
|
+
Topic: {specific research question from user's request}
|
|
121
|
+
Output: Return findings as structured markdown in your response.
|
|
122
|
+
Mode: external-research
|
|
123
|
+
|
|
124
|
+
{detailed research instructions}
|
|
125
|
+
</research_assignment>"
|
|
126
|
+
})
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
After researchers complete, synthesize findings inline and continue the Socratic conversation with the user about what was discovered.
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
106
133
|
## Mid-Conversation Research
|
|
107
134
|
|
|
108
135
|
When a knowledge gap emerges during the conversation — you're unsure about a library, pattern, or approach — surface it explicitly.
|
|
@@ -172,7 +172,7 @@ After running all 10 checks and collecting results, if any of the following auto
|
|
|
172
172
|
|
|
173
173
|
| Pattern | Detection | Fix Action |
|
|
174
174
|
|---------|-----------|------------|
|
|
175
|
-
| Missing STATE.md frontmatter | Check 5 finds STATE.md without `---` block | Regenerate frontmatter from ROADMAP.md phase data (current_phase,
|
|
175
|
+
| Missing STATE.md frontmatter | Check 5 finds STATE.md without `---` block | Regenerate frontmatter from ROADMAP.md phase data (current_phase, phase_slug, status) |
|
|
176
176
|
| STATE.md phase_slug mismatch | Check 5/7 finds phase_slug doesn't match current phase directory name | Correct phase_slug to match the actual directory name in `.planning/phases/` |
|
|
177
177
|
| Missing config.json | Check 1/2 finds no `.planning/config.json` | Create with default config template (same as `/pbr:setup` defaults) |
|
|
178
178
|
| Orphaned .active-skill file | Check 10 or general scan finds `.planning/.active-skill` older than 1 hour | Delete the stale `.active-skill` file |
|
|
@@ -44,6 +44,7 @@ Task({
|
|
|
44
44
|
2. **Budget: ~500 tokens.** The briefing must be concise. The subagent reads full files in its own context; the orchestrator receives only the summary.
|
|
45
45
|
3. **No suggestions.** The briefing reports state, it does not recommend actions. The skill logic decides what to do.
|
|
46
46
|
4. **Read-only.** The briefing task must not write any files.
|
|
47
|
+
5. **No subagent_type needed.** This is the ONE exception to the "always use `pbr:*` agents" rule. Bare `Task()` without `subagent_type` is intentional here — these are lightweight read-only briefings that don't need agent-specific prompts. Do NOT generalize this pattern to other Task() calls — all research, execution, and analysis Task() calls MUST use `subagent_type: "pbr:{agent}"`.
|
|
47
48
|
|
|
48
49
|
### Using the Briefing
|
|
49
50
|
|
|
@@ -53,7 +53,7 @@ Progress: [{progress_bar}] {percent}%
|
|
|
53
53
|
Phase 3 of 10 = 20% → [████░░░░░░░░░░░░░░░░] 20%
|
|
54
54
|
Phase 7 of 10 = 70% → [██████████████░░░░░░] 70%
|
|
55
55
|
```
|
|
56
|
-
Calculation: `filled = Math.round((completed_phases /
|
|
56
|
+
Calculation: `filled = Math.round((completed_phases / phase_count) * 20)` where `phase_count` is derived from ROADMAP.md (available via `stateLoad` as `phase_count`)
|
|
57
57
|
|
|
58
58
|
### 3. Accumulated Context (lines 16-25)
|
|
59
59
|
```
|
|
@@ -26,6 +26,7 @@ These rules prevent context rot -- quality degradation as the context window fil
|
|
|
26
26
|
## Task/Subagent Rules (apply to every skill)
|
|
27
27
|
|
|
28
28
|
10. **Never** invoke `Skill()` inside a `Task()` subagent -- the Skill tool is not available in subagent contexts. Agents spawned by `Task()` cannot resolve `/pbr:*` skill prefixes, so `Skill({ skill: "pbr:plan" })` will silently fail. Instead, chain skills at the orchestrator level (return control to the orchestrator, then call `Skill()` from there). For subagent work, use `subagent_type: "pbr:{agent}"` which auto-loads agent definitions.
|
|
29
|
+
11. **NEVER** use non-PBR agent types (`general-purpose`, `Explore`, `Plan`, `Bash`, `feature-dev`, etc.) -- ALWAYS use `subagent_type: "pbr:{agent}"` (e.g., `pbr:researcher`, `pbr:executor`, `pbr:general`). PBR agents have project-aware prompts, audit logging, and workflow context. Generic agents bypass all of this. A PreToolUse hook **blocks** non-PBR agent spawns by default. Exceptions: (a) bare `Task()` with no `subagent_type` for lightweight read-only briefings (see context-loader-task pattern), (b) if the user says "use native agents", add `[native]` to the Task description to bypass the block for that call.
|
|
29
30
|
|
|
30
31
|
## Behavioral Rules (apply to every skill)
|
|
31
32
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pbr",
|
|
3
3
|
"displayName": "Plan-Build-Run",
|
|
4
|
-
"version": "2.56.
|
|
4
|
+
"version": "2.56.2",
|
|
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",
|
|
@@ -361,7 +361,7 @@ All phases with status and completion data.
|
|
|
361
361
|
node ${CLAUDE_PLUGIN_ROOT}/scripts/pbr-tools.js init progress
|
|
362
362
|
```
|
|
363
363
|
|
|
364
|
-
**Output:** `current_phase`, `
|
|
364
|
+
**Output:** `current_phase`, `phase_count`, `status`, `phases` array, `total_plans`, `completed_plans`, `percentage`.
|
|
365
365
|
|
|
366
366
|
---
|
|
367
367
|
|
|
@@ -375,7 +375,7 @@ Multi-field atomic STATE.md update. Updates all fields in a single pass.
|
|
|
375
375
|
node ${CLAUDE_PLUGIN_ROOT}/scripts/pbr-tools.js state patch '{"status":"executing","last_activity":"now"}'
|
|
376
376
|
```
|
|
377
377
|
|
|
378
|
-
**Valid fields:** `current_phase`, `status`, `plans_complete`, `last_activity`, `progress_percent`, `phase_slug`, `
|
|
378
|
+
**Valid fields:** `current_phase`, `status`, `plans_complete`, `last_activity`, `progress_percent`, `phase_slug`, `last_command`, `blockers`
|
|
379
379
|
|
|
380
380
|
**Output:** `{ "success": true, "updated": ["status", "last_activity"] }`
|
|
381
381
|
|
|
@@ -154,11 +154,11 @@ Task({
|
|
|
154
154
|
})
|
|
155
155
|
```
|
|
156
156
|
|
|
157
|
-
Also spawn a git analysis agent
|
|
157
|
+
Also spawn a git analysis agent:
|
|
158
158
|
|
|
159
159
|
```
|
|
160
160
|
Task({
|
|
161
|
-
subagent_type: "
|
|
161
|
+
subagent_type: "pbr:general",
|
|
162
162
|
model: "haiku",
|
|
163
163
|
prompt: "Run these git commands in {project_dir}:
|
|
164
164
|
1. git log --since='{from}' --until='{to}' --format='%h|%s|%an|%ai' --all
|
|
@@ -22,7 +22,9 @@ Then proceed to Step 1.
|
|
|
22
22
|
|
|
23
23
|
You are running the **explore** skill. Your job is to help the user think through ideas that might become a todo, requirement, phase, decision, or nothing yet. This is Socratic conversation, not requirements gathering. No phase number is needed.
|
|
24
24
|
|
|
25
|
-
This skill runs **inline** (no Task delegation), with optional Task() spawns for context loading and mid-conversation research.
|
|
25
|
+
This skill runs **inline** (no Task delegation), with optional Task() spawns for context loading, upfront research, and mid-conversation research.
|
|
26
|
+
|
|
27
|
+
**CRITICAL: Agent type rule** — When spawning ANY research or analysis Task(), ALWAYS use `subagent_type: "pbr:researcher"`. NEVER use `general-purpose`, `Explore`, or other non-PBR agent types. The PreToolUse hook will block non-PBR agents.
|
|
26
28
|
|
|
27
29
|
---
|
|
28
30
|
|
|
@@ -104,6 +106,31 @@ Reference `skills/shared/domain-probes.md` for technology-specific follow-up que
|
|
|
104
106
|
|
|
105
107
|
---
|
|
106
108
|
|
|
109
|
+
## Upfront Research Delegation
|
|
110
|
+
|
|
111
|
+
When the user's initial request is research-heavy (e.g., "explore best practices for X", "research how other projects do Y", "compare approaches to Z"), delegate immediately to `pbr:researcher` agents rather than doing inline research.
|
|
112
|
+
|
|
113
|
+
**Detection**: If `$ARGUMENTS` contains words like "research", "compare", "explore examples", "best practices", "how do others", or describes gathering external information — this is an upfront research task.
|
|
114
|
+
|
|
115
|
+
**Pattern**: Spawn one or more `pbr:researcher` agents in parallel, then synthesize their findings inline:
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
Task({
|
|
119
|
+
subagent_type: "pbr:researcher",
|
|
120
|
+
prompt: "<research_assignment>
|
|
121
|
+
Topic: {specific research question from user's request}
|
|
122
|
+
Output: Return findings as structured markdown in your response.
|
|
123
|
+
Mode: external-research
|
|
124
|
+
|
|
125
|
+
{detailed research instructions}
|
|
126
|
+
</research_assignment>"
|
|
127
|
+
})
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
After researchers complete, synthesize findings inline and continue the Socratic conversation with the user about what was discovered.
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
107
134
|
## Mid-Conversation Research
|
|
108
135
|
|
|
109
136
|
When a knowledge gap emerges during the conversation — you're unsure about a library, pattern, or approach — surface it explicitly.
|
|
@@ -173,7 +173,7 @@ After running all 10 checks and collecting results, if any of the following auto
|
|
|
173
173
|
|
|
174
174
|
| Pattern | Detection | Fix Action |
|
|
175
175
|
|---------|-----------|------------|
|
|
176
|
-
| Missing STATE.md frontmatter | Check 5 finds STATE.md without `---` block | Regenerate frontmatter from ROADMAP.md phase data (current_phase,
|
|
176
|
+
| Missing STATE.md frontmatter | Check 5 finds STATE.md without `---` block | Regenerate frontmatter from ROADMAP.md phase data (current_phase, phase_slug, status) |
|
|
177
177
|
| STATE.md phase_slug mismatch | Check 5/7 finds phase_slug doesn't match current phase directory name | Correct phase_slug to match the actual directory name in `.planning/phases/` |
|
|
178
178
|
| Missing config.json | Check 1/2 finds no `.planning/config.json` | Create with default config template (same as `/pbr:setup` defaults) |
|
|
179
179
|
| Orphaned .active-skill file | Check 10 or general scan finds `.planning/.active-skill` older than 1 hour | Delete the stale `.active-skill` file |
|
|
@@ -44,6 +44,7 @@ Task({
|
|
|
44
44
|
2. **Budget: ~500 tokens.** The briefing must be concise. The subagent reads full files in its own context; the orchestrator receives only the summary.
|
|
45
45
|
3. **No suggestions.** The briefing reports state, it does not recommend actions. The skill logic decides what to do.
|
|
46
46
|
4. **Read-only.** The briefing task must not write any files.
|
|
47
|
+
5. **No subagent_type needed.** This is the ONE exception to the "always use `pbr:*` agents" rule. Bare `Task()` without `subagent_type` is intentional here — these are lightweight read-only briefings that don't need agent-specific prompts. Do NOT generalize this pattern to other Task() calls — all research, execution, and analysis Task() calls MUST use `subagent_type: "pbr:{agent}"`.
|
|
47
48
|
|
|
48
49
|
### Using the Briefing
|
|
49
50
|
|
|
@@ -53,7 +53,7 @@ Progress: [{progress_bar}] {percent}%
|
|
|
53
53
|
Phase 3 of 10 = 20% → [████░░░░░░░░░░░░░░░░] 20%
|
|
54
54
|
Phase 7 of 10 = 70% → [██████████████░░░░░░] 70%
|
|
55
55
|
```
|
|
56
|
-
Calculation: `filled = Math.round((completed_phases /
|
|
56
|
+
Calculation: `filled = Math.round((completed_phases / phase_count) * 20)` where `phase_count` is derived from ROADMAP.md (available via `stateLoad` as `phase_count`)
|
|
57
57
|
|
|
58
58
|
### 3. Accumulated Context (lines 16-25)
|
|
59
59
|
```
|
|
@@ -26,6 +26,7 @@ These rules prevent context rot -- quality degradation as the context window fil
|
|
|
26
26
|
## Task/Subagent Rules (apply to every skill)
|
|
27
27
|
|
|
28
28
|
10. **Never** invoke `Skill()` inside a `Task()` subagent -- the Skill tool is not available in subagent contexts. Agents spawned by `Task()` cannot resolve `/pbr:*` skill prefixes, so `Skill({ skill: "pbr:plan" })` will silently fail. Instead, chain skills at the orchestrator level (return control to the orchestrator, then call `Skill()` from there). For subagent work, use `subagent_type: "pbr:{agent}"` which auto-loads agent definitions.
|
|
29
|
+
11. **NEVER** use non-PBR agent types (`general-purpose`, `Explore`, `Plan`, `Bash`, `feature-dev`, etc.) -- ALWAYS use `subagent_type: "pbr:{agent}"` (e.g., `pbr:researcher`, `pbr:executor`, `pbr:general`). PBR agents have project-aware prompts, audit logging, and workflow context. Generic agents bypass all of this. A PreToolUse hook **blocks** non-PBR agent spawns by default. Exceptions: (a) bare `Task()` with no `subagent_type` for lightweight read-only briefings (see context-loader-task pattern), (b) if the user says "use native agents", add `[native]` to the Task description to bypass the block for that call.
|
|
29
30
|
|
|
30
31
|
## Behavioral Rules (apply to every skill)
|
|
31
32
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pbr",
|
|
3
|
-
"version": "2.56.
|
|
3
|
+
"version": "2.56.2",
|
|
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",
|
|
@@ -361,7 +361,7 @@ All phases with status and completion data.
|
|
|
361
361
|
node ${CLAUDE_PLUGIN_ROOT}/scripts/pbr-tools.js init progress
|
|
362
362
|
```
|
|
363
363
|
|
|
364
|
-
**Output:** `current_phase`, `
|
|
364
|
+
**Output:** `current_phase`, `phase_count`, `status`, `phases` array, `total_plans`, `completed_plans`, `percentage`.
|
|
365
365
|
|
|
366
366
|
---
|
|
367
367
|
|
|
@@ -375,7 +375,7 @@ Multi-field atomic STATE.md update. Updates all fields in a single pass.
|
|
|
375
375
|
node ${CLAUDE_PLUGIN_ROOT}/scripts/pbr-tools.js state patch '{"status":"executing","last_activity":"now"}'
|
|
376
376
|
```
|
|
377
377
|
|
|
378
|
-
**Valid fields:** `current_phase`, `status`, `plans_complete`, `last_activity`, `progress_percent`, `phase_slug`, `
|
|
378
|
+
**Valid fields:** `current_phase`, `status`, `plans_complete`, `last_activity`, `progress_percent`, `phase_slug`, `last_command`, `blockers`
|
|
379
379
|
|
|
380
380
|
**Output:** `{ "success": true, "updated": ["status", "last_activity"] }`
|
|
381
381
|
|
|
@@ -347,7 +347,7 @@ function validateState(content, _filePath) {
|
|
|
347
347
|
warnings.push('Unclosed YAML frontmatter');
|
|
348
348
|
} else {
|
|
349
349
|
const frontmatter = content.substring(3, frontmatterEnd);
|
|
350
|
-
const requiredFields = ['version', 'current_phase', '
|
|
350
|
+
const requiredFields = ['version', 'current_phase', 'phase_slug', 'status'];
|
|
351
351
|
for (const field of requiredFields) {
|
|
352
352
|
if (!frontmatter.includes(`${field}:`)) {
|
|
353
353
|
warnings.push(`Frontmatter missing "${field}" field`);
|
|
@@ -440,14 +440,12 @@ function syncStateBody(content, filePath) {
|
|
|
440
440
|
|
|
441
441
|
const fm = content.substring(3, fmEnd);
|
|
442
442
|
const phaseMatch = fm.match(/^current_phase:\s*(\d+)/m);
|
|
443
|
-
const totalMatch = fm.match(/^total_phases:\s*(\d+)/m);
|
|
444
443
|
const slugMatch = fm.match(/^phase_name:\s*"?([^"\r\n]+)"?/m);
|
|
445
444
|
const statusMatch = fm.match(/^status:\s*"?([^"\r\n]+)"?/m);
|
|
446
445
|
|
|
447
446
|
if (!phaseMatch) return null;
|
|
448
447
|
|
|
449
448
|
const fmPhase = phaseMatch[1];
|
|
450
|
-
const fmTotal = totalMatch ? totalMatch[1] : null;
|
|
451
449
|
const fmName = slugMatch ? slugMatch[1] : null;
|
|
452
450
|
const fmStatus = statusMatch ? statusMatch[1] : null;
|
|
453
451
|
|
|
@@ -459,9 +457,10 @@ function syncStateBody(content, filePath) {
|
|
|
459
457
|
|
|
460
458
|
// Fix phase line drift
|
|
461
459
|
if (bodyPhaseMatch && bodyPhaseMatch[1] !== fmPhase) {
|
|
462
|
-
const
|
|
463
|
-
|
|
464
|
-
: `Phase: ${fmPhase} of ${
|
|
460
|
+
const bodyTotal = bodyPhaseMatch ? bodyPhaseMatch[2] : null;
|
|
461
|
+
const newPhaseLine = bodyTotal
|
|
462
|
+
? (fmName ? `Phase: ${fmPhase} of ${bodyTotal} (${fmName})` : `Phase: ${fmPhase} of ${bodyTotal}`)
|
|
463
|
+
: `Phase: ${fmPhase}`;
|
|
465
464
|
updated = updated.replace(/^Phase:\s*\d+\s*of\s*\d+.*/m, newPhaseLine);
|
|
466
465
|
needsFix = true;
|
|
467
466
|
}
|
|
@@ -210,9 +210,6 @@ function updateStatePosition(content, updates) {
|
|
|
210
210
|
if (updates.fmCurrentPhase !== undefined) {
|
|
211
211
|
fm = fm.replace(/^(current_phase:\s*).*/m, (_, p) => `${p}${updates.fmCurrentPhase}`);
|
|
212
212
|
}
|
|
213
|
-
if (updates.fmTotalPhases !== undefined) {
|
|
214
|
-
fm = fm.replace(/^(total_phases:\s*).*/m, (_, p) => `${p}${updates.fmTotalPhases}`);
|
|
215
|
-
}
|
|
216
213
|
if (updates.fmPhaseSlug !== undefined) {
|
|
217
214
|
fm = fm.replace(/^(phase_slug:\s*).*/m, (_, p) => `${p}"${updates.fmPhaseSlug}"`);
|
|
218
215
|
}
|
|
@@ -420,7 +417,6 @@ function checkStateSync(data) {
|
|
|
420
417
|
if (currentPhase !== null && currentPhase !== phaseNumInt) {
|
|
421
418
|
stateUpdates.phaseLine = `${phaseNumInt} of ${totalPhases} (${phaseName})`;
|
|
422
419
|
stateUpdates.fmCurrentPhase = phaseNumInt;
|
|
423
|
-
stateUpdates.fmTotalPhases = totalPhases;
|
|
424
420
|
stateUpdates.fmPhaseSlug = phaseSlug;
|
|
425
421
|
stateUpdates.fmPhaseName = phaseName;
|
|
426
422
|
messages.push(`STATE.md: Phase ${currentPhase} → ${phaseNumInt}`);
|
|
@@ -503,7 +499,6 @@ function checkStateSync(data) {
|
|
|
503
499
|
if (currentPhase !== null && currentPhase !== phaseNumInt) {
|
|
504
500
|
stateUpdates.phaseLine = `${phaseNumInt} of ${totalPhases} (${phaseName})`;
|
|
505
501
|
stateUpdates.fmCurrentPhase = phaseNumInt;
|
|
506
|
-
stateUpdates.fmTotalPhases = totalPhases;
|
|
507
502
|
stateUpdates.fmPhaseSlug = phaseSlug;
|
|
508
503
|
stateUpdates.fmPhaseName = phaseName;
|
|
509
504
|
messages.push(`STATE.md: Phase ${currentPhase} → ${phaseNumInt}`);
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* checkUnmanagedCommit(data) — PreToolUse Bash: advises git commits to use /pbr:quick
|
|
14
14
|
*
|
|
15
15
|
* All functions return null for pass, or { exitCode, output } for action.
|
|
16
|
-
* checkNonPbrAgent
|
|
16
|
+
* checkNonPbrAgent defaults to blocking (exitCode 2) — blocks non-PBR agents.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
'use strict';
|
|
@@ -136,8 +136,9 @@ const AGENT_MAPPING = {
|
|
|
136
136
|
* - subagent_type is missing/empty (can't determine type)
|
|
137
137
|
* - Enforcement level is "off"
|
|
138
138
|
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
139
|
+
* Defaults to **blocking** (exitCode 2) unless config overrides to "advisory".
|
|
140
|
+
* This is stricter than checkUnmanagedSourceWrite/checkUnmanagedCommit because
|
|
141
|
+
* non-PBR agents bypass audit logging, workflow context, and project-aware prompts.
|
|
141
142
|
*
|
|
142
143
|
* @param {Object} data - parsed hook input from Claude Code
|
|
143
144
|
* @returns {null|{ exitCode: number, output: Object }}
|
|
@@ -149,6 +150,10 @@ function checkNonPbrAgent(data) {
|
|
|
149
150
|
// Already using a PBR agent
|
|
150
151
|
if (subagentType.startsWith('pbr:')) return null;
|
|
151
152
|
|
|
153
|
+
// Per-call bypass: user says "use native agents" and the LLM includes [native] in description
|
|
154
|
+
const description = (data.tool_input && data.tool_input.description) || '';
|
|
155
|
+
if (/\[native\]/i.test(description)) return null;
|
|
156
|
+
|
|
152
157
|
const cwd = process.cwd();
|
|
153
158
|
const planningDir = path.join(cwd, '.planning');
|
|
154
159
|
|
|
@@ -158,14 +163,35 @@ function checkNonPbrAgent(data) {
|
|
|
158
163
|
const config = loadEnforcementConfig(planningDir);
|
|
159
164
|
if (config.level === 'off') return null;
|
|
160
165
|
|
|
166
|
+
// For agent enforcement, determine the effective level.
|
|
167
|
+
// Priority: workflow.enforce_pbr_agents > workflow.enforce_pbr_skills > default "block"
|
|
168
|
+
// Agent enforcement is stricter than source write/commit checks — blocks by default.
|
|
169
|
+
let agentLevel = 'block'; // default: block non-PBR agents
|
|
170
|
+
try {
|
|
171
|
+
const configPath = path.join(planningDir, 'config.json');
|
|
172
|
+
const parsed = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
173
|
+
const agentExplicit = parsed.workflow && parsed.workflow.enforce_pbr_agents;
|
|
174
|
+
const skillExplicit = parsed.workflow && parsed.workflow.enforce_pbr_skills;
|
|
175
|
+
if (agentExplicit === 'advisory' || agentExplicit === 'block' || agentExplicit === 'off') {
|
|
176
|
+
agentLevel = agentExplicit;
|
|
177
|
+
} else if (skillExplicit === 'advisory' || skillExplicit === 'block' || skillExplicit === 'off') {
|
|
178
|
+
agentLevel = skillExplicit;
|
|
179
|
+
}
|
|
180
|
+
} catch (_e) {
|
|
181
|
+
// No config — keep default (block)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (agentLevel === 'off') return null;
|
|
185
|
+
|
|
161
186
|
const suggestion = AGENT_MAPPING[subagentType] || 'a pbr:* agent (e.g., pbr:researcher, pbr:general, pbr:executor)';
|
|
162
187
|
|
|
163
|
-
|
|
188
|
+
// Block non-PBR agents unless explicitly set to advisory
|
|
189
|
+
if (agentLevel !== 'advisory') {
|
|
164
190
|
const blockMessage =
|
|
165
191
|
`PBR workflow violation: spawning generic agent "${subagentType}" is blocked. ` +
|
|
166
192
|
`Use ${suggestion} instead. ` +
|
|
167
193
|
'PBR agents are auto-loaded via subagent_type — just change the type, no extra setup needed. ' +
|
|
168
|
-
'
|
|
194
|
+
'If the user explicitly requested a native agent, add [native] to the Task description to bypass this check.';
|
|
169
195
|
|
|
170
196
|
logHook('enforce-pbr-workflow', 'PreToolUse', 'block', { agentType: subagentType, suggestion });
|
|
171
197
|
return {
|
|
@@ -31,7 +31,6 @@ function parseStateMd(content) {
|
|
|
31
31
|
if (frontmatter.version === 2 || frontmatter.current_phase !== undefined) {
|
|
32
32
|
result.format = 'frontmatter';
|
|
33
33
|
result.current_phase = frontmatter.current_phase || null;
|
|
34
|
-
result.total_phases = frontmatter.total_phases || null;
|
|
35
34
|
result.phase_name = frontmatter.phase_slug || frontmatter.phase_name || null;
|
|
36
35
|
result.status = frontmatter.status || null;
|
|
37
36
|
result.progress = frontmatter.progress_percent !== undefined ? frontmatter.progress_percent : null;
|
|
@@ -301,7 +300,6 @@ function stateUpdate(field, value, planningDir) {
|
|
|
301
300
|
'last_activity',
|
|
302
301
|
'progress_percent',
|
|
303
302
|
'phase_slug',
|
|
304
|
-
'total_phases',
|
|
305
303
|
'last_command',
|
|
306
304
|
'blockers'
|
|
307
305
|
];
|
|
@@ -340,7 +338,7 @@ function statePatch(jsonStr, planningDir) {
|
|
|
340
338
|
if (!fs.existsSync(statePath)) return { success: false, error: "STATE.md not found" };
|
|
341
339
|
let fields;
|
|
342
340
|
try { fields = JSON.parse(jsonStr); } catch (_e) { return { success: false, error: "Invalid JSON" }; }
|
|
343
|
-
const validFields = ["current_phase", "status", "plans_complete", "last_activity", "progress_percent", "phase_slug", "
|
|
341
|
+
const validFields = ["current_phase", "status", "plans_complete", "last_activity", "progress_percent", "phase_slug", "last_command", "blockers"];
|
|
344
342
|
const updates = [], errors = [];
|
|
345
343
|
for (const [field, value] of Object.entries(fields)) {
|
|
346
344
|
if (!validFields.includes(field)) { errors.push("Unknown field: " + field); continue; }
|
|
@@ -539,7 +539,7 @@ async function main() {
|
|
|
539
539
|
const field = args[2];
|
|
540
540
|
const value = args[3];
|
|
541
541
|
if (!field || value === undefined) {
|
|
542
|
-
error('Usage: pbr-tools.js state update <field> <value>\nFields: current_phase, status, plans_complete, last_activity, progress_percent, phase_slug,
|
|
542
|
+
error('Usage: pbr-tools.js state update <field> <value>\nFields: current_phase, status, plans_complete, last_activity, progress_percent, phase_slug, last_command, blockers');
|
|
543
543
|
}
|
|
544
544
|
output(stateUpdate(field, value));
|
|
545
545
|
} else if (command === 'config' && subcommand === 'validate') {
|
|
@@ -242,12 +242,11 @@ function buildStatusLine(content, ctxPercent, cfg, stdinData, planningDir) {
|
|
|
242
242
|
// Phase section (always includes brand text)
|
|
243
243
|
if (sections.includes('phase')) {
|
|
244
244
|
const fmPhase = fm && fm.current_phase;
|
|
245
|
-
const fmTotal = fm && fm.total_phases;
|
|
246
245
|
const fmName = fm && fm.phase_name;
|
|
247
246
|
const phaseMatch = content.match(/Phase:\s*(\d+)\s*of\s*(\d+)\s*(?:\(([^)]+)\))?/);
|
|
248
247
|
|
|
249
248
|
const phaseNum = fmPhase || (phaseMatch && phaseMatch[1]);
|
|
250
|
-
const phaseTotal =
|
|
249
|
+
const phaseTotal = phaseMatch && phaseMatch[2];
|
|
251
250
|
const phaseName = fmName || (phaseMatch && phaseMatch[3]);
|
|
252
251
|
|
|
253
252
|
if (phaseNum && phaseTotal) {
|
|
@@ -263,11 +262,11 @@ function buildStatusLine(content, ctxPercent, cfg, stdinData, planningDir) {
|
|
|
263
262
|
// Plan section
|
|
264
263
|
if (sections.includes('plan')) {
|
|
265
264
|
const fmComplete = fm && fm.plans_complete;
|
|
266
|
-
const
|
|
265
|
+
const fmPlansTotal = fm && fm.plans_total;
|
|
267
266
|
const planMatch = content.match(/Plan:\s*(\d+)\s*of\s*(\d+)/);
|
|
268
267
|
|
|
269
268
|
const done = fmComplete != null ? parseInt(fmComplete, 10) : (planMatch ? parseInt(planMatch[1], 10) : null);
|
|
270
|
-
const total =
|
|
269
|
+
const total = fmPlansTotal != null ? parseInt(fmPlansTotal, 10) : (planMatch ? parseInt(planMatch[2], 10) : null);
|
|
271
270
|
|
|
272
271
|
if (done != null && total != null && total > 0) {
|
|
273
272
|
const planColor = done === total ? c.green : c.white;
|
|
@@ -155,11 +155,11 @@ Task({
|
|
|
155
155
|
})
|
|
156
156
|
```
|
|
157
157
|
|
|
158
|
-
Also spawn a git analysis agent
|
|
158
|
+
Also spawn a git analysis agent:
|
|
159
159
|
|
|
160
160
|
```
|
|
161
161
|
Task({
|
|
162
|
-
subagent_type: "
|
|
162
|
+
subagent_type: "pbr:general",
|
|
163
163
|
model: "haiku",
|
|
164
164
|
prompt: "Run these git commands in {project_dir}:
|
|
165
165
|
1. git log --since='{from}' --until='{to}' --format='%h|%s|%an|%ai' --all
|
|
@@ -23,7 +23,9 @@ Then proceed to Step 1.
|
|
|
23
23
|
|
|
24
24
|
You are running the **explore** skill. Your job is to help the user think through ideas that might become a todo, requirement, phase, decision, or nothing yet. This is Socratic conversation, not requirements gathering. No phase number is needed.
|
|
25
25
|
|
|
26
|
-
This skill runs **inline** (no Task delegation), with optional Task() spawns for context loading and mid-conversation research.
|
|
26
|
+
This skill runs **inline** (no Task delegation), with optional Task() spawns for context loading, upfront research, and mid-conversation research.
|
|
27
|
+
|
|
28
|
+
**CRITICAL: Agent type rule** — When spawning ANY research or analysis Task(), ALWAYS use `subagent_type: "pbr:researcher"`. NEVER use `general-purpose`, `Explore`, or other non-PBR agent types. The PreToolUse hook will block non-PBR agents.
|
|
27
29
|
|
|
28
30
|
---
|
|
29
31
|
|
|
@@ -105,6 +107,31 @@ Reference `skills/shared/domain-probes.md` for technology-specific follow-up que
|
|
|
105
107
|
|
|
106
108
|
---
|
|
107
109
|
|
|
110
|
+
## Upfront Research Delegation
|
|
111
|
+
|
|
112
|
+
When the user's initial request is research-heavy (e.g., "explore best practices for X", "research how other projects do Y", "compare approaches to Z"), delegate immediately to `pbr:researcher` agents rather than doing inline research.
|
|
113
|
+
|
|
114
|
+
**Detection**: If `$ARGUMENTS` contains words like "research", "compare", "explore examples", "best practices", "how do others", or describes gathering external information — this is an upfront research task.
|
|
115
|
+
|
|
116
|
+
**Pattern**: Spawn one or more `pbr:researcher` agents in parallel, then synthesize their findings inline:
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
Task({
|
|
120
|
+
subagent_type: "pbr:researcher",
|
|
121
|
+
prompt: "<research_assignment>
|
|
122
|
+
Topic: {specific research question from user's request}
|
|
123
|
+
Output: Return findings as structured markdown in your response.
|
|
124
|
+
Mode: external-research
|
|
125
|
+
|
|
126
|
+
{detailed research instructions}
|
|
127
|
+
</research_assignment>"
|
|
128
|
+
})
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
After researchers complete, synthesize findings inline and continue the Socratic conversation with the user about what was discovered.
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
108
135
|
## Mid-Conversation Research
|
|
109
136
|
|
|
110
137
|
When a knowledge gap emerges during the conversation — you're unsure about a library, pattern, or approach — surface it explicitly.
|
|
@@ -174,7 +174,7 @@ After running all 10 checks and collecting results, if any of the following auto
|
|
|
174
174
|
|
|
175
175
|
| Pattern | Detection | Fix Action |
|
|
176
176
|
|---------|-----------|------------|
|
|
177
|
-
| Missing STATE.md frontmatter | Check 5 finds STATE.md without `---` block | Regenerate frontmatter from ROADMAP.md phase data (current_phase,
|
|
177
|
+
| Missing STATE.md frontmatter | Check 5 finds STATE.md without `---` block | Regenerate frontmatter from ROADMAP.md phase data (current_phase, phase_slug, status) |
|
|
178
178
|
| STATE.md phase_slug mismatch | Check 5/7 finds phase_slug doesn't match current phase directory name | Correct phase_slug to match the actual directory name in `.planning/phases/` |
|
|
179
179
|
| Missing config.json | Check 1/2 finds no `.planning/config.json` | Create with default config template (same as `/pbr:setup` defaults) |
|
|
180
180
|
| Orphaned .active-skill file | Check 10 or general scan finds `.planning/.active-skill` older than 1 hour | Delete the stale `.active-skill` file |
|
|
@@ -44,6 +44,7 @@ Task({
|
|
|
44
44
|
2. **Budget: ~500 tokens.** The briefing must be concise. The subagent reads full files in its own context; the orchestrator receives only the summary.
|
|
45
45
|
3. **No suggestions.** The briefing reports state, it does not recommend actions. The skill logic decides what to do.
|
|
46
46
|
4. **Read-only.** The briefing task must not write any files.
|
|
47
|
+
5. **No subagent_type needed.** This is the ONE exception to the "always use `pbr:*` agents" rule. Bare `Task()` without `subagent_type` is intentional here — these are lightweight read-only briefings that don't need agent-specific prompts. Do NOT generalize this pattern to other Task() calls — all research, execution, and analysis Task() calls MUST use `subagent_type: "pbr:{agent}"`.
|
|
47
48
|
|
|
48
49
|
### Using the Briefing
|
|
49
50
|
|
|
@@ -53,7 +53,7 @@ Progress: [{progress_bar}] {percent}%
|
|
|
53
53
|
Phase 3 of 10 = 20% → [████░░░░░░░░░░░░░░░░] 20%
|
|
54
54
|
Phase 7 of 10 = 70% → [██████████████░░░░░░] 70%
|
|
55
55
|
```
|
|
56
|
-
Calculation: `filled = Math.round((completed_phases /
|
|
56
|
+
Calculation: `filled = Math.round((completed_phases / phase_count) * 20)` where `phase_count` is derived from ROADMAP.md (available via `stateLoad` as `phase_count`)
|
|
57
57
|
|
|
58
58
|
### 3. Accumulated Context (lines 16-25)
|
|
59
59
|
```
|
|
@@ -26,6 +26,7 @@ These rules prevent context rot -- quality degradation as the context window fil
|
|
|
26
26
|
## Task/Subagent Rules (apply to every skill)
|
|
27
27
|
|
|
28
28
|
10. **Never** invoke `Skill()` inside a `Task()` subagent -- the Skill tool is not available in subagent contexts. Subagents spawned by `Task()` cannot resolve `/pbr:*` skill prefixes, so `Skill({ skill: "pbr:plan" })` will silently fail. Instead, chain skills at the orchestrator level (return control to the orchestrator, then call `Skill()` from there). For subagent work, use `subagent_type: "pbr:{agent}"` which auto-loads agent definitions.
|
|
29
|
+
11. **NEVER** use non-PBR agent types (`general-purpose`, `Explore`, `Plan`, `Bash`, `feature-dev`, etc.) -- ALWAYS use `subagent_type: "pbr:{agent}"` (e.g., `pbr:researcher`, `pbr:executor`, `pbr:general`). PBR agents have project-aware prompts, audit logging, and workflow context. Generic agents bypass all of this. A PreToolUse hook **blocks** non-PBR agent spawns by default. Exceptions: (a) bare `Task()` with no `subagent_type` for lightweight read-only briefings (see context-loader-task pattern), (b) if the user says "use native agents", add `[native]` to the Task description to bypass the block for that call.
|
|
29
30
|
|
|
30
31
|
## Behavioral Rules (apply to every skill)
|
|
31
32
|
|