@sienklogic/plan-build-run 2.21.1 → 2.22.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 +35 -0
- package/package.json +1 -1
- package/plugins/copilot-pbr/agents/executor.agent.md +1 -0
- package/plugins/copilot-pbr/hooks/hooks.json +24 -0
- package/plugins/copilot-pbr/plugin.json +1 -1
- package/plugins/copilot-pbr/skills/build/SKILL.md +3 -3
- package/plugins/copilot-pbr/skills/continue/SKILL.md +8 -2
- package/plugins/copilot-pbr/skills/import/SKILL.md +2 -0
- package/plugins/copilot-pbr/skills/milestone/SKILL.md +2 -0
- package/plugins/copilot-pbr/skills/pause/SKILL.md +7 -1
- package/plugins/cursor-pbr/.cursor-plugin/plugin.json +1 -1
- package/plugins/cursor-pbr/agents/executor.md +1 -0
- package/plugins/cursor-pbr/hooks/hooks.json +20 -0
- package/plugins/cursor-pbr/skills/build/SKILL.md +3 -3
- package/plugins/cursor-pbr/skills/continue/SKILL.md +8 -2
- package/plugins/cursor-pbr/skills/import/SKILL.md +2 -0
- package/plugins/cursor-pbr/skills/milestone/SKILL.md +2 -0
- package/plugins/cursor-pbr/skills/pause/SKILL.md +7 -1
- package/plugins/pbr/.claude-plugin/plugin.json +1 -1
- package/plugins/pbr/agents/executor.md +1 -0
- package/plugins/pbr/hooks/hooks.json +20 -0
- package/plugins/pbr/scripts/auto-continue.js +26 -2
- package/plugins/pbr/scripts/block-skill-self-read.js +72 -0
- package/plugins/pbr/scripts/check-agent-state-write.js +63 -0
- package/plugins/pbr/scripts/check-cross-plugin-sync.js +93 -0
- package/plugins/pbr/scripts/check-dangerous-commands.js +2 -2
- package/plugins/pbr/scripts/check-plan-format.js +111 -23
- package/plugins/pbr/scripts/check-roadmap-sync.js +140 -1
- package/plugins/pbr/scripts/check-state-sync.js +57 -3
- package/plugins/pbr/scripts/check-summary-gate.js +1 -1
- package/plugins/pbr/scripts/post-write-dispatch.js +47 -0
- package/plugins/pbr/scripts/pre-write-dispatch.js +9 -1
- package/plugins/pbr/scripts/session-cleanup.js +3 -4
- package/plugins/pbr/scripts/validate-task.js +14 -19
- package/plugins/pbr/skills/build/SKILL.md +3 -3
- package/plugins/pbr/skills/continue/SKILL.md +8 -2
- package/plugins/pbr/skills/import/SKILL.md +2 -0
- package/plugins/pbr/skills/milestone/SKILL.md +2 -0
- package/plugins/pbr/skills/pause/SKILL.md +7 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,41 @@ 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.22.0](https://github.com/SienkLogic/plan-build-run/compare/plan-build-run-v2.21.1...plan-build-run-v2.22.0) (2026-02-23)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* **24-01:** add check-agent-state-write.js module ([b73ab69](https://github.com/SienkLogic/plan-build-run/commit/b73ab69d8893970595d538a6289d8183b7b08b2b))
|
|
14
|
+
* **24-01:** wire agent state write blocker into pre-write-dispatch ([9f46053](https://github.com/SienkLogic/plan-build-run/commit/9f460530d21e4c3f37389f0bd2731ad0fd99e593))
|
|
15
|
+
* **24-02:** add .auto-next fallback writes to auto_advance hard stops in build skill ([9d59fc1](https://github.com/SienkLogic/plan-build-run/commit/9d59fc13b494cacdbe71e4e236d89bba0724a412))
|
|
16
|
+
* **25-01:** add ROADMAP.md read to continue skill for milestone boundary detection ([49482c2](https://github.com/SienkLogic/plan-build-run/commit/49482c2a7c0fbe49a39b215bf9070381295daa1c))
|
|
17
|
+
* **25-01:** GREEN - add validateRoadmap and ROADMAP.md validation to check-plan-format ([73256de](https://github.com/SienkLogic/plan-build-run/commit/73256dea9ea9c86a55dbd63fe057678e9757a798))
|
|
18
|
+
* **25-01:** GREEN - PLAN.md writes trigger ROADMAP Planning status without regression ([e8e028a](https://github.com/SienkLogic/plan-build-run/commit/e8e028ae3528a856a8c406a3b508802550e0f75f))
|
|
19
|
+
* **25-02:** GREEN - add checkRoadmapWrite routing to post-write-dispatch ([c7db2e0](https://github.com/SienkLogic/plan-build-run/commit/c7db2e0a4433a962a4f499941b29927a16583425))
|
|
20
|
+
* **25-02:** GREEN - implement isHighRisk with status regression and phase gap detection ([cea48b4](https://github.com/SienkLogic/plan-build-run/commit/cea48b4ccce2554a7c698af280e2725a233e69cb))
|
|
21
|
+
* **25-02:** GREEN - implement validatePostMilestone for milestone completion checks ([c666de8](https://github.com/SienkLogic/plan-build-run/commit/c666de84530eb7a6310a8def7744cec4ff5f8358))
|
|
22
|
+
* **26-02:** GREEN - add 150-line advisory warning to checkStateWrite ([9374009](https://github.com/SienkLogic/plan-build-run/commit/937400997580e9666f9efa18b4e0a80c5fe3b668))
|
|
23
|
+
* **26-02:** GREEN - add cross-plugin sync advisory hook ([a55ad12](https://github.com/SienkLogic/plan-build-run/commit/a55ad1273a7193cc521cd6e953ea185f51e7af50))
|
|
24
|
+
* **27-01:** add PreToolUse Read hook to block SKILL.md self-reads ([afe6acd](https://github.com/SienkLogic/plan-build-run/commit/afe6acd8a55a0807e28266b35b2f4fe961c9ecf5))
|
|
25
|
+
* **27-01:** add session length guard to auto-continue with warn at 3, hard-stop at 6 ([fd394d8](https://github.com/SienkLogic/plan-build-run/commit/fd394d893f2e7d93ad4a4bb29acd0a889da3fd67))
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
### Bug Fixes
|
|
29
|
+
|
|
30
|
+
* **24-01:** remove building from ADVANCED_STATUSES gate ([6e1fdf7](https://github.com/SienkLogic/plan-build-run/commit/6e1fdf7fb3897efdb1dca2ef77dbab78bab13ed2))
|
|
31
|
+
* **24-02:** raise consecutive-continue guard threshold from 3 to 6 ([918394c](https://github.com/SienkLogic/plan-build-run/commit/918394c34356f84772a4454061b312601f8ca26d))
|
|
32
|
+
* **24-02:** remove .auto-next cleanup from session-cleanup to prevent race with Stop hook ([d86e39e](https://github.com/SienkLogic/plan-build-run/commit/d86e39e48b51a3765e42c2807ee7ef277f8d3a5d))
|
|
33
|
+
* **25-02:** remove unused path import and result variable (lint) ([f84764a](https://github.com/SienkLogic/plan-build-run/commit/f84764ae3b4a5fce09a7d126624bb1719c57c10b))
|
|
34
|
+
* **26-01:** add CRITICAL dual-update markers to import Step 8b and milestone new Step 8 ([36bd68c](https://github.com/SienkLogic/plan-build-run/commit/36bd68c42d2fc556581de8f2f23a7b9d6447392b))
|
|
35
|
+
* **26-01:** add CRITICAL frontmatter update marker to pause skill STATE.md step ([ec35f3b](https://github.com/SienkLogic/plan-build-run/commit/ec35f3b529c1fe2b2928bb8ef97d768b101f2f0b))
|
|
36
|
+
* **26-02:** sync cross-plugin-sync hook to cursor-pbr and copilot-pbr hooks.json ([2083a1d](https://github.com/SienkLogic/plan-build-run/commit/2083a1d11c1ced3c7f2b4dc83df2c2a4ed684529))
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
### Documentation
|
|
40
|
+
|
|
41
|
+
* **27-01:** add no-reread anti-pattern to executor agents across all plugins ([8b572fa](https://github.com/SienkLogic/plan-build-run/commit/8b572fa6f43dfc3fe1a0ae8caf167ce2351f46f9))
|
|
42
|
+
|
|
8
43
|
## [2.21.1](https://github.com/SienkLogic/plan-build-run/compare/plan-build-run-v2.21.0...plan-build-run-v2.21.1) (2026-02-23)
|
|
9
44
|
|
|
10
45
|
|
package/package.json
CHANGED
|
@@ -254,6 +254,7 @@ Record timestamps at start and end using `node -e "console.log(new Date().toISOS
|
|
|
254
254
|
11. DO NOT continue past a checkpoint — STOP means STOP
|
|
255
255
|
12. DO NOT re-execute completed tasks when continuing
|
|
256
256
|
13. DO NOT force-push or amend commits
|
|
257
|
+
14. DO NOT re-read PLAN.md or PLAN files if the plan was already provided in your prompt context — this wastes tokens on redundant reads
|
|
257
258
|
|
|
258
259
|
---
|
|
259
260
|
|
|
@@ -91,6 +91,18 @@
|
|
|
91
91
|
}
|
|
92
92
|
],
|
|
93
93
|
"preToolUse": [
|
|
94
|
+
{
|
|
95
|
+
"matcher": "Read",
|
|
96
|
+
"hooks": [
|
|
97
|
+
{
|
|
98
|
+
"type": "command",
|
|
99
|
+
"bash": "node \"$(cd \"$(dirname \"$0\")\" && pwd)/../../pbr/scripts/run-hook.js\" block-skill-self-read.js",
|
|
100
|
+
"powershell": "node (Join-Path (Split-Path -Parent $PSScriptRoot) 'pbr\\scripts\\run-hook.js') block-skill-self-read.js",
|
|
101
|
+
"cwd": ".",
|
|
102
|
+
"timeoutSec": 15
|
|
103
|
+
}
|
|
104
|
+
]
|
|
105
|
+
},
|
|
94
106
|
{
|
|
95
107
|
"matcher": "Bash",
|
|
96
108
|
"hooks": [
|
|
@@ -103,6 +115,18 @@
|
|
|
103
115
|
}
|
|
104
116
|
]
|
|
105
117
|
},
|
|
118
|
+
{
|
|
119
|
+
"matcher": "Bash",
|
|
120
|
+
"hooks": [
|
|
121
|
+
{
|
|
122
|
+
"type": "command",
|
|
123
|
+
"bash": "node \"$(cd \"$(dirname \"$0\")\" && pwd)/../../pbr/scripts/run-hook.js\" check-cross-plugin-sync.js",
|
|
124
|
+
"powershell": "node (Join-Path (Split-Path -Parent $PSScriptRoot) 'pbr\\scripts\\run-hook.js') check-cross-plugin-sync.js",
|
|
125
|
+
"cwd": ".",
|
|
126
|
+
"timeoutSec": 15
|
|
127
|
+
}
|
|
128
|
+
]
|
|
129
|
+
},
|
|
106
130
|
{
|
|
107
131
|
"matcher": "Write|Edit",
|
|
108
132
|
"hooks": [
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pbr",
|
|
3
3
|
"displayName": "Plan-Build-Run",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.22.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",
|
|
@@ -751,9 +751,9 @@ Chain to the next skill directly within this session. This eliminates manual pha
|
|
|
751
751
|
|-------------|-------------|-----|
|
|
752
752
|
| Verification passed, more phases | Plan next phase | `Skill({ skill: "pbr:plan", args: "{N+1}" })` |
|
|
753
753
|
| Verification skipped | Run review | `Skill({ skill: "pbr:review", args: "{N}" })` |
|
|
754
|
-
| Verification gaps found | **HARD STOP** — present gaps to user | Do NOT auto-advance past failures |
|
|
755
|
-
| Last phase in current milestone | **HARD STOP** — milestone boundary | Suggest `/pbr:milestone audit`. Explain: "auto_advance pauses at milestone boundaries — your sign-off is required." |
|
|
756
|
-
| Build errors occurred | **HARD STOP** — errors need human review | Do NOT auto-advance past errors |
|
|
754
|
+
| Verification gaps found | **HARD STOP** — present gaps to user | If `auto_continue` also true: write `.planning/.auto-next` with `/pbr:review {N}` before stopping. Do NOT auto-advance past failures. |
|
|
755
|
+
| Last phase in current milestone | **HARD STOP** — milestone boundary | If `auto_continue` also true: write `.planning/.auto-next` with `/pbr:milestone complete` before stopping. Suggest `/pbr:milestone audit`. Explain: "auto_advance pauses at milestone boundaries — your sign-off is required." |
|
|
756
|
+
| Build errors occurred | **HARD STOP** — errors need human review | If `auto_continue` also true: write `.planning/.auto-next` with `/pbr:build {N}` before stopping. Do NOT auto-advance past errors. |
|
|
757
757
|
|
|
758
758
|
After invoking the chained skill, it runs within the same session. When it completes, the chained skill may itself chain further (review→plan, plan→build) if auto_advance remains true. This creates the full cycle: build→review→plan→build→...
|
|
759
759
|
|
|
@@ -48,6 +48,12 @@ Read `.planning/STATE.md` and determine current position:
|
|
|
48
48
|
- Current plan progress
|
|
49
49
|
- Phase status (planning, building, reviewing, complete)
|
|
50
50
|
|
|
51
|
+
Then read `.planning/ROADMAP.md` to identify the current milestone boundary:
|
|
52
|
+
- Find which `## Milestone:` section contains the current phase
|
|
53
|
+
- Determine if the current phase is the **last phase** in that milestone section
|
|
54
|
+
- If this is the last phase and it is verified/complete, warn: "This is the final phase of milestone {name}. After verification, run `/pbr:milestone` to complete it."
|
|
55
|
+
- If the current phase's `Depends on` references a phase from the **previous** milestone that is not yet complete, warn: "Cross-milestone dependency: Phase {N} depends on Phase {M} from milestone {prev}, which is not yet complete."
|
|
56
|
+
|
|
51
57
|
If STATE.md doesn't exist, display:
|
|
52
58
|
```
|
|
53
59
|
ERROR
|
|
@@ -67,10 +73,10 @@ Before proceeding to priority evaluation, check for runaway continue chains:
|
|
|
67
73
|
- Check `.planning/.active-skill` file — if it contains `continue`, treat as a chained continue
|
|
68
74
|
- Check STATE.md `last_action` field — if it contains `continue`, treat as a chained continue
|
|
69
75
|
- If neither source is available, assume this is the first invocation (do not warn)
|
|
70
|
-
4. **If this is the
|
|
76
|
+
4. **If this is the 6th consecutive `/pbr:continue` in a row**, display:
|
|
71
77
|
|
|
72
78
|
```
|
|
73
|
-
WARNING: Context budget warning:
|
|
79
|
+
WARNING: Context budget warning: 6 consecutive auto-continues detected.
|
|
74
80
|
Recommend running /pbr:pause then resuming in a fresh session.
|
|
75
81
|
```
|
|
76
82
|
|
|
@@ -337,6 +337,8 @@ Perform all state updates in this order:
|
|
|
337
337
|
5. Update the `Status` column to `planned`
|
|
338
338
|
6. Save the file — do NOT skip this step
|
|
339
339
|
|
|
340
|
+
**CRITICAL -- DO NOT SKIP: Update STATE.md frontmatter AND body with import status.**
|
|
341
|
+
|
|
340
342
|
**8b. Update STATE.md:**
|
|
341
343
|
- Set current phase plan status to "planned"
|
|
342
344
|
- Note source: "imported from {filepath}" or "imported from user input"
|
|
@@ -146,6 +146,8 @@ Start a new milestone cycle with new phases.
|
|
|
146
146
|
- **Status:** In progress
|
|
147
147
|
```
|
|
148
148
|
|
|
149
|
+
**CRITICAL -- DO NOT SKIP: Update STATE.md frontmatter AND body with new milestone info.**
|
|
150
|
+
|
|
149
151
|
8. **Update STATE.md:**
|
|
150
152
|
- Set current phase to the first new phase
|
|
151
153
|
- Update milestone info
|
|
@@ -130,7 +130,13 @@ Read `skills/pause/templates/continue-here.md.tmpl` for the handoff file format.
|
|
|
130
130
|
|
|
131
131
|
### Step 5: Update STATE.md
|
|
132
132
|
|
|
133
|
-
|
|
133
|
+
**CRITICAL -- DO NOT SKIP: Update STATE.md frontmatter AND body. Both must be updated atomically.**
|
|
134
|
+
|
|
135
|
+
First, update the STATE.md YAML frontmatter:
|
|
136
|
+
- Set `last_command: "/pbr:pause"`
|
|
137
|
+
- Set `last_activity: {ISO datetime}`
|
|
138
|
+
|
|
139
|
+
Then update the Session Continuity section of STATE.md:
|
|
134
140
|
|
|
135
141
|
```markdown
|
|
136
142
|
### Session Continuity
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pbr",
|
|
3
3
|
"displayName": "Plan-Build-Run",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.22.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",
|
|
@@ -253,6 +253,7 @@ Record timestamps at start and end using `node -e "console.log(new Date().toISOS
|
|
|
253
253
|
11. DO NOT continue past a checkpoint — STOP means STOP
|
|
254
254
|
12. DO NOT re-execute completed tasks when continuing
|
|
255
255
|
13. DO NOT force-push or amend commits
|
|
256
|
+
14. DO NOT re-read PLAN.md or PLAN files if the plan was already provided in your prompt context — this wastes tokens on redundant reads
|
|
256
257
|
|
|
257
258
|
---
|
|
258
259
|
|
|
@@ -77,6 +77,16 @@
|
|
|
77
77
|
}
|
|
78
78
|
],
|
|
79
79
|
"PreToolUse": [
|
|
80
|
+
{
|
|
81
|
+
"matcher": "Read",
|
|
82
|
+
"hooks": [
|
|
83
|
+
{
|
|
84
|
+
"type": "command",
|
|
85
|
+
"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'))\" block-skill-self-read.js",
|
|
86
|
+
"statusMessage": "Checking skill self-read..."
|
|
87
|
+
}
|
|
88
|
+
]
|
|
89
|
+
},
|
|
80
90
|
{
|
|
81
91
|
"matcher": "Bash",
|
|
82
92
|
"hooks": [
|
|
@@ -87,6 +97,16 @@
|
|
|
87
97
|
}
|
|
88
98
|
]
|
|
89
99
|
},
|
|
100
|
+
{
|
|
101
|
+
"matcher": "Bash",
|
|
102
|
+
"hooks": [
|
|
103
|
+
{
|
|
104
|
+
"type": "command",
|
|
105
|
+
"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-cross-plugin-sync.js",
|
|
106
|
+
"statusMessage": "Checking cross-plugin sync..."
|
|
107
|
+
}
|
|
108
|
+
]
|
|
109
|
+
},
|
|
90
110
|
{
|
|
91
111
|
"matcher": "Write|Edit",
|
|
92
112
|
"hooks": [
|
|
@@ -752,9 +752,9 @@ Chain to the next skill directly within this session. This eliminates manual pha
|
|
|
752
752
|
|-------------|-------------|-----|
|
|
753
753
|
| Verification passed, more phases | Plan next phase | `Skill({ skill: "pbr:plan", args: "{N+1}" })` |
|
|
754
754
|
| Verification skipped | Run review | `Skill({ skill: "pbr:review", args: "{N}" })` |
|
|
755
|
-
| Verification gaps found | **HARD STOP** — present gaps to user | Do NOT auto-advance past failures |
|
|
756
|
-
| Last phase in current milestone | **HARD STOP** — milestone boundary | Suggest `/pbr:milestone audit`. Explain: "auto_advance pauses at milestone boundaries — your sign-off is required." |
|
|
757
|
-
| Build errors occurred | **HARD STOP** — errors need human review | Do NOT auto-advance past errors |
|
|
755
|
+
| Verification gaps found | **HARD STOP** — present gaps to user | If `auto_continue` also true: write `.planning/.auto-next` with `/pbr:review {N}` before stopping. Do NOT auto-advance past failures. |
|
|
756
|
+
| Last phase in current milestone | **HARD STOP** — milestone boundary | If `auto_continue` also true: write `.planning/.auto-next` with `/pbr:milestone complete` before stopping. Suggest `/pbr:milestone audit`. Explain: "auto_advance pauses at milestone boundaries — your sign-off is required." |
|
|
757
|
+
| Build errors occurred | **HARD STOP** — errors need human review | If `auto_continue` also true: write `.planning/.auto-next` with `/pbr:build {N}` before stopping. Do NOT auto-advance past errors. |
|
|
758
758
|
|
|
759
759
|
After invoking the chained skill, it runs within the same session. When it completes, the chained skill may itself chain further (review→plan, plan→build) if auto_advance remains true. This creates the full cycle: build→review→plan→build→...
|
|
760
760
|
|
|
@@ -48,6 +48,12 @@ Read `.planning/STATE.md` and determine current position:
|
|
|
48
48
|
- Current plan progress
|
|
49
49
|
- Phase status (planning, building, reviewing, complete)
|
|
50
50
|
|
|
51
|
+
Then read `.planning/ROADMAP.md` to identify the current milestone boundary:
|
|
52
|
+
- Find which `## Milestone:` section contains the current phase
|
|
53
|
+
- Determine if the current phase is the **last phase** in that milestone section
|
|
54
|
+
- If this is the last phase and it is verified/complete, warn: "This is the final phase of milestone {name}. After verification, run `/pbr:milestone` to complete it."
|
|
55
|
+
- If the current phase's `Depends on` references a phase from the **previous** milestone that is not yet complete, warn: "Cross-milestone dependency: Phase {N} depends on Phase {M} from milestone {prev}, which is not yet complete."
|
|
56
|
+
|
|
51
57
|
If STATE.md doesn't exist, display:
|
|
52
58
|
```
|
|
53
59
|
ERROR
|
|
@@ -67,10 +73,10 @@ Before proceeding to priority evaluation, check for runaway continue chains:
|
|
|
67
73
|
- Check `.planning/.active-skill` file — if it contains `continue`, treat as a chained continue
|
|
68
74
|
- Check STATE.md `last_action` field — if it contains `continue`, treat as a chained continue
|
|
69
75
|
- If neither source is available, assume this is the first invocation (do not warn)
|
|
70
|
-
4. **If this is the
|
|
76
|
+
4. **If this is the 6th consecutive `/pbr:continue` in a row**, display:
|
|
71
77
|
|
|
72
78
|
```
|
|
73
|
-
WARNING: Context budget warning:
|
|
79
|
+
WARNING: Context budget warning: 6 consecutive auto-continues detected.
|
|
74
80
|
Recommend running /pbr:pause then resuming in a fresh session.
|
|
75
81
|
```
|
|
76
82
|
|
|
@@ -338,6 +338,8 @@ Perform all state updates in this order:
|
|
|
338
338
|
5. Update the `Status` column to `planned`
|
|
339
339
|
6. Save the file — do NOT skip this step
|
|
340
340
|
|
|
341
|
+
**CRITICAL -- DO NOT SKIP: Update STATE.md frontmatter AND body with import status.**
|
|
342
|
+
|
|
341
343
|
**8b. Update STATE.md:**
|
|
342
344
|
- Set current phase plan status to "planned"
|
|
343
345
|
- Note source: "imported from {filepath}" or "imported from user input"
|
|
@@ -147,6 +147,8 @@ Start a new milestone cycle with new phases.
|
|
|
147
147
|
- **Status:** In progress
|
|
148
148
|
```
|
|
149
149
|
|
|
150
|
+
**CRITICAL -- DO NOT SKIP: Update STATE.md frontmatter AND body with new milestone info.**
|
|
151
|
+
|
|
150
152
|
8. **Update STATE.md:**
|
|
151
153
|
- Set current phase to the first new phase
|
|
152
154
|
- Update milestone info
|
|
@@ -130,7 +130,13 @@ Read `skills/pause/templates/continue-here.md.tmpl` for the handoff file format.
|
|
|
130
130
|
|
|
131
131
|
### Step 5: Update STATE.md
|
|
132
132
|
|
|
133
|
-
|
|
133
|
+
**CRITICAL -- DO NOT SKIP: Update STATE.md frontmatter AND body. Both must be updated atomically.**
|
|
134
|
+
|
|
135
|
+
First, update the STATE.md YAML frontmatter:
|
|
136
|
+
- Set `last_command: "/pbr:pause"`
|
|
137
|
+
- Set `last_activity: {ISO datetime}`
|
|
138
|
+
|
|
139
|
+
Then update the Session Continuity section of STATE.md:
|
|
134
140
|
|
|
135
141
|
```markdown
|
|
136
142
|
### Session Continuity
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pbr",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.22.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",
|
|
@@ -260,6 +260,7 @@ Record timestamps at start and end using `node -e "console.log(new Date().toISOS
|
|
|
260
260
|
11. DO NOT continue past a checkpoint — STOP means STOP
|
|
261
261
|
12. DO NOT re-execute completed tasks when continuing
|
|
262
262
|
13. DO NOT force-push or amend commits
|
|
263
|
+
14. DO NOT re-read PLAN.md or PLAN files if the plan was already provided in your prompt context — this wastes tokens on redundant reads
|
|
263
264
|
|
|
264
265
|
---
|
|
265
266
|
|
|
@@ -77,6 +77,16 @@
|
|
|
77
77
|
}
|
|
78
78
|
],
|
|
79
79
|
"PreToolUse": [
|
|
80
|
+
{
|
|
81
|
+
"matcher": "Read",
|
|
82
|
+
"hooks": [
|
|
83
|
+
{
|
|
84
|
+
"type": "command",
|
|
85
|
+
"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'))\" block-skill-self-read.js",
|
|
86
|
+
"statusMessage": "Checking skill self-read..."
|
|
87
|
+
}
|
|
88
|
+
]
|
|
89
|
+
},
|
|
80
90
|
{
|
|
81
91
|
"matcher": "Bash",
|
|
82
92
|
"hooks": [
|
|
@@ -87,6 +97,16 @@
|
|
|
87
97
|
}
|
|
88
98
|
]
|
|
89
99
|
},
|
|
100
|
+
{
|
|
101
|
+
"matcher": "Bash",
|
|
102
|
+
"hooks": [
|
|
103
|
+
{
|
|
104
|
+
"type": "command",
|
|
105
|
+
"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-cross-plugin-sync.js",
|
|
106
|
+
"statusMessage": "Checking cross-plugin sync..."
|
|
107
|
+
}
|
|
108
|
+
]
|
|
109
|
+
},
|
|
90
110
|
{
|
|
91
111
|
"matcher": "Write|Edit",
|
|
92
112
|
"hooks": [
|
|
@@ -63,6 +63,9 @@ function main() {
|
|
|
63
63
|
} catch (_todoErr) {
|
|
64
64
|
// Ignore errors scanning todos
|
|
65
65
|
}
|
|
66
|
+
// Reset continue count on normal session stop (no signal)
|
|
67
|
+
const countPathNoSig = path.join(planningDir, '.continue-count');
|
|
68
|
+
try { fs.unlinkSync(countPathNoSig); } catch (_e) { /* ignore */ }
|
|
66
69
|
logHook('auto-continue', 'Stop', 'no-signal', {});
|
|
67
70
|
process.exit(0);
|
|
68
71
|
}
|
|
@@ -97,19 +100,40 @@ function main() {
|
|
|
97
100
|
process.exit(0);
|
|
98
101
|
}
|
|
99
102
|
|
|
103
|
+
// Track consecutive continues for session length guard
|
|
104
|
+
const countPath = path.join(planningDir, '.continue-count');
|
|
105
|
+
let continueCount = 0;
|
|
106
|
+
try {
|
|
107
|
+
continueCount = parseInt(fs.readFileSync(countPath, 'utf8').trim(), 10) || 0;
|
|
108
|
+
} catch (_e) { /* file missing — start at 0 */ }
|
|
109
|
+
continueCount++;
|
|
110
|
+
try { fs.writeFileSync(countPath, String(continueCount)); } catch (_e) { /* ignore */ }
|
|
111
|
+
|
|
112
|
+
// Hard stop after 6 consecutive continues — context is likely degraded
|
|
113
|
+
if (continueCount > 6) {
|
|
114
|
+
logHook('auto-continue', 'Stop', 'hard-stop-session-length', { count: continueCount });
|
|
115
|
+
process.exit(0);
|
|
116
|
+
}
|
|
117
|
+
|
|
100
118
|
// Extract last_assistant_message for richer continuation context
|
|
101
119
|
const lastMsg = hookInput.last_assistant_message || '';
|
|
102
120
|
const msgSuffix = lastMsg
|
|
103
121
|
? ` (last message excerpt: ${lastMsg.slice(0, 200)})`
|
|
104
122
|
: '';
|
|
105
123
|
|
|
106
|
-
logHook('auto-continue', 'Stop', 'continue', { next: nextCommand, hasLastMsg: !!lastMsg });
|
|
124
|
+
logHook('auto-continue', 'Stop', 'continue', { next: nextCommand, hasLastMsg: !!lastMsg, continueCount });
|
|
125
|
+
|
|
126
|
+
// Build reason string with optional advisory
|
|
127
|
+
let reasonStr = `Auto-continue: execute ${nextCommand}${msgSuffix}`;
|
|
128
|
+
if (continueCount > 3) {
|
|
129
|
+
reasonStr += `\n\n[pbr] Advisory: ${continueCount} consecutive continues. Consider /pbr:pause + fresh session to avoid context degradation.`;
|
|
130
|
+
}
|
|
107
131
|
|
|
108
132
|
// Block the stop and inject the next command as Claude's continuation reason.
|
|
109
133
|
// Claude Code Stop hooks use { decision: "block", reason: "..." } to keep going.
|
|
110
134
|
const output = {
|
|
111
135
|
decision: 'block',
|
|
112
|
-
reason:
|
|
136
|
+
reason: reasonStr
|
|
113
137
|
};
|
|
114
138
|
process.stdout.write(JSON.stringify(output));
|
|
115
139
|
process.exit(0);
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* PreToolUse Read hook: blocks skills from re-reading their own SKILL.md.
|
|
5
|
+
*
|
|
6
|
+
* Skills are already loaded into context by Claude Code — re-reading
|
|
7
|
+
* wastes ~13k tokens. This hook checks .planning/.active-skill to
|
|
8
|
+
* determine the current skill and blocks if the Read target matches.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
'use strict';
|
|
12
|
+
|
|
13
|
+
const fs = require('fs');
|
|
14
|
+
const path = require('path');
|
|
15
|
+
const { logHook } = require('./hook-logger');
|
|
16
|
+
|
|
17
|
+
function main() {
|
|
18
|
+
try {
|
|
19
|
+
let hookInput = {};
|
|
20
|
+
try {
|
|
21
|
+
const stdin = fs.readFileSync(0, 'utf8').trim();
|
|
22
|
+
if (stdin) hookInput = JSON.parse(stdin);
|
|
23
|
+
} catch (_parseErr) {
|
|
24
|
+
// No stdin or invalid JSON
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const cwd = hookInput.cwd || process.cwd();
|
|
28
|
+
const toolInput = hookInput.tool_input || {};
|
|
29
|
+
const filePath = toolInput.file_path || '';
|
|
30
|
+
|
|
31
|
+
if (!filePath) {
|
|
32
|
+
process.exit(0);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Read .active-skill to get current skill name
|
|
36
|
+
const activeSkillPath = path.join(cwd, '.planning', '.active-skill');
|
|
37
|
+
let skillName = '';
|
|
38
|
+
try {
|
|
39
|
+
skillName = fs.readFileSync(activeSkillPath, 'utf8').trim();
|
|
40
|
+
} catch (_readErr) {
|
|
41
|
+
// No .active-skill file — nothing to block
|
|
42
|
+
process.exit(0);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (!skillName) {
|
|
46
|
+
process.exit(0);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Check if file_path ends with skills/{skill-name}/SKILL.md
|
|
50
|
+
const normalized = filePath.replace(/\\/g, '/');
|
|
51
|
+
const pattern = `skills/${skillName}/SKILL.md`.toLowerCase();
|
|
52
|
+
const match = normalized.toLowerCase().endsWith(pattern);
|
|
53
|
+
|
|
54
|
+
if (match) {
|
|
55
|
+
logHook('block-skill-self-read', 'PreToolUse', 'block', { skill: skillName, file: filePath });
|
|
56
|
+
const output = {
|
|
57
|
+
decision: 'block',
|
|
58
|
+
reason: `SKILL.md self-read blocked.\n\nThe active skill (${skillName}) attempted to read its own SKILL.md. Skills are already loaded into context by Claude Code \u2014 re-reading wastes ~13k tokens.\n\nNo action needed. The skill content is already available in your prompt.`
|
|
59
|
+
};
|
|
60
|
+
process.stdout.write(JSON.stringify(output));
|
|
61
|
+
} else {
|
|
62
|
+
logHook('block-skill-self-read', 'PreToolUse', 'allow', { skill: skillName, file: filePath });
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
process.exit(0);
|
|
66
|
+
} catch (_e) {
|
|
67
|
+
// Don't block on errors
|
|
68
|
+
process.exit(0);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
main();
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* PreToolUse hook: Blocks subagents (except pbr:general) from writing STATE.md.
|
|
5
|
+
*
|
|
6
|
+
* STATE.md is the source of truth for project position and should only be
|
|
7
|
+
* written by skills (orchestrators) or the general agent, never by specialized
|
|
8
|
+
* agents like executor, planner, or verifier.
|
|
9
|
+
*
|
|
10
|
+
* Detection: reads .planning/.active-agent (written by log-subagent.js).
|
|
11
|
+
*
|
|
12
|
+
* Exit codes:
|
|
13
|
+
* 0 = allowed or not applicable
|
|
14
|
+
* 2 = blocked (agent not allowed to write STATE.md)
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const fs = require('fs');
|
|
18
|
+
const path = require('path');
|
|
19
|
+
|
|
20
|
+
const BLOCKED_AGENTS = [
|
|
21
|
+
'pbr:executor',
|
|
22
|
+
'pbr:planner',
|
|
23
|
+
'pbr:verifier',
|
|
24
|
+
'pbr:researcher',
|
|
25
|
+
'pbr:plan-checker',
|
|
26
|
+
'pbr:integration-checker',
|
|
27
|
+
'pbr:debugger',
|
|
28
|
+
'pbr:codebase-mapper',
|
|
29
|
+
'pbr:synthesizer',
|
|
30
|
+
'pbr:audit',
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
function checkAgentStateWrite(data) {
|
|
34
|
+
const filePath = data.tool_input?.file_path || data.tool_input?.path || '';
|
|
35
|
+
if (!filePath) return null;
|
|
36
|
+
|
|
37
|
+
const normalized = filePath.replace(/\\/g, '/');
|
|
38
|
+
if (!normalized.endsWith('.planning/STATE.md')) return null;
|
|
39
|
+
|
|
40
|
+
// Check if we're inside a subagent
|
|
41
|
+
const cwd = process.cwd();
|
|
42
|
+
const agentFile = path.join(cwd, '.planning', '.active-agent');
|
|
43
|
+
|
|
44
|
+
let agent;
|
|
45
|
+
try {
|
|
46
|
+
agent = fs.readFileSync(agentFile, 'utf8').trim();
|
|
47
|
+
} catch (_e) {
|
|
48
|
+
// No .active-agent file — not in an agent context
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (!agent || !BLOCKED_AGENTS.includes(agent)) return null;
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
exitCode: 2,
|
|
56
|
+
output: {
|
|
57
|
+
decision: 'block',
|
|
58
|
+
reason: `Agent write to STATE.md blocked.\n\n${agent} is not allowed to write STATE.md. Only skills (orchestrators) and pbr:general may update this file to prevent state corruption.\n\nReturn results to the calling skill and let it update STATE.md.`
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
module.exports = { checkAgentStateWrite, BLOCKED_AGENTS };
|