@tduyng/pi-prewalk 0.0.2 → 0.0.3
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 +72 -73
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,66 +1,87 @@
|
|
|
1
1
|
# @tduyng/pi-prewalk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Plan on the frontier model, execute on the cheap one, in one unbroken context. The first edit swaps the model, and the planner comes back only when the executor hits a wall.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## What it costs
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
`prewalk_plan` is deferred at 716 tokens in the sessions that load it, and nothing before that. The router is one hook on `streamSimple` and registers no extra schema, so an armed session pays the router and the plan tool, and an unarmed one pays nothing.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
The saving is the tier. On SWE-bench this reached 92 to 97 percent of the frontier pass rate for 53 to 61 percent of its cost. Planning is the expensive step, and it is bought once per task rather than once per turn.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
## Why not a plan document
|
|
12
|
+
|
|
13
|
+
Stencil measured 1.81B tokens over about 2M tool calls and found edits are roughly 9 percent of them. Reads are the rest, so a plan document does not help: whoever executes it opens the same files again.
|
|
14
|
+
|
|
15
|
+
prewalk keeps one context instead. The planner explores and makes the first edit, and the cheap model carries on from the same history with the plan in hand.
|
|
12
16
|
|
|
13
17
|
## The router
|
|
14
18
|
|
|
15
|
-
prewalk registers one virtual model, `prewalk/auto
|
|
19
|
+
prewalk registers one virtual model, `prewalk/auto`, selected with `/prewalk` or from `/model`. Pi calls the router before every request, so prewalk never moves the session's model itself and no `setModel` runs mid task. Every model change in the session file is one prewalk made.
|
|
16
20
|
|
|
17
|
-
Each route returns one request's model, so
|
|
21
|
+
Each route returns one request's model, so planner and executor can differ inside a single task.
|
|
18
22
|
|
|
19
23
|
## A task boundary
|
|
20
24
|
|
|
21
|
-
prewalk asks one question, and only when a task is about to start. The boundary is the gap between one settled run and the next prompt typed after it, so a task
|
|
25
|
+
prewalk asks one question, and only when a task is about to start. The boundary is the gap between one settled run and the next prompt typed after it, so a task routes once and the turns inside it are never touched.
|
|
26
|
+
|
|
27
|
+
Pi's own `reason: "user"` cannot carry that boundary, because it fires for a steer and a follow-up too. prewalk keeps its own flag set from the `input` event, which reads `streamingBehavior` as the three cases it is: undefined when the session was idle, `steer` when the text joins the turn in flight, and `followUp` when it waits for that turn to settle and opens a task of its own. The first router call that sees the flag consumes it, so one prompt routes once. A message from another extension opens a task the same way, and the only text that opens nothing is prewalk's own nudge, recognized by its `[prewalk]` prefix.
|
|
28
|
+
|
|
29
|
+
| You type | What happens |
|
|
30
|
+
| --- | --- |
|
|
31
|
+
| A prompt during the task in flight | The model stays, the prompt runs as written, no routing call. This is the common case, and what keeps the bill linear in turns rather than quadratic |
|
|
32
|
+
| A question while the executor is in play | A steer long enough to be a question moves the task back to the planner, which stays until the next edit hands it over. No routing call, because the phase answers it. A one-word steer is a redirect and stays where it is |
|
|
33
|
+
| A new task | The session moves to the planner before the first token |
|
|
34
|
+
| A prompt under 8 characters | Not a task: it holds whatever is in play |
|
|
22
35
|
|
|
23
|
-
|
|
36
|
+
## The handoff
|
|
24
37
|
|
|
25
|
-
|
|
38
|
+
The planner explores, then must commit a structured plan through `prewalk_plan` before it can edit. The first edit is blocked once with a message naming the tool, and a planner that ignores the block degrades to a plain edit-only swap.
|
|
26
39
|
|
|
27
|
-
|
|
40
|
+
The first `edit`, `write`, `multiedit`, or `notebookedit` after the plan swaps the session to the executor, and so does a bash command that writes a file outside the temp dir (a redirect, `sed -i`, `tee`, `patch`, `git apply`, or an inline script that writes), which also demands the plan first. A third tool call after the plan still hands over, for a planner that writes in a way the check cannot see. An edit under the temp dir is scratch and swaps nothing.
|
|
28
41
|
|
|
29
|
-
|
|
42
|
+
The plan tool returns the handoff brief itself: the goal, the facts with file:line, each step with file, anchor, change, and verify command, the out-of-scope list, and the rules of engagement. Both roles read the same bytes, so neither cache is rewritten.
|
|
30
43
|
|
|
31
|
-
|
|
44
|
+
## When the executor is stuck
|
|
32
45
|
|
|
33
|
-
|
|
46
|
+
Three failed tool results in a row are a wall. One miss does not hand the task back, and any success resets the count. The third failure appends a brief naming the step, and the planner takes the task back on the next request until its next edit.
|
|
34
47
|
|
|
35
|
-
|
|
48
|
+
A task buys two upgrades, because each swap re-reads the whole prefix at the new model's input rate, and a task cannot ping-pong between the models.
|
|
36
49
|
|
|
37
|
-
|
|
50
|
+
When the executor finishes the plan, or stalls after its nudge, the planner takes the task back once per plan. It reads the edits already in the transcript, runs the final check, and fixes what is wrong. Work the plan did not cover gets a new plan, which is how a long task runs in phases of up to 20 steps. `"review": false` in `prewalk.json` turns that off.
|
|
38
51
|
|
|
39
|
-
|
|
52
|
+
The session badge reads `prewalk replan` while this happens.
|
|
40
53
|
|
|
41
|
-
The
|
|
54
|
+
## The plan tool
|
|
55
|
+
|
|
56
|
+
`prewalk_plan` is in the active set while prewalk is armed in plan mode, and the executor meets it only through tool search. Its description carries the planning brief, which is why nothing is prepended to your prompt.
|
|
42
57
|
|
|
43
|
-
|
|
58
|
+
| Field | Meaning |
|
|
59
|
+
| --- | --- |
|
|
60
|
+
| `summary` | One-line goal |
|
|
61
|
+
| `facts` | Findings from exploration the executor cannot re-derive, each with file:line |
|
|
62
|
+
| `steps` | `{ file, change, anchor?, verify? }` in order, up to 20 |
|
|
63
|
+
| `check` | Final verification command |
|
|
64
|
+
| `outOfScope` | Files the executor must not touch |
|
|
44
65
|
|
|
45
|
-
|
|
66
|
+
## Progress
|
|
46
67
|
|
|
47
|
-
|
|
68
|
+
After each edit the extension matches the edited path against the plan steps and advances a step pointer, walking forward from the current step so batched edits and missed results catch up instead of freezing the count. A short footer is appended to the edit result: what was done, what comes next, the anchor, and the verify command. No model cooperation is needed.
|
|
48
69
|
|
|
49
|
-
The
|
|
70
|
+
The badge reads `prewalk route` between tasks, `prewalk plan` or `prewalk run` on the first turn of one, `prewalk exec 3/7` while the plan runs, and `prewalk done 7/7` at the end.
|
|
50
71
|
|
|
51
|
-
|
|
72
|
+
A planner that commits a plan but ends the turn without an edit still gets the swap, and the executor is nudged to start step 1. An executor that settles with steps open gets one steer to resume. Your input or progress re-arms it, so at most one nudge is spent per stall.
|
|
52
73
|
|
|
53
|
-
|
|
74
|
+
## Cache
|
|
54
75
|
|
|
55
|
-
|
|
76
|
+
A prompt cache belongs to one model, so the swap is the only thing that has to be paid for, and a task pays it at most once: the executor meets a prefix it has never seen, at the cheap model's input rate.
|
|
56
77
|
|
|
57
|
-
|
|
78
|
+
Prompts are never rewritten. There is no wrapper on your message and no message is edited afterwards, so both models read the transcript you wrote and each keeps its cache warm across its own turns. The one message prewalk writes is the plan tool's result, at the swap.
|
|
58
79
|
|
|
59
|
-
|
|
80
|
+
`prewalk_plan` stays in the active set for as long as prewalk is armed in plan mode, because a toolset change rewrites the system prompt and the tool list, and the claude provider answers that by opening a new session that replays the whole transcript.
|
|
60
81
|
|
|
61
82
|
## Model chains
|
|
62
83
|
|
|
63
|
-
Each role is an ordered list, walked until one model resolves against pi's registry and has credentials. Two ordinary things break a single model: a provider with no
|
|
84
|
+
Each role is an ordered list, walked until one model resolves against pi's registry and has credentials. Two ordinary things break a single model: a provider with no key, and a frontier model that runs out of its usage window part way through the day. The chain absorbs both without a config edit.
|
|
64
85
|
|
|
65
86
|
```json
|
|
66
87
|
{
|
|
@@ -69,54 +90,36 @@ Each role is an ordered list, walked until one model resolves against pi's regis
|
|
|
69
90
|
}
|
|
70
91
|
```
|
|
71
92
|
|
|
72
|
-
`/prewalk models` prints both chains and marks each entry `router`, `ready`, or `unavailable` against the registry
|
|
73
|
-
|
|
74
|
-
## Progress tracking
|
|
75
|
-
|
|
76
|
-
After each edit, the extension matches the edited file path against the plan steps and auto-advances a step pointer. The match walks forward from the current step, so batched edits and missed results catch up instead of freezing the count. A short footer is appended to the edit result: what was done, what comes next, the anchor, and the verify command. No model cooperation is required.
|
|
77
|
-
|
|
78
|
-
The status badge reads `prewalk route` between tasks, `prewalk plan` or `prewalk run` on the first turn of one, `prewalk exec 3/7` while the plan runs, and `prewalk done 7/7` at the end.
|
|
79
|
-
|
|
80
|
-
If the planner commits a plan but the turn ends without an edit, the extension swaps anyway and nudges the executor to start step 1. When the executor settles with steps open, one steer resumes the plan. User input or progress re-arms it, so at most one nudge is spent per stall.
|
|
81
|
-
|
|
82
|
-
## The plan tool
|
|
83
|
-
|
|
84
|
-
`prewalk_plan` is in the active set while prewalk is armed in plan mode, and the executor only meets it through tool search. Its description carries the planning brief, which is why nothing is prepended to your prompt. Its schema:
|
|
85
|
-
|
|
86
|
-
- `summary`: one-line goal
|
|
87
|
-
- `facts`: findings from exploration the executor cannot re-derive, each with file:line
|
|
88
|
-
- `steps`: `{ file, change, anchor?, verify? }` in order, max 20
|
|
89
|
-
- `check`: final verification command
|
|
90
|
-
- `outOfScope`: files the executor must not touch
|
|
93
|
+
`/prewalk models` prints both chains and marks each entry `router`, `ready`, or `unavailable` against the registry `/model` reads, with the context window and input price, and the mode underneath.
|
|
91
94
|
|
|
92
95
|
## Commands
|
|
93
96
|
|
|
94
|
-
| Command
|
|
95
|
-
|
|
|
96
|
-
| `/prewalk`
|
|
97
|
-
| `/prewalk off`
|
|
98
|
-
| `/prewalk status`
|
|
99
|
-
| `/prewalk models`
|
|
100
|
-
| `/prewalk mode off`
|
|
101
|
-
| `/prewalk mode plan`
|
|
102
|
-
| `/prewalk planner <model>...`
|
|
103
|
-
| `/prewalk executor <model>...`
|
|
104
|
-
| `/prewalk plan [task]`
|
|
105
|
-
| `/prewalk run [task]`
|
|
106
|
-
| `/prewalk <executor> [task]`
|
|
107
|
-
| `/prewalk <planner> <executor> [task]` |
|
|
97
|
+
| Command | Effect |
|
|
98
|
+
| --- | --- |
|
|
99
|
+
| `/prewalk` | Status while armed, arm from `prewalk.json` when not |
|
|
100
|
+
| `/prewalk off` | Disarm |
|
|
101
|
+
| `/prewalk status` | Both chains, the mode, and where the task is |
|
|
102
|
+
| `/prewalk models` | Both chains, what resolves, what it costs, and the mode |
|
|
103
|
+
| `/prewalk mode off` | Nothing happens unless you ask |
|
|
104
|
+
| `/prewalk mode plan` | Every task plans (the default) |
|
|
105
|
+
| `/prewalk planner <model>...` | Replace the planner chain, or pick one from a list |
|
|
106
|
+
| `/prewalk executor <model>...` | Replace the executor chain, or pick one from a list |
|
|
107
|
+
| `/prewalk plan [task]` | The next task plans, decided by hand |
|
|
108
|
+
| `/prewalk run [task]` | The next task runs on the cheap model, decided by hand |
|
|
109
|
+
| `/prewalk <executor> [task]` | Set the executor. A task given here starts on the planner |
|
|
110
|
+
| `/prewalk <planner> <executor> [task]` | Set both roles and, with a task, start it |
|
|
108
111
|
|
|
109
|
-
|
|
112
|
+
A role named with no model opens the same dialog pi's own model list is built from, each line carrying `provider/id`, the context window, and the input price per million, sorted by price because the executor is the tier you pay for.
|
|
110
113
|
|
|
111
|
-
|
|
114
|
+
Slash commands and skill blocks are left alone, so skill expansion still works.
|
|
112
115
|
|
|
113
|
-
An armed prewalk owns the session model, because every task routes through the router. A switch away from it
|
|
116
|
+
An armed prewalk owns the session model, because every task routes through the router. A switch away from it leaves a session where nothing routes for the rest of its life, and one press of the model cycle key used to do that silently: the `12:20` model change in one session left 130 assistant messages on a cheap model with no routing at all. prewalk now takes the router back on `model_select` and on every session start and branch switch, and says which model it took. `/prewalk off` is how a physical model is kept.
|
|
114
117
|
|
|
115
|
-
Model naming is a bare id (`deepseek-v4-flash`) or provider/id (`google/gemini-3-flash`). Resolution is exact provider/id, then exact bare id, then unique id suffix
|
|
118
|
+
Model naming is a bare id (`deepseek-v4-flash`) or provider/id (`google/gemini-3-flash`). Resolution is exact provider/id, then exact bare id, then unique id suffix, and a bare id that several providers carry is an error rather than a guess.
|
|
116
119
|
|
|
117
|
-
##
|
|
120
|
+
## Configure
|
|
118
121
|
|
|
119
|
-
`~/.pi/agent/prewalk.json` holds the machine-wide settings. A project's `.pi/prewalk.json` overrides `planner`, `executor
|
|
122
|
+
`~/.pi/agent/prewalk.json` holds the machine-wide settings. A project's `.pi/prewalk.json` overrides `planner`, `executor`, and `mode` field by field. The commands write to the project file when one exists, otherwise to the agent dir.
|
|
120
123
|
|
|
121
124
|
```json
|
|
122
125
|
{
|
|
@@ -127,13 +130,9 @@ Model naming is a bare id (`deepseek-v4-flash`) or provider/id (`google/gemini-3
|
|
|
127
130
|
}
|
|
128
131
|
```
|
|
129
132
|
|
|
130
|
-
`mode`
|
|
131
|
-
|
|
132
|
-
The router must be selected for any of this to run. An armed session takes it back on session start and on a branch switch, and says which model it took. A session that was never armed stays on whatever model you chose.
|
|
133
|
-
|
|
134
|
-
A string is still accepted for either role, so a file written before the chains existed reads the same way. A missing, unparseable, or wrongly shaped file costs its settings and not the session.
|
|
133
|
+
`mode` decides how a task gets its model. `plan` is the default: every task starts on the frontier model and the executor carries the steps it was given. `off` plans nothing unless you ask, so every task runs on the executor. A file written before the score was removed, with `mode: "auto"`, reads as `plan`.
|
|
135
134
|
|
|
136
|
-
|
|
135
|
+
The router must be selected for any of this to run. A string is still accepted for either role, so a file written before the chains existed reads the same. A missing, unparseable, or wrongly shaped file costs its settings and not the session.
|
|
137
136
|
|
|
138
137
|
## Install
|
|
139
138
|
|