pi-plan-task 1.1.0 → 4.0.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/README.md +535 -68
- package/extensions/build-session.test.ts +25 -27
- package/extensions/build-session.ts +26 -11
- package/extensions/command-surface.test.ts +15 -0
- package/extensions/config.ts +12 -40
- package/extensions/files.test.ts +21 -1
- package/extensions/files.ts +11 -27
- package/extensions/framing.test.ts +1 -0
- package/extensions/framing.ts +5 -2
- package/extensions/history.test.ts +24 -0
- package/extensions/history.ts +42 -0
- package/extensions/index.ts +523 -245
- package/extensions/integration.test.ts +231 -0
- package/extensions/migration.test.ts +34 -0
- package/extensions/parse.ts +80 -4
- package/extensions/paths.ts +26 -32
- package/extensions/planning-and-task-breakdown.md +10 -8
- package/extensions/planning-method.test.ts +15 -2
- package/extensions/planning-method.ts +4 -2
- package/extensions/policy.test.ts +11 -0
- package/extensions/prompts.test.ts +54 -9
- package/extensions/prompts.ts +100 -32
- package/extensions/recovery.test.ts +15 -0
- package/extensions/review.test.ts +19 -0
- package/extensions/review.ts +53 -0
- package/extensions/state.test.ts +25 -0
- package/extensions/state.ts +198 -0
- package/extensions/task-ui.ts +59 -0
- package/extensions/tool-policy.ts +4 -0
- package/extensions/tools.test.ts +10 -0
- package/extensions/tools.ts +16 -0
- package/extensions/types.ts +53 -5
- package/extensions/validation.test.ts +38 -0
- package/extensions/workflow-policy.test.ts +76 -0
- package/extensions/workflow-policy.ts +117 -0
- package/extensions/workflow-store.test.ts +48 -0
- package/extensions/workflow-store.ts +165 -0
- package/package.json +29 -5
package/README.md
CHANGED
|
@@ -1,136 +1,603 @@
|
|
|
1
1
|
# pi-plan-task
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
[](https://opensource.org/licenses/MIT)
|
|
3
|
+
A safe, file-backed planning and execution workflow for [Pi](https://github.com/badlogic/pi-mono):
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
```text
|
|
6
|
+
Plan → Review → Approve → Execute → Verify → Continue / Stop
|
|
7
|
+
```
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
`pi-plan-task` separates planning from implementation, binds approval to the exact submitted plan structure, executes one focused task at a time, and persists enough state to resume after reloads or session changes.
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
[](https://www.npmjs.com/package/pi-plan-task)
|
|
12
|
+
[](https://opensource.org/licenses/MIT)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
## Contents
|
|
16
|
+
|
|
17
|
+
- [Highlights](#highlights)
|
|
18
|
+
- [Requirements](#requirements)
|
|
19
|
+
- [Installation](#installation)
|
|
20
|
+
- [Quick start](#quick-start)
|
|
21
|
+
- [Commands](#commands)
|
|
22
|
+
- [`/plan`](#plan--planning-and-approval)
|
|
23
|
+
- [`/build`](#build--execution)
|
|
24
|
+
- [`/tasks`](#tasks--inspection-and-rework)
|
|
25
|
+
- [LLM tool: `plan_task`](#llm-tool-plan_task)
|
|
26
|
+
- [Task file contract](#task-file-contract)
|
|
27
|
+
- [Durable files](#durable-files)
|
|
28
|
+
- [Lifecycle](#lifecycle)
|
|
29
|
+
- [State](#state)
|
|
30
|
+
- [Resume and recovery](#resume-and-recovery)
|
|
31
|
+
- [Configuration](#configuration)
|
|
32
|
+
- [Events](#events)
|
|
33
|
+
- [Optional Plannotator integration](#optional-plannotator-integration)
|
|
34
|
+
- [Troubleshooting](#troubleshooting)
|
|
35
|
+
- [Development](#development)
|
|
36
|
+
- [Safety notes](#safety-notes)
|
|
37
|
+
## Highlights
|
|
38
|
+
|
|
39
|
+
- Only three user-facing commands: `/plan`, `/build`, and `/tasks`.
|
|
40
|
+
- Planning writes to an isolated `.plan_task/draft/` area.
|
|
41
|
+
- Explicit approval is required before implementation.
|
|
42
|
+
- Approval is revoked if submitted plan or task structure changes.
|
|
43
|
+
- Task implementation and verification are separate states.
|
|
44
|
+
- `task.md` is the single source of truth for execution progress.
|
|
45
|
+
- One task can run here, in a new session, or in a clean session.
|
|
46
|
+
- All remaining tasks can run here or one-per-session.
|
|
47
|
+
- State updates are validated and serialized; multi-file changes use transactional replacement with rollback.
|
|
48
|
+
- Optional Plannotator integration provides browser-based plan review.
|
|
49
|
+
|
|
50
|
+
## Requirements
|
|
51
|
+
|
|
52
|
+
- Pi with extension/package support.
|
|
53
|
+
- `ask_user_question` is required at runtime when planning or execution reaches a consequential user decision.
|
|
54
|
+
- Plannotator is optional. After a plan is submitted, choose `review` if the CLI is installed.
|
|
55
|
+
|
|
56
|
+
## Installation
|
|
11
57
|
|
|
12
58
|
```bash
|
|
13
59
|
pi install npm:@juicesharp/rpiv-ask-user-question
|
|
14
60
|
pi install npm:pi-plan-task
|
|
15
61
|
```
|
|
16
62
|
|
|
17
|
-
Restart Pi or run `/reload
|
|
63
|
+
Restart Pi or run `/reload` after installation.
|
|
18
64
|
|
|
19
|
-
|
|
65
|
+
For local development:
|
|
20
66
|
|
|
21
67
|
```bash
|
|
22
68
|
pi install /absolute/path/to/pi-plan-task
|
|
23
69
|
```
|
|
24
70
|
|
|
25
|
-
|
|
71
|
+
Alternatively, add the package path to `packages` in `~/.pi/agent/settings.json`.
|
|
72
|
+
|
|
73
|
+
## Quick start
|
|
74
|
+
|
|
75
|
+
```text
|
|
76
|
+
/plan Add OAuth login
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
When the draft is valid, choose one of:
|
|
80
|
+
|
|
81
|
+
```text
|
|
82
|
+
approve lock the submitted plan (then choose here/new/fresh, or run /build later)
|
|
83
|
+
review open optional Plannotator review
|
|
84
|
+
reject reject and revise with feedback
|
|
85
|
+
later leave the submitted plan ready for later approval
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
A typical flow is:
|
|
89
|
+
|
|
90
|
+
1. Run `/plan <request>`.
|
|
91
|
+
2. The agent writes `.plan_task/draft/plan.md` and `.plan_task/draft/task.md`.
|
|
92
|
+
3. The extension validates both draft files.
|
|
93
|
+
4. The valid draft is transactionally submitted as `.plan_task/plan.md` and `.plan_task/task.md`, with rollback on failure.
|
|
94
|
+
5. Review or approve the submitted plan.
|
|
95
|
+
6. Run one task with `/build`, or all remaining tasks with `/build all`.
|
|
96
|
+
7. Each task follows `pending → implementation-complete → verified`.
|
|
97
|
+
8. Only verification checks the task and permits progression.
|
|
98
|
+
|
|
99
|
+
Execution is approval-gated. A missing, changed, or unapproved plan cannot start implementation.
|
|
26
100
|
|
|
27
101
|
## Commands
|
|
28
102
|
|
|
29
|
-
|
|
103
|
+
The extension registers exactly three user-facing slash commands:
|
|
104
|
+
|
|
105
|
+
```text
|
|
106
|
+
/plan create, approve, and reject plans
|
|
107
|
+
/build execute one or all tasks
|
|
108
|
+
/tasks inspect and manage tasks
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### `/plan` — planning and approval
|
|
112
|
+
|
|
113
|
+
| Command | Description |
|
|
30
114
|
| --- | --- |
|
|
31
|
-
| `/plan
|
|
32
|
-
| `/
|
|
33
|
-
| `/
|
|
34
|
-
| `/
|
|
35
|
-
| `/
|
|
36
|
-
| `/
|
|
115
|
+
| `/plan` | Plan from the current conversation and repository. |
|
|
116
|
+
| `/plan <request>` | Plan from a free-text request. |
|
|
117
|
+
| `/plan <file> [notes]` | Use a repository spec file with optional guidance. |
|
|
118
|
+
| `/plan request <text>` | Force text beginning with a reserved subcommand to be treated as a request. |
|
|
119
|
+
| `/plan approve` | Approve the submitted plan. Does not start execution. |
|
|
120
|
+
| `/plan reject [feedback]` | Reject the submitted plan and initialize a revision draft. |
|
|
121
|
+
|
|
122
|
+
The first argument to `/plan` is reserved when it is one of:
|
|
123
|
+
|
|
124
|
+
```text
|
|
125
|
+
approve reject request
|
|
126
|
+
```
|
|
37
127
|
|
|
38
|
-
|
|
128
|
+
If the actual request starts with a reserved word, use `/plan request ...`:
|
|
39
129
|
|
|
40
|
-
|
|
130
|
+
```text
|
|
131
|
+
/plan request review the login page accessibility
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
`/plan approve` only locks the submitted structure. In a UI session it then asks where the next task should run (`here`, `new`, or `fresh`). In non-UI mode it stops after approval; run `/build` or `/build all` to execute. `/plan reject` works from `ready`, `approved`, `blocked`, or `completed`.
|
|
135
|
+
|
|
136
|
+
#### Draft behavior
|
|
137
|
+
|
|
138
|
+
- New work receives a new `workId` and does not inherit old blocked/task runtime state.
|
|
139
|
+
- Revision preserves the current submitted files until the new draft validates successfully.
|
|
140
|
+
- An unchanged draft is not resubmitted.
|
|
141
|
+
- Invalid or half-written drafts never replace current files.
|
|
142
|
+
- Only draft files are writable during Plan mode.
|
|
143
|
+
|
|
144
|
+
### `/build` — execution
|
|
41
145
|
|
|
42
|
-
|
|
146
|
+
| Command | Description |
|
|
147
|
+
| --- | --- |
|
|
148
|
+
| `/build` | Execute one pending task in this session. |
|
|
149
|
+
| `/build all` | Execute all remaining tasks in this session. |
|
|
150
|
+
|
|
151
|
+
`--all` is accepted as an alias for `all`. Unknown and duplicate options are rejected.
|
|
152
|
+
|
|
153
|
+
After a single task is verified, a UI session asks:
|
|
43
154
|
|
|
155
|
+
```text
|
|
156
|
+
Continue in this session
|
|
157
|
+
Continue in a new session
|
|
158
|
+
Stop
|
|
44
159
|
```
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
160
|
+
|
|
161
|
+
Choosing a new session persists `continueMode: "all-new"` and opens a replacement session that runs `/build` for the next task. `/build all` continues remaining tasks here without prompting. In non-UI modes, `/build` stops after the current task.
|
|
162
|
+
|
|
163
|
+
#### Session placement
|
|
164
|
+
|
|
165
|
+
Placement is chosen in UI prompts, not as `/build` flags:
|
|
166
|
+
|
|
167
|
+
- `here` continues in the current session.
|
|
168
|
+
- `new` records the current session as parent and opens a replacement session.
|
|
169
|
+
- `fresh` is offered after `/plan approve` and opens a clean session without the planning conversation as parent context.
|
|
170
|
+
- If session creation is cancelled, the plan remains approved and can be started again with `/build`.
|
|
171
|
+
|
|
172
|
+
### `/tasks` — inspection and rework
|
|
173
|
+
|
|
174
|
+
| Command | Description |
|
|
175
|
+
| --- | --- |
|
|
176
|
+
| `/tasks` | Show lifecycle status, work identity, approved hash, current task, and the canonical checklist. |
|
|
177
|
+
| `/tasks rework <id>` | Reopen a verified task and every later task. |
|
|
178
|
+
|
|
179
|
+
Rework is intentionally strict:
|
|
180
|
+
|
|
181
|
+
- The target must exist and already be verified.
|
|
182
|
+
- The target and every later task return to `pending`.
|
|
183
|
+
- Their top-level checklist items are unchecked.
|
|
184
|
+
- Verification, completion, and block metadata are cleared.
|
|
185
|
+
- Approval is revoked.
|
|
186
|
+
- The plan returns to `ready` and must be approved again.
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
## LLM tool: `plan_task`
|
|
190
|
+
|
|
191
|
+
`plan_task` is callable by the model; it is not a slash command.
|
|
192
|
+
|
|
193
|
+
### Status
|
|
194
|
+
|
|
195
|
+
```json
|
|
196
|
+
{"action":"status"}
|
|
50
197
|
```
|
|
51
198
|
|
|
52
|
-
|
|
199
|
+
Returns the canonical checklist and progress.
|
|
53
200
|
|
|
54
|
-
###
|
|
201
|
+
### Complete implementation
|
|
55
202
|
|
|
203
|
+
```json
|
|
204
|
+
{"action":"complete","id":1}
|
|
56
205
|
```
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
206
|
+
|
|
207
|
+
Valid only when:
|
|
208
|
+
|
|
209
|
+
- the plan is `executing`;
|
|
210
|
+
- the ID is the current task;
|
|
211
|
+
- the task exists and is `pending`;
|
|
212
|
+
- the submitted structure still matches the approved hash.
|
|
213
|
+
|
|
214
|
+
`complete` changes task runtime state to `implementation-complete`. It does **not** check the task and does **not** advance execution.
|
|
215
|
+
|
|
216
|
+
### Verify
|
|
217
|
+
|
|
218
|
+
```json
|
|
219
|
+
{"action":"verify","id":1,"reason":"Focused tests and typecheck passed"}
|
|
61
220
|
```
|
|
62
221
|
|
|
63
|
-
`
|
|
222
|
+
Valid only for the current `implementation-complete` task and requires a non-empty verification result. A successful verification performs one serialized transaction that:
|
|
64
223
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
224
|
+
1. records `verified` state and evidence;
|
|
225
|
+
2. checks the matching top-level item in `task.md`;
|
|
226
|
+
3. persists state;
|
|
227
|
+
4. emits `pi-plan-task:task-verified`;
|
|
228
|
+
5. allows execution to continue.
|
|
69
229
|
|
|
70
|
-
|
|
230
|
+
### Block
|
|
71
231
|
|
|
72
|
-
|
|
232
|
+
```json
|
|
233
|
+
{"action":"block","id":1,"reason":"Waiting for API decision"}
|
|
234
|
+
```
|
|
73
235
|
|
|
74
|
-
|
|
236
|
+
Valid only for the current `pending` or `implementation-complete` task and requires a non-empty reason. The pre-block state is retained so the task can return to the correct state later.
|
|
75
237
|
|
|
76
|
-
|
|
77
|
-
- checklist lines in the form `- [ ] N. Title`
|
|
238
|
+
### Unblock
|
|
78
239
|
|
|
79
|
-
|
|
240
|
+
```json
|
|
241
|
+
{"action":"unblock","id":1}
|
|
242
|
+
```
|
|
80
243
|
|
|
81
|
-
|
|
244
|
+
Restores a blocked task to `pending` or `implementation-complete`. It does not automatically start execution. If the whole plan was blocked, unblocking restores it to an approved, buildable state.
|
|
82
245
|
|
|
83
|
-
|
|
246
|
+
Invalid tool actions fail without changing files, state, or emitting success events.
|
|
247
|
+
|
|
248
|
+
## Task file contract
|
|
249
|
+
|
|
250
|
+
`.plan_task/task.md` is the canonical execution queue and completion source. It must begin with numbered top-level checklist items:
|
|
251
|
+
|
|
252
|
+
```markdown
|
|
253
|
+
# Tasks
|
|
84
254
|
|
|
85
|
-
-
|
|
86
|
-
-
|
|
87
|
-
- Later turns in the same phase inject nothing unless the checklist actually changed; then a small build-status message is appended.
|
|
88
|
-
- `context` keeps only the newest framing for the current phase. Stale plan/build messages are dropped from the model context. While idle, every injected message is filtered out.
|
|
255
|
+
- [ ] 1. Add the login API
|
|
256
|
+
- [ ] 2. Add the login UI
|
|
89
257
|
|
|
90
|
-
|
|
258
|
+
## Task 1: Add the login API
|
|
91
259
|
|
|
92
|
-
|
|
260
|
+
**Description:** Create the endpoint.
|
|
93
261
|
|
|
94
|
-
|
|
262
|
+
**Acceptance criteria:**
|
|
263
|
+
- [ ] Requests validate input.
|
|
264
|
+
- [ ] Valid requests return 200.
|
|
95
265
|
|
|
96
|
-
|
|
97
|
-
-
|
|
98
|
-
-
|
|
266
|
+
**Verification:**
|
|
267
|
+
- [ ] Run the focused API tests.
|
|
268
|
+
- [ ] Run the typecheck.
|
|
99
269
|
|
|
100
|
-
|
|
270
|
+
## Task 2: Add the login UI
|
|
101
271
|
|
|
102
|
-
|
|
272
|
+
**Description:** Create the login form.
|
|
103
273
|
|
|
104
|
-
|
|
274
|
+
**Acceptance criteria:**
|
|
275
|
+
- [ ] The form submits valid credentials.
|
|
105
276
|
|
|
277
|
+
**Verification:**
|
|
278
|
+
- [ ] Run the focused UI tests.
|
|
106
279
|
```
|
|
107
|
-
|
|
108
|
-
|
|
280
|
+
|
|
281
|
+
Validation requires:
|
|
282
|
+
|
|
283
|
+
- exact top-level format `- [ ] N. Title` or `- [x] N. Title`;
|
|
284
|
+
- unique positive task IDs;
|
|
285
|
+
- one matching `## Task N: Title` section per checklist item;
|
|
286
|
+
- heading titles matching checklist titles;
|
|
287
|
+
- a description, acceptance criteria, and verification instructions for every task;
|
|
288
|
+
- no orphan or duplicate task headings.
|
|
289
|
+
|
|
290
|
+
Nested acceptance/verification checkboxes are not execution tasks.
|
|
291
|
+
|
|
292
|
+
Do not manually check top-level task items. Only a successful `plan_task verify` should do that.
|
|
293
|
+
|
|
294
|
+
## Durable files
|
|
295
|
+
|
|
296
|
+
```text
|
|
297
|
+
.plan_task/
|
|
298
|
+
├── plan.md # submitted plan; immutable during execution
|
|
299
|
+
├── task.md # canonical queue and completion truth
|
|
300
|
+
├── state.json # validated workflow state and task runtime metadata
|
|
301
|
+
├── draft/ # exists only while planning or revising
|
|
302
|
+
│ ├── plan.md
|
|
303
|
+
│ └── task.md
|
|
304
|
+
├── history/ # immutable submitted-plan snapshots
|
|
305
|
+
└── .lock/ # short-lived cross-process workflow lock
|
|
109
306
|
```
|
|
110
307
|
|
|
111
|
-
|
|
308
|
+
Writes use:
|
|
112
309
|
|
|
113
|
-
|
|
114
|
-
-
|
|
115
|
-
-
|
|
310
|
+
- an in-process serial queue;
|
|
311
|
+
- a project workflow lock;
|
|
312
|
+
- random temporary file names;
|
|
313
|
+
- atomic replacement with rollback for multi-file changes.
|
|
314
|
+
|
|
315
|
+
A stale lock older than ten minutes may be removed during recovery.
|
|
316
|
+
|
|
317
|
+
### Approval hash
|
|
318
|
+
|
|
319
|
+
Approval stores a SHA-256 structure hash computed from:
|
|
320
|
+
|
|
321
|
+
- the exact `plan.md` content;
|
|
322
|
+
- the exact `task.md` content, except top-level `[ ]`/`[x]` progress markers are normalized.
|
|
323
|
+
|
|
324
|
+
As a result:
|
|
325
|
+
|
|
326
|
+
- normal verified-task progress does not invalidate approval;
|
|
327
|
+
- changing task titles, bodies, criteria, verification steps, or plan context revokes approval;
|
|
328
|
+
- `/build`, task mutation tools, task progression, and session recovery all enforce the approved hash;
|
|
329
|
+
- a mismatch fails closed and returns the plan to `ready`.
|
|
330
|
+
|
|
331
|
+
`plan.md` is not updated as tasks complete. Runtime progress exists only in `task.md` and `state.json`.
|
|
332
|
+
|
|
333
|
+
## Lifecycle
|
|
334
|
+
|
|
335
|
+
### Plan lifecycle
|
|
336
|
+
|
|
337
|
+
```text
|
|
338
|
+
idle → planning → ready → approved → executing → completed
|
|
339
|
+
↑ ↘ ↘
|
|
340
|
+
└─ rework blocked ──┘
|
|
116
341
|
```
|
|
117
342
|
|
|
118
|
-
|
|
343
|
+
Important rules:
|
|
119
344
|
|
|
120
|
-
|
|
345
|
+
- `planning → ready` only happens after a valid changed draft is submitted.
|
|
346
|
+
- `ready → approved` recomputes and stores the approved structure hash.
|
|
347
|
+
- `approved → executing` occurs only after files, state, hash, and queue are validated.
|
|
348
|
+
- `executing → completed` requires every task to be checked **and** have `verified` runtime state.
|
|
349
|
+
- If every remaining unchecked task is blocked, the plan becomes `blocked`; it is never reported complete.
|
|
350
|
+
- Revision or rework clears approval.
|
|
121
351
|
|
|
122
|
-
|
|
352
|
+
### Task lifecycle
|
|
353
|
+
|
|
354
|
+
```text
|
|
355
|
+
pending → implementation-complete → verified
|
|
356
|
+
↘ ↘
|
|
357
|
+
blocked
|
|
358
|
+
```
|
|
123
359
|
|
|
124
|
-
|
|
125
|
-
|
|
360
|
+
`unblock` restores the task to whichever active state existed before blocking.
|
|
361
|
+
|
|
362
|
+
## State
|
|
363
|
+
|
|
364
|
+
`state.json` is validated before use. Unknown versions, malformed statuses, invalid IDs, invalid hashes, invalid dates, verified tasks without evidence, and blocked tasks without reasons fail closed.
|
|
365
|
+
|
|
366
|
+
Example:
|
|
126
367
|
|
|
127
368
|
```json
|
|
128
369
|
{
|
|
129
|
-
"
|
|
370
|
+
"version": 2,
|
|
371
|
+
"status": "executing",
|
|
372
|
+
"workId": "f2f0c9b4e4c1a2d3",
|
|
373
|
+
"planningRequest": "Add OAuth login",
|
|
374
|
+
"currentTaskId": 2,
|
|
375
|
+
"continueMode": "all-new",
|
|
376
|
+
"executionMode": "automatic",
|
|
377
|
+
"draftStructureHash": "0000000000000000000000000000000000000000000000000000000000000000",
|
|
378
|
+
"approvedStructureHash": "1111111111111111111111111111111111111111111111111111111111111111",
|
|
379
|
+
"sessionFile": "...",
|
|
380
|
+
"updatedAt": "2026-01-01T00:00:00.000Z",
|
|
381
|
+
"tasks": {
|
|
382
|
+
"1": {
|
|
383
|
+
"status": "verified",
|
|
384
|
+
"verification": "Focused tests passed",
|
|
385
|
+
"verifiedAt": "2026-01-01T00:00:00.000Z"
|
|
386
|
+
},
|
|
387
|
+
"2": {
|
|
388
|
+
"status": "implementation-complete",
|
|
389
|
+
"completedAt": "2026-01-01T00:05:00.000Z"
|
|
390
|
+
},
|
|
391
|
+
"3": {
|
|
392
|
+
"status": "blocked",
|
|
393
|
+
"reason": "Needs API decision",
|
|
394
|
+
"blockedFrom": "pending"
|
|
395
|
+
}
|
|
396
|
+
}
|
|
130
397
|
}
|
|
131
398
|
```
|
|
132
399
|
|
|
133
|
-
|
|
400
|
+
Do not hand-edit `state.json` to bypass workflow checks.
|
|
401
|
+
|
|
402
|
+
## Resume and recovery
|
|
403
|
+
|
|
404
|
+
The extension restores persisted behavior during startup, reload, resume, and fork:
|
|
405
|
+
|
|
406
|
+
| Persisted state | Restored behavior |
|
|
407
|
+
| --- | --- |
|
|
408
|
+
| `planning` | Restores Plan mode, draft write boundary, and planning request framing. |
|
|
409
|
+
| `ready` | Leaves the submitted plan ready for review/approval. |
|
|
410
|
+
| `approved` | Leaves the plan approved and ready to build after hash verification. |
|
|
411
|
+
| `executing` | Restores current task, build framing, and continuation policy. |
|
|
412
|
+
| `blocked` | Restores blocked state and reasons without reporting completion. |
|
|
413
|
+
| `completed` | Preserves completed history; verified work can be explicitly reopened. |
|
|
414
|
+
|
|
415
|
+
If approved files changed while Pi was not running, approval is revoked during recovery. If `state.json` is malformed, execution is disabled rather than guessing or overwriting the damaged state.
|
|
416
|
+
|
|
417
|
+
## Configuration
|
|
418
|
+
|
|
419
|
+
Configuration is merged in this order:
|
|
420
|
+
|
|
421
|
+
1. defaults;
|
|
422
|
+
2. global `~/.pi/agent/plan_task.json`;
|
|
423
|
+
3. project `.pi/plan_task.json`.
|
|
424
|
+
|
|
425
|
+
Example:
|
|
426
|
+
|
|
427
|
+
```json
|
|
428
|
+
{
|
|
429
|
+
"planTools": ["read", "grep", "find", "ls", "rg"],
|
|
430
|
+
"executionMode": "automatic"
|
|
431
|
+
}
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
### `planTools`
|
|
435
|
+
|
|
436
|
+
Read-only tools that may be used during Plan mode. Values are filtered through the extension's safe allowlist:
|
|
437
|
+
|
|
438
|
+
```text
|
|
439
|
+
read grep find ls rg plan_task ask_user_question
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
`write` and `edit` are added specifically for the two draft files. Calls targeting other paths are blocked.
|
|
443
|
+
|
|
444
|
+
Shell tools, unknown tools, current submitted files, and implementation tools are blocked during Plan mode even if another extension exposes them.
|
|
445
|
+
|
|
446
|
+
### `executionMode`
|
|
447
|
+
|
|
448
|
+
| Value | Behavior |
|
|
449
|
+
| --- | --- |
|
|
450
|
+
| `automatic` | The extension starts and coordinates local implementation sessions. |
|
|
451
|
+
| `external` | Approval emits `pi-plan-task:plan-approved`; local `/build` does not execute. |
|
|
452
|
+
|
|
453
|
+
New-session model and thinking behavior follow Pi defaults.
|
|
454
|
+
|
|
455
|
+
## Events
|
|
456
|
+
|
|
457
|
+
Other extensions can subscribe through Pi's shared event bus:
|
|
458
|
+
|
|
459
|
+
```text
|
|
460
|
+
pi-plan-task:plan-ready
|
|
461
|
+
pi-plan-task:plan-approved
|
|
462
|
+
pi-plan-task:plan-rejected
|
|
463
|
+
pi-plan-task:task-started
|
|
464
|
+
pi-plan-task:task-completed
|
|
465
|
+
pi-plan-task:task-verified
|
|
466
|
+
pi-plan-task:task-blocked
|
|
467
|
+
pi-plan-task:execution-finished
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
Event payloads include workflow metadata such as:
|
|
471
|
+
|
|
472
|
+
```text
|
|
473
|
+
cwd
|
|
474
|
+
planPath
|
|
475
|
+
taskPath
|
|
476
|
+
planHash
|
|
477
|
+
taskId
|
|
478
|
+
sessionFile
|
|
479
|
+
feedback
|
|
480
|
+
reason
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
Event semantics:
|
|
484
|
+
|
|
485
|
+
| Event | Meaning |
|
|
486
|
+
| --- | --- |
|
|
487
|
+
| `plan-ready` | A valid draft was transactionally submitted. |
|
|
488
|
+
| `plan-approved` | Current structure was validated and approved. |
|
|
489
|
+
| `plan-rejected` | Review rejected the submitted plan and initialized a revision draft. |
|
|
490
|
+
| `task-started` | A current task was selected and persisted. |
|
|
491
|
+
| `task-completed` | Implementation reached `implementation-complete`; verification is still required. |
|
|
492
|
+
| `task-verified` | Verification evidence was persisted and the checklist item was checked. |
|
|
493
|
+
| `task-blocked` | The current task was blocked with a reason. |
|
|
494
|
+
| `execution-finished` | Every task is checked and verified. |
|
|
495
|
+
|
|
496
|
+
Events are emitted only after the corresponding state/file update succeeds.
|
|
497
|
+
|
|
498
|
+
## Prompt and context behavior
|
|
499
|
+
|
|
500
|
+
Phase instructions are conversation messages rather than permanent system-prompt patches:
|
|
501
|
+
|
|
502
|
+
- Plan and build commands send visible user requests.
|
|
503
|
+
- Phase/task framing is injected once when a phase or task starts.
|
|
504
|
+
- Planning requests are persisted so reload can restore framing.
|
|
505
|
+
- Stale framing is filtered from model context without rewriting session history.
|
|
506
|
+
- Build framing includes `plan.md` as untrusted reference context.
|
|
507
|
+
- Current task instructions and safety rules take precedence over plan content.
|
|
508
|
+
- A clean session does not inherit the planning conversation as parent context.
|
|
509
|
+
- An `implementation-complete` task that is resumed for verification receives verification-only framing and must not call `complete` again.
|
|
510
|
+
|
|
511
|
+
## Optional Plannotator integration
|
|
512
|
+
|
|
513
|
+
Plannotator is not a core dependency.
|
|
514
|
+
|
|
515
|
+
If the `plannotator` CLI is installed, choose `review` after a plan is submitted. That opens the submitted plan for browser review. Approved results are normalized to `/plan approve`; annotated or rejected results are normalized to `/plan reject <feedback>`.
|
|
516
|
+
|
|
517
|
+
If Plannotator is unavailable, use:
|
|
518
|
+
|
|
519
|
+
```text
|
|
520
|
+
/tasks
|
|
521
|
+
/plan approve
|
|
522
|
+
/plan reject <feedback>
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
## Troubleshooting
|
|
526
|
+
|
|
527
|
+
### “Plan files changed after approval”
|
|
528
|
+
|
|
529
|
+
The submitted structure no longer matches the approved hash. Inspect the files, then run:
|
|
530
|
+
|
|
531
|
+
```text
|
|
532
|
+
/tasks
|
|
533
|
+
/plan approve
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
### “Implementation is complete but verification is pending”
|
|
537
|
+
|
|
538
|
+
The task has called `complete` but has not passed verification. Run the task's verification steps and let the model call:
|
|
539
|
+
|
|
540
|
+
```json
|
|
541
|
+
{"action":"verify","id":1,"reason":"Describe the successful checks"}
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
### “Execution blocked”
|
|
545
|
+
|
|
546
|
+
Every remaining unchecked task is blocked. Resolve the reason, then ask the agent to call:
|
|
547
|
+
|
|
548
|
+
```json
|
|
549
|
+
{"action":"unblock","id":1}
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
Run `/build` again when ready.
|
|
553
|
+
|
|
554
|
+
### Invalid `state.json`
|
|
555
|
+
|
|
556
|
+
The extension fails closed and will not execute. Inspect `.plan_task/history/` for snapshots. Restore a known-good state or start an explicitly new plan rather than weakening state validation.
|
|
557
|
+
|
|
558
|
+
### Stale `.plan_task/.lock`
|
|
559
|
+
|
|
560
|
+
Normal operations remove the lock automatically. A lock older than ten minutes is considered stale and may be recovered automatically. Do not remove a recent lock while another Pi process is operating on the same project.
|
|
561
|
+
|
|
562
|
+
### Plannotator is unavailable
|
|
563
|
+
|
|
564
|
+
Use the built-in text workflow:
|
|
565
|
+
|
|
566
|
+
```text
|
|
567
|
+
/tasks
|
|
568
|
+
/plan approve
|
|
569
|
+
/plan reject <feedback>
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
## Development
|
|
573
|
+
|
|
574
|
+
```bash
|
|
575
|
+
npm test
|
|
576
|
+
npm run typecheck
|
|
577
|
+
npm run bundle
|
|
578
|
+
npm pack --dry-run
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
The test suite includes:
|
|
582
|
+
|
|
583
|
+
- parser and Markdown-boundary tests;
|
|
584
|
+
- strict plan validation tests;
|
|
585
|
+
- state schema tests;
|
|
586
|
+
- structure hash tests;
|
|
587
|
+
- concurrent workflow mutation tests;
|
|
588
|
+
- command-surface tests;
|
|
589
|
+
- ExtensionAPI mock integration tests for planning, approval, execution, verification, blocking, rework, recovery framing, session handoff, cancellation, and external mode.
|
|
590
|
+
|
|
591
|
+
## Safety notes
|
|
592
|
+
|
|
593
|
+
- Treat `plan.md` as untrusted reference data, not executable instructions.
|
|
594
|
+
- Never edit history snapshots to make work appear complete.
|
|
595
|
+
- Do not manually check top-level execution tasks.
|
|
596
|
+
- Do not confuse nested acceptance checkboxes with execution completion.
|
|
597
|
+
- Do not bypass approval by hand-editing state.
|
|
598
|
+
- Unverified and blocked tasks are never silently skipped as completed.
|
|
599
|
+
- Use `/tasks rework <id>` for explicit, approval-gated retries.
|
|
600
|
+
- Browser review is optional; Markdown files and validated state are the durable core.
|
|
134
601
|
|
|
135
602
|
## License
|
|
136
603
|
|