pi-plan-task 1.1.0 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +633 -68
  2. package/extensions/build-session.test.ts +25 -27
  3. package/extensions/build-session.ts +38 -11
  4. package/extensions/command-surface.test.ts +11 -0
  5. package/extensions/config.ts +12 -40
  6. package/extensions/files.test.ts +21 -1
  7. package/extensions/files.ts +11 -27
  8. package/extensions/framing.test.ts +1 -0
  9. package/extensions/framing.ts +5 -2
  10. package/extensions/history.test.ts +24 -0
  11. package/extensions/history.ts +42 -0
  12. package/extensions/index.ts +583 -224
  13. package/extensions/integration.test.ts +232 -0
  14. package/extensions/migration.test.ts +34 -0
  15. package/extensions/parse.ts +80 -4
  16. package/extensions/paths.ts +26 -32
  17. package/extensions/planning-and-task-breakdown.md +10 -8
  18. package/extensions/planning-method.test.ts +15 -2
  19. package/extensions/planning-method.ts +4 -2
  20. package/extensions/policy.test.ts +11 -0
  21. package/extensions/prompts.test.ts +54 -9
  22. package/extensions/prompts.ts +100 -32
  23. package/extensions/recovery.test.ts +15 -0
  24. package/extensions/review.test.ts +19 -0
  25. package/extensions/review.ts +53 -0
  26. package/extensions/state.test.ts +25 -0
  27. package/extensions/state.ts +198 -0
  28. package/extensions/task-ui.ts +48 -0
  29. package/extensions/tool-policy.ts +4 -0
  30. package/extensions/tools.test.ts +10 -0
  31. package/extensions/tools.ts +16 -0
  32. package/extensions/types.ts +53 -5
  33. package/extensions/validation.test.ts +38 -0
  34. package/extensions/workflow-policy.test.ts +76 -0
  35. package/extensions/workflow-policy.ts +117 -0
  36. package/extensions/workflow-store.test.ts +48 -0
  37. package/extensions/workflow-store.ts +165 -0
  38. package/package.json +29 -5
package/README.md CHANGED
@@ -1,136 +1,701 @@
1
1
  # pi-plan-task
2
2
 
3
- [![npm version](https://img.shields.io/npm/v/pi-plan-task.svg)](https://www.npmjs.com/package/pi-plan-task)
4
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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
- One Pi package: `/plan`, `/build`, `/goal`, and `/tasks`. Progress lives on disk, so a new session or a Pi restart can continue from the next unfinished task.
5
+ ```text
6
+ Plan → Review → Approve → Execute → Verify → Continue / Stop
7
+ ```
7
8
 
8
- Structured questions use [`@juicesharp/rpiv-ask-user-question`](https://pi.dev/packages/@juicesharp/rpiv-ask-user-question). This package does not register `ask_user_question`.
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
- ## Install
11
+ [![npm version](https://img.shields.io/npm/v/pi-plan-task.svg)](https://www.npmjs.com/package/pi-plan-task)
12
+ [![License](https://img.shields.io/badge/license-MIT-yellow.svg)](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 v2](#state-v2)
30
+ - [Resume and recovery](#resume-and-recovery)
31
+ - [Configuration](#configuration)
32
+ - [Events](#events)
33
+ - [Optional Plannotator integration](#optional-plannotator-integration)
34
+ - [Upgrading to v3](#upgrading-to-v3)
35
+ - [Legacy command migration](#legacy-command-migration)
36
+ - [Troubleshooting](#troubleshooting)
37
+ - [Development](#development)
38
+ - [Safety notes](#safety-notes)
39
+ ## Highlights
40
+
41
+ - Only three user-facing commands: `/plan`, `/build`, and `/tasks`.
42
+ - Planning writes to an isolated `.plan_task/draft/` area.
43
+ - Explicit approval is required before implementation.
44
+ - Approval is revoked if submitted plan or task structure changes.
45
+ - Task implementation and verification are separate states.
46
+ - `task.md` is the single source of truth for execution progress.
47
+ - One task can run here, in a new session, or in a clean session.
48
+ - All remaining tasks can run here or one-per-session.
49
+ - State updates are validated and serialized; multi-file changes use transactional replacement with rollback.
50
+ - State v1 projects are backed up and migrated safely.
51
+ - Optional Plannotator integration provides browser-based plan review.
52
+
53
+ ## Requirements
54
+
55
+ - Pi with extension/package support.
56
+ - `ask_user_question` is required at runtime when planning or execution reaches a consequential user decision.
57
+ - Plannotator is optional and only needed for `/plan review`.
58
+
59
+ ## Installation
11
60
 
12
61
  ```bash
13
62
  pi install npm:@juicesharp/rpiv-ask-user-question
14
63
  pi install npm:pi-plan-task
15
64
  ```
16
65
 
17
- Restart Pi or run `/reload`. If juicesharp is missing, this package warns on session start.
66
+ Restart Pi or run `/reload` after installation.
18
67
 
19
- Local checkout (development):
68
+ For local development:
20
69
 
21
70
  ```bash
22
71
  pi install /absolute/path/to/pi-plan-task
23
72
  ```
24
73
 
25
- Or add the source to `packages` in `~/.pi/agent/settings.json`.
74
+ Alternatively, add the package path to `packages` in `~/.pi/agent/settings.json`.
75
+
76
+ ## Quick start
77
+
78
+ ```text
79
+ /plan Add OAuth login
80
+ ```
81
+
82
+ When the draft is valid, choose one of:
83
+
84
+ ```text
85
+ current approve and execute in this session
86
+ new approve and execute in a normal new session
87
+ fresh approve and execute in a clean session
88
+ review open optional Plannotator review
89
+ revise edit a new draft with feedback
90
+ reject reject and revise with feedback
91
+ later leave the submitted plan ready for later approval
92
+ ```
93
+
94
+ A typical flow is:
95
+
96
+ 1. Run `/plan <request>`.
97
+ 2. The agent writes `.plan_task/draft/plan.md` and `.plan_task/draft/task.md`.
98
+ 3. The extension validates both draft files.
99
+ 4. The valid draft is transactionally submitted as `.plan_task/plan.md` and `.plan_task/task.md`, with rollback on failure.
100
+ 5. Review or approve the submitted plan.
101
+ 6. Run one task with `/build`, or all remaining tasks with `/build all`.
102
+ 7. Each task follows `pending → implementation-complete → verified`.
103
+ 8. Only verification checks the task and permits progression.
104
+
105
+ Execution is approval-gated. A missing, changed, or unapproved plan cannot start implementation.
26
106
 
27
107
  ## Commands
28
108
 
29
- | Command | What it does |
109
+ The extension registers exactly three user-facing slash commands:
110
+
111
+ ```text
112
+ /plan create, review, and approve plans
113
+ /build execute one or all tasks
114
+ /tasks inspect and manage tasks
115
+ ```
116
+
117
+ ### `/plan` — planning and approval
118
+
119
+ | Command | Description |
30
120
  | --- | --- |
31
- | `/plan [file or goal]` | Read-only planning. Writes `.plan_task/plan.md` and `.plan_task/task.md`. |
32
- | `/build` | Execute the next unfinished task in this session, then ask whether to continue here or in a new session. |
33
- | `/build new` | Same as `/build`, but start that task in a new session. |
34
- | `/goal` | Execute remaining tasks until `task.md` is complete. No session prompts. All in this session. |
35
- | `/goal new` | Same as `/goal`, but each remaining task starts in a new session. |
36
- | `/tasks` | Show the current task list and progress. |
121
+ | `/plan` | Plan from the current conversation and repository. |
122
+ | `/plan <request>` | Plan from a free-text request. |
123
+ | `/plan <file> [notes]` | Use a repository spec file with optional guidance. |
124
+ | `/plan request <text>` | Force text beginning with a reserved subcommand to be treated as a request. |
125
+ | `/plan review` | Open the submitted `plan.md` in optional Plannotator. |
126
+ | `/plan approve` | Interactively choose `current`, `new`, `fresh`, `revise`, or `cancel`. |
127
+ | `/plan approve current` | Approve and execute the next task in this session. |
128
+ | `/plan approve new` | Approve and execute the next task in a normal new session. |
129
+ | `/plan approve fresh` | Approve and execute the next task in a clean session without parent conversation context. |
130
+ | `/plan reject [feedback]` | Reject the submitted plan and initialize a revision draft. |
131
+ | `/plan revise` | Initialize a revision draft and ask for revision feedback. |
132
+ | `/plan status` | Show lifecycle state, work identity, progress, hash, and current task. |
133
+ | `/plan history` | List immutable submitted-plan snapshots. |
134
+ | `/plan diff` | Compare current submitted files with the newest valid snapshot. |
135
+
136
+ The first argument to `/plan` is reserved when it is one of:
137
+
138
+ ```text
139
+ review approve reject revise status history diff request
140
+ ```
37
141
 
38
- Restarting Pi does not auto-start work. Run `/build` or `/goal` again.
142
+ If the actual request starts with one of those words, use `/plan request ...`:
39
143
 
40
- Session prompts only happen after a `/build` task finishes. `/goal` and `/goal new` never ask. Those prompts use this package's `select` dialog, not `ask_user_question`.
144
+ ```text
145
+ /plan request review the login page accessibility
146
+ ```
147
+
148
+ #### Draft behavior
149
+
150
+ - New work receives a new `workId` and does not inherit old blocked/task runtime state.
151
+ - Revision preserves the current submitted files until the new draft validates successfully.
152
+ - An unchanged draft is not resubmitted.
153
+ - Invalid or half-written drafts never replace current files.
154
+ - Only draft files are writable during Plan mode.
41
155
 
42
- ### `/plan` arguments
156
+ ### `/build` — execution
43
157
 
158
+ | Command | Description |
159
+ | --- | --- |
160
+ | `/build` | Execute one pending task in this session. |
161
+ | `/build new` | Execute one task in a normal new session. |
162
+ | `/build fresh` | Execute one task in a clean session. |
163
+ | `/build all` | Execute all remaining tasks in this session. |
164
+ | `/build all new` | Execute one task per new session and continue automatically. |
165
+ | `/build all fresh` | Start in a clean session, then execute all remaining tasks in that clean session. |
166
+ | `/build all --approval` | Execute here and pause for approval after every verified task. |
167
+ | `/build all new --approval` | Use one new session per task and pause after every verified task. |
168
+ | `/build all fresh --approval` | Start in a clean session and pause after every verified task. |
169
+
170
+ Long-form aliases are accepted:
171
+
172
+ ```text
173
+ --all --new --fresh --approval
44
174
  ```
45
- /plan
46
- /plan Add login with OAuth
47
- /plan docs/auth-spec.md
48
- /plan docs/auth-spec.md focus on the callback flow
49
- /plan @docs/auth-spec.md
175
+
176
+ Unknown, duplicate, and conflicting options are rejected. For example, `/build new fresh` is invalid.
177
+
178
+ `--approval` applies only to all-task execution. In non-UI modes, per-task approval cannot prompt, so execution stops safely after the current task.
179
+
180
+ #### Session placement
181
+
182
+ - `new` records the current session as parent and opens a replacement session.
183
+ - `fresh` opens a clean session without the planning conversation as parent context.
184
+ - `/build all new` persists its continuation policy, so reloads and subsequent session handoffs resume one task per session.
185
+ - If initial session creation is cancelled, the plan remains approved and can be started again.
186
+
187
+ ### `/tasks` — inspection and rework
188
+
189
+ | Command | Description |
190
+ | --- | --- |
191
+ | `/tasks` | Show the canonical checklist and progress. |
192
+ | `/tasks review [id]` | Show a task, its criteria, unstaged/staged changes, and untracked files. |
193
+ | `/tasks rework <id>` | Reopen a verified task and every later task. |
194
+
195
+ `/tasks review` truncates output at approximately 50 KB or 2000 lines. Use `git diff`, `git diff --cached`, and `git status --short` for complete output.
196
+
197
+ Rework is intentionally strict:
198
+
199
+ - The target must exist and already be verified.
200
+ - The target and every later task return to `pending`.
201
+ - Their top-level checklist items are unchecked.
202
+ - Verification, completion, and block metadata are cleared.
203
+ - Approval is revoked.
204
+ - The plan returns to `ready` and must be approved again.
205
+
206
+ Legacy standalone command names are not aliases. See [Legacy command migration](#legacy-command-migration).
207
+
208
+ ## LLM tool: `plan_task`
209
+
210
+ `plan_task` is callable by the model; it is not a slash command.
211
+
212
+ ### Status
213
+
214
+ ```json
215
+ {"action":"status"}
50
216
  ```
51
217
 
52
- If the first argument is an existing file — or looks like a path such as `./spec.md`, `notes.txt`, or `@spec.md` — that file is the spec. Anything after it is extra planning guidance. Missing explicit paths are rejected instead of being treated as a prompt.
218
+ Returns the canonical checklist and progress.
53
219
 
54
- ### `/build` and `/goal`
220
+ ### Complete implementation
55
221
 
222
+ ```json
223
+ {"action":"complete","id":1}
56
224
  ```
57
- /build
58
- /build new
59
- /goal
60
- /goal new
225
+
226
+ Valid only when:
227
+
228
+ - the plan is `executing`;
229
+ - the ID is the current task;
230
+ - the task exists and is `pending`;
231
+ - the submitted structure still matches the approved hash.
232
+
233
+ `complete` changes task runtime state to `implementation-complete`. It does **not** check the task and does **not** advance execution.
234
+
235
+ ### Verify
236
+
237
+ ```json
238
+ {"action":"verify","id":1,"reason":"Focused tests and typecheck passed"}
61
239
  ```
62
240
 
63
- `new` and `--new` are equivalent.
241
+ Valid only for the current `implementation-complete` task and requires a non-empty verification result. A successful verification performs one serialized transaction that:
64
242
 
65
- - `/build` runs one task here. After it is marked complete, Pi asks whether to continue in this session or a new session.
66
- - `/build new` opens a new session for that one task, then asks the same question when it finishes.
67
- - `/goal` runs every remaining task in this session.
68
- - `/goal new` opens a new session for the next unfinished task, then another new session after each completed task, until the list is done.
243
+ 1. records `verified` state and evidence;
244
+ 2. checks the matching top-level item in `task.md`;
245
+ 3. persists state;
246
+ 4. emits `pi-plan-task:task-verified`;
247
+ 5. allows execution to continue.
69
248
 
70
- ## Planning method
249
+ ### Block
71
250
 
72
- `/plan` uses `extensions/planning-and-task-breakdown.md` as the planning prompt.
251
+ ```json
252
+ {"action":"block","id":1,"reason":"Waiting for API decision"}
253
+ ```
254
+
255
+ 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.
73
256
 
74
- That file keeps the same section headings as `planning-and-task-breakdown.md`, so later methodology edits can be copied section-by-section from that source. Plan-task only changes output paths and the checklist form `/build` and `/goal` need:
257
+ ### Unblock
75
258
 
76
- - `.plan_task/plan.md` and `.plan_task/task.md`
77
- - checklist lines in the form `- [ ] N. Title`
259
+ ```json
260
+ {"action":"unblock","id":1}
261
+ ```
78
262
 
79
- This package does not install or load a skill. It also does not modify Pi's system prompt.
263
+ 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.
80
264
 
81
- ## Prompt injection
265
+ Invalid tool actions fail without changing files, state, or emitting success events.
82
266
 
83
- Phase instructions are conversation messages, not system-prompt patches:
267
+ ## Task file contract
84
268
 
85
- - `/plan`, `/build`, and `/goal` send a short visible user message to start the turn.
86
- - The planning method or current-task instructions are injected once, as a hidden message, when that phase or task starts.
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.
269
+ `.plan_task/task.md` is the canonical execution queue and completion source. It must begin with numbered top-level checklist items:
89
270
 
90
- Session history still stores the injected messages. Filtering is non-destructive.
271
+ ```markdown
272
+ # Tasks
91
273
 
92
- ## Ask user
274
+ - [ ] 1. Add the login API
275
+ - [ ] 2. Add the login UI
93
276
 
94
- `/plan`, `/build`, and `/goal` keep juicesharp's `ask_user_question` available and tell the model to call it for consequential choices the repo cannot answer:
277
+ ## Task 1: Add the login API
95
278
 
96
- - 1-4 questions per call, each with a short `header` and 2-4 described options
97
- - recommended option first, with `(Recommended)` on the label
98
- - do not author `Other` or `Type something.` — juicesharp appends a custom-answer row
279
+ **Description:** Create the endpoint.
99
280
 
100
- Do not also register another `ask_user_question` tool. The names collide and the schemas differ.
281
+ **Acceptance criteria:**
282
+ - [ ] Requests validate input.
283
+ - [ ] Valid requests return 200.
101
284
 
102
- ## Files
285
+ **Verification:**
286
+ - [ ] Run the focused API tests.
287
+ - [ ] Run the typecheck.
103
288
 
104
- Created in the current project:
289
+ ## Task 2: Add the login UI
105
290
 
291
+ **Description:** Create the login form.
292
+
293
+ **Acceptance criteria:**
294
+ - [ ] The form submits valid credentials.
295
+
296
+ **Verification:**
297
+ - [ ] Run the focused UI tests.
106
298
  ```
107
- .plan_task/plan.md
108
- .plan_task/task.md
299
+
300
+ Validation requires:
301
+
302
+ - exact top-level format `- [ ] N. Title` or `- [x] N. Title`;
303
+ - unique positive task IDs;
304
+ - one matching `## Task N: Title` section per checklist item;
305
+ - heading titles matching checklist titles;
306
+ - a description, acceptance criteria, and verification instructions for every task;
307
+ - no orphan or duplicate task headings.
308
+
309
+ Nested acceptance/verification checkboxes are not execution tasks.
310
+
311
+ Do not manually check top-level task items. Only a successful `plan_task verify` should do that.
312
+
313
+ ## Durable files
314
+
315
+ ```text
316
+ .plan_task/
317
+ ├── plan.md # submitted plan; immutable during execution
318
+ ├── task.md # canonical queue and completion truth
319
+ ├── state.json # validated state v2 and task runtime metadata
320
+ ├── draft/ # exists only while planning or revising
321
+ │ ├── plan.md
322
+ │ └── task.md
323
+ ├── history/ # immutable snapshots and migration backups
324
+ └── .lock/ # short-lived cross-process workflow lock
109
325
  ```
110
326
 
111
- `task.md` must start with numbered checklist lines:
327
+ Writes use:
112
328
 
113
- ```markdown
114
- - [ ] 1. Add login API
115
- - [ ] 2. Add login UI
329
+ - an in-process serial queue;
330
+ - a project workflow lock;
331
+ - random temporary file names;
332
+ - atomic replacement with rollback for multi-file changes.
333
+
334
+ A stale lock older than ten minutes may be removed during recovery.
335
+
336
+ ### Approval hash
337
+
338
+ Approval stores a SHA-256 structure hash computed from:
339
+
340
+ - the exact `plan.md` content;
341
+ - the exact `task.md` content, except top-level `[ ]`/`[x]` progress markers are normalized.
342
+
343
+ As a result:
344
+
345
+ - normal verified-task progress does not invalidate approval;
346
+ - changing task titles, bodies, criteria, verification steps, or plan context revokes approval;
347
+ - `/build`, task mutation tools, task progression, and session recovery all enforce the approved hash;
348
+ - a mismatch fails closed and returns the plan to `ready`.
349
+
350
+ `plan.md` is not updated as tasks complete. Runtime progress exists only in `task.md` and `state.json`.
351
+
352
+ ## Lifecycle
353
+
354
+ ### Plan lifecycle
355
+
356
+ ```text
357
+ idle → planning → ready → approved → executing → completed
358
+ ↑ ↘ ↘
359
+ └─ rework blocked ──┘
116
360
  ```
117
361
 
118
- `/build` and `/goal` resume from the first unchecked item.
362
+ Important rules:
119
363
 
120
- ## Config
364
+ - `planning → ready` only happens after a valid changed draft is submitted.
365
+ - `ready → approved` recomputes and stores the approved structure hash.
366
+ - `approved → executing` occurs only after files, state, hash, and queue are validated.
367
+ - `executing → completed` requires every task to be checked **and** have `verified` runtime state.
368
+ - If every remaining unchecked task is blocked, the plan becomes `blocked`; it is never reported complete.
369
+ - Revision or rework clears approval.
370
+
371
+ ### Task lifecycle
372
+
373
+ ```text
374
+ pending → implementation-complete → verified
375
+ ↘ ↘
376
+ blocked
377
+ ```
121
378
 
122
- Allowed `/plan` tools:
379
+ `unblock` restores the task to whichever active state existed before blocking.
123
380
 
124
- - Global: `~/.pi/agent/plan_task.json`
125
- - Project override: `.pi/plan_task.json`
381
+ ## State v2
382
+
383
+ `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.
384
+
385
+ Example:
126
386
 
127
387
  ```json
128
388
  {
129
- "planTools": ["read", "bash", "grep", "find", "ls", "pwsh", "rg"]
389
+ "version": 2,
390
+ "status": "executing",
391
+ "workId": "f2f0c9b4e4c1a2d3",
392
+ "planningRequest": "Add OAuth login",
393
+ "currentTaskId": 2,
394
+ "continueMode": "all-new",
395
+ "approvalEachTask": true,
396
+ "executionMode": "automatic",
397
+ "draftStructureHash": "0000000000000000000000000000000000000000000000000000000000000000",
398
+ "approvedStructureHash": "1111111111111111111111111111111111111111111111111111111111111111",
399
+ "sessionFile": "...",
400
+ "updatedAt": "2026-01-01T00:00:00.000Z",
401
+ "tasks": {
402
+ "1": {
403
+ "status": "verified",
404
+ "verification": "Focused tests passed",
405
+ "verifiedAt": "2026-01-01T00:00:00.000Z"
406
+ },
407
+ "2": {
408
+ "status": "implementation-complete",
409
+ "completedAt": "2026-01-01T00:05:00.000Z"
410
+ },
411
+ "3": {
412
+ "status": "blocked",
413
+ "reason": "Needs API decision",
414
+ "blockedFrom": "pending"
415
+ }
416
+ }
130
417
  }
131
418
  ```
132
419
 
133
- During `/plan`, `write` and `edit` stay available but can only touch the two plan files. Bash is limited to read-only commands. `plan_task` and `ask_user_question` stay available in every mode.
420
+ Do not hand-edit `state.json` to bypass workflow checks.
421
+
422
+ ## Resume and recovery
423
+
424
+ The extension restores persisted behavior during startup, reload, resume, and fork:
425
+
426
+ | Persisted state | Restored behavior |
427
+ | --- | --- |
428
+ | `planning` | Restores Plan mode, draft write boundary, and planning request framing. |
429
+ | `ready` | Leaves the submitted plan ready for review/approval. |
430
+ | `approved` | Leaves the plan approved and ready to build after hash verification. |
431
+ | `executing` | Restores current task, build framing, continuation policy, and task approval mode. |
432
+ | `blocked` | Restores blocked state and reasons without reporting completion. |
433
+ | `completed` | Preserves completed history; verified work can be explicitly reopened. |
434
+
435
+ 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.
436
+
437
+ ## Configuration
438
+
439
+ Configuration is merged in this order:
440
+
441
+ 1. defaults;
442
+ 2. global `~/.pi/agent/plan_task.json`;
443
+ 3. project `.pi/plan_task.json`.
444
+
445
+ Example:
446
+
447
+ ```json
448
+ {
449
+ "planTools": ["read", "grep", "find", "ls", "rg"],
450
+ "executionMode": "automatic"
451
+ }
452
+ ```
453
+
454
+ ### `planTools`
455
+
456
+ Read-only tools that may be used during Plan mode. Values are filtered through the extension's safe allowlist:
457
+
458
+ ```text
459
+ read grep find ls rg plan_task ask_user_question
460
+ ```
461
+
462
+ `write` and `edit` are added specifically for the two draft files. Calls targeting other paths are blocked.
463
+
464
+ Shell tools, unknown tools, current submitted files, and implementation tools are blocked during Plan mode even if another extension exposes them.
465
+
466
+ ### `executionMode`
467
+
468
+ | Value | Behavior |
469
+ | --- | --- |
470
+ | `automatic` | The extension starts and coordinates local implementation sessions. |
471
+ | `external` | Approval emits `pi-plan-task:plan-approved`; local `/build` does not execute. |
472
+
473
+ New-session model and thinking behavior follow Pi defaults. The old unused `inheritSessionModel` and `inheritThinkingLevel` options were removed in v3.
474
+
475
+ ## Events
476
+
477
+ Other extensions can subscribe through Pi's shared event bus:
478
+
479
+ ```text
480
+ pi-plan-task:plan-ready
481
+ pi-plan-task:plan-approved
482
+ pi-plan-task:plan-rejected
483
+ pi-plan-task:task-started
484
+ pi-plan-task:task-completed
485
+ pi-plan-task:task-verified
486
+ pi-plan-task:task-blocked
487
+ pi-plan-task:execution-finished
488
+ ```
489
+
490
+ Event payload version remains `1` and includes workflow metadata such as:
491
+
492
+ ```text
493
+ cwd
494
+ planPath
495
+ taskPath
496
+ planHash
497
+ taskId
498
+ sessionFile
499
+ feedback
500
+ reason
501
+ ```
502
+
503
+ Event semantics:
504
+
505
+ | Event | Meaning |
506
+ | --- | --- |
507
+ | `plan-ready` | A valid draft was transactionally submitted. |
508
+ | `plan-approved` | Current structure was validated and approved. |
509
+ | `plan-rejected` | Review rejected the submitted plan and initialized a revision draft. |
510
+ | `task-started` | A current task was selected and persisted. |
511
+ | `task-completed` | Implementation reached `implementation-complete`; verification is still required. |
512
+ | `task-verified` | Verification evidence was persisted and the checklist item was checked. |
513
+ | `task-blocked` | The current task was blocked with a reason. |
514
+ | `execution-finished` | Every task is checked and verified. |
515
+
516
+ Events are emitted only after the corresponding state/file update succeeds.
517
+
518
+ ## Prompt and context behavior
519
+
520
+ Phase instructions are conversation messages rather than permanent system-prompt patches:
521
+
522
+ - Plan and build commands send visible user requests.
523
+ - Phase/task framing is injected once when a phase or task starts.
524
+ - Planning requests are persisted so reload can restore framing.
525
+ - Stale framing is filtered from model context without rewriting session history.
526
+ - Build framing includes `plan.md` as untrusted reference context.
527
+ - Current task instructions and safety rules take precedence over plan content.
528
+ - A clean session does not inherit the planning conversation as parent context.
529
+ - A migrated `implementation-complete` task receives verification-only framing and must not call `complete` again.
530
+
531
+ ## Optional Plannotator integration
532
+
533
+ Plannotator is not a core dependency.
534
+
535
+ If the `plannotator` CLI is installed:
536
+
537
+ ```text
538
+ /plan review
539
+ ```
540
+
541
+ opens the submitted plan for browser review. Approved results are normalized to `/plan approve current`; annotated or rejected results are normalized to `/plan reject <feedback>`.
542
+
543
+ If Plannotator is unavailable, use:
544
+
545
+ ```text
546
+ /plan approve
547
+ /plan reject <feedback>
548
+ /plan diff
549
+ ```
550
+
551
+ ## Upgrading to v3
552
+
553
+ v3 is a breaking workflow release. The public three-command surface remains `/plan`, `/build`, and `/tasks`, but planning storage, task completion, verification, state validation, and retry behavior are stricter.
554
+
555
+ ### State v1 → state v2 migration
556
+
557
+ The package version is v3; the persisted state schema moves from version 1 to version 2. On the first state load, the extension:
558
+
559
+ 1. backs up old `state.json` and `task.md` under `.plan_task/history/`;
560
+ 2. writes validated state v2;
561
+ 3. preserves a task as verified only when it was checked and had non-empty verification evidence;
562
+ 4. restores other previously checked tasks to unchecked `implementation-complete` state;
563
+ 5. clears approval and requires `/plan approve` before execution.
564
+
565
+ Migrated `implementation-complete` tasks retain their implementation but must run verification again.
566
+
567
+ ### Changed planning storage
568
+
569
+ Planning and revision now write only to:
570
+
571
+ ```text
572
+ .plan_task/draft/plan.md
573
+ .plan_task/draft/task.md
574
+ ```
575
+
576
+ Current submitted files remain unchanged until the draft validates and is transactionally submitted.
577
+
578
+ ### Changed completion semantics
579
+
580
+ In v2, `complete` could check a task. In v3:
581
+
582
+ ```text
583
+ complete implementation finished, verification pending
584
+ verify verification passed, task checked and eligible to advance
585
+ ```
586
+
587
+ ### Changed rework semantics
588
+
589
+ `/tasks rework <id>` now reopens the selected verified task and every later task, revokes approval, and requires a new approval before execution.
590
+
591
+ ### Removed configuration
592
+
593
+ The unused options below are ignored and should be deleted:
594
+
595
+ ```json
596
+ {
597
+ "inheritSessionModel": true,
598
+ "inheritThinkingLevel": true
599
+ }
600
+ ```
601
+
602
+ ## Legacy command migration
603
+
604
+ If upgrading from a release older than the three-command interface, use these replacements:
605
+
606
+ | Removed | Replacement |
607
+ | --- | --- |
608
+ | `/plan-review` | `/plan review` |
609
+ | `/plan-approve` | `/plan approve` |
610
+ | `/plan-reject` | `/plan reject` |
611
+ | `/plan-status` | `/plan status` |
612
+ | `/plan-history` | `/plan history` |
613
+ | `/plan-diff` | `/plan diff` |
614
+ | `/goal` | `/build all` |
615
+ | `/task-review` | `/tasks review` |
616
+ | `/task-rework` | `/tasks rework` |
617
+ | `/build-next-session` | internal public `/build` handoff |
618
+ | `/goal-next-session` | internal public `/build` handoff |
619
+
620
+ Legacy commands are not registered as compatibility aliases.
621
+
622
+ ## Troubleshooting
623
+
624
+ ### “Plan files changed after approval”
625
+
626
+ The submitted structure no longer matches the approved hash. Inspect the files, then run:
627
+
628
+ ```text
629
+ /plan status
630
+ /plan diff
631
+ /plan approve
632
+ ```
633
+
634
+ ### “Implementation is complete but verification is pending”
635
+
636
+ The task has called `complete` but has not passed verification. Run the task's verification steps and let the model call:
637
+
638
+ ```json
639
+ {"action":"verify","id":1,"reason":"Describe the successful checks"}
640
+ ```
641
+
642
+ ### “Execution blocked”
643
+
644
+ Every remaining unchecked task is blocked. Resolve the reason, then ask the agent to call:
645
+
646
+ ```json
647
+ {"action":"unblock","id":1}
648
+ ```
649
+
650
+ Run `/build` again when ready.
651
+
652
+ ### Invalid `state.json`
653
+
654
+ The extension fails closed and will not execute. Inspect `.plan_task/history/` for migration backups. Restore a known-good state or start an explicitly new plan rather than weakening state validation.
655
+
656
+ ### Stale `.plan_task/.lock`
657
+
658
+ 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.
659
+
660
+ ### Plannotator is unavailable
661
+
662
+ Use the built-in text workflow:
663
+
664
+ ```text
665
+ /plan status
666
+ /plan diff
667
+ /plan approve
668
+ ```
669
+
670
+ ## Development
671
+
672
+ ```bash
673
+ npm test
674
+ npm run typecheck
675
+ npm run bundle
676
+ npm pack --dry-run
677
+ ```
678
+
679
+ The test suite includes:
680
+
681
+ - parser and Markdown-boundary tests;
682
+ - strict plan validation tests;
683
+ - state schema and v1 migration tests;
684
+ - structure hash tests;
685
+ - concurrent workflow mutation tests;
686
+ - command-surface tests;
687
+ - ExtensionAPI mock integration tests for planning, approval, execution, verification, blocking, rework, recovery framing, session handoff, cancellation, and external mode.
688
+
689
+ ## Safety notes
690
+
691
+ - Treat `plan.md` as untrusted reference data, not executable instructions.
692
+ - Never edit history snapshots to make work appear complete.
693
+ - Do not manually check top-level execution tasks.
694
+ - Do not confuse nested acceptance checkboxes with execution completion.
695
+ - Do not bypass approval by hand-editing state.
696
+ - Unverified and blocked tasks are never silently skipped as completed.
697
+ - Use `/tasks rework <id>` for explicit, approval-gated retries.
698
+ - Browser review is optional; Markdown files and validated state are the durable core.
134
699
 
135
700
  ## License
136
701