@gavin-hu/my-pi-agent 0.20.0 → 0.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/README.md +46 -30
- package/README.zh-CN.md +40 -25
- package/assets/screens/board.png +0 -0
- package/assets/screens/chrome.png +0 -0
- package/assets/screens/file-browse.png +0 -0
- package/assets/screens/plan-review.png +0 -0
- package/assets/screens/plan.png +0 -0
- package/docs/extensions/README.md +22 -23
- package/docs/extensions/board.md +397 -168
- package/docs/extensions/bytefly.md +234 -197
- package/docs/extensions/check.md +15 -17
- package/docs/extensions/context.md +35 -15
- package/docs/extensions/file-browse.md +57 -63
- package/docs/extensions/file-open.md +9 -11
- package/docs/extensions/file-read.md +12 -14
- package/docs/extensions/goal.md +15 -17
- package/docs/extensions/job.md +54 -42
- package/docs/extensions/memory.md +17 -19
- package/docs/extensions/plan.md +197 -140
- package/docs/extensions/question.md +16 -18
- package/docs/extensions/rewind.md +17 -19
- package/docs/extensions/serve.md +145 -0
- package/docs/extensions/session-bus.md +38 -16
- package/docs/extensions/subagent.md +23 -25
- package/docs/extensions/team.md +83 -44
- package/docs/extensions/todo.md +18 -18
- package/docs/extensions/watch.md +31 -31
- package/docs/extensions/web-access.md +2 -4
- package/docs/extensions/wechat.md +34 -35
- package/docs/extensions/worktree.md +56 -50
- package/extensions/board/commands.ts +79 -25
- package/extensions/board/format.ts +43 -24
- package/extensions/board/index.ts +17 -4
- package/extensions/board/input.ts +4 -9
- package/extensions/board/join.ts +5 -20
- package/extensions/board/lazy-page.ts +40 -0
- package/extensions/board/page.ts +65 -93
- package/extensions/board/result.ts +30 -39
- package/extensions/board/rows.ts +62 -25
- package/extensions/board/schema.ts +49 -11
- package/extensions/board/snapshot.ts +8 -6
- package/extensions/board/tone.ts +22 -0
- package/extensions/board/tools.ts +154 -55
- package/extensions/board/transport/router.ts +3 -5
- package/extensions/board/transport/server.ts +59 -28
- package/extensions/board/types.ts +36 -42
- package/extensions/board/view/card.ts +229 -0
- package/extensions/board/view/client.ts +35 -16
- package/extensions/board/view/dialog.ts +169 -6
- package/extensions/board/view/empty.ts +47 -0
- package/extensions/board/view/keys.ts +13 -2
- package/extensions/board/view/live.ts +90 -28
- package/extensions/board/view/names.ts +13 -4
- package/extensions/board/view/page.ts +38 -13
- package/extensions/board/view/render.ts +219 -277
- package/extensions/board/view/styles.ts +130 -32
- package/extensions/board/view/team.ts +297 -76
- package/extensions/bytefly/block/fallback.ts +1 -1
- package/extensions/bytefly/doctor/runtime.ts +5 -2
- package/extensions/bytefly/footer/collect/label.ts +60 -0
- package/extensions/bytefly/footer/collect/snapshot.ts +8 -1
- package/extensions/bytefly/footer/config.ts +7 -8
- package/extensions/bytefly/footer/register.ts +33 -4
- package/extensions/bytefly/footer/render/footer.ts +18 -4
- package/extensions/bytefly/footer/render/key.ts +46 -0
- package/extensions/bytefly/footer/render/layout.ts +13 -3
- package/extensions/bytefly/footer/render/lines.ts +10 -7
- package/extensions/bytefly/footer/render/segments.ts +41 -38
- package/extensions/bytefly/footer/render/status.ts +0 -11
- package/extensions/bytefly/footer/types.ts +7 -0
- package/extensions/bytefly/header/component.ts +4 -20
- package/extensions/bytefly/header/config.ts +1 -1
- package/extensions/bytefly/index.ts +32 -6
- package/extensions/bytefly/mode/editor.ts +115 -0
- package/extensions/bytefly/panel/commands.ts +210 -120
- package/extensions/bytefly/panel/format.ts +4 -4
- package/extensions/bytefly/panel/settings.ts +73 -6
- package/extensions/bytefly/panel/tui/keys.ts +2 -6
- package/extensions/bytefly/update/cache.ts +1 -1
- package/extensions/bytefly/update/register.ts +4 -4
- package/extensions/bytefly/working/config.ts +5 -7
- package/extensions/bytefly/working/format.ts +10 -13
- package/extensions/bytefly/working/register.ts +22 -27
- package/extensions/check/commands.ts +3 -2
- package/extensions/check/render.ts +10 -1
- package/extensions/check/{tui.ts → view/check-screens.ts} +14 -19
- package/extensions/context/commands.ts +2 -2
- package/extensions/context/{tui.ts → view/context-report.ts} +51 -19
- package/extensions/file-browse/config/config.ts +4 -19
- package/extensions/file-browse/index.ts +89 -79
- package/extensions/file-browse/live/live.ts +1 -1
- package/extensions/file-browse/transport/router.ts +12 -4
- package/extensions/file-browse/transport/server.ts +61 -28
- package/extensions/file-browse/view/chrome.ts +4 -4
- package/extensions/file-browse/view/client.ts +3 -1
- package/extensions/file-browse/view/html.ts +73 -40
- package/extensions/file-browse/view/live-client.ts +2 -2
- package/extensions/file-browse/view/markdown.ts +13 -14
- package/extensions/file-browse/view/palette.ts +2 -2
- package/extensions/file-browse/view/raw-html.ts +9 -9
- package/extensions/file-browse/view/tree.ts +1 -1
- package/extensions/file-browse/view/urls.ts +20 -6
- package/extensions/file-read/render.ts +4 -4
- package/extensions/goal/plan-route.ts +2 -2
- package/extensions/goal/tui.ts +12 -2
- package/extensions/job/child.ts +527 -0
- package/extensions/job/clock.ts +142 -0
- package/extensions/job/commands.ts +4 -2
- package/extensions/job/config.ts +8 -1
- package/extensions/job/format.ts +22 -1
- package/extensions/job/log-writer.ts +13 -2
- package/extensions/job/registry.ts +63 -7
- package/extensions/job/render.ts +34 -0
- package/extensions/job/runtime.ts +296 -655
- package/extensions/job/session.ts +132 -19
- package/extensions/job/store.ts +7 -7
- package/extensions/job/tools.ts +21 -9
- package/extensions/job/types.ts +47 -0
- package/extensions/job/{tui.ts → view/jobs-screen.ts} +19 -99
- package/extensions/job/waiters.ts +44 -1
- package/extensions/memory/commands.ts +4 -2
- package/extensions/memory/{tui.ts → view/memory-picker.ts} +12 -12
- package/extensions/plan/commands.ts +12 -9
- package/extensions/plan/feedback.ts +62 -16
- package/extensions/plan/format.ts +8 -2
- package/extensions/plan/git-bash.ts +115 -16
- package/extensions/plan/index.ts +58 -51
- package/extensions/plan/plan-index.ts +4 -2
- package/extensions/plan/plan-text.ts +114 -0
- package/extensions/plan/plans.ts +5 -54
- package/extensions/plan/policy.ts +8 -10
- package/extensions/plan/review-lazy.ts +85 -0
- package/extensions/plan/review.ts +2 -2
- package/extensions/plan/runtime.ts +61 -41
- package/extensions/plan/sections.ts +1 -1
- package/extensions/plan/steps.ts +3 -3
- package/extensions/plan/todos.ts +1 -1
- package/extensions/plan/tools/cancel.ts +27 -62
- package/extensions/plan/tools/enter.ts +55 -81
- package/extensions/plan/tools/exit.ts +221 -238
- package/extensions/plan/tools/refusal.ts +18 -0
- package/extensions/plan/tools/steps.ts +75 -92
- package/extensions/plan/tools/write.ts +77 -120
- package/extensions/plan/tools.ts +188 -30
- package/extensions/plan/tui.ts +5 -5
- package/extensions/plan/types.ts +48 -5
- package/extensions/plan/web-blocks.ts +76 -5
- package/extensions/plan/web-chrome.ts +4 -0
- package/extensions/plan/web-client.ts +102 -2
- package/extensions/plan/web-collab.ts +4 -4
- package/extensions/plan/web-comments.ts +39 -8
- package/extensions/plan/web-composer.ts +14 -3
- package/extensions/plan/web-keys.ts +149 -25
- package/extensions/plan/web-lazy.ts +53 -0
- package/extensions/plan/web-markdown.ts +10 -68
- package/extensions/plan/web-outline.ts +22 -2
- package/extensions/plan/web-page.ts +56 -86
- package/extensions/plan/web-payload.ts +188 -0
- package/extensions/plan/web-plan.ts +23 -13
- package/extensions/plan/web-router.ts +18 -9
- package/extensions/plan/web-settle.ts +14 -7
- package/extensions/plan/web-share-session.ts +24 -55
- package/extensions/plan/web-share.ts +19 -37
- package/extensions/plan/web-write.ts +112 -0
- package/extensions/plan/web.ts +67 -131
- package/extensions/question/tools.ts +6 -2
- package/extensions/question/{tui.ts → view/question-screen.ts} +11 -11
- package/extensions/rewind/commands/commands.ts +6 -3
- package/extensions/rewind/state/runtime.ts +1 -1
- package/extensions/rewind/{view/status.ts → status.ts} +4 -4
- package/extensions/rewind/view/review-tui.ts +4 -4
- package/extensions/serve/config.ts +39 -0
- package/extensions/serve/index.ts +85 -0
- package/extensions/serve/registry.ts +260 -0
- package/extensions/session-bus/commands.ts +11 -6
- package/extensions/session-bus/join-request.ts +17 -9
- package/extensions/session-bus/mail-watch.ts +26 -17
- package/extensions/session-bus/protocol.ts +15 -3
- package/extensions/session-bus/resolve.ts +5 -7
- package/extensions/session-bus/result.ts +1 -27
- package/extensions/session-bus/runtime.ts +40 -12
- package/extensions/session-bus/store.ts +101 -19
- package/extensions/session-bus/tools.ts +5 -4
- package/extensions/session-bus/types.ts +19 -0
- package/extensions/session-bus/{tui.ts → view/session-list.ts} +16 -16
- package/extensions/subagent/agents.ts +1 -1
- package/extensions/subagent/commands.ts +4 -2
- package/extensions/subagent/format.ts +15 -15
- package/extensions/subagent/index.ts +1 -1
- package/extensions/subagent/render.ts +3 -3
- package/extensions/subagent/{background-tui.ts → view/agents-board.ts} +11 -11
- package/extensions/team/commands.ts +24 -5
- package/extensions/team/dispatch.ts +18 -4
- package/extensions/team/format.ts +17 -2
- package/extensions/team/index.ts +9 -8
- package/extensions/team/schema.ts +6 -5
- package/extensions/team/tools.ts +107 -45
- package/extensions/team/types.ts +3 -2
- package/extensions/todo/commands.ts +4 -2
- package/extensions/todo/format.ts +11 -0
- package/extensions/todo/render.ts +57 -0
- package/extensions/todo/runtime.ts +1 -1
- package/extensions/todo/tools.ts +1 -1
- package/extensions/todo/{tui.ts → view/todo-screen.ts} +18 -90
- package/extensions/todo/widget.ts +47 -0
- package/extensions/watch/commands.ts +4 -2
- package/extensions/watch/format.ts +36 -7
- package/extensions/watch/render.ts +57 -0
- package/extensions/watch/runtime.ts +27 -22
- package/extensions/watch/tools.ts +4 -4
- package/extensions/watch/{tui.ts → view/watch-screen.ts} +18 -80
- package/extensions/web-access/fetch/tool.ts +12 -4
- package/extensions/wechat/commands/commands.ts +18 -14
- package/extensions/wechat/index.ts +72 -37
- package/extensions/wechat/state/credentials.ts +1 -1
- package/extensions/wechat/state/state.ts +1 -1
- package/extensions/wechat/text/status.ts +112 -0
- package/extensions/wechat/types.ts +2 -2
- package/extensions/wechat/view/status-screen.ts +4 -103
- package/extensions/worktree/commands.ts +11 -9
- package/extensions/worktree/enter.ts +2 -2
- package/extensions/worktree/exit.ts +2 -2
- package/extensions/worktree/index.ts +5 -5
- package/extensions/worktree/screen.ts +3 -3
- package/extensions/worktree/status.ts +2 -2
- package/extensions/worktree/tools.ts +113 -116
- package/lib/README.md +28 -13
- package/lib/board/actions.ts +111 -0
- package/lib/board/artifact.ts +149 -0
- package/lib/board/card.ts +163 -52
- package/lib/board/config.ts +58 -0
- package/lib/board/contract.ts +113 -0
- package/lib/board/join.ts +38 -0
- package/lib/board/lanes.ts +182 -0
- package/lib/board/lead.ts +130 -0
- package/lib/board/limits.ts +78 -0
- package/lib/board/links.ts +31 -10
- package/lib/board/page-pointer.ts +30 -5
- package/lib/board/read.ts +83 -0
- package/lib/board/reason.ts +102 -0
- package/lib/board/round-text.ts +68 -6
- package/lib/board/round.ts +31 -15
- package/lib/board/rules.ts +151 -307
- package/lib/board/seat.ts +35 -0
- package/lib/board/session.ts +199 -51
- package/lib/board/skipped.ts +22 -0
- package/lib/board/steps.ts +487 -0
- package/lib/board/store.ts +119 -36
- package/lib/board/tone.ts +92 -0
- package/lib/board/view.ts +81 -63
- package/lib/bus-request.ts +83 -0
- package/{extensions/watch → lib}/child.ts +40 -21
- package/lib/env.ts +65 -7
- package/lib/format.ts +13 -0
- package/lib/http/index.ts +17 -11
- package/lib/http/mount.ts +142 -0
- package/lib/http/port.ts +30 -0
- package/lib/http/serve.ts +170 -46
- package/lib/http/server.ts +3 -3
- package/lib/lazy.ts +45 -0
- package/lib/plan-entry.ts +46 -21
- package/lib/plans/paths.ts +82 -0
- package/lib/policy.ts +9 -6
- package/lib/report.ts +3 -2
- package/lib/requirements.ts +10 -10
- package/lib/session-label.ts +129 -7
- package/lib/session-roster.ts +43 -1
- package/lib/session-tool.ts +39 -22
- package/lib/stray-fields.ts +7 -2
- package/lib/tool-names.ts +5 -10
- package/lib/tui/README.md +29 -11
- package/lib/tui/chrome.ts +16 -15
- package/lib/tui/cursor.ts +18 -3
- package/lib/tui/glyphs.ts +11 -11
- package/lib/tui/render-cache.ts +29 -0
- package/lib/tui/tokens.ts +33 -2
- package/lib/tui/tool.ts +33 -4
- package/lib/web/README.md +21 -0
- package/lib/web/client-runtime.ts +27 -1
- package/lib/web/components.ts +5 -1
- package/lib/web/index.ts +1 -0
- package/lib/web/markdown.ts +83 -0
- package/lib/web/markup.ts +20 -2
- package/lib/web/runtime.ts +9 -10
- package/package.json +8 -2
- package/skills/init/SKILL.md +5 -5
- package/skills/next/SKILL.md +3 -5
- package/extensions/board/config.ts +0 -36
- package/extensions/board/seat.ts +0 -28
- package/lib/tui/index.ts +0 -34
- package/skills/project-docs/SKILL.md +0 -133
- package/skills/project-docs/references/audit.md +0 -131
- package/skills/project-docs/references/changelog.md +0 -105
- package/skills/project-docs/references/discovery.md +0 -127
- package/skills/project-docs/references/readme.md +0 -80
- package/skills/project-docs/references/release.md +0 -84
- package/skills/project-docs/references/roadmap.md +0 -93
- package/skills/project-docs/scripts/state.ts +0 -316
package/docs/extensions/plan.md
CHANGED
|
@@ -8,50 +8,50 @@ executes.
|
|
|
8
8
|
|
|
9
9
|
## Capabilities
|
|
10
10
|
|
|
11
|
-
Status records what a reader can rely on: **Shipped** is in a tagged release, **Unreleased** is complete in the current tree but not yet tagged, and **Partial** has one released part and one unreleased part. Rows are ordered by user value, highest first.
|
|
12
|
-
|
|
13
11
|
### Planning lifecycle
|
|
14
12
|
|
|
15
|
-
| Capability | How | What you get |
|
|
16
|
-
|
|
17
|
-
| Read-only planning | `
|
|
18
|
-
| Confirmed model entry | `
|
|
19
|
-
| Read-only git shell | `bash` with the read-only git allowlist | Plan mode can inspect `git status`, `diff`, `log`, and `show`; pipes, redirects, and non-git commands are refused. |
|
|
20
|
-
| Read-only delegation | `subagent` with forced `readOnly: true` | A delegated agent can read and search but cannot write, edit, or run a shell while the plan is being researched. |
|
|
21
|
-
| Absolute-path guard | `path-guard.ts` | A path outside the project is refused unless it is a known plan-safe reader, so planning cannot write through an absolute path. |
|
|
22
|
-
| One writable artifact | `
|
|
23
|
-
| Approval gate | `
|
|
24
|
-
| Session goal at approval | `goal` at approval | A `planning` goal is promoted to the plan's objective, and a session with none gets it, without a second dialog; an active goal is left alone. |
|
|
25
|
-
| Steps as todos | `
|
|
26
|
-
| Plan kept current | `
|
|
27
|
-
| Stale-step protection | `expected` in `
|
|
28
|
-
| Cancel without a plan | `
|
|
29
|
-
| Plans index | `/plan list` | Every saved plan with its title, modified time, and step progress, newest first, under a header naming the store's size and its oldest plan. |
|
|
30
|
-
| Plan-store migration | `<repo>/.pi/plans` to the agent-dir store | A store left by an older version is moved in once, with a notice, so worktrees and main see the same index. |
|
|
31
|
-
| Instruction-file bootstrap | `/skill:init` | The packaged `init` skill plans and gates a project's `AGENTS.md`, writing only after approval. |
|
|
32
|
-
| Branch-following mode | the `plan-mode` session entry | `/resume` and `/tree` restore the mode and its tool set for the branch they land on. |
|
|
13
|
+
| Capability | How | What you get |
|
|
14
|
+
|---|---|---|
|
|
15
|
+
| Read-only planning | `plan` action `enter`, `/plan`, `Shift+Tab` (bytefly), `--plan` | The session keeps only its readers, so the model investigates and proposes without touching the tree. |
|
|
16
|
+
| Confirmed model entry | `plan` action `enter` | The model asks before it takes write access away, and the user answers first. |
|
|
17
|
+
| Read-only git shell | `bash` with the read-only git allowlist | Plan mode can inspect `git status`, `diff`, `log`, and `show`; pipes, redirects, and non-git commands are refused. |
|
|
18
|
+
| Read-only delegation | `subagent` with forced `readOnly: true` | A delegated agent can read and search but cannot write, edit, or run a shell while the plan is being researched. |
|
|
19
|
+
| Absolute-path guard | `path-guard.ts` | A path outside the project is refused unless it is a known plan-safe reader, so planning cannot write through an absolute path. |
|
|
20
|
+
| One writable artifact | `plan` action `write` | The plan lands as markdown under the agent directory, one store per repository, shared by its worktrees. |
|
|
21
|
+
| Approval gate | `plan` action `exit` | The plan is read back and presented; nothing is written until the user approves it. |
|
|
22
|
+
| Session goal at approval | `goal` at approval | A `planning` goal is promoted to the plan's objective, and a session with none gets it, without a second dialog; an active goal is left alone. |
|
|
23
|
+
| Steps as todos | `plan` action `exit` | Approval seeds the plan's steps into the todo list, with the verification section as the last item; approving the same plan again replaces the items its earlier approval seeded. |
|
|
24
|
+
| Plan kept current | `plan` action `steps` | Ticking a step rewrites its checkbox in the file and its todo item in one call. |
|
|
25
|
+
| Stale-step protection | `expected` in `plan` action `steps` | A step whose number moved, is out of range, or no longer matches its text refuses the whole batch instead of ticking the wrong line. |
|
|
26
|
+
| Cancel without a plan | `plan` action `cancel`, `/plan cancel` | Write access returns, and no todo items or goal are recorded. |
|
|
27
|
+
| Plans index | `/plan list` | Every saved plan with its title, modified time, and step progress, newest first, under a header naming the store's size and its oldest plan. |
|
|
28
|
+
| Plan-store migration | `<repo>/.pi/plans` to the agent-dir store | A store left by an older version is moved in once, with a notice, so worktrees and main see the same index. |
|
|
29
|
+
| Instruction-file bootstrap | `/skill:init` | The packaged `init` skill plans and gates a project's `AGENTS.md`, writing only after approval. |
|
|
30
|
+
| Branch-following mode | the `plan-mode` session entry | `/resume` and `/tree` restore the mode and its tool set for the branch they land on. |
|
|
33
31
|
|
|
34
32
|
### Review
|
|
35
33
|
|
|
36
34
|
| Capability | How | What you get | Status |
|
|
37
35
|
|---|---|---|---|
|
|
38
|
-
| Review screen | `
|
|
36
|
+
| Review screen | `plan` action `exit` | A scrollable, themed plan with approve, refine, keep, browser, and exit in the footer. | Shipped |
|
|
39
37
|
| Browser page | `/plan review`, `w` on the review screen | The plan opens in a local browser as a reading-first page with live section and step progress. | Partial |
|
|
40
38
|
| Approval in the browser | the `/plan review` page's **Approve & run** | The plan is approved without returning to the terminal, and the steps are seeded. | Shipped |
|
|
41
39
|
| Inline comments | the page's `+ Comment`, **Save feedback** | Comments are saved into the plan file as `> [!REVIEW]` lines and returned to the model. | Shipped |
|
|
42
40
|
| Live page | the page's `events` stream, the plan-file poll | An edit made elsewhere repaints every open page without a reload. | Shipped |
|
|
43
|
-
| Changed sections | the `
|
|
41
|
+
| Changed sections | the `exit` review screen, the `/plan review` outline | After a refinement, only the sections that changed are marked. | Shipped |
|
|
42
|
+
| Block-level change marks | the `/plan review` page's **Changed** view | After a refinement, each block that is new or edited is marked — an inserted step marks itself and leaves the rest of its section alone — and a section that lost blocks says how much shorter it became. **All** / **Changed** / **Comments** switch what the page shows, `v` cycles them, `n`/`N` walk the blocks that carry a comment, and a printed review is always the whole plan. | Unreleased |
|
|
43
|
+
| Settled comments | the page's `Resolve` / `Reopen` on a note you wrote | The note keeps its place, its quote and its history and is written `> [!REVIEW resolved]`, where a later review and the model read it as closed; the panel counts `2 open · 1 resolved`, and every card names who wrote it. | Unreleased |
|
|
44
44
|
| Section navigation | the review screen, `n`/`p` | The screen names the section you are in and jumps between headings. | Shipped |
|
|
45
|
-
| Remote review | `
|
|
45
|
+
| Remote review | `plan` action `exit` on a WeChat turn | The plan file is sent, then one compact prompt to approve, keep planning, or exit. | Shipped |
|
|
46
46
|
|
|
47
47
|
### Collaboration
|
|
48
48
|
|
|
49
|
-
| Capability | How | What you get |
|
|
50
|
-
|
|
51
|
-
| Shared review | `/plan share`, **Share** | A reviewer link, with a QR a phone can scan, opens the same plan from another machine on this Wi-Fi. |
|
|
52
|
-
| One link per teammate | **New link**, **Revoke**, `/plan share stop` | Each teammate holds a link of their own, and one is revoked without disturbing the rest. |
|
|
53
|
-
| Two roles | the owner's `token`, a reviewer's link | Only the owner saves, approves, cancels, and manages links; a reviewer reads and comments. |
|
|
54
|
-
| Signed comments | the page's `name` control | A reviewer's name binds to her link on its first post, so her notes are hers and the file records who wrote them. |
|
|
49
|
+
| Capability | How | What you get |
|
|
50
|
+
|---|---|---|
|
|
51
|
+
| Shared review | `/plan share`, **Share** | A reviewer link, with a QR a phone can scan, opens the same plan from another machine on this Wi-Fi. |
|
|
52
|
+
| One link per teammate | **New link**, **Revoke**, `/plan share stop` | Each teammate holds a link of their own, and one is revoked without disturbing the rest. |
|
|
53
|
+
| Two roles | the owner's `token`, a reviewer's link | Only the owner saves, approves, cancels, and manages links; a reviewer reads and comments. |
|
|
54
|
+
| Signed comments | the page's `name` control | A reviewer's name binds to her link on its first post, so her notes are hers and the file records who wrote them. |
|
|
55
55
|
|
|
56
56
|
## Quickstart
|
|
57
57
|
|
|
@@ -64,34 +64,43 @@ pi install ./ # install the package for a user
|
|
|
64
64
|
```text
|
|
65
65
|
/plan # toggle plan mode
|
|
66
66
|
/plan add rate limiting to the public API # enter plan mode and send the task
|
|
67
|
+
Shift+Tab # toggle too, from bytefly's editor
|
|
67
68
|
```
|
|
68
69
|
|
|
69
|
-
The model calls `
|
|
70
|
-
`
|
|
70
|
+
The model calls `plan` with action `enter` before a non-trivial task; `/plan` and
|
|
71
|
+
`Shift+Tab` are the user's own switch. Shift+Tab is bytefly's: the editor binds
|
|
72
|
+
it and asks plan through `PLAN_TOGGLE_REQUEST`, so a session that loads `plan`
|
|
73
|
+
without bytefly uses `/plan` (or `--plan`) instead.
|
|
71
74
|
|
|
72
75
|
## Tools
|
|
73
76
|
|
|
74
|
-
|
|
77
|
+
One tool with five actions — `enter`, `write`, `exit`, `steps`, `cancel` — because
|
|
78
|
+
the verbs share one domain, the way `board` and `todo` keep theirs in one tool. How
|
|
79
|
+
the `write` and `exit` calls and their results look in the transcript — the call
|
|
80
|
+
line as a headline and the body indented under it:
|
|
75
81
|
|
|
76
|
-
<img src="../../assets/tools/
|
|
82
|
+
<img src="../../assets/tools/plan-write.png" alt="The plan tool's write action: the call line and an indented body with the saved plan path" width="100%">
|
|
77
83
|
|
|
78
|
-
<img src="../../assets/tools/
|
|
84
|
+
<img src="../../assets/tools/plan-exit.png" alt="The plan tool's exit action: the call line and an indented body with the approval line and the approved plan preview" width="100%">
|
|
79
85
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
86
|
+
The tool is `executionMode: "sequential"`, closed-world, and active in both modes;
|
|
87
|
+
each action refuses outside its own, so plan mode never has to hide it. Its one
|
|
88
|
+
annotation set is the strictest of the five, because `write` overwrites a plan file
|
|
89
|
+
with `plan_path`; the actions that only change the mode are exempted by the guard
|
|
90
|
+
in `index.ts`, the one place that can still tell them apart, and the policy's
|
|
91
|
+
`isAllowed` stays a statement about files rather than about this tool.
|
|
83
92
|
|
|
84
|
-
|
|
|
93
|
+
| Action | Active | Purpose |
|
|
85
94
|
|---|---|---|
|
|
86
|
-
| `
|
|
87
|
-
| `
|
|
88
|
-
| `
|
|
89
|
-
| `
|
|
90
|
-
| `
|
|
95
|
+
| `enter` | either mode | Ask to enter plan mode; no fields, confirmed with `ctx.ui.confirm`. |
|
|
96
|
+
| `write` | plan mode | Save the plan: `title` (file-name slug), `content` (full markdown in the documented outline), optional `plan_path` to overwrite a refinement. Returns the absolute path. |
|
|
97
|
+
| `exit` | plan mode | Read the plan file (`plan_path`) and present it for approval. |
|
|
98
|
+
| `steps` | normal mode | Set the checkboxes of the given top-level steps of an approved plan in one write, and their todo items with them. |
|
|
99
|
+
| `cancel` | plan mode | Leave plan mode without a plan file or a review. No fields. |
|
|
91
100
|
|
|
92
|
-
### `
|
|
101
|
+
### `enter`
|
|
93
102
|
|
|
94
|
-
No
|
|
103
|
+
No fields. It confirms with `ctx.ui.confirm` before switching the tool set,
|
|
95
104
|
because the model is changing the mode on the user's behalf; a declined confirm
|
|
96
105
|
answers "stayed in normal mode" and the session keeps write access. Already
|
|
97
106
|
planning, it says so. With no UI it fails with an actionable message instead of
|
|
@@ -100,12 +109,12 @@ deciding for the user.
|
|
|
100
109
|
On a remote turn the confirmation is a short consent sentence in the peer's
|
|
101
110
|
language, and the notice names how to leave.
|
|
102
111
|
|
|
103
|
-
### `
|
|
112
|
+
### `write`
|
|
104
113
|
|
|
105
114
|
`title` is the file-name slug, `content` the full markdown, and `plan_path`
|
|
106
115
|
overwrites an existing plan when refining. The result carries the absolute path,
|
|
107
|
-
the relative path, and the byte count — the absolute path is what `
|
|
108
|
-
|
|
116
|
+
the relative path, and the byte count — the absolute path is what `exit` takes. A
|
|
117
|
+
call with neither `title` nor `content` is refused before anything is written.
|
|
109
118
|
|
|
110
119
|
The file lands in
|
|
111
120
|
`<agent-dir>/plans/<repo-key>/<YYYY-MM-DD-HHmm>-<slug>.md`, keyed by the
|
|
@@ -115,8 +124,8 @@ repository the store is `<agent-dir>/plans`. Plans are outside the project, so
|
|
|
115
124
|
they are never untracked files and never appear in a `rewind` snapshot; a store
|
|
116
125
|
an older version left in `<repo>/.pi/plans` is moved in once, with a notice.
|
|
117
126
|
|
|
118
|
-
The description documents a canonical outline — a `# <Title>`, then
|
|
119
|
-
`## Context`, `## Approach`, `## Visual`, `## Steps`, `## Risks`, and
|
|
127
|
+
The tool's description documents a canonical outline — a `# <Title>`, then
|
|
128
|
+
`## Goal`, `## Context`, `## Approach`, `## Visual`, `## Steps`, `## Risks`, and
|
|
120
129
|
`## Verification` — and the model is guided to follow it. Every example in the
|
|
121
130
|
template is the shape wanted rather than a description of it, and each section
|
|
122
131
|
has one job: the goal is one sentence, the context is the facts that force the
|
|
@@ -139,7 +148,7 @@ A plan with more than 50 top-level steps in its `Steps` section is refused with
|
|
|
139
148
|
the cap and the fix named, and nothing is written.
|
|
140
149
|
|
|
141
150
|
The file is the source of truth. On approval the model follows the plan file's
|
|
142
|
-
steps, and refinements rewrite the same file (`
|
|
151
|
+
steps, and refinements rewrite the same file (`write` with `plan_path`), so
|
|
143
152
|
the reviewed artifact is the executed artifact. The text a refinement replaces is
|
|
144
153
|
kept beside it, as a dotfile named for the plan and the revision
|
|
145
154
|
(`.2026-10-26-1008-add-rate-limiting-r001.md`), up to the newest five: that is
|
|
@@ -150,9 +159,9 @@ the review never offers it for approval — and a refinement that changed nothin
|
|
|
150
159
|
keeps nothing, because the copy would be the plan itself. The write's result names
|
|
151
160
|
the revision it kept.
|
|
152
161
|
|
|
153
|
-
### `
|
|
162
|
+
### `exit`
|
|
154
163
|
|
|
155
|
-
`plan_path` names the file `
|
|
164
|
+
`plan_path` names the file `write` returned; the action reads it back and
|
|
156
165
|
presents it for approval. A hand-edited or older file whose step list is over the
|
|
157
166
|
cap is refused before the review screen. The user approves, keeps planning, asks
|
|
158
167
|
for a refinement, or exits plan mode without approving; the last keeps the plan
|
|
@@ -172,19 +181,19 @@ the todo list:
|
|
|
172
181
|
- The plan's `## Verification` section follows as the **last** todo item,
|
|
173
182
|
summarized on one line (`Verify: …`) — a fenced block contributes its
|
|
174
183
|
commands, not its fence lines. It is not a plan step, so it is ticked in the
|
|
175
|
-
todo list rather than with `
|
|
184
|
+
todo list rather than with the `steps` action, and it never counts against the
|
|
176
185
|
50-step cap.
|
|
177
186
|
- A plan without a `Steps` heading keeps the older rule — the shallowest list in
|
|
178
187
|
the document — so prose bullets in a plan that follows the outline never become
|
|
179
188
|
todos, and its verification bullets are already covered.
|
|
180
189
|
- Each seeded item is matched back to its step by text, so ticking a step with
|
|
181
|
-
`
|
|
190
|
+
`steps` completes the item too.
|
|
182
191
|
- An approval records the step texts it seeded, per plan path, as a `plan-seeded`
|
|
183
|
-
entry. A plan refined after approval is approved again — `
|
|
192
|
+
entry. A plan refined after approval is approved again — `write` needs plan
|
|
184
193
|
mode, so a second round is the way back — and that second approval **replaces the
|
|
185
194
|
leftovers its own earlier approval made**: an untouched item whose step was
|
|
186
195
|
renamed or dropped goes, while one somebody started or finished is kept and
|
|
187
|
-
named, because deleting it would erase work a reader did. `
|
|
196
|
+
named, because deleting it would erase work a reader did. `write` says the
|
|
188
197
|
list is stale when it refines a plan that was approved before.
|
|
189
198
|
|
|
190
199
|
**Goal-aware.** While planning, the injected context restates a pursued session
|
|
@@ -196,15 +205,10 @@ the decision. A session with no goal at all is given the same objective, also
|
|
|
196
205
|
without asking. An `active` or `achieved` goal is never rewritten: a final
|
|
197
206
|
objective is the user's. No path spends a model turn.
|
|
198
207
|
|
|
199
|
-
### `
|
|
200
|
-
|
|
201
|
-
Leaves plan mode without a plan file or a review. Restores write access, records
|
|
202
|
-
no todo items or goal, and keeps any saved plan. Empty schema.
|
|
203
|
-
|
|
204
|
-
### `set_plan_steps`
|
|
208
|
+
### `steps`
|
|
205
209
|
|
|
206
210
|
Keep an approved plan current: `plan_path`, plus `updates`, each a 1-based `step`
|
|
207
|
-
in the order `
|
|
211
|
+
in the order `exit` listed, a `status` of `pending` or `completed`, and
|
|
208
212
|
`expected` — the step's text, so an update whose step number moved is refused
|
|
209
213
|
instead of ticking the wrong line. It is a single all-or-nothing write: a step out
|
|
210
214
|
of range, or an `expected` text that no longer matches the file, refuses every
|
|
@@ -213,27 +217,32 @@ marker.
|
|
|
213
217
|
|
|
214
218
|
The todo item approval seeded from a step is ticked with it: the file is written
|
|
215
219
|
first and is authoritative, a renamed item is left alone and reported as
|
|
216
|
-
unmatched, and a failed todo write is reported in the result. The
|
|
217
|
-
while plan mode is on — refine the plan with `
|
|
220
|
+
unmatched, and a failed todo write is reported in the result. The action refuses
|
|
221
|
+
while plan mode is on — refine the plan with `write` instead.
|
|
222
|
+
|
|
223
|
+
### `cancel`
|
|
224
|
+
|
|
225
|
+
Leaves plan mode without a plan file or a review. Restores write access, records
|
|
226
|
+
no todo items or goal, and keeps any saved plan. No fields.
|
|
218
227
|
|
|
219
228
|
### Transcript
|
|
220
229
|
|
|
221
|
-
The
|
|
222
|
-
|
|
223
|
-
|
|
230
|
+
The blocks reuse the transcript component, and `exit` separates the plan body from
|
|
231
|
+
its header with a blank line; the collapse hint binds to `app.tools.expand`
|
|
232
|
+
(`ctrl+o` by default).
|
|
224
233
|
|
|
225
234
|
```
|
|
226
|
-
|
|
235
|
+
plan enter
|
|
227
236
|
✓ Plan mode enabled
|
|
228
237
|
```
|
|
229
238
|
|
|
230
239
|
```
|
|
231
|
-
|
|
240
|
+
plan write Add rate limiting
|
|
232
241
|
✓ Saved plan ~/.pi/agent/plans/a1f9c02/2026-10-09-1809-add-rate-limiting.md
|
|
233
242
|
```
|
|
234
243
|
|
|
235
244
|
```
|
|
236
|
-
|
|
245
|
+
plan exit 2026-10-09-1809-add-rate-limiting
|
|
237
246
|
✓ Plan approved
|
|
238
247
|
~/.pi/agent/plans/a1f9c02/2026-10-09-1809-add-rate-limiting.md
|
|
239
248
|
|
|
@@ -247,7 +256,7 @@ exit_plan_mode submitted a plan
|
|
|
247
256
|
|
|
248
257
|
| Path | Who starts it | Confirmation |
|
|
249
258
|
|---|---|---|
|
|
250
|
-
| `
|
|
259
|
+
| `plan` (action `enter`) | the model, before a non-trivial task | `ctx.ui.confirm` |
|
|
251
260
|
| `/plan` | the user | immediate |
|
|
252
261
|
| `/plan <prompt>` | the user, with the task | immediate |
|
|
253
262
|
| `/plan list` | the user, browsing the plans directory | immediate |
|
|
@@ -255,7 +264,7 @@ exit_plan_mode submitted a plan
|
|
|
255
264
|
| `/plan share [stop]` | the user, handing the review to a teammate | immediate |
|
|
256
265
|
| `/plan cancel` | the user, leaving plan mode without approving | immediate |
|
|
257
266
|
| `/skill:init` | the user, creating or updating `AGENTS.md` | enters plan mode; write waits for plan approval |
|
|
258
|
-
| `
|
|
267
|
+
| `Shift+Tab` (bytefly) | the user | immediate |
|
|
259
268
|
| `--plan` | the user, at launch | immediate |
|
|
260
269
|
|
|
261
270
|
`/plan` with no argument toggles plan mode; `/plan <prompt>` enters it (if it is
|
|
@@ -267,10 +276,13 @@ already runs read-only:
|
|
|
267
276
|
```
|
|
268
277
|
|
|
269
278
|
`/plan <prompt>` never disables plan mode; only the argument-less `/plan` (or
|
|
270
|
-
`
|
|
271
|
-
the toggle that works
|
|
272
|
-
|
|
273
|
-
is on
|
|
279
|
+
`Shift+Tab`, through bytefly) toggles. Because slash commands go through Pi
|
|
280
|
+
directly, `/plan` is the toggle that works with or without bytefly. Bytefly's
|
|
281
|
+
footer shows `▶ auto` in accent in its mode segment, and `≡ plan` in warning there
|
|
282
|
+
while plan mode is on; the bar draws that word itself, so the plan file name the
|
|
283
|
+
chip carries never reaches it. `auto` is Pi's default mode — every tool as it ships,
|
|
284
|
+
writes included — so the chip says which mode the session is in, not that a decision
|
|
285
|
+
was taken for you.
|
|
274
286
|
|
|
275
287
|
`/plan list` walks the plans directory and shows every plan with its title,
|
|
276
288
|
modified time, and step progress, newest first — in the TUI as a docked list
|
|
@@ -291,7 +303,7 @@ never swallows one.
|
|
|
291
303
|
`/plan share` prints the reviewer link and its QR, and `/plan share stop` revokes
|
|
292
304
|
every link; the page's **Share** button does the same. With no browser review open
|
|
293
305
|
it says so and points at `/plan review`. `/plan cancel` leaves plan mode without
|
|
294
|
-
approving, exactly like `
|
|
306
|
+
approving, exactly like `cancel`: write access returns and the plan file
|
|
295
307
|
stays for a later review. Both are exact words — `share the tokens` and `cancel
|
|
296
308
|
that idea` stay tasks — as is `list`.
|
|
297
309
|
|
|
@@ -310,7 +322,7 @@ approval. Its workflow is:
|
|
|
310
322
|
└─ unavailable/cancelled ──> evidence + assumptions
|
|
311
323
|
└─> draft: new file, exact edits, or an honest no-op
|
|
312
324
|
└─> quality gate
|
|
313
|
-
└─>
|
|
325
|
+
└─> plan · write ──> plan · exit
|
|
314
326
|
├─ not approved ──> refine the same plan
|
|
315
327
|
└─ approved ──────> write/edit the target
|
|
316
328
|
└─ read back + quality checklist
|
|
@@ -366,9 +378,13 @@ session token, and the owner's token is the one that opened the page.
|
|
|
366
378
|
| `POST /api/share/revoke?token=…` | owner only: revoke one link by `{ id }`, leaving the others answering |
|
|
367
379
|
| `POST /api/share/stop?token=…` | owner only: revoke every reviewer link |
|
|
368
380
|
|
|
381
|
+
Every route that reads a body takes JSON and only JSON: a form-encoded, `text/plain`,
|
|
382
|
+
or headerless body is refused `415` before the role check, so a form cannot reach the
|
|
383
|
+
parser even from the page's own origin.
|
|
384
|
+
|
|
369
385
|
## Behaviour by mode
|
|
370
386
|
|
|
371
|
-
The review screen is TUI-only: `
|
|
387
|
+
The review screen is TUI-only: `exit` opens `PlanViewComponent`, and `w`
|
|
372
388
|
on it opens the browser review. RPC and other non-interactive runs get no screen.
|
|
373
389
|
|
|
374
390
|
Dialog-capable non-TUI modes (RPC/WeChat) use one editor prompt instead: on a
|
|
@@ -391,10 +407,10 @@ its closing rule on a short terminal.
|
|
|
391
407
|
Browser review is a local-turn feature: the server binds `127.0.0.1`, so a remote
|
|
392
408
|
(WeChat) turn cannot reach it and `/plan review` there refuses with a notice
|
|
393
409
|
instead of opening a server nobody can use. The browser's **Approve & run** is
|
|
394
|
-
offered only for the review `
|
|
410
|
+
offered only for the review `exit` opens, since only that flow owns
|
|
395
411
|
leaving plan mode; `/plan review` stays comment-only.
|
|
396
412
|
|
|
397
|
-
Aborting the turn closes a browser review. `
|
|
413
|
+
Aborting the turn closes a browser review. `exit` forwards the call's
|
|
398
414
|
abort signal to the review server, so an aborted turn returns "not approved"
|
|
399
415
|
and stops listening instead of waiting on a page nobody is watching.
|
|
400
416
|
|
|
@@ -409,7 +425,7 @@ command. The read-only guarantee is layered:
|
|
|
409
425
|
git commands through `bash` (chained with `&&`/`;`), `powershell` is blocked
|
|
410
426
|
outright, and other mutating tools (worktree mutations, MCP tools) are blocked
|
|
411
427
|
until you exit plan mode. `subagent` stays active but is forced read-only. The
|
|
412
|
-
only permitted write is the plan
|
|
428
|
+
only permitted write is the `plan` tool's `write` action, which can only
|
|
413
429
|
create or overwrite markdown plan files directly inside the plans directory —
|
|
414
430
|
never dotfiles and never through a symlink.
|
|
415
431
|
- **Capability policy.** A tool is allowed only when it is a known structured
|
|
@@ -421,18 +437,18 @@ command. The read-only guarantee is layered:
|
|
|
421
437
|
file path is refused unless it is a known plan-safe reader. `path-guard.ts`
|
|
422
438
|
scans nested arguments and path-shaped values, not just fixed top-level keys.
|
|
423
439
|
- **Control-tool identity.** The `tool_call` guard exempts plan's own tools —
|
|
424
|
-
`
|
|
440
|
+
the `plan` tool's `write`, `exit`, and `cancel` actions — only
|
|
425
441
|
when the registered tool is this extension's, matched by source path, so a
|
|
426
442
|
same-named tool from another extension cannot borrow the exemption.
|
|
427
|
-
|
|
443
|
+
the tool is exempted as a whole, and its `enter` action answers "already"
|
|
428
444
|
is answered with "Already in plan mode" instead of being refused as not
|
|
429
445
|
read-only; the policy still denies it, so it stays hidden while planning.
|
|
430
|
-
- **Contained writes.** `
|
|
446
|
+
- **Contained writes.** `write` only writes markdown non-dotfiles whose
|
|
431
447
|
real parent resolves inside the plans directory, and every plan write —
|
|
432
|
-
create, refine, `
|
|
448
|
+
create, refine, `steps`, browser feedback — goes through a hidden
|
|
433
449
|
temp file followed by a rename, so an interrupted write cannot leave a
|
|
434
450
|
truncated plan.
|
|
435
|
-
- **Sanitized model text.** The plan file is model-authored, so `
|
|
451
|
+
- **Sanitized model text.** The plan file is model-authored, so `exit`
|
|
436
452
|
strips control characters from the plan body before rendering it in the
|
|
437
453
|
transcript and in non-TUI notices; a plan file cannot drive the terminal.
|
|
438
454
|
- **Loopback browser review.** The review server binds `127.0.0.1` and requires a
|
|
@@ -468,8 +484,19 @@ git diff -- extensions\plan # allowed: a Windows path separator
|
|
|
468
484
|
git status && rm -rf x # blocked: the second segment is not git
|
|
469
485
|
git status | sh # blocked: pipes are never allowed
|
|
470
486
|
git diff > out.patch # blocked: redirection is a write
|
|
487
|
+
git config --get user.email # allowed: a read
|
|
488
|
+
git config --add core.hooksPath x # blocked: it writes .git/config
|
|
471
489
|
```
|
|
472
490
|
|
|
491
|
+
`git config` reads only. Its flags are an allowlist — `--get`, `--get-all`,
|
|
492
|
+
`--get-regexp`, `--list`, and the modifiers that shape them (`--show-origin`,
|
|
493
|
+
`--show-scope`, `--local`, `--global`, `--null`) — one bare `git config <name>` reads a
|
|
494
|
+
key, and every action that writes is refused by name: `--add`, `--replace-all`, `--unset`,
|
|
495
|
+
`--unset-all`, `--rename-section`, `--remove-section`, `--edit`, or a `<name> <value>`
|
|
496
|
+
pair. A write action used to pass as long as a read flag appeared beside it, so
|
|
497
|
+
`git config --show-scope --replace-all core.fsmonitor /tmp/hook.sh` configured a hook from
|
|
498
|
+
inside a plan and the next `git status` ran it.
|
|
499
|
+
|
|
473
500
|
A refused shell command explains the fix: the working directory is already the
|
|
474
501
|
project root (so `cd` is unnecessary), and files belong to the `read`, `grep`,
|
|
475
502
|
`find`, and `ls` tools.
|
|
@@ -507,7 +534,7 @@ agent file that overrides it.
|
|
|
507
534
|
|
|
508
535
|
<img src="../../assets/screens/plan.png" alt="The terminal plan review: a Plan Review title rule, a notice that one section changed since the last review, the plan body with its headings and ◼/◻ task checkboxes, a scroll gauge naming the current section and the visible line range, and the Esc/a/r/w, scroll, and section-jump hints" width="100%">
|
|
509
536
|
|
|
510
|
-
`
|
|
537
|
+
`exit` opens this screen on the plan file it just wrote. The body is
|
|
511
538
|
rendered with Pi's own `Markdown` component and `getMarkdownTheme()`, so
|
|
512
539
|
headings, lists, inline code, code blocks, links, and quotes carry the active
|
|
513
540
|
theme's colours; task items get the shared `◼` (done) or `◻` (pending) marker,
|
|
@@ -562,6 +589,12 @@ reveals a **+ Comment** action on hover; select
|
|
|
562
589
|
text first to quote it. **Save feedback** writes the comments into the plan
|
|
563
590
|
file and returns them to the model.
|
|
564
591
|
|
|
592
|
+
- **A comment can be settled.** **Resolve** (on your own note) keeps it — its place, its
|
|
593
|
+
quote, its history — and marks it `> [!REVIEW resolved]` in the file, where a later review
|
|
594
|
+
and the model both read it as closed; **Reopen** puts it back. The panel counts
|
|
595
|
+
`2 open · 1 resolved`. A note you wrote is labelled **You** on your page and **The owner**
|
|
596
|
+
on somebody else's, a reviewer's is `@name`, and one sentence beside the facts says what
|
|
597
|
+
**Approve & run** and **Save feedback** each do.
|
|
565
598
|
- **Shared theme.** The page uses the same Bytefly tokens, base rules, and
|
|
566
599
|
syntax-token colours as `file-browse` (`lib/web/`), follows the system light/dark
|
|
567
600
|
preference until the header toggle sets an explicit choice, and remembers that
|
|
@@ -629,7 +662,7 @@ file and returns them to the model.
|
|
|
629
662
|
Stripping is fence-aware: a `> [!REVIEW]` line inside a code block is
|
|
630
663
|
documentation, not feedback. The file is the only copy of a saved comment; the
|
|
631
664
|
ones this tab has not saved yet live in its own `sessionStorage` and nowhere else.
|
|
632
|
-
- **A revision keeps the review.** `
|
|
665
|
+
- **A revision keeps the review.** `write` passes the file it is replacing
|
|
633
666
|
through `carryFeedback`, which re-attaches each comment by the strongest evidence
|
|
634
667
|
that survived: the anchored block's text, per occurrence, so a plan that repeats
|
|
635
668
|
a step keeps the comments apart; then the block whose wording still overlaps it —
|
|
@@ -654,14 +687,15 @@ file and returns them to the model.
|
|
|
654
687
|
save that carries no comments asks for nothing, so the review screen comes back
|
|
655
688
|
instead. `/plan review` sends them as a user message (a plan-mode revision or a
|
|
656
689
|
plain update, depending on the mode).
|
|
657
|
-
- **Loopback first, tokenized.** The
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
saved theme
|
|
690
|
+
- **Loopback first, tokenized.** The review mounts `/plan/<id>` on the session's one
|
|
691
|
+
server, which binds `127.0.0.1`; the URL carries a random per-session token, a `Host`
|
|
692
|
+
header the server was not bound on is rejected, a cross-origin POST is refused, only
|
|
693
|
+
`GET`, `HEAD`, and `POST` are served, and the request body is capped. Sharing asks that
|
|
694
|
+
mount for one LAN listener (below); it never widens the loopback socket. A save or
|
|
695
|
+
cancel resolves the session only after its HTTP response is delivered, so the browser
|
|
696
|
+
never sees a false "Failed to fetch". The prefix is the review's, on the session's one
|
|
697
|
+
origin, so the browser's saved theme survives a review. It is closed on the owner's
|
|
698
|
+
save or cancel, on the owner's
|
|
665
699
|
page going away, or on `session_shutdown`; a reload reconnects inside that grace,
|
|
666
700
|
so refreshing or reloading a conflicted page does not end the review. A
|
|
667
701
|
reviewer's tab opening or closing is not the review's lifetime.
|
|
@@ -741,13 +775,13 @@ both.
|
|
|
741
775
|
keeps no registry, so it sees an external edit or a hand-copied plan
|
|
742
776
|
immediately; it lists a file over the 256 KiB plan limit without reading it,
|
|
743
777
|
and does not index the agent directory's plans while a worktree is active.
|
|
744
|
-
- Approval tracks at most 50 steps: `
|
|
745
|
-
`
|
|
778
|
+
- Approval tracks at most 50 steps: `write` refuses a larger plan, and
|
|
779
|
+
`exit` refuses to present one, so no reviewed step is silently
|
|
746
780
|
dropped. A step longer than 200 characters is shortened in the todo list and
|
|
747
781
|
the approval listing — a display rule only, because the plan file always keeps
|
|
748
782
|
the full text.
|
|
749
783
|
- The todo item for a step is matched by its text. An item renamed after
|
|
750
|
-
approval no longer matches, so `
|
|
784
|
+
approval no longer matches, so `steps` leaves it alone and says so in
|
|
751
785
|
its result; the plan file is still updated.
|
|
752
786
|
- Browser review needs a local browser: the server is loopback-only, so a remote
|
|
753
787
|
turn cannot drive it.
|
|
@@ -766,14 +800,24 @@ both.
|
|
|
766
800
|
refuses a file it did not render (`409`). It is a poll rather than a file
|
|
767
801
|
watcher, so a change on a filesystem that reports nothing at all is still seen
|
|
768
802
|
at the next request, because every page read re-compares the file.
|
|
803
|
+
- **A settled note is a flag in the marker.** `> [!REVIEW resolved]` (and
|
|
804
|
+
`moved resolved`) is read as open when absent; a build from before this one does not know
|
|
805
|
+
the flag and shows the marker line as body text, so a file reviewed on both sides of the
|
|
806
|
+
upgrade reads differently there.
|
|
769
807
|
- A shared review holds at most eight links. Each is a live bearer credential, so
|
|
770
808
|
a ninth is refused with the cap named rather than minted.
|
|
809
|
+
- **One tool means one filter.** Pi's per-tool filter is all-or-nothing, so a
|
|
810
|
+
session that disables `plan` loses every action with it, and plan mode
|
|
811
|
+
force-activates the tool while it is on (and puts the user's set back when it
|
|
812
|
+
ends). `rewind` also snapshots a run at the tool's first call rather than at
|
|
813
|
+
the first real write, because one annotation set cannot say that `enter` writes
|
|
814
|
+
nothing; it is still one snapshot per run, of the same tree.
|
|
771
815
|
|
|
772
816
|
## Non-goals
|
|
773
817
|
|
|
774
818
|
- **Not a sandbox.** Extensions share Pi's OS permissions.
|
|
775
819
|
- **No progress tracker of record.** `todo` owns completion state; the plan
|
|
776
|
-
file only mirrors it (`
|
|
820
|
+
file only mirrors it (`steps`), and plan mode does not read completion
|
|
777
821
|
back out.
|
|
778
822
|
- **No auto-execution.** Approval hands control back to the model.
|
|
779
823
|
|
|
@@ -781,10 +825,11 @@ both.
|
|
|
781
825
|
|
|
782
826
|
| Integration point | How |
|
|
783
827
|
|---|---|
|
|
784
|
-
| Tools | `
|
|
785
|
-
| Commands and flags | `/plan` (toggle, or enter and send a task), `/plan list` (plans index), `/plan review [path]` (browser review), `/plan share [stop]` (reviewer link), `/plan cancel` (leave without approving), `/skill:init` (skill-backed `AGENTS.md` bootstrap), `--plan` launch flag
|
|
828
|
+
| Tools | one `plan` tool, active in both modes, with five actions: `enter`, `write`, `exit`, `steps`, `cancel`. It is `executionMode: "sequential"`, closed-world, and carries one annotation set — `readOnlyHint: false`, `destructiveHint: true`, `idempotentHint: false` — because `write` overwrites a plan file: the actions that only change the mode are exempted by the guard in `index.ts`, the only place that can tell them apart. Each action returns typed `details` discriminated by `action` (`EnterPlanModeDetails`, `WritePlanDetails`, `ExitPlanModeDetails`, `CancelPlanModeDetails`, `SetPlanStepsDetails`); a refusal carries `RefusedPlanDetails` (`refused`, `error`) and no action's state; no `outputSchema`/`structuredContent`. |
|
|
829
|
+
| Commands and flags | `/plan` (toggle, or enter and send a task), `/plan list` (plans index), `/plan review [path]` (browser review), `/plan share [stop]` (reviewer link), `/plan cancel` (leave without approving), `/skill:init` (skill-backed `AGENTS.md` bootstrap), `--plan` launch flag. `Shift+Tab` is bytefly's editor chord, not a registered shortcut: `app.thinking.cycle` is reserved, so the editor requests a toggle over the event bus instead. |
|
|
786
830
|
| State | Enabled flag and the tools it hid persisted with `pi.appendEntry("plan-mode", { enabled, removed })`, and each review's baseline persisted with `pi.appendEntry("plan-baseline", { path, sections })` as one digest per heading section; both rebuilt from `ctx.sessionManager.getBranch()`, so `/resume` and `/tree` restore the mode and the changed markers of the branch they land on. Plan writes a goal only at approval, through `ctx.executeTool("goal", { objective })` when the `goal` tool is registered: a `planning` goal is promoted to the plan's `## Goal`, a session with none is given the same objective, and an `active`/`achieved` goal is left alone — no path asks first. A review that shows the same content appends nothing. The last plan path lives in runtime memory for the footer chip, and a bare `/plan review` falls back to the newest plan file in the directory. |
|
|
787
|
-
| Entry requests | `pi.events`
|
|
831
|
+
| Entry requests | `pi.events` channels from `lib/plan-entry.ts`: `PLAN_ENTER_REQUEST` (the `goal` workflow asks, with the shared consent sentence, and plan enables the mode on the caller's context without a second dialog) and `PLAN_TOGGLE_REQUEST` (bytefly's Shift+Tab asks to flip it and gets the state back). Both share one `PlanModeRequest` payload and `isPlanExtensionLoaded`. Subscribed on `session_start`, released on `session_shutdown`. |
|
|
832
|
+
| `board` while planning | The board is one action-shaped tool, so its annotation cannot say it reads: plan mode reads the action instead, through `lib/policy.ts`'s `isBoardRead` and `lib/board/actions.ts`'s table. The refusal is built by `boardWriteRefusal` in that same module — the board's words, because the sentence names the board's order: claim a card before you plan, and record its plan once it is approved. |
|
|
788
833
|
| Hooks | `tool_call` blocks non-read-only calls and forces `subagent` read-only; `before_agent_start` injects the hidden `[PLAN MODE ACTIVE]` context, with a pursued session goal read from the branch through `lib/goal-state.ts`; `context` keeps only the newest plan context while enabled and drops stale ones otherwise. |
|
|
789
834
|
| Lifecycle | `session_start`/`session_tree` restore state; `session_shutdown` clears the footer status and closes any browser review server. |
|
|
790
835
|
|
|
@@ -792,16 +837,16 @@ both.
|
|
|
792
837
|
|
|
793
838
|
- **Consent is one dialog, whichever extension asks.** The goal workflow offers
|
|
794
839
|
plan mode as a phase of the goal, but a command context cannot call
|
|
795
|
-
`
|
|
840
|
+
the `plan` tool (`ExtensionCommandContext` has no `executeTool`). So the
|
|
796
841
|
consent sentence left `policy.ts` for `lib/plan-entry.ts`, and the entry itself
|
|
797
842
|
is a `pi.events` request: the asker shows the question, plan enables silently
|
|
798
|
-
with the asker's context. `
|
|
843
|
+
with the asker's context. The tool's `enter` action keeps its own confirm, using the
|
|
799
844
|
same sentence, so the model-initiated path is unchanged and the two texts
|
|
800
845
|
cannot drift. A request that nobody answers resolves `false` rather than
|
|
801
846
|
hanging, so `goal` loaded alone still works.
|
|
802
847
|
- **One review loop owns the human gate.** `review.ts` asks however the session
|
|
803
848
|
is attached — TUI screen, dialog plus editor, remote file plus digest, or
|
|
804
|
-
browser — and returns one `ReviewDecision`, so `
|
|
849
|
+
browser — and returns one `ReviewDecision`, so `exit` and
|
|
805
850
|
`/plan review` no longer carry two copies of the browser lifecycle and the
|
|
806
851
|
tool's own `for(;;)` with a `continue` per outcome. The loop also owns the
|
|
807
852
|
baseline rule (mark what the screen showed, after it showed it) and forwards
|
|
@@ -809,9 +854,11 @@ both.
|
|
|
809
854
|
- **Two tools, not one.** `EnterPlanMode`/`ExitPlanMode` are a pair: entering is
|
|
810
855
|
consent to explore read-only, exiting is consent to act. A single toggle tool
|
|
811
856
|
cannot express "the model wants to plan but the user declines".
|
|
812
|
-
- **User entry is instant, model entry confirmed.** `/plan`, `
|
|
813
|
-
`--plan` are the user's own action and take effect at once; `
|
|
814
|
-
changes the mode on the user's behalf, so it confirms first.
|
|
857
|
+
- **User entry is instant, model entry confirmed.** `/plan`, `Shift+Tab`, and
|
|
858
|
+
`--plan` are the user's own action and take effect at once; the `enter` action
|
|
859
|
+
changes the mode on the user's behalf, so it confirms first. Shift+Tab travels
|
|
860
|
+
through bytefly's editor and `PLAN_TOGGLE_REQUEST`, so the mode stays owned by
|
|
861
|
+
`plan` even when the key is pressed in another extension's surface.
|
|
815
862
|
- **Review the file, decide in a screen.** The plan is a file, so it is the
|
|
816
863
|
artifact already on screen. `ctx.ui.confirm()` is a non-scrollable selector
|
|
817
864
|
that pushes buttons off-screen for a long plan, so the TUI gets a scrollable
|
|
@@ -819,7 +866,7 @@ both.
|
|
|
819
866
|
renders the body with Pi's `Markdown` component so the plan reads like any
|
|
820
867
|
other markdown in the app; the plan text is sanitized before it reaches the
|
|
821
868
|
renderer, so only the theme's own ANSI survives.
|
|
822
|
-
- **`
|
|
869
|
+
- **`write` is the only write.** It is not the builtin `write`, so the
|
|
823
870
|
capability policy and path backstop stay intact; a `plan_path` must name a
|
|
824
871
|
markdown non-dotfile whose real parent resolves inside the plans directory,
|
|
825
872
|
so symlinks and the directory's own `.gitignore` are never writable targets.
|
|
@@ -842,7 +889,7 @@ both.
|
|
|
842
889
|
authoritative, so a failed nested write is reported in the result text — once
|
|
843
890
|
one artifact has changed there is no previous state to hand back.
|
|
844
891
|
- **A cap is enforced where it can still be fixed.** Both refusal points —
|
|
845
|
-
`
|
|
892
|
+
`write` and `exit` — sit before the write and before the review,
|
|
846
893
|
because those are the moments the model can still regroup the steps. A note on
|
|
847
894
|
a successful write would arrive after the file existed and the review had
|
|
848
895
|
already listed every step, which is exactly when the overflow becomes lost
|
|
@@ -856,7 +903,7 @@ both.
|
|
|
856
903
|
a session entry rather than the previous text, so the markers survive a resume
|
|
857
904
|
without copying the plan file into the branch, and the reader and the writer
|
|
858
905
|
share one normalization so a tab cannot read as a change.
|
|
859
|
-
- **The outline guides, it does not enforce.** `
|
|
906
|
+
- **The outline guides, it does not enforce.** `write` documents the
|
|
860
907
|
canonical shape in its description and stores whatever markdown it is given;
|
|
861
908
|
no section is required and nothing is rewritten. The description names the two
|
|
862
909
|
headings that do carry behavior — `Steps` is what approval reads as steps, and
|
|
@@ -868,7 +915,7 @@ both.
|
|
|
868
915
|
source-line map, so `tui.ts` splits the body at its headings and renders each
|
|
869
916
|
section separately. That gives exact offsets for the current-section label and
|
|
870
917
|
`n`/`p`; the single-section case is byte-for-byte the old render.
|
|
871
|
-
- **`
|
|
918
|
+
- **`steps` is a second contained write.** It changes only the named
|
|
872
919
|
steps' checkboxes, in an existing markdown plan inside the plans directory
|
|
873
920
|
(`isContainedPlan`), in a single all-or-nothing write — refusing every entry
|
|
874
921
|
if any step is out of range or an entry's `expected` text no longer matches —
|
|
@@ -925,20 +972,21 @@ both.
|
|
|
925
972
|
|
|
926
973
|
| File | Responsibility |
|
|
927
974
|
|---|---|
|
|
928
|
-
| `index.ts` | Wiring: tools, command, flag,
|
|
929
|
-
| `types.ts` | `
|
|
975
|
+
| `index.ts` | Wiring: tools, command, flag, events, context injection. |
|
|
976
|
+
| `types.ts` | `PLAN_ACTIONS`, `PlanModeEntry`, the five action `details` types and their `PlanDetails` union, and `RefusedPlanDetails`. |
|
|
930
977
|
| `policy.ts` | Plan mode's read-only policy, the shared prompt summary, and the bash-refusal guidance. |
|
|
931
978
|
| `git-bash.ts` | `checkReadOnlyGit`: the pure allowlist that restricts `bash` to read-only git commands. |
|
|
932
|
-
| `plans.ts` | Plan-file store: slug/stamp naming, directory
|
|
979
|
+
| `plans.ts` | Plan-file store: slug/stamp naming, the store's directory (`<agent-dir>/plans/`, keyed by the repository, unkeyed outside git, through `lib/plans/paths.ts`), `write`/`setSteps`/`saveFeedback`, and `read`/`latest`. |
|
|
980
|
+
| `lib/plans/paths.ts` | Where a plan lives, and which paths are one: `plansDir` for `<agent-dir>/plans/` (keyed by the repository, unkeyed outside it), the markdown/non-dotfile name rule, symlink-safe containment, and `resolvePlanArg`. Shared with `board`, which records the file a card is executed against. |
|
|
933
981
|
| `plan-files.ts` | How a plan file reaches the disk: `writeAtomic` (a dotfile temp, then a rename, so a crash cannot truncate the plan a review is reading) and `keepRevision`, which keeps the text a refinement replaces beside it, numbered, up to the newest five. |
|
|
934
982
|
| `todos.ts` | Approval-time todo merge (pure): the last list replayed from the branch, and the merge of the plan's steps into it with the cap respected. |
|
|
935
983
|
| `steps.ts` | Plan-document structure: the outline, step extraction and the `Steps`-section scope, the plan's own goal (`goalSection`), and the checkbox edit. |
|
|
936
984
|
| `sections.ts` | The one fence-aware heading scan: `extractSections`, `sectionKeys` (the key that tells two identically titled sections apart), and the `HEADING` / `FENCE` / `normalizeHeadingText` vocabulary `blocks.ts` reads a heading through. |
|
|
937
985
|
| `format.ts` | Pure result/approval text: the plan preview, the step-cap diagnosis, step labels, the merge summary, and the verification note. |
|
|
938
986
|
| `plan-text.ts` | The plan text a review shows and compares: `sanitizePlanText`, the one normalization both sides use, the per-section `sectionDigests`, and `changedSections`, which hands each section back with its flag. |
|
|
939
|
-
| `runtime.ts` | Enabled state, tool gating, persistence (mode and review baseline),
|
|
940
|
-
| `tools.ts` |
|
|
941
|
-
| `tools/` | One module per
|
|
987
|
+
| `runtime.ts` | Enabled state, tool gating, persistence (mode and review baseline), the `plan` tool's identity and its place in the active set, footer status. |
|
|
988
|
+
| `tools.ts` | The one registration: the flat action schema, the dispatch over the five actions, and the call and result blocks they draw. |
|
|
989
|
+
| `tools/` | One module per action (`enter.ts`, `write.ts`, `exit.ts`, `cancel.ts`, `steps.ts`), each exporting its `execute`/`call`/`text` seam; plus `refusal.ts` (the one rejected-call shape), `todo-seed.ts` (the two nested `todo` writes) and `nested.ts` (reading a nested result). |
|
|
942
990
|
| `review.ts` | The review gate: one decision from the TUI screen, a dialog, or the browser, the shared browser lifecycle, and the "mark what was shown" baseline rule. |
|
|
943
991
|
| `review-prompt.ts` | Pure rendering and parsing for the compact remote review: one action table behind both the prompt and the reply parser. |
|
|
944
992
|
| `commands.ts` | `/plan` (enter, optional task), `/plan review [path]`, `/plan list`, `/plan share [stop]`, and `/plan cancel`. |
|
|
@@ -946,14 +994,18 @@ both.
|
|
|
946
994
|
| `plan-index.ts` | `/plan list`: the notice text and the docked index screen (store size and oldest plan, title, step progress, age, focused path; Enter reviews). |
|
|
947
995
|
| `blocks.ts` | Source-line block model (fence-aware headings, paragraphs, list items, code, quotes, tables, rules, blanks), and `contentBlockAt`: the block with content a comment beside blank space belongs to. |
|
|
948
996
|
| `feedback.ts` | Comment codec: authored markers, `stripFeedback`, `readFeedback`/`parseFeedback` (body, blocks, and comments out of one parse), `formatFeedback` (writer-scoped), `displayFeedback`, `carryFeedback`, `feedbackSummary`, and payload validation. |
|
|
949
|
-
| `
|
|
997
|
+
| `review-lazy.ts` | The review gate behind a dynamic import: `reviewPlan` and `runBrowserReview` load `review.ts` (and its TUI screen) on the first review, so registration, `/plan cancel`, and the tool schemas never do. The decision and baseline types live here, where a type import costs nothing. |
|
|
998
|
+
| `web-lazy.ts` | The review behind `lib/lazy`: `NO_SERVER_DEPS`, and the proxy `/plan` and the tools share, so `web.ts` loads on the first review and shutdown closes only an opened one |
|
|
999
|
+
| `web.ts` | `createPlanWebReview`: the review session (per-token roles, the change stream, the plan-file poll, the body cap, settle-after-flush, abort) over `lib/http`'s one loopback server, and the router wiring — the island is `web-payload.ts` and the writes are `web-write.ts`. |
|
|
950
1000
|
| `web-tokens.ts` | The token table: the role each token names, the collision rule that keeps two roles off one token, and the names the other live links have bound. |
|
|
951
1001
|
| `web-streams.ts` | The event streams: who is listening, what a frame is addressed to, and the closed-tab grace that ends the review when the owner's page goes away. |
|
|
952
1002
|
| `web-router.ts` | Pure request handler: token role, `Host` allowlist, origin, and method checks through one POST-and-role guard, then the page, comment, owner-save, approve, cancel, and the four share routes. |
|
|
953
|
-
| `web-page.ts` | The review page shell (header, reading progress, review facts, section outline, shortcut sheet, approve confirmation, share and name dialogs)
|
|
1003
|
+
| `web-page.ts` | The review page shell (header, reading progress, review facts, section outline, shortcut sheet, approve confirmation, share and name dialogs) and inline CSS. |
|
|
1004
|
+
| `web-payload.ts` | The page's data island: `ReviewPageData` and `reviewPageData`, which builds every fact the browser renders — the blocks, the stored comments, the outline and its change marks, the step progress, the highlighted code, the caps, and who is asking — from one read of the plan, with no server or socket in sight. |
|
|
1005
|
+
| `web-write.ts` | The review's two write paths over the plan store: `saveOwnerAnnotations` (the owner's save, which returns the plan it wrote) and `postReviewerAnnotations` (a reviewer's post, signed and scoped to its link), sharing one 404/409 check so a comment can never land beside text nobody read. |
|
|
954
1006
|
| `web-share.ts` | Pure sharing rules: the reachable LAN addresses from an injected snapshot, one tokenized URL, the link table (mint, find, revoke, list, state) with its cap, and the reasons a share is unavailable. |
|
|
955
1007
|
| `web-share-session.ts` | The shared listener: its bound address, the link table over the session's tokens, `ShareState`, and invite/revoke/stop/close, injected with the request handler, role map, and frame hooks. |
|
|
956
|
-
| `web-keys.ts` | The client's keyboard as typed source (`WEB_KEYS_JS`): `
|
|
1008
|
+
| `web-keys.ts` | The client's keyboard as typed source (`WEB_KEYS_JS`), and the one table the page's keys come from: `webKeys()` gives each binding its keys, the shortcut sheet's sentence, the sidebar hint's words and whether the page offers it — a function rather than a constant, because the bundle carries a body and `String()` of a table would drop the closures — read by `handleKey` (Esc peels the composer before closing, a field and the sheet own their keys, `s` is the write the page offers) and by the sheet and hint line the page renders; plus `rememberSelection`, which keeps the text a reader selected as the next comment's quote, and the `keyRows`/`surfaceOf` the handler and the page's own sheet both read, spliced with them for the same reason. |
|
|
957
1009
|
| `web-settle.ts` | The client's settlement as typed source (`WEB_SETTLE_JS`): `submitAnnotations` — one POST shape whose 409 disables the writes, offers a reload and says the server's own sentence — and the four ways a review ends, of which only the owner's save, approve and close settle it. |
|
|
958
1010
|
| `web-plan.ts` | The client's frame as typed source (`WEB_PLAN_JS`, `renderPlanFrame`): it draws every block and its comment rail, then puts the reader back — focus only when it was inside the plan, the active block in place rather than by scrolling. Reads arrive as getters, mutations leave as callbacks, so the bundle keeps every variable. |
|
|
959
1011
|
| `web-composer.ts` | The client's composer lifecycle as typed source (`WEB_COMPOSER_JS`): `closeComposer` (over one `ComposerDeps` the client builds where the state is), `reopenComposer` for the draft a reload interrupted, and `commentOnActive`, which returns the index so the client keeps its one `activeIndex`. |
|
|
@@ -962,7 +1014,7 @@ both.
|
|
|
962
1014
|
| `web-client.ts` | The `/client.js` source: the composition root, and nothing else by decision — the element handles, the state each rule is handed, one zero-argument adapter per rule, the listeners that attach them, the `EventSource` that keeps a tab's presence known, and the boot order. Every rule it used to hold lives in the `web-*.ts` modules below, where it can be typed and driven. |
|
|
963
1015
|
| `web-comments.ts` | The client's comment half: selection quotes, the composer, authored cards and who may edit them, delete-with-undo. |
|
|
964
1016
|
| `web-collab.ts` | The client's collaboration half: the link list with copy and per-link revoke, the reviewer's name, and the island refetch a stream frame triggers. |
|
|
965
|
-
| `web-markdown.ts` | The client's
|
|
1017
|
+
| `web-markdown.ts` | The client's block half: tables, fenced code, headings, quotes, and lists, with each block's text handed to the shared `renderInline` from `lib/web/markdown.ts` (interpolated into `web-client.ts`). |
|
|
966
1018
|
| `web-chrome.ts` | The client's chrome half: the state chip, the status line, the header, and reading progress (interpolated into `web-client.ts`). |
|
|
967
1019
|
| `web-outline.ts` | The client's outline as typed source (`WEB_OUTLINE_JS`): `sectionFor` — the last heading at or before a line — `renderOutline`, which builds the list and hands back the counters it made, `observeSections`, which watches the blocks and returns the one watcher the client keeps, and `renderFacts`, which paints the step progress and counts each comment under its heading. |
|
|
968
1020
|
| `path-guard.ts` | Recursive path-argument detection for the read-only backstop. |
|
|
@@ -973,7 +1025,7 @@ both.
|
|
|
973
1025
|
| [`../../lib/qr.ts`](../../lib/qr.ts) | QR matrix, terminal half-blocks, and inline SVG for the share link (shared with `wechat`). |
|
|
974
1026
|
| [`../../lib/http/`](../../lib/http/) | The one loopback server entry, the bind, `Host` allowlist, header sets, and response kit both browser surfaces serve through. |
|
|
975
1027
|
| [`../../lib/web/index.ts`](../../lib/web/index.ts) | Shared Bytefly web brand system: tokens, base rules, `tok-*` colors, layout, the bootstrap, the toggle wiring, the shortcut sheet (`keysSheet`, `keysDialogScript`), and shared markup. |
|
|
976
|
-
| [`../../lib/http/index.ts`](../../lib/http/index.ts) |
|
|
1028
|
+
| [`../../lib/http/index.ts`](../../lib/http/index.ts) | The served-page kit shared with `file-browse`: the page policy and header sets, `ServeResponse`, the request-envelope helpers, bind/respond/close. Reached from the handler that serves a page; the mount contract is the leaf [`mount.ts`](../../lib/http/mount.ts). |
|
|
977
1029
|
| `../../lib/policy.ts` | Shared read-only capability policy (default-deny + `readOnlyHint`). |
|
|
978
1030
|
| `../../lib/tui/chrome.ts` | Shared screen header, viewport-row helper, and styled key-hint footer. |
|
|
979
1031
|
|
|
@@ -983,21 +1035,27 @@ both.
|
|
|
983
1035
|
bun test extensions/plan
|
|
984
1036
|
```
|
|
985
1037
|
|
|
986
|
-
|
|
1038
|
+
Thirteen co-located suites, declared in `test/suite-manifest.ts`:
|
|
987
1039
|
|
|
988
|
-
- `plans.test.ts` — the plan-file store: naming, directory
|
|
989
|
-
writes, `read`/`latest`/`index`,
|
|
990
|
-
|
|
1040
|
+
- `plans.test.ts` — the plan-file store: naming, the store's directory, atomic
|
|
1041
|
+
writes, `read`/`latest`/`index`, `setSteps`, `saveFeedback`, and step extraction;
|
|
1042
|
+
the location and path rules it runs through (`plansDir`, `plansDirFor`, the name
|
|
1043
|
+
rule, symlink-safe containment) are `lib/plans/paths.ts` and its own suite.
|
|
991
1044
|
- `feedback.test.ts` — the comment codec: authored markers, stripping and
|
|
992
1045
|
parsing, who a reviewer's write is signed by, carrying feedback onto a
|
|
993
1046
|
revision, and displaying stored comments.
|
|
994
|
-
- `tools.test.ts` —
|
|
1047
|
+
- `tools.test.ts` — all five actions against a real plan store, the approval merge into
|
|
995
1048
|
`todo`, the session goal, and the call/result renderings.
|
|
1049
|
+
- `tool-registration.test.ts` — the registration itself: the flat action schema,
|
|
1050
|
+
the strictest-of-five annotations, and the refusal each action gives when it
|
|
1051
|
+
needs a field or runs outside its mode.
|
|
996
1052
|
- `review-prompt.test.ts` — the compact remote prompt and its reply parser
|
|
997
1053
|
against one action table.
|
|
998
|
-
- `web
|
|
999
|
-
|
|
1000
|
-
|
|
1054
|
+
- `web-*.test.ts` — the browser review, one capability per suite: the comment
|
|
1055
|
+
codec and the router (`web-router`), the page roles and its shell (`web-page`),
|
|
1056
|
+
the client script's rules (`web-client`, `web-outline`, `web-composer`,
|
|
1057
|
+
`web-settlement`), the stream and the plan-file poll (`web-stream`), the
|
|
1058
|
+
loopback session (`web-session`), and the share rules (`web-shared-review`).
|
|
1001
1059
|
- `web-behaviour.test.ts` — the served review, driven in a real browser through
|
|
1002
1060
|
the router: the blocks and the plan's name, a block's comment control opening the
|
|
1003
1061
|
composer with Escape peeling it before the review, a stored comment in its block's
|
|
@@ -1006,9 +1064,9 @@ Twelve co-located suites, declared in `test/suite-manifest.ts`:
|
|
|
1006
1064
|
- `web-share.test.ts` — the LAN address selector, `shareUrl`, the link table with
|
|
1007
1065
|
its cap, and the reasons a share is unavailable.
|
|
1008
1066
|
- `commands.test.ts` — `/plan review`, `/plan list`, `/plan share`, and the one
|
|
1009
|
-
review gate shared by `
|
|
1067
|
+
review gate shared by `exit` and the browser, including the abort and
|
|
1010
1068
|
baseline rules.
|
|
1011
|
-
- `runtime.test.ts` — tool gating, persistence and status,
|
|
1069
|
+
- `runtime.test.ts` — tool gating, persistence and status, the `plan` tool's identity,
|
|
1012
1070
|
the review baseline, branch restore, the read-only git allowlist, and the
|
|
1013
1071
|
path-argument scan.
|
|
1014
1072
|
- `tui.test.ts` — the review screen at fixed widths: Markdown body, scrolling,
|
|
@@ -1016,6 +1074,5 @@ Twelve co-located suites, declared in `test/suite-manifest.ts`:
|
|
|
1016
1074
|
refine editor, and the changed-section markers.
|
|
1017
1075
|
- `sections.test.ts` — the fence-aware scan: heading shape, fences, the preamble,
|
|
1018
1076
|
source lines and levels, and the occurrence key.
|
|
1019
|
-
- `extension.test.ts` — the Pi wiring: registration, the
|
|
1020
|
-
session lifecycle, the tool-call guard, injected context, the command
|
|
1021
|
-
shortcut.
|
|
1077
|
+
- `extension.test.ts` — the Pi wiring: registration, the enter and toggle requests,
|
|
1078
|
+
the session lifecycle, the tool-call guard, injected context, and the command.
|