@cr1ms0n/pi-subagent 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -2
- package/README.md +130 -672
- package/README.zh-CN.md +132 -0
- package/docs/DEVELOPMENT.md +124 -0
- package/docs/PLAN.md +2 -0
- package/docs/REFERENCE.md +436 -0
- package/docs/RELEASING.md +151 -32
- package/docs/ROADMAP.md +2 -0
- package/docs/SECURITY.md +17 -18
- package/package.json +9 -1
- package/skills/subagent/SKILL.md +8 -4
- package/src/config.ts +1 -1
- package/src/jev-router.ts +7 -11
- package/src/routing-policy.ts +26 -18
- package/src/routing-types.ts +4 -4
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
# Usage and configuration reference
|
|
2
|
+
|
|
3
|
+
Return to the [English README](../README.md) or [Chinese README](../README.zh-CN.md) for installation. This reference documents the extension-managed Jev path and the separate explicit-spec SDK. The underlying subagent engine comes from Luke Parke's upstream extension; Jev routing and startup capability verification are additions in this fork.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
### Credential setup
|
|
8
|
+
|
|
9
|
+
Version `0.10.0` reads the TypeSafe key from `jevRouting.apiKey` in your private, user-level `~/.pi/subagent.json`. Set the key locally using an editor, preserve unrelated configuration and replace the placeholder in the [routing example](#jev-routing). Do not paste the key into chat, shell commands, source control or task descriptions.
|
|
10
|
+
|
|
11
|
+
This file stores the credential in plaintext. Restrict access to your user account and protect editor backups and synchronized copies. Same-user processes, including children with filesystem access, may read it; neither profiles nor worktrees provide an OS sandbox. See [SECURITY](SECURITY.md#routing-disclosure-and-credentials).
|
|
12
|
+
|
|
13
|
+
When upgrading from published npm `0.9.0`, remove `apiKeyEnv` and add `apiKey` with the actual key locally. The old field is rejected even if both fields are present. There is no environment fallback, automatic migration or default key. Published `0.9.0` still requires its older `apiKeyEnv` setup, while `0.10.0` uses the config-file credential contract.
|
|
14
|
+
|
|
15
|
+
Reload or restart Pi after changing extension code. Subsequent dispatches re-read the config file, so a later key edit does not require setting an environment variable. Provider credentials for execution models are configured independently using Pi's own authentication mechanisms. Rotate credentials exposed in source, logs or conversation.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
### Quick usage
|
|
20
|
+
|
|
21
|
+
These are request objects for the `subagent` tool, not shell commands. New work calls Jev; omit `model` and `fallback_models`.
|
|
22
|
+
|
|
23
|
+
#### Foreground and named agents
|
|
24
|
+
|
|
25
|
+
Use an explicit read-only profile for exploration. Single tasks otherwise default to `general`.
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
{
|
|
29
|
+
"task": "Find all call sites of parseConfig and summarize patterns.",
|
|
30
|
+
"description": "Map parseConfig usage",
|
|
31
|
+
"profile": "explore"
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
A named agent supplies a persona and non-model defaults; Jev still chooses the model and tools.
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"task": "Review this diff for security issues.",
|
|
40
|
+
"agent": "reviewer",
|
|
41
|
+
"profile": "review"
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
#### Parallel tasks and synthesis
|
|
46
|
+
|
|
47
|
+
Parallel tasks default to `explore`. Optional synthesis starts an additional read-only child and has its own routing selection. Raw worker results remain available if synthesis fails.
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"tasks": [
|
|
52
|
+
{ "task": "Audit backend error handling.", "description": "Backend audit" },
|
|
53
|
+
{ "task": "Audit frontend error handling.", "description": "Frontend audit" }
|
|
54
|
+
],
|
|
55
|
+
"synthesis": "Merge both audits into one prioritized findings list."
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Omit `synthesis` when you only need the separate worker reports.
|
|
60
|
+
|
|
61
|
+
#### Background work and collection
|
|
62
|
+
|
|
63
|
+
Start a background run and keep its returned run ID:
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{ "task": "Audit dependency licenses.", "profile": "review", "async": true }
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Inspect without consuming the deliverable:
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{ "action": "status", "id": "<run-id>" }
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Collect the result with the same tool:
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{ "action": "wait", "id": "<run-id>" }
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Or pass this request to `subagent_wait`, which delegates to the same collection handler:
|
|
82
|
+
|
|
83
|
+
```json
|
|
84
|
+
{ "id": "<run-id>", "timeout_ms": 30000 }
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
An interrupted or timed-out wait does not cancel or consume a still-running task. Cancel it explicitly when needed:
|
|
88
|
+
|
|
89
|
+
```json
|
|
90
|
+
{ "action": "cancel", "id": "<run-id>" }
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
#### Inspect a paid plan
|
|
94
|
+
|
|
95
|
+
A plan runs local preflights and Jev selection without spawning a child or creating a run entry. It can incur selector fees; a later dispatch selects again. It checks the same model/tool/budget/isolation resolution as a launch.
|
|
96
|
+
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"action": "plan",
|
|
100
|
+
"tasks": [
|
|
101
|
+
{ "task": "Implement feature A.", "profile": "general", "isolation": "worktree" }
|
|
102
|
+
]
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
#### Structured output
|
|
107
|
+
|
|
108
|
+
The child must produce a fenced `json:result` block matching the requested schema. The parent validates it and allows one repair round. An unresolved schema failure preserves raw output as a partial result rather than discarding paid work.
|
|
109
|
+
|
|
110
|
+
```json
|
|
111
|
+
{
|
|
112
|
+
"task": "Audit the auth module.",
|
|
113
|
+
"profile": "review",
|
|
114
|
+
"output_schema": {
|
|
115
|
+
"type": "object",
|
|
116
|
+
"required": ["findings", "risk"],
|
|
117
|
+
"properties": {
|
|
118
|
+
"findings": { "type": "array", "items": { "type": "string" } },
|
|
119
|
+
"risk": { "type": "string", "enum": ["low", "medium", "high"] }
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
#### Resume, fork and steering
|
|
126
|
+
|
|
127
|
+
A fork starts from a branch of the persisted parent conversation. It is single-task only:
|
|
128
|
+
|
|
129
|
+
```json
|
|
130
|
+
{ "task": "Implement the plan we agreed on.", "context": "fork", "profile": "general" }
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Find a resumable child session ID in status, then start a new invocation:
|
|
134
|
+
|
|
135
|
+
```json
|
|
136
|
+
{ "task": "Continue from your findings and propose a fix plan.", "resume": "<session-id>" }
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Both operations select again. To guide an existing child instead, steer it; parallel runs use `index` to select the worker:
|
|
140
|
+
|
|
141
|
+
```json
|
|
142
|
+
{ "action": "steer", "id": "<run-id>", "index": 0, "message": "Skip tests; focus on src and wrap up." }
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
#### Budgets and retries
|
|
146
|
+
|
|
147
|
+
A budget breach requests a final answer and allows the configured grace turns. Transient failures retry the already selected model and tool set; they never trigger reselection or fallback models.
|
|
148
|
+
|
|
149
|
+
```json
|
|
150
|
+
{ "task": "Audit dependencies.", "profile": "review", "max_turns": 15, "grace_turns": 2, "max_retries": 1 }
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
#### Isolated writers
|
|
154
|
+
|
|
155
|
+
Use separate worktrees for parallel changes:
|
|
156
|
+
|
|
157
|
+
```json
|
|
158
|
+
{
|
|
159
|
+
"tasks": [
|
|
160
|
+
{ "task": "Implement feature A.", "profile": "general", "isolation": "worktree" },
|
|
161
|
+
{ "task": "Implement feature B.", "profile": "general", "isolation": "worktree" }
|
|
162
|
+
]
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Inspect each finished patch:
|
|
167
|
+
|
|
168
|
+
```json
|
|
169
|
+
{ "action": "diff", "id": "<run-id>", "index": 0 }
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Apply it as uncommitted changes in the parent checkout:
|
|
173
|
+
|
|
174
|
+
```json
|
|
175
|
+
{ "action": "apply", "id": "<run-id>", "index": 0 }
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Discard an unwanted worktree and branch:
|
|
179
|
+
|
|
180
|
+
```json
|
|
181
|
+
{ "action": "discard", "id": "<run-id>", "index": 1 }
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
The `/subagents` overlay provides the same loop: `s` to steer, `a` to apply and `x` to discard.
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
### Side questions (`/btw`)
|
|
189
|
+
|
|
190
|
+
Ask a side question in Pi:
|
|
191
|
+
|
|
192
|
+
```text
|
|
193
|
+
/btw does this repo have a rate limiter?
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Or open the question prompt:
|
|
197
|
+
|
|
198
|
+
```text
|
|
199
|
+
/btw
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
`/btw` runs a one-off read-only subagent for _you_, not for the model. It uses the same policy, budget, semaphore and process-lock machinery as any run, but delivers its answer as a custom session entry, which does not participate in LLM context. The main agent keeps working and never sees the question or the answer; useful for checking something mid-task without derailing the conversation or polluting the context window.
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
### Backends
|
|
207
|
+
|
|
208
|
+
Jev routing manages Pi-backed new dispatch only. A `backend: "codex"` or `backend: "claude"` new task is refused before any selector or provider work, including a backend inherited from agent frontmatter; the extension never silently switches it to Pi. Existing Codex/Claude runs stay manageable: `status`, `wait`, `cancel`, `steer`, `diff`, `apply` and `discard` all still work. Provider diversity is not lost, because another provider's execution model stays eligible through Pi once it is in your configured candidate list.
|
|
209
|
+
|
|
210
|
+
The following new-work request is refused; use the Pi-backed path instead:
|
|
211
|
+
|
|
212
|
+
```json
|
|
213
|
+
{ "task": "Summarize this module", "backend": "codex", "profile": "explore" }
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
The low-level SDK is a different contract: `runTasks`/`runSubagent` execute the explicit `TaskSpec` you hand them, so embedding code can still select a backend directly. Everything else (worktrees, process locks, depth limits, budgets, orphan reclaim) is backend-agnostic and applies unchanged.
|
|
217
|
+
|
|
218
|
+
Capabilities differ, and **unsupported combinations are refused with an explanation rather than silently ignored**: a dropped `max_cost` or unenforced read-only profile would be a safety regression, not a minor degradation.
|
|
219
|
+
|
|
220
|
+
| | `pi` (default) | `codex` | `claude` |
|
|
221
|
+
| ------------------------------- | -------------- | ------------------------------------- | ---------------------- |
|
|
222
|
+
| `max_cost` | yes | **refused** (reports tokens, no cost) | yes (`total_cost_usd`) |
|
|
223
|
+
| read-only profile | tool allowlist | `--sandbox read-only` (OS-level) | `--allowedTools` |
|
|
224
|
+
| steering / graceful wrap-up | yes | **no** (no stdin channel) | **no** (one-shot) |
|
|
225
|
+
| `resume` | yes | yes | yes |
|
|
226
|
+
| `context:'fork'`, `fork_resume` | yes | **refused** | yes |
|
|
227
|
+
| `thinking` | yes | no | no |
|
|
228
|
+
| `output_schema` | yes | yes | yes |
|
|
229
|
+
|
|
230
|
+
A budget breach on a backend without steering hard-stops instead of asking the child to wrap up. Codex's read-only sandbox is enforced by the OS, which is stronger than a tool allowlist.
|
|
231
|
+
|
|
232
|
+
Agent frontmatter `backend:` remains a default. New extension-managed work rejects any effective backend other than Pi, including a native backend inherited from an agent. Direct SDK specs retain the backend capabilities listed above.
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
### Profiles
|
|
237
|
+
|
|
238
|
+
| Profile | Tools | Writes |
|
|
239
|
+
| ---------------------------- | ------------------------------------------------------- | ------------------------------------------- |
|
|
240
|
+
| `explore` (parallel default) | Jev-selected subset of locally permitted read-only candidates + available Pi context tools | no project-file writes |
|
|
241
|
+
| `review` | same as explore | no project-file writes |
|
|
242
|
+
| `general` | Jev chooses from the full available locally permitted catalog + Pi context tools | yes for selected write-capable tools; unknown custom tools count as writable |
|
|
243
|
+
|
|
244
|
+
Jev chooses individual tool names, not a capability bundle. Candidates come from the full available locally permitted catalog, not from the agent file's `tools` defaults and not from the parent's currently active tools. An explicit task `tools` list is a ceiling, and explore/review keep their read-only rule regardless of what the selector returns. An empty selection never means "all tools".
|
|
245
|
+
|
|
246
|
+
For the Pi backend, the context-management tools `new_context`, `get_context_remaining`, `history`, and `notes` are added locally when the parent exposes them, so they are never a selector question. They are control-plane tools: they may update continuity notes or the remote context window, but cannot modify the child checkout or run a shell command. This exception also applies when a task supplies a narrower tool list, so Pi's `contextManagement` remains usable for configured gateway models. Locally added controls are reported in the route metadata.
|
|
247
|
+
|
|
248
|
+
The finalized tool set is passed to the child as Pi's `--tools` allowlist (`--no-tools` for a true empty set). Pi 0.86.0 is the verified baseline for built-in, extension and late-registered tool enforcement; a host that cannot honor that allowlist is refused rather than silently weakened, and the extension does not claim identical behavior on untested older releases. Before the real task prompt is sent, the child is also asked to confirm the selected model and the finalized tool names through a verified private startup command; if the host cannot verify that command or the child cannot confirm both, the launch aborts with a startup diagnostic instead of running with a broader tool set.
|
|
249
|
+
|
|
250
|
+
Parallel write-capable tasks sharing one checkout are rejected unless each uses `isolation: "worktree"`, distinct `cwd`, or explicit `allow_shared_writes: true`.
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
### Configuration
|
|
255
|
+
|
|
256
|
+
Defaults can be overridden in `~/.pi/subagent.json` and per-field via env vars (env wins over file):
|
|
257
|
+
|
|
258
|
+
| Setting | Env var | Default |
|
|
259
|
+
| ----------------------- | ------------------------------------- | ------------------------------------- |
|
|
260
|
+
| `maxTasksPerRun` | `PI_SUBAGENT_MAX_TASKS` | 8 |
|
|
261
|
+
| `maxActiveProcesses` | `PI_SUBAGENT_MAX_ACTIVE` | 4 |
|
|
262
|
+
| `maxQueuedTasks` | `PI_SUBAGENT_MAX_QUEUED` | 32 |
|
|
263
|
+
| `maxGlobalActive` | `PI_SUBAGENT_MAX_GLOBAL_ACTIVE` | 16 |
|
|
264
|
+
| `defaultTimeoutMs` | `PI_SUBAGENT_TIMEOUT_MS` | 900000 |
|
|
265
|
+
| `maxDepth` | `PI_SUBAGENT_MAX_DEPTH` | 2 |
|
|
266
|
+
| `killGraceMs` | `PI_SUBAGENT_KILL_GRACE_MS` | 3000 |
|
|
267
|
+
| `sessionDir` | `PI_SUBAGENT_SESSION_DIR` | `~/.pi/subagent-sessions` |
|
|
268
|
+
| `worktreeDir` | `PI_SUBAGENT_WORKTREE_DIR` | `~/.pi/subagent-worktrees` |
|
|
269
|
+
| `lockDir` | `PI_SUBAGENT_LOCK_DIR` | `~/.pi/subagent-locks` |
|
|
270
|
+
| `worktreeRetentionDays` | `PI_SUBAGENT_WORKTREE_RETENTION_DAYS` | unused (lifecycle GC) |
|
|
271
|
+
| `sessionRetentionDays` | `PI_SUBAGENT_SESSION_RETENTION_DAYS` | unused (lifecycle GC) |
|
|
272
|
+
| `lockRetentionDays` | `PI_SUBAGENT_LOCK_RETENTION_DAYS` | 7 |
|
|
273
|
+
| `taskDefaults` | - | none |
|
|
274
|
+
| `jevRouting` | - | required for new dispatch (see below) |
|
|
275
|
+
| `graceTurns` | `PI_SUBAGENT_GRACE_TURNS` | 2 |
|
|
276
|
+
| `stallAfterMs` | `PI_SUBAGENT_STALL_AFTER_MS` | 90000 |
|
|
277
|
+
| `stallKillAfterMs` | `PI_SUBAGENT_STALL_KILL_AFTER_MS` | 90000 |
|
|
278
|
+
| `maxRetries` | `PI_SUBAGENT_MAX_RETRIES` | 1 |
|
|
279
|
+
| `widget` | `PI_SUBAGENT_WIDGET` | `background` (`off` disables) |
|
|
280
|
+
| `notifications` | `PI_SUBAGENT_NOTIFICATIONS` | `batched` (`off` disables) |
|
|
281
|
+
| (bin) | `PI_SUBAGENT_BIN` | auto (`process.execPath` + CLI entry) |
|
|
282
|
+
|
|
283
|
+
#### Jev routing
|
|
284
|
+
|
|
285
|
+
New subagent dispatches are selected by Jev, TypeSafe's structured-decision API, against a dedicated candidate list you maintain in `~/.pi/subagent.json`. Fixed routing is gone: a `modelPolicy` block produces a migration error, and an explicit `model` or `fallback_models` on new work is rejected rather than bypassing selection. Management actions (`status`, `wait`, `cancel`, `steer`, `diff`, `apply`, `discard`) never call the selector and need no credential.
|
|
286
|
+
|
|
287
|
+
```json
|
|
288
|
+
{
|
|
289
|
+
"jevRouting": {
|
|
290
|
+
"selectorModel": "jev-latest",
|
|
291
|
+
"apiKey": "<your-typesafe-api-key>",
|
|
292
|
+
"timeoutMs": 15000,
|
|
293
|
+
"models": [
|
|
294
|
+
{
|
|
295
|
+
"model": "<provider/model-id>",
|
|
296
|
+
"description": "<your characteristics notes, Chinese allowed>"
|
|
297
|
+
}
|
|
298
|
+
]
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
- `selectorModel` defaults to the stable alias `jev-latest`. Pin an exact version to control which selector version is requested. This does not guarantee deterministic choices; the extension records the version that actually answered.
|
|
304
|
+
- `apiKey` is required and has no default. It must be a non-blank string; surrounding whitespace is trimmed and embedded whitespace/control characters are rejected. Store it only in the private config file. The transport uses it for the Authorization header and does not copy it into prompts, selector JSON bodies, argv, logs, receipts or results. `apiKeyEnv` is rejected with migration guidance; environment variables cannot supply or override the key.
|
|
305
|
+
- `timeoutMs` defaults to 15000 and must be an integer between 100 and 600000. It bounds one logical task selection, including all its HTTP requests and queue waits. Parallel workers each have a selection allowance, still capped by their absolute task `timeout_ms` deadline. Deferred synthesis has a separate allowance.
|
|
306
|
+
- `models` holds 1 to 255 entries, each with an exact `provider/model-id` and a non-blank description. Those descriptions are what Jev matches against your task, so write them the way you would explain the model to a colleague. `thinking` is optional.
|
|
307
|
+
|
|
308
|
+
Plan and background-start native usage attachments are limited to 1024 selector HTTP receipts per invocation. Larger requests fail with a request-splitting error; background work has not started at that point. Previously incurred selector tokens remain in the ledger. This bounds an atomic delivery record, not the number of tools Jev may consider within each task.
|
|
309
|
+
|
|
310
|
+
The candidate list is intersected with the models the local Pi registry reports as available. A configured model Pi cannot resolve is not eligible, and an empty eligible pool fails before any request. Adding a model anywhere else in Pi does not authorize it, and legacy `modelPolicy` entries are never imported automatically. An unknown `jevRouting` field is an error, not a silent default.
|
|
311
|
+
|
|
312
|
+
Jev receives only the current delegated task text, your model IDs and descriptions, candidate tool names and descriptions, and the permission/output requirements it needs to choose. It does not receive repository files, conversation history, full system prompts, persona text or tool parameter schemas. Task text and descriptions are user content and may contain sensitive material, so treat what you delegate as disclosure to TypeSafe.
|
|
313
|
+
|
|
314
|
+
Every new extension-managed dispatch routes through Jev: `task`/`tasks[]`, `action:"plan"`, `/btw`, resume, fork, locally permitted nested dispatch and the optional `synthesis` child. `action:"plan"` calls Jev and runs the same local preflights, returns the resolved model/tool plan and the selector usage, and creates no child or run entry. A later dispatch selects again; there is no cached decision to reuse. If optional synthesis selection fails, the worker plan and its usage stay valid and synthesis is reported as blocked with its diagnostic.
|
|
315
|
+
|
|
316
|
+
`thinking` is optional and is an opaque Pi thinking-level string. Common values include `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, and `max`, but the package does not remap or restrict model-specific values. Pi receives the value unchanged and decides whether the active model supports it. Resolution order is: explicit task `thinking` > agent frontmatter `thinking` > profile `taskDefaults.<profile>.thinking` > the selected candidate's optional `thinking` > the parent session's thinking level. Jev never chooses a thinking level.
|
|
317
|
+
|
|
318
|
+
The extension re-reads `jevRouting` on each dispatch and injects non-secret routing guidance into the parent prompt, never the key. Configuration edits reach the next decision without a code change. Missing or invalid `jevRouting.apiKey`, or other invalid routing configuration, rejects new dispatch and plan with a remedy; management stays available.
|
|
319
|
+
|
|
320
|
+
The mandatory routing above is the Extension dispatch contract. The stable SDK exports (`runTasks` and `runSubagent`) are trusted low-level library APIs: they execute the explicit `TaskSpec` you pass and perform no implicit routing, config discovery or network call. Library callers own model and tool choice, and must not read these SDK calls as Jev enforcement.
|
|
321
|
+
|
|
322
|
+
#### Named agent files
|
|
323
|
+
|
|
324
|
+
Define reusable subagent personas as markdown files, discovered from the same conventional roots skills use (higher root wins name conflicts):
|
|
325
|
+
|
|
326
|
+
| Priority | Location | Scope |
|
|
327
|
+
| -------- | ----------------------------------------------------------------------- | --------------------------- |
|
|
328
|
+
| 1 | `.pi/agents/<name>.md` | project (authoritative) |
|
|
329
|
+
| 2 | `.agents/agents/<name>.md` | shared cross-tool workspace |
|
|
330
|
+
| 3 | `$PI_CODING_AGENT_DIR/agents/<name>.md` (default `~/.pi/agent/agents/`) | global |
|
|
331
|
+
|
|
332
|
+
The markdown body becomes the child's appended system prompt; frontmatter supplies defaults using the same snake_case names as the tool parameters:
|
|
333
|
+
|
|
334
|
+
```md
|
|
335
|
+
---
|
|
336
|
+
description: Security-focused code reviewer
|
|
337
|
+
# Legacy model/fallback fields are ignored; Jev routing owns model/tool choice.
|
|
338
|
+
thinking: high
|
|
339
|
+
profile: review
|
|
340
|
+
max_turns: 20
|
|
341
|
+
spawns: false # or "*", "scout", "[reviewer, scout]"
|
|
342
|
+
---
|
|
343
|
+
|
|
344
|
+
You are a security auditor. Review code for injection flaws, auth issues,
|
|
345
|
+
and sensitive data exposure. Report findings with file:line evidence and
|
|
346
|
+
severity ratings.
|
|
347
|
+
|
|
348
|
+
@include shared/review-checklist.md
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
Agent files may also pin a structured contract with `output_schema: {"type": "object", …}` (single-line inline JSON) or `output_schema: @contract.json` (path relative to the agent file).
|
|
352
|
+
|
|
353
|
+
`spawns:` controls which agents a child of this persona may spawn: `false` disables further nesting (no tool registered in that child), `"*"` (or omit) is unrestricted, and a comma/bracket list is an allowlist (agentless tasks are rejected under an allowlist). The policy is passed to the child via `PI_SUBAGENT_SPAWNS` and enforced on each subsequent spawn.
|
|
354
|
+
|
|
355
|
+
Body lines that consist solely of `@include relative/path.md` expand that file one level deep (relative to the agent file, same 64KB/symlink guards as `@contract.json`). Missing or rejected includes leave the line verbatim; includes do not recurse.
|
|
356
|
+
|
|
357
|
+
Invoke with `{ task: "…", agent: "reviewer" }`. The agent file supplies persona, capability, thinking and budget defaults only: model and tool selection stay with Jev routing, and a legacy `model`/`fallback_models` in frontmatter is ignored. An explicit `system_prompt` appends after the persona body. Profiles still enforce capability: `profile: review` filters candidates to read-only tools. Legacy agent `tools` defaults are ignored; an explicit task `tools` list requesting write tools under review fails closed. The agent catalog is advertised in the tool's system-prompt guidelines (session start) and in bare `status` output (live), and file changes are picked up within seconds; no restart needed.
|
|
358
|
+
|
|
359
|
+
#### Per-profile task defaults
|
|
360
|
+
|
|
361
|
+
`taskDefaults` in `~/.pi/subagent.json` remains available for non-model fields such as thinking, budgets, and retry counts. Its legacy `model` and `fallbackModels` fields are ignored; model and tool routing belong only to `jevRouting`. A profile `thinking` value overrides the selected candidate's optional `thinking` default. Invalid fields are dropped field-by-field.
|
|
362
|
+
|
|
363
|
+
Notes on behavior:
|
|
364
|
+
|
|
365
|
+
- `timeout_ms` is the absolute task deadline: local preflight, Jev selection, setup, queue time and runtime all count against it, and selection cannot reset it. Timed-out tasks report `state: "timeout"` with `timeoutPhase: "queued"|"starting"|"running"` so agents can retry capacity issues without confusing them for task failures.
|
|
366
|
+
- Budget stops (`max_turns`, `max_cost`) trigger a **graceful wrap-up**: the child is steered to produce its final answer NOW and allowed `graceTurns` more turns before SIGTERM. Results end as `partial` with `wrappedUp: true` when the child concluded in time. `graceTurns: 0` restores immediate stops.
|
|
367
|
+
- A **stall watchdog** flags children with no protocol activity for `stallAfterMs` (a liveness probe distinguishes quiet-but-thinking from dead), then kills after `stallKillAfterMs` more silence; feeding automatic retry instead of burning the whole timeout.
|
|
368
|
+
- **Transient failures retry automatically** (queue timeouts, stalls, spawn errors, provider errors) up to `maxRetries` extra attempts on the already selected model and tool set. There are no emergency or fallback models, and a quality or budget failure never reselects. Usage accumulates across attempts; results record `attempts`. Task-quality failures (nonzero exit with complete protocol, cancellations, budget stops, running timeouts) never retry.
|
|
369
|
+
- `context: "fork"` starts a single child from a real branched copy of the parent conversation (`--fork` on the parent's session file). It requires a persisted parent session, cannot combine with `resume`, and is rejected for parallel fanout (context duplication × N is a cost bug, not a feature).
|
|
370
|
+
- **Structured output** (`output_schema`): the contract is appended to the child's system prompt; the final message must end with a fenced `json:result` block. Validation runs parent-side against a dependency-free JSON-Schema subset (type/properties/required/items/enum/const; unknown keywords are ignored, never rejected). Invalid output triggers **one steer-based repair round**; still-invalid results end `partial` with `structuredError` set and the raw text delivered; paid work is never discarded. Validated parallel results feed the `synthesis` child as clean JSON instead of prose.
|
|
371
|
+
- **Arg repair**: double-encoded task text (literal `\n` / `\"` escapes from LLM re-encoding) is conservatively de-mangled once at validation time. Identifier fields and paths are never touched. Protocol streams truncated after useful assistant output also end as `partial`.
|
|
372
|
+
- Aborting a `wait` returns immediately without cancelling the background run.
|
|
373
|
+
- Child processes are launched via the same Node runtime + CLI entry as the parent when possible (`PI_SUBAGENT_BIN` overrides). Bare `pi` on PATH is only a logged last resort.
|
|
374
|
+
- Direct resume is exclusive **across processes** via durable locks under `lockDir`. Lost runs block resume until startup orphan reconciliation kills (or confirms dead) the recorded child process group.
|
|
375
|
+
- `maxGlobalActive` bounds concurrent children across every Pi parent process on the machine (in addition to the per-session semaphore).
|
|
376
|
+
- Nested children at the depth ceiling do not re-register the subagent tool; only top-level parents run maintenance/orphan reclaim/worktree GC.
|
|
377
|
+
- Preserved worktrees live under `worktreeDir` (durable, not `/tmp`) and are garbage-collected on startup by **lifecycle**, not wall-clock retention: once a run is over (not live, past a 1h concurrency race guard), the worktree's unique work is archived as one applyable patch under `<repo-container>/_patches/` and the directory is reclaimed immediately. Branches holding commits that exist on no other ref are never deleted. `diff`/`apply`/`discard` transparently fall back to the archived patch when the directory is already gone. Live runs are never swept: the current session's live worktrees plus any worktree recorded on a running run record (concurrent Pi processes) are shielded machine-wide.
|
|
378
|
+
- Startup GC sweeps **every** repo container under `worktreeDir`, not just the current checkout's, so repos you stop visiting are still reclaimed. A container whose base repo no longer exists is kept and reported, never deleted; its worktrees' object stores lived inside the deleted repo, so unique work cannot be distinguished from a pristine checkout, let alone archived. Empty containers (no worktrees, no archived patches) are removed.
|
|
379
|
+
- Child session transcripts are likewise distilled on lifecycle: when a run is over and nothing on the parent branch references its session, the transcript is reduced to a small `.digest.json` (task, final output, model, usage, turn/tool/error counts) and the raw `.jsonl` is deleted. Resume needs the transcript, so anything referenced or busy machine-wide is kept.
|
|
380
|
+
- `keep_background: true` on a task keeps processes the child intentionally backgrounded (e.g. dev servers) alive after a clean exit.
|
|
381
|
+
- `include_wip: true` (with `isolation: "worktree"`) seeds the worktree with the parent checkout's uncommitted changes so the child sees your dirty baseline. `diff`/`apply` subtract that baseline when clean, else report the combined delta with an explicit `[includes parent WIP]` warning.
|
|
382
|
+
|
|
383
|
+
---
|
|
384
|
+
|
|
385
|
+
### Using the runner as a library
|
|
386
|
+
|
|
387
|
+
Import the stable public SDK from the package root or the explicit `/sdk` subpath; do not reach into `src/*` internals (those paths are not part of the supported contract):
|
|
388
|
+
|
|
389
|
+
```ts
|
|
390
|
+
import {
|
|
391
|
+
runTasks,
|
|
392
|
+
runSubagent,
|
|
393
|
+
ChildRunner,
|
|
394
|
+
WorktreeManager,
|
|
395
|
+
Semaphore,
|
|
396
|
+
ProcessLockManager,
|
|
397
|
+
addUsage,
|
|
398
|
+
normalizeUsage,
|
|
399
|
+
emptyUsage,
|
|
400
|
+
type TaskSpec,
|
|
401
|
+
type TaskResult,
|
|
402
|
+
type RunState,
|
|
403
|
+
type UsageStats,
|
|
404
|
+
} from "@cr1ms0n/pi-subagent/sdk";
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
The package root is an alias for the same SDK: `import { runTasks } from "@cr1ms0n/pi-subagent"`.
|
|
408
|
+
|
|
409
|
+
The Extension dispatch path routes every new task through Jev, so callers never pass a model to it. The low-level SDK is the opposite contract: it is explicit-spec and performs no implicit routing, config discovery or network call, so embedding code supplies the model (and tool list) it resolved itself. This placeholder is illustrative only and configures nothing:
|
|
410
|
+
|
|
411
|
+
```ts
|
|
412
|
+
const task: TaskSpec = {
|
|
413
|
+
task: "Audit src/ for unsafe parsing",
|
|
414
|
+
profile: "explore",
|
|
415
|
+
model: "<provider/model-id resolved by your embedding code>",
|
|
416
|
+
timeoutMs: 10 * 60_000,
|
|
417
|
+
};
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
Prefer `runTasks()` for multi-task / worktree orchestration (same path the extension and pi-workflows use). `runSubagent()` runs a single child process directly without the extension host, but durable coordination is **opt-in**. Pass both `locks` (a `ProcessLockManager`) and a stable `runId` if you want global concurrency slots and orphan reclaim to see the child. Without those options no durable run record is written, so a parent restart cannot reclassify the process and nested children vanish from reconcile. There is intentionally no implicit default lock manager; embedding code that needs durability must construct and share one.
|
|
421
|
+
|
|
422
|
+
The Pi extension entry is unchanged: package `pi.extensions` still points at `./extensions/subagent.ts`.
|
|
423
|
+
|
|
424
|
+
---
|
|
425
|
+
|
|
426
|
+
### Cost accounting
|
|
427
|
+
|
|
428
|
+
`status`, `/subagent-cost`, and the `/subagents` overlay header show separate **root**, **subagent**, **routing**, and **combined** totals based on provider-reported usage. On Pi builds after v0.80.10, delivered runs also report their total usage natively on the tool result ([pi#6671](https://github.com/earendil-works/pi/pull/6671)), so Pi's own footer, `/session`, and RPC totals include subagent spend exactly once per run. Older Pi hosts ignore the field. Nested usage reported by a child's tool results (e.g. grandchild subagents) folds into the run's totals and budgets. The extension footer stays terse (running/ready counts only). Delivery and replay do not double count runs. See [docs/COST-ACCOUNTING.md](COST-ACCOUNTING.md).
|
|
429
|
+
|
|
430
|
+
Jev selection is billed separately from execution. TypeSafe reports tokens, not currency, so the ledger shows routing tokens as their own category, counts each selector request once by its request ID (including plan and pre-spawn failures), and marks routing cost as **unreported** rather than free. Numeric dollar totals exclude unreported routing spend, and `max_cost` caps provider-reported execution cost only; it does not cap TypeSafe charges. Route metadata (selected model, selected tools, locally added controls, selector version, confidence, outcome, latency) travels with the run alongside usage.
|
|
431
|
+
|
|
432
|
+
---
|
|
433
|
+
|
|
434
|
+
### Engine contract
|
|
435
|
+
|
|
436
|
+
The [architecture contract](ARCHITECTURE.md) owns the complete lifecycle, persistence, permission and delivery invariants. The [security model](SECURITY.md) explains the limits of tool profiles and worktree isolation. For source layout and checks available in a fresh checkout, see [development](DEVELOPMENT.md).
|
package/docs/RELEASING.md
CHANGED
|
@@ -1,32 +1,151 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
This is an independent community fork of `@parke.dev/pi-subagent
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
1
|
+
# Release and repository maintenance
|
|
2
|
+
|
|
3
|
+
This is an independent community fork of Luke Parke's `@parke.dev/pi-subagent`. Preserve the original [MIT license](../LICENSE), copyright and upstream attribution. Do not publish under the upstream scope. This standalone repository does not inherit the upstream monorepo's tag automation.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
### Choose the scope first
|
|
8
|
+
|
|
9
|
+
A README or repository-presentation update does not require a new npm version, tag, GitHub Release, package installation or binary upload. An edit to a Release body should change only that body. A new package release is a separate operation with artifact verification and explicit publication approval.
|
|
10
|
+
|
|
11
|
+
Read [package.json](../package.json), [CHANGELOG.md](../CHANGELOG.md), the working tree and index before making changes. Record the original local HEAD, remote main and any remote metadata you intend to update. Preserve unrelated modifications and existing commit history by default. A separately approved single-root conversion must follow the history-replacement safeguards below; do not infer that permission from a documentation update or another project’s release rules.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
### Public source-tree boundary
|
|
16
|
+
|
|
17
|
+
Commit production source, the distributed [subagent skill](../skills/subagent/SKILL.md), public documentation and package metadata. Keep local maintainer tooling and private artifacts out of the public tree: `.trellis/`, `.agents/`, `.codex/`, project-local `.pi/` configuration, `AGENTS.md`, `LOCAL-PATCH.md`, Trellis-named support files, credentials, sessions, logs, dependencies, generated bundles and tarballs.
|
|
18
|
+
|
|
19
|
+
The product directory [skills/](../skills/) is not the local `.agents/skills/` directory. Never remove the product skill merely because local workflow skills are excluded. No Actions workflow or contributor guide is required for this manual release process.
|
|
20
|
+
|
|
21
|
+
Do not stage or discard local `.gitignore` edits. Where exclusion rules are maintained in `.git/info/exclude`, preserve its existing content and keep that file local. Ignore rules do not untrack files already in Git. When a reviewed cleanup needs to stop tracking local files, use `git rm --cached -- <explicit paths>` after backing them up and verifying their contents; never delete the working copies to clean the public tree. An ordinary commit does not erase those files from older history.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
### Documentation-only source updates
|
|
26
|
+
|
|
27
|
+
Keep [README.md](../README.md) and [README.zh-CN.md](../README.zh-CN.md) synchronized in the same change. Preserve the language switch, package identity, original copyright and license links. Each README ends with one Linux.do acknowledgement; do not expand it into a community/contact section. Do not add a documentation-index table, contribution guide or stale release-promotion block to the landing page.
|
|
28
|
+
|
|
29
|
+
Run the relevant [development checks](DEVELOPMENT.md), including relative-link and translation review, whitespace checks and the package dry run. A fresh checkout has no bundled test runner or typecheck script; do not claim upstream/private harness commands are available.
|
|
30
|
+
|
|
31
|
+
Stage only explicitly reviewed paths. For example, when both README files are the complete change:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
git add -- README.md README.zh-CN.md
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Inspect the staged names:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
git diff --cached --name-status
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Inspect the actual staged patch:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
git diff --cached
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Create an ordinary commit after reviewing and approving its scope. Do not use broad `git add -A`, `--amend -a`, history squashing or a force push for documentation maintenance.
|
|
50
|
+
|
|
51
|
+
Before an authorized push, re-read remote main and compare it with the value saved at the start. Stop on an unexplained change rather than accepting a new baseline. The local branch can be named differently from remote main; target the reviewed commit deliberately:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
git push origin HEAD:refs/heads/main
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Use a normal fast-forward push for ordinary maintenance. Afterward, confirm local HEAD and remote main match, read back affected files, and verify the intended current tree no longer exposes local-only paths. Update GitHub About fields only when that specific edit was approved, and re-read them afterward. Source push and About edits can succeed separately; report their actual status separately.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
### Explicitly approved history replacement
|
|
62
|
+
|
|
63
|
+
Only replace the main history when the repository owner has explicitly requested that scope. Preserve the original graph in a local-only backup ref and an external Git bundle, verify the bundle in a separate repository, and retain working-file and index backups. Construct a parentless candidate from the reviewed public tree; verify its tree and that its reachable history contains exactly one commit before changing the local branch. Local maintenance files must remain on disk.
|
|
64
|
+
|
|
65
|
+
Before replacing remote main, obtain approval for the exact candidate and original remote SHA. Recheck remote state and use an explicit `--force-with-lease=refs/heads/main:<original-sha>` with only `<candidate-sha>:refs/heads/main`. Stop if the lease fails; never refresh the expected SHA to bypass it. Do not push backup refs, use an unqualified force or alter tags and other branches.
|
|
66
|
+
|
|
67
|
+
Read back the remote commit, parent list and tree after the update. A single-root main history does not erase old objects from GitHub caches, other clones or local backups. It also does not authorize npm publication, installation or About changes.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
### Prepare an npm release
|
|
72
|
+
|
|
73
|
+
Only perform this section for an approved version release:
|
|
74
|
+
|
|
75
|
+
1. Choose an unpublished version and update package metadata and changelog together. Keep README install examples consistent with the intended release.
|
|
76
|
+
2. Run the checks available in the actual environment, as described in [development](DEVELOPMENT.md). A syntax transform is not a semantic typecheck. Record missing tooling and any separately configured typecheck/fixture results. Do not run real provider calls without permission.
|
|
77
|
+
3. Inspect the package dry-run list for unexpected files.
|
|
78
|
+
4. Pack the source, record the tarball's integrity, and test the packed source in an isolated installation where suitable offline verification is available. Do not imply a missing harness was run.
|
|
79
|
+
5. Review the final name, version, tarball, contents and verification results before requesting publication approval.
|
|
80
|
+
|
|
81
|
+
Dry-run contents:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
npm pack --dry-run --ignore-scripts --json
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Create the release artifact only when preparing a release:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
npm pack --ignore-scripts
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Install the reviewed artifact into a separate temporary prefix using `--ignore-scripts --legacy-peer-deps` if installation checks are part of the approved release scope. Never replace the working Pi installation merely to inspect a package.
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
### Publish with verified TLS
|
|
98
|
+
|
|
99
|
+
Use an existing npm login or a securely supplied environment-based credential. Never put tokens in command text, source files, a committed `.npmrc` or diagnostics.
|
|
100
|
+
|
|
101
|
+
If the environment contains `NODE_TLS_REJECT_UNAUTHORIZED=0`, remove that override before any credential-bearing registry operation. `--strict-ssl=true` does not undo a Node-level TLS override.
|
|
102
|
+
|
|
103
|
+
In Bash:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
unset NODE_TLS_REJECT_UNAUTHORIZED
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
In PowerShell:
|
|
110
|
+
|
|
111
|
+
```powershell
|
|
112
|
+
Remove-Item Env:NODE_TLS_REJECT_UNAUTHORIZED -ErrorAction SilentlyContinue
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Check the authenticated account without displaying credentials:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
npm whoami --strict-ssl=true --registry=https://registry.npmjs.org/
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
After explicit approval, publish the reviewed tarball. Replace `<version>` with the approved version:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
npm publish "./cr1ms0n-pi-subagent-<version>.tgz" --access public --ignore-scripts --strict-ssl=true --registry=https://registry.npmjs.org/
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Read the exact version's registry metadata:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
npm view "@cr1ms0n/pi-subagent@<version>" name version dist.integrity --strict-ssl=true --registry=https://registry.npmjs.org/
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Registry propagation can lag. A successful publish is not proof that the exact version is already readable. Verify name/version/integrity against the reviewed local artifact before replacing an installation; do not repeat a publication blindly after an uncertain response. All files in a published tarball become public.
|
|
134
|
+
|
|
135
|
+
GitHub tags, Releases and attachments are separate from npm publication. Do not create or modify them implicitly. If explicitly requested, inspect the existing remote objects, use a tool that actually supports the operation, update only the approved fields/assets, then read back and verify the result.
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
### Install and replace
|
|
140
|
+
|
|
141
|
+
Installation is a separate local change. After artifact verification and approval, replace `<version>` with the verified release:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
pi install "npm:@cr1ms0n/pi-subagent@<version>"
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Back up the old package selection/source and keep it for rollback. Do not enable this fork and `@parke.dev/pi-subagent` simultaneously: both register the same tools. Verify the physical installed package version and files rather than relying only on a command's exit status or the settings entry. Reload or restart Pi after changing packages.
|
|
148
|
+
|
|
149
|
+
This fork uses the same configuration and persisted-state paths as upstream. Switching packages is not a data migration. Do not overwrite model choices or credentials during upgrades. Configure `jevRouting` in `~/.pi/subagent.json` before starting new tasks, as described in the [reference](REFERENCE.md#jev-routing).
|
|
150
|
+
|
|
151
|
+
Report preparation, publication, remote synchronization and local installation as distinct states, including checks that could not be performed.
|
package/docs/ROADMAP.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Roadmap
|
|
2
2
|
|
|
3
|
+
> **Historical upstream roadmap.** Retained for rationale and deferred ideas, not as this fork's current release schedule. Phases 2-4 are recorded as shipped in [the historical execution plan](PLAN.md); their future-tense sketches below do not mean these features are missing. Jev routing supersedes the old model-selection assumptions. Use [the current reference](REFERENCE.md), [architecture contract](ARCHITECTURE.md) and [development checks](DEVELOPMENT.md) for current behavior and available tooling. Historical test claims are not verification results for this checkout.
|
|
4
|
+
|
|
3
5
|
> Execution details for the remaining phases (work breakdown, acceptance
|
|
4
6
|
> criteria, test plans, release gates) live in [PLAN.md](./PLAN.md). This
|
|
5
7
|
> document holds the rationale, design sketches, and deferral decisions.
|