pi-prompt-template-model-enhanced 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/README.md ADDED
@@ -0,0 +1,1004 @@
1
+ <p>
2
+ <img src="banner.png" alt="pi-prompt-template-model-enhanced" width="1100">
3
+ </p>
4
+
5
+ # Prompt Template Model Extension
6
+
7
+ > This package is an enhanced fork of [`pi-prompt-template-model`](https://github.com/nicobailon/pi-prompt-template-model). It builds on the original extension's solid prompt-template foundation, stays close to upstream, and publishes the additional features under the separate package name `pi-prompt-template-model-enhanced`.
8
+
9
+ Adds model selection, thinking levels, reusable prompt partials, and one-or-many skill injection to pi prompt templates. Define slash commands that switch to the right model, include shared instructions, load the exact skills needed, and auto-restore your session when done.
10
+
11
+ ```
12
+ /review src/server.ts
13
+ → switches to Sonnet
14
+ → includes shared repo-review instructions
15
+ → loads tmux + TypeScript skills
16
+ → restores your previous model when finished
17
+ ```
18
+
19
+ ## Why?
20
+
21
+ Each prompt template becomes a self-contained agent mode. `/quick-debug` spins up a cheap model with REPL skills. `/deep-analysis` brings in extended thinking with refactoring expertise. `/review` can include the same shared repo rules every time without copying them into every template. When the command finishes, you're back to your daily driver without touching anything.
22
+
23
+ No more manually switching models, copying standard instructions between prompts, or hoping the agent picks up the right skills. You define the configuration once, and the slash command handles the rest.
24
+
25
+ ## What this adds
26
+
27
+ - **Model routing**: choose one model, an explicit provider/model pair, or a fallback list.
28
+ - **Thinking control**: set per-command thinking levels.
29
+ - **Prompt includes**: reuse shared Markdown partials with `includes`, `include`, `<includes />`, and inline `<include file="..." />` directives.
30
+ - **Multiple skills**: inject one skill with `skill`, many skills with `skills`, or constrained wildcard groups like `golang-*`.
31
+ - **Execution control**: loops, model rotation, fresh context, boomerang collapse, delegated subagents, chains, and best-of-N compare prompts.
32
+
33
+ ## Installation
34
+
35
+ ```bash
36
+ pi install npm:pi-prompt-template-model-enhanced
37
+ ```
38
+
39
+ Restart pi to load the extension.
40
+
41
+ For delegated subagent execution (`subagent` and `inheritContext` frontmatter), install [pi-subagents](https://github.com/nicobailon/pi-subagents/) separately:
42
+
43
+ ```bash
44
+ pi install npm:pi-subagents
45
+ ```
46
+
47
+ pi-subagents is optional — everything else works without it. Using `subagent: true` without it installed fails fast with a clear error.
48
+
49
+ ## Quick Start
50
+
51
+ Add `model`, optional `includes`, and optional `skill` / `skills` to any prompt template:
52
+
53
+ ```markdown
54
+ ---
55
+ description: Review TypeScript with shared repo rules
56
+ model: claude-sonnet-4-20250514
57
+ includes:
58
+ - shared/repo-rules.md
59
+ - shared/review-checklist.md
60
+ skills:
61
+ - tmux
62
+ - typescript-*
63
+ ---
64
+ Review this change: $@
65
+ ```
66
+
67
+ Run `/review src/server.ts` and the agent switches to Sonnet, prepends the shared partials, injects the requested skills, and starts working. When it finishes, your previous model is restored.
68
+
69
+ For a smaller prompt, the old single-skill form still works:
70
+
71
+ ```markdown
72
+ ---
73
+ description: Debug Python in tmux REPL
74
+ model: claude-sonnet-4-20250514
75
+ skill: tmux
76
+ ---
77
+ Start a Python REPL session and help me debug: $@
78
+ ```
79
+
80
+ ## Frontmatter Reference
81
+
82
+ All fields are optional. Templates that don't use any extension features (no `model`, `skill`, `skills`, `include`, `includes`, `thinking`, etc.) are left to pi's default prompt loader.
83
+
84
+ ### Core Fields
85
+
86
+ | Field | Default | What it does |
87
+ |-------|---------|--------------|
88
+ | `model` | current session model | Which model to use. Accepts a single model, a `provider/model-id` pair, or a comma-separated fallback list (see [Model Format](#model-format)). Ignored when `chain` is set. |
89
+ | `skill` | — | Injects a skill, or a constrained suffix-`*` wildcard selector such as `golang-*`, as context before the agent handles your task. Kept for backward compatibility and simple prompts. See [Skills](#skills). |
90
+ | `skills` | — | List of skills to inject, with optional suffix-`*` wildcard selectors such as `golang-*`. See [Skills](#skills). |
91
+ | `thinking` | — | Thinking level for the model: `off`, `minimal`, `low`, `medium`, `high`, or `xhigh`. |
92
+ | `includes` | — | List of shared `.md` partials to insert into the prompt. See [Prompt includes](#prompt-includes). |
93
+ | `include` | — | Shortcut for a single partial, equivalent to `includes: [file.md]`. See [Prompt includes](#prompt-includes). |
94
+ | `description` | — | Short text shown next to the command in autocomplete. |
95
+ | `chain` | — | Declares a reusable pipeline of templates (`step -> step`). When set, the body is ignored. See [Chain Templates](#chain-templates). |
96
+ | `chainContext` | — | Chain templates only. Set to `summary` so delegated steps receive a compact summary of what previous steps did. Steps with `inheritContext: true` are excluded. See [Chain context for delegated steps](#chain-context-for-delegated-steps). |
97
+
98
+ ### Execution Control
99
+
100
+ | Field | Default | What it does |
101
+ |-------|---------|--------------|
102
+ | `restore` | `true` | After the command finishes, switch back to whatever model and thinking level were active before. Set `false` to stay on the new model. |
103
+ | `loop` | — | Run this template multiple times by default (1–999, `true`, or `unlimited`). CLI `--loop` overrides this. See [Loop Execution](#loop-execution). |
104
+ | `rotate` | `false` | When `true` and looping, cycle through models in the `model` list instead of using fallback semantics. Thinking levels can also be comma-separated to pair with each model. |
105
+ | `fresh` | `false` | When looping, collapse the conversation between iterations to a brief summary instead of carrying the full context forward. Saves tokens on long loops. |
106
+ | `converge` | `true` | When looping, stop early if an iteration makes no file changes. Set `false` to always run every iteration. |
107
+ | `boomerang` | `false` | After a non-chain prompt finishes, collapse its execution context back to the branch point with a brief summary. Works with loops, including `fresh` loop summaries. Useful for review prompts like `/double-check`. |
108
+ | `worktree` | `false` | When `true`, parallel delegated work runs in separate git worktrees. Valid on chain templates with `parallel()` steps, on delegated prompts with `parallel: N`, and on compare templates via `bestOfN.worktree`. |
109
+
110
+ ### Delegation
111
+
112
+ | Field | Default | What it does |
113
+ |-------|---------|--------------|
114
+ | `subagent` | — | Delegate execution to a subagent instead of running in the current session. `true` uses the default `delegate` agent; a string value like `reviewer` targets that specific agent. Requires [pi-subagents](https://github.com/nicobailon/pi-subagents/). |
115
+ | `inheritContext` | `false` | Only meaningful with `subagent`. When `true`, the subagent receives a fork of the current conversation context instead of starting fresh. |
116
+ | `parallel` | — | Delegated prompts only. Repeats the same subagent in parallel `N` times. Each copy gets a slot header like `[Parallel subagent 2/3]` prepended to the task. Must be an integer greater than or equal to 2. |
117
+ | `bestOfN` | — | Compare templates only. Nested compare authoring block with `workers`, `reviewers`, optional `finalApplier`, and optional `worktree`. Top-level compare fields are not supported in templates. |
118
+ | `bestOfN.workers` | — | Ordered worker lineup used for the worker phase. Each slot object supports optional `agent`/`subagent`, optional `model`, optional `task`, optional `taskSuffix`, optional `cwd`, and optional `count`. If both `agent` and `subagent` are omitted, the default agent is `delegate`. |
119
+ | `bestOfN.reviewers` | — | Ordered reviewer lineup used after worker aggregation. Slot shape matches workers. If both `agent` and `subagent` are omitted, the default agent is `reviewer`. |
120
+ | `bestOfN.finalApplier` | — | Optional single-slot final apply phase that edits the real branch after reviewers. Supports optional `agent`/`subagent`, optional `model`, optional `task`, and optional `taskSuffix`. If both `agent` and `subagent` are omitted, the default agent is `delegate`. `count` and `cwd` are not supported. Requires `bestOfN.worktree: true` at runtime. |
121
+ | `cwd` | — | Working directory for delegated subagent subprocesses. Must be an absolute path (`~/...` is expanded). Valid with `subagent`, on chain templates as the default cwd for delegated steps, and on compare prompts as the default repo cwd. Worker/reviewer slots can also set their own `cwd` inside `bestOfN.workers` / `bestOfN.reviewers`. |
122
+
123
+ ## Model Format
124
+
125
+ ```yaml
126
+ model: claude-sonnet-4-20250514 # bare model ID — auto-selects provider
127
+ model: anthropic/claude-sonnet-4-20250514 # explicit provider/model
128
+ ```
129
+
130
+ Bare model IDs resolve through a provider priority list: `openai-codex` → `anthropic` → `github-copilot` → `openrouter`. The first provider with valid auth wins.
131
+
132
+ For explicit control:
133
+
134
+ ```yaml
135
+ model: anthropic/claude-opus-4-5 # Direct Anthropic API
136
+ model: openai-codex/gpt-5.2 # Via Codex subscription (OAuth)
137
+ model: github-copilot/claude-opus-4-5 # Via Copilot subscription
138
+ model: openrouter/claude-opus-4-5 # Via OpenRouter
139
+ model: openai/gpt-5.2 # Direct OpenAI API
140
+ ```
141
+
142
+ ### Model Fallback
143
+
144
+ Comma-separated lists try each model in order:
145
+
146
+ ```yaml
147
+ model: claude-haiku-4-5, claude-sonnet-4-20250514
148
+ ```
149
+
150
+ Haiku is tried first. If it can't be found or has no API key, Sonnet is used instead. If the session is already on one of the listed models, that one is kept without switching. When every candidate fails, you get a single error listing what was tried.
151
+
152
+ You can mix bare IDs and explicit provider specs:
153
+
154
+ ```yaml
155
+ model: anthropic/claude-haiku-4-5, openrouter/claude-haiku-4-5, claude-sonnet-4-20250514
156
+ ```
157
+
158
+ ## Skills
159
+
160
+ Normally, pi lists available skills in the system prompt, the agent reads your task, decides which skill it needs, and loads it with the read tool. That's an extra round-trip, and the agent might not pick the right one.
161
+
162
+ The `skill` field bypasses all of that and remains fully backward compatible:
163
+
164
+ ```markdown
165
+ ---
166
+ description: Browser testing mode
167
+ model: claude-sonnet-4-20250514
168
+ skill: surf
169
+ ---
170
+ $@
171
+ ```
172
+
173
+ The skill content is injected as a context message before the agent processes your task. No decision-making, no tool call — immediate expertise. If a requested skill can't be found or read, the command fails fast instead of running without it.
174
+
175
+ To load multiple skills, use `skills:` as a YAML list:
176
+
177
+ ```markdown
178
+ ---
179
+ description: Go review mode
180
+ model: claude-sonnet-4-20250514
181
+ skills:
182
+ - tmux
183
+ - golang-style
184
+ - golang-tests
185
+ ---
186
+ Review this change: $@
187
+ ```
188
+
189
+ Scalar `skills` values are invalid. Use `skill: tmux` for one skill, not `skills: tmux`. A prompt with invalid `skills` frontmatter is skipped with a diagnostic rather than registered without its requested context.
190
+
191
+ You can combine `skill` and `skills` during migration or composition. The singular `skill` is loaded first, followed by the list entries:
192
+
193
+ ```yaml
194
+ skill: tmux
195
+ skills:
196
+ - golang-style
197
+ - golang-tests
198
+ # loads: tmux, golang-style, golang-tests
199
+ ```
200
+
201
+ After wildcard expansion, duplicate skill names are removed from the final load list; the first requested occurrence wins. For example, `skills: [golang-style, golang-*]` injects `golang-style` only once even if the wildcard also matches it.
202
+
203
+ Skills are resolved and validated before any deterministic script runs, before model switching, and before the user prompt is sent. That means invalid skill configuration aborts before potentially side-effectful deterministic steps execute.
204
+
205
+ ### Skill Resolution
206
+
207
+ Skill names accept a bare name or a `skill:` prefix:
208
+
209
+ ```yaml
210
+ skill: tmux
211
+ skill: skill:tmux # equivalent
212
+ ```
213
+
214
+ The same normalization applies inside `skills:` entries, including wildcard selectors: `skill:golang-*` is equivalent to `golang-*`.
215
+
216
+ Resolution order:
217
+
218
+ 1. Registered skill commands from `pi.getCommands()` (source: `"skill"`)
219
+ 2. `<cwd>/.pi/skills/<name>/SKILL.md` or `<cwd>/.pi/skills/<name>.md`
220
+ 3. `.agents/skills` in the current directory and ancestors (up to the git root, or the filesystem root if no git root is found)
221
+ 4. `~/.pi/agent/skills/<name>/SKILL.md` or `~/.pi/agent/skills/<name>.md`
222
+ 5. `~/.agents/skills/<name>/SKILL.md` or `~/.agents/skills/<name>.md`
223
+
224
+ ### Skill wildcards
225
+
226
+ `skill` and `skills:` entries may use one constrained wildcard form: a non-empty prefix followed by a final `*`. This means `skill: golang-*` is valid too; it can inject more than one matching skill while preserving the same ordering and de-dupe rules.
227
+
228
+ ```yaml
229
+ skills:
230
+ - golang-*
231
+ - repo-review
232
+ ```
233
+
234
+ This is prefix matching, not general globbing. `golang-*` is valid; `*`, `go**`, `go*lang`, `go?*`, path-like selectors, and selectors containing whitespace or XML/quote characters are rejected.
235
+
236
+ Wildcard expansion searches the same skill sources as exact skill resolution, in the same source order. Within each source, matches are sorted lexically by normalized skill name. If the same normalized name appears in more than one source, the first source wins. If a wildcard matches nothing, prompt execution aborts with an error such as `No skills matched "golang-*"`.
237
+
238
+ Wildcard discovery is bounded to direct skill entries only: direct `name.md` files and direct `name/SKILL.md` directories. It does not recursively scan nested directories.
239
+
240
+ Skill-to-skill references are not recursive in v1. Loaded skills are treated as Markdown content only; if a skill mentions another skill in prose, frontmatter, `related_skills`, or other metadata, that other skill is not loaded automatically. Add every required skill to the prompt's `skill`/`skills` frontmatter explicitly.
241
+
242
+ ### Skills with chains and subagents
243
+
244
+ `skill` and `skills` apply to direct prompt execution.
245
+
246
+ Chain wrapper templates ignore `skill` and `skills`; put skill frontmatter on the step templates instead. When a chain runs a step, that step uses its own skill configuration.
247
+
248
+ Delegated prompts cannot combine `subagent:` with `skill` or `skills` in v1. Such prompts are rejected at registration time. Runtime delegation overrides such as `--subagent` and `--fork` also reject prompts or chain steps that declare skills, so they do not silently run without requested skill context.
249
+
250
+ Compare prompts (`bestOfN`) cannot combine with `skill` or `skills` in v1 because compare execution delegates worker/reviewer/final-applier tasks. Add required skill instructions to the compare prompt body instead.
251
+
252
+ ## Prompt includes
253
+
254
+ Prompt includes let you write the common parts of your prompts once and reuse them. Put shared Markdown in partials, then pull those partials into any prompt that needs them.
255
+
256
+ ### Syntax
257
+
258
+ Use `includes:` for the shared block you want at the top of a prompt:
259
+
260
+ ```markdown
261
+ ---
262
+ description: Review with shared repo rules
263
+ model: claude-sonnet-4-20250514
264
+ includes:
265
+ - shared/repo-rules.md
266
+ - shared/review-checklist.md
267
+ ---
268
+ Review this change: $@
269
+ ```
270
+
271
+ If the body has no `<includes />` marker, Pi prepends the rendered partials:
272
+
273
+ ```markdown
274
+ <rendered shared/repo-rules.md>
275
+
276
+ <rendered shared/review-checklist.md>
277
+
278
+ Review this change: $@
279
+ ```
280
+
281
+ Add `<includes />` when the shared block belongs somewhere else:
282
+
283
+ ```markdown
284
+ ---
285
+ model: claude-sonnet-4-20250514
286
+ includes:
287
+ - shared/context.md
288
+ - shared/checklist.md
289
+ ---
290
+ Start with the project-specific context.
291
+
292
+ <includes />
293
+
294
+ Now answer the user's request: $@
295
+ ```
296
+
297
+ For one partial, `include:` is shorter:
298
+
299
+ ```markdown
300
+ ---
301
+ model: claude-sonnet-4-20250514
302
+ include: shared/repo-rules.md
303
+ ---
304
+ Apply the shared rules above, then inspect: $@
305
+ ```
306
+
307
+ Use an inline include when the partial belongs at an exact spot in the prompt:
308
+
309
+ ```markdown
310
+ ---
311
+ model: claude-sonnet-4-20250514
312
+ includes:
313
+ - shared/repo-rules.md
314
+ ---
315
+ <includes />
316
+
317
+ Focus area:
318
+ <include file="languages/typescript.md" />
319
+
320
+ Task: $@
321
+ ```
322
+
323
+ Partials can include other partials with the same inline syntax.
324
+
325
+ ### Partial roots and resolution order
326
+
327
+ Include paths are local `.md` files. Resolution starts next to the file that asked for the include. For frontmatter `include` / `includes` and inline includes in the prompt body, that means the prompt file. For nested inline includes, it means the current partial.
328
+
329
+ If Pi does not find the file there, it checks these roots in order:
330
+
331
+ 1. The directory of the file containing the directive
332
+ 2. The owning prompt root: `~/.pi/agent/prompts` for user prompts, or `<cwd>/.pi/prompts` for project prompts
333
+ 3. `~/.pi/agent/prompt-partials`
334
+ 4. `<cwd>/.pi/prompt-partials`
335
+
336
+ Example layout:
337
+
338
+ ```text
339
+ ~/.pi/agent/prompts/review.md
340
+ ~/.pi/agent/prompts/shared/repo-rules.md
341
+ ~/.pi/agent/prompt-partials/shared/review-checklist.md
342
+ <cwd>/.pi/prompt-partials/languages/typescript.md
343
+ ```
344
+
345
+ With that layout, `review.md` can include `shared/repo-rules.md`, `shared/review-checklist.md`, and `languages/typescript.md` without absolute paths.
346
+
347
+ ### Rules and guardrails
348
+
349
+ - Partials must be Markdown files (`.md`).
350
+ - Includes are local files. URLs and globs are rejected, even if a local file happens to have that name.
351
+ - Nested includes work. Cycles do not: Pi skips the command and reports a diagnostic.
352
+ - Include expansion stops after 64 nested levels. If a chain goes deeper, Pi skips the command and points the diagnostic at the partial with the include that crossed the limit.
353
+ - Partial frontmatter is stripped and ignored. Put active `include` / `includes` metadata on prompt templates, not inside partials. For nesting, use `<include file="..." />` in the partial body.
354
+ - Missing or invalid includes skip command registration. Broken slash commands should fail loudly, not register half-rendered prompts.
355
+ - `chain:` wrapper templates cannot use frontmatter `include` or `includes` in v1. Put includes on the step templates instead.
356
+ - `~/...` paths are allowed only when they resolve under a Pi prompt root or prompt-partials root. Other absolute paths are rejected.
357
+ - Include boundary comments appear only in debug/diagnostic mode. Normal prompt content does not contain `<!-- BEGIN include ... -->` / `<!-- END include ... -->` comments.
358
+
359
+ ## Inline Model Conditionals
360
+
361
+ Prompt bodies can include sections that only render for specific models:
362
+
363
+ ```markdown
364
+ ---
365
+ description: Cross-model code review
366
+ model: claude-haiku-4-5, claude-sonnet-4-20250514
367
+ ---
368
+ Summarize the change first.
369
+
370
+ <if-model is="claude-haiku-4-5">
371
+ Keep the answer brief and cost-conscious.
372
+ <else>
373
+ Do a deeper pass and call out subtle risks.
374
+ </if-model>
375
+ ```
376
+
377
+ Conditionals evaluate against whichever model actually runs — after fallback resolution for multi-model templates, or against the session model when `model` is omitted.
378
+
379
+ The `is` attribute supports exact model IDs, `provider/model-id` pairs, provider wildcards like `anthropic/*`, and comma-separated combinations:
380
+
381
+ ```markdown
382
+ <if-model is="anthropic/*">Anthropic-specific instructions</if-model>
383
+ <if-model is="openai/gpt-5.2, anthropic/*">Either OpenAI or Anthropic</if-model>
384
+ ```
385
+
386
+ `<else>` is the fallback branch. Nested `<if-model>` blocks work.
387
+
388
+ ## Argument Substitution
389
+
390
+ Prompt bodies support placeholders that expand to the arguments passed after the command name:
391
+
392
+ | Placeholder | Expands to |
393
+ |-------------|------------|
394
+ | `$1`, `$2`, ... | The Nth argument (1-indexed) |
395
+ | `$@` or `@$` or `$ARGUMENTS` | All arguments joined with spaces |
396
+ | `${@:N}` | All arguments from position N onward |
397
+ | `${@:N:L}` | L arguments starting from position N |
398
+
399
+ ```markdown
400
+ ---
401
+ model: claude-sonnet-4-20250514
402
+ ---
403
+ Analyze $1 focusing on $2. Additional context: ${@:3}
404
+ ```
405
+
406
+ `/analyze src/main.ts performance edge cases error handling` expands `$1` to `src/main.ts`, `$2` to `performance`, and `${@:3}` to `edge cases error handling`.
407
+
408
+ ## Delegated Subagent Execution
409
+
410
+ Instead of running a prompt in the current session, you can hand it off to a subagent:
411
+
412
+ ```markdown
413
+ ---
414
+ model: anthropic/claude-sonnet-4-20250514
415
+ subagent: true
416
+ ---
417
+ Review and simplify this code: $@
418
+ ```
419
+
420
+ `subagent: true` delegates to the default `delegate` agent. To target a specific agent:
421
+
422
+ ```markdown
423
+ ---
424
+ model: anthropic/claude-sonnet-4-20250514
425
+ subagent: reviewer
426
+ inheritContext: true
427
+ ---
428
+ Audit this diff for correctness and edge cases: $@
429
+ ```
430
+
431
+ `inheritContext: true` forks the current conversation so the subagent has full context. Without it, the subagent starts fresh.
432
+
433
+ To force a subagent into a specific working directory, add `cwd`:
434
+
435
+ ```markdown
436
+ ---
437
+ model: claude-sonnet-4-20250514
438
+ subagent: browser-screenshoter
439
+ cwd: /tmp/screenshots
440
+ ---
441
+ Use url in the prompt to take screenshot: $@
442
+ ```
443
+
444
+ The subagent process runs with `/tmp/screenshots` as its working directory. Paths must be absolute (`~/...` is expanded). The directory is validated at execution time.
445
+
446
+ To fan the same delegated prompt out to multiple copies in parallel, add `parallel: N`:
447
+
448
+ ```markdown
449
+ ---
450
+ model: anthropic/claude-sonnet-4-20250514
451
+ subagent: simplifier
452
+ inheritContext: true
453
+ parallel: 3
454
+ worktree: true
455
+ ---
456
+ Review changed code and fix any issues found.
457
+ ```
458
+
459
+ This expands to three parallel `pi-subagents` tasks targeting the same agent. Each one receives the same rendered prompt plus an automatic slot header like `[Parallel subagent 1/3]`, `[Parallel subagent 2/3]`, and `[Parallel subagent 3/3]` so the body can assign different roles to each copy. `worktree: true` is optional here and gives each parallel run its own git worktree.
460
+
461
+ During execution, a live progress widget appears above the editor showing elapsed time, tool count, token usage, and the current tool. When the run finishes, it's replaced by a completion card with the task preview, tool call history, output, and usage stats.
462
+
463
+ You can override delegation at runtime per invocation with `--subagent`, `--subagent=<name>`, `--subagent:<name>`, or `--cwd=<path>`. `--cwd=<path>` must be absolute after optional `~/...` expansion. Runtime flags take precedence for that invocation only.
464
+
465
+ Two additional runtime flags work for any prompt (not just delegated ones):
466
+
467
+ - `--model=provider/model-id` — override the template's `model` for this invocation. Works with single execution, loops, and delegation.
468
+ - `--fork` — run with `inheritContext` (forked context). Implies `--subagent` if not already set.
469
+
470
+ ```
471
+ /double-check --model=anthropic/claude-opus-4-6
472
+ /double-check --fork --subagent:worker
473
+ /deslop --model=openai/gpt-5.4 --loop 3
474
+ ```
475
+
476
+ Compare templates also accept runtime lineup overrides:
477
+
478
+ Prompt-template frontmatter authoring uses `bestOfN:`. Runtime overrides stay on the low-level flags below.
479
+
480
+ - `--workers=<json-array>` / `--reviewers=<json-array>` replace the corresponding frontmatter lineup.
481
+ - `--workers-append=<json-array>` / `--reviewers-append=<json-array>` append to the corresponding lineup.
482
+ - `--final-applier=<json-object-or-one-element-array>` replaces the optional final apply slot.
483
+
484
+ Each worker/reviewer JSON array entry must be an object with either `subagent` or `agent`, plus optional `model`, `task`, `taskSuffix`, `cwd`, and `count`. In worker slots, `"subagent": true` maps to `delegate`. In reviewer slots, `"subagent": true` maps to `reviewer`. `--final-applier=` accepts one slot object (or a one-element array) with `subagent`/`agent`, optional `model`, optional `task`, and optional `taskSuffix`; for this final slot, `"subagent": true` maps to `delegate`, and both `count` and `cwd` are not supported.
485
+
486
+ ## Best-of-N Compare Prompt
487
+
488
+ This repo ships one example compare prompt under `examples/`:
489
+
490
+ - `examples/best-of-n.md` installs as `/best-of-n`, runs in the current repo, and shows mixed workers, mixed reviewers, and an optional final apply phase.
491
+ - Smoke test: `/best-of-n smoke test`.
492
+
493
+ Install it manually from this repo checkout (or from the installed package directory):
494
+
495
+ ```bash
496
+ PTM_DIR=/path/to/pi-prompt-template-model-enhanced
497
+ mkdir -p ~/.pi/agent/prompts
498
+ cp "$PTM_DIR/examples/best-of-n.md" ~/.pi/agent/prompts/best-of-n.md
499
+ ```
500
+
501
+ After copying the file, restart `pi` if it is already running. The prompt then runs an explicit compare flow:
502
+
503
+ Compare prompt templates are authored under `bestOfN:`. Top-level `workers`, `reviewers`, and `finalApplier` frontmatter fields are rejected with migration diagnostics.
504
+
505
+ 1. Worker phase: run the worker lineup in parallel (`context: fork`) so workers generate candidate implementations in temporary worktrees.
506
+ 2. Continue as long as at least one worker succeeds. Reviewer slots receive successful worker outputs plus worker/worktree summaries and produce findings only.
507
+ 3. Optional final apply phase: if `finalApplier` is configured, run one delegated apply step on the real compare repo (`compareCwd`) to pick a winner or synthesize/cherry-pick and apply the final patch.
508
+ 4. If all reviewers fail but `finalApplier` exists, the final apply step still runs with fallback context from workers plus reviewer failure summaries.
509
+
510
+ Worker/reviewer lineups are fully configurable from `bestOfN` frontmatter or runtime overrides, so there is no fixed three-model worker assumption. If a compare prompt omits `bestOfN.workers`, it falls back to one `delegate` worker using the current/main model. If it omits `bestOfN.reviewers`, it falls back to one `reviewer` slot. `bestOfN.finalApplier` is optional, and compare runs reject an effective final applier unless `bestOfN.worktree: true` is set.
511
+
512
+ For same-model best-of-N, use `count: N` on one worker slot:
513
+
514
+ ```yaml
515
+ bestOfN:
516
+ workers:
517
+ - model: openai-codex/gpt-5.4:low
518
+ count: 4
519
+ ```
520
+
521
+ You can also mix models and give each slot its own count:
522
+
523
+ ```yaml
524
+ bestOfN:
525
+ workers:
526
+ - model: openai-codex/gpt-5.4:low
527
+ count: 3
528
+ - model: google/gemini-2.5-pro:medium
529
+ count: 2
530
+ - model: anthropic/claude-sonnet-4-20250514:high
531
+ ```
532
+
533
+ Reviewer slots support the same lineup shape, and `bestOfN.finalApplier` is one optional single-slot final apply step:
534
+
535
+ ```yaml
536
+ bestOfN:
537
+ reviewers:
538
+ - model: openai-codex/gpt-5.4:low
539
+ count: 2
540
+ - model: google/gemini-2.5-pro:medium
541
+ taskSuffix: Focus on regression risk.
542
+ finalApplier:
543
+ model: anthropic/claude-sonnet-4-20250514:high
544
+ taskSuffix: Apply the final patch on the current branch and report verification.
545
+ ```
546
+
547
+ Within compare lineups, omitting both `agent` and `subagent` uses phase defaults: `delegate` in workers, `reviewer` in reviewers, and `delegate` in finalApplier. You can still set explicit `agent` or `subagent` when needed.
548
+
549
+ Explicitly repeating the same slot still works, but `count: N` is the cleaner shorthand when the slot is identical.
550
+
551
+ Within a compare lineup, use `task` for a full per-slot override and `taskSuffix` for a small per-slot append. `taskSuffix` is added after the shared worker task (or after the slot's `task` if you set one), which makes it the better fit for things like per-model output file names.
552
+
553
+ When a compare prompt uses `bestOfN.worktree: true`, all worker slots must resolve to the same `cwd`. Mixed worker `cwd` values are only allowed when worktree isolation is off. Worktree isolation is for the worker phase only; `bestOfN.finalApplier` always applies on the real branch (`compareCwd`).
554
+
555
+ ## Deterministic Steps
556
+
557
+ Prompt templates can run one deterministic command or script before any optional LLM turn. Use this when the first step should be direct code, not model latency.
558
+
559
+ The flow is simple:
560
+
561
+ 1. Run one command or script.
562
+ 2. Always render a visible deterministic result card with the command, exit code, duration, and stdout/stderr previews.
563
+ 3. Optionally hand the structured result to the model as a `[Deterministic step]` preamble before the prompt body.
564
+ 4. If `handoff: never`, stop after the result card and a visible completion marker — no LLM turn happens.
565
+
566
+ That handoff preamble is intentionally structured and uses stable field names like `status`, `executionKind`, `command`, `cwd`, `exitCode`, `signal`, `durationMs`, `timedOut`, `lineCount`, `charCount`, `truncated`, `omittedChars`, and `preview`.
567
+
568
+ V1 scope is intentionally narrow: deterministic execution only works on single prompt templates. It does not combine with chain templates, delegated/subagent prompts, `parallel`, or loops. At runtime, deterministic prompts explicitly reject `--loop`, `--subagent`, and `--fork` in v1.
569
+
570
+ ### Authoring forms
571
+
572
+ You can write deterministic steps as **top-level shorthand** or **nested under `deterministic:`**. Both are equivalent. Use shorthand for brevity, nested when you want everything grouped under one key.
573
+
574
+ **Top-level shorthand** — put `run`, `script`, `handoff`, `timeout`, `cwd`, `env`, and `nonInteractive` directly in frontmatter:
575
+
576
+ ```markdown
577
+ ---
578
+ run: git push origin HEAD:main
579
+ handoff: on-failure
580
+ timeout: 30000
581
+ ---
582
+ If the push failed, explain why and suggest the next step.
583
+ ```
584
+
585
+ You can also use `script:` as shorthand:
586
+
587
+ ```markdown
588
+ ---
589
+ script: ./scripts/ship.sh
590
+ handoff: always
591
+ timeout: 15000
592
+ ---
593
+ Summarize the script result.
594
+ ```
595
+
596
+ **Nested form** — group everything under `deterministic:`:
597
+
598
+ ```markdown
599
+ ---
600
+ model: claude-sonnet-4-20250514
601
+ deterministic:
602
+ script:
603
+ path: ./scripts/ship.sh
604
+ args:
605
+ - --fast
606
+ handoff: always
607
+ timeout: 15000
608
+ cwd: ~/src/my-repo
609
+ ---
610
+ Summarize the script result and call out anything risky.
611
+ ```
612
+
613
+ **Structured command form** — when you need explicit args instead of a single shell string, use `deterministic.run.command` with `args`:
614
+
615
+ ```markdown
616
+ ---
617
+ model: claude-sonnet-4-20250514
618
+ deterministic:
619
+ run:
620
+ command: git
621
+ args: [status, --short]
622
+ handoff: always
623
+ ---
624
+ Interpret the repo state.
625
+ ```
626
+
627
+ Do not mix top-level shorthand with nested `deterministic:` in the same prompt. Pick one style.
628
+
629
+ ### Model requirement
630
+
631
+ Deterministic prompts that hand off to the model (`handoff: always`, `on-success`, or `on-failure`) need a model to continue into. You can either:
632
+
633
+ - Add a `model:` field explicitly
634
+ - Omit `model:` and let the prompt inherit whatever model is currently active
635
+
636
+ `handoff: never` prompts do not need a model field because they never reach the LLM.
637
+
638
+ ### Handoff values
639
+
640
+ - `always` — always continue into the LLM after the deterministic card is emitted.
641
+ - `never` — stop after the deterministic card and completion marker.
642
+ - `on-success` — continue only when the command exits `0`.
643
+ - `on-failure` — continue only when the command exits non-zero.
644
+
645
+ Command descriptions in the slash-command picker show this feature as `deterministic-step:<handoff>`.
646
+
647
+ ### Timeout
648
+
649
+ `timeout` is in milliseconds. When a timeout fires, the runner sends `SIGTERM` first. If the process still has not exited after a short grace window, it escalates to `SIGKILL`.
650
+
651
+ ### Script path resolution
652
+
653
+ Relative script paths resolve from the prompt file's directory first, then fall back to the command invocation `cwd`. Absolute script paths also work.
654
+
655
+ ### Environment and non-interactive mode
656
+
657
+ You can provide explicit environment variables and control the runner's non-interactive guardrails:
658
+
659
+ ```markdown
660
+ ---
661
+ deterministic:
662
+ run: ./deploy.sh
663
+ handoff: never
664
+ nonInteractive: false
665
+ env:
666
+ SPECIAL_TOKEN: abc123
667
+ RETRIES: 2
668
+ ---
669
+ ```
670
+
671
+ `nonInteractive` defaults to `true`. In that mode the runner keeps stdin ignored and adds a few guardrail environment defaults such as `CI=1`, `GIT_TERMINAL_PROMPT=0`, `PAGER=cat`, and `GIT_PAGER=cat`. Set `nonInteractive: false` when the command needs a more normal process environment and you explicitly want to opt out of those defaults. Explicit `env` values override the built-in defaults.
672
+
673
+ ### Output capping
674
+
675
+ Large stdout/stderr streams are capped before they are stored in the conversation card payload. The card and the LLM handoff block both show the total character and line counts plus explicit truncation metadata when output was capped.
676
+
677
+ ## Loop Execution
678
+
679
+ Run a template multiple times with `--loop`:
680
+
681
+ ```
682
+ /deslop --loop 5
683
+ /deslop --loop=5
684
+ /deslop --loop # unlimited — runs until convergence or cap (999)
685
+ ```
686
+
687
+ You can also set a default in frontmatter. CLI `--loop` always overrides:
688
+
689
+ ```markdown
690
+ ---
691
+ loop: 5
692
+ ---
693
+ ```
694
+
695
+ Use `loop: unlimited` (or `loop: true`) for open-ended loops that run until convergence, user interrupt, or the safety cap of 999 iterations:
696
+
697
+ ```markdown
698
+ ---
699
+ loop: unlimited
700
+ converge: false
701
+ fresh: true
702
+ subagent: true
703
+ ---
704
+ ```
705
+
706
+ ### How looping works
707
+
708
+ Each iteration runs the same prompt. By default, context accumulates — iteration 3 sees the full conversation from iterations 1 and 2 and builds on that work.
709
+
710
+ **Convergence**: If an iteration makes no file changes (no `write` or `edit` tool calls), the loop stops early. This is on by default. Use `--no-converge` or `converge: false` to always run every iteration.
711
+
712
+ **Fresh context**: Add `--fresh` (or `fresh: true` in frontmatter) to collapse the conversation between iterations. Each iteration gets a clean slate with only brief summaries of what previous iterations did. Good for long loops where accumulated context would blow up the token count.
713
+
714
+ **Status**: The TUI status bar shows `loop 2/5` during execution.
715
+
716
+ Model, thinking level, and skill are maintained throughout. If `restore: true` (the default), everything is restored after the final iteration.
717
+
718
+ ## Model Rotation
719
+
720
+ `rotate: true` turns a comma-separated `model` list from a fallback chain into a cycling list. Each loop iteration uses the next model in the list, wrapping around:
721
+
722
+ ```markdown
723
+ ---
724
+ model: claude-opus-4-6, gpt-5.4, gpt-5.3-codex
725
+ thinking: high, xhigh, off
726
+ loop: 9
727
+ rotate: true
728
+ fresh: true
729
+ ---
730
+ Review and fix issues in this codebase.
731
+ ```
732
+
733
+ Iteration 1 runs Opus + `high`, iteration 2 runs GPT-5.4 + `xhigh`, iteration 3 runs Codex + `off`, then wraps back to Opus. The status bar shows which model is active: `loop 2/9 · gpt-5.4 xhigh`.
734
+
735
+ This is especially useful for [ralph-style loops](https://ghuntley.com/ralph/) where different models catch different things. The `subagent` examples below require [pi-subagents](https://github.com/nicobailon/pi-subagents/). A single-model ralph loop that delegates with fresh context each iteration:
736
+
737
+ ```markdown
738
+ ---
739
+ model: claude-sonnet-4-20250514
740
+ subagent: true
741
+ inheritContext: true
742
+ loop: 5
743
+ fresh: true
744
+ ---
745
+ Simplify this code: $@
746
+ ```
747
+
748
+ Add `rotate` and multiple models to cycle different perspectives on each pass:
749
+
750
+ ```markdown
751
+ ---
752
+ model: claude-opus-4-6, gpt-5.4, gpt-5.3-codex
753
+ thinking: xhigh, high, high
754
+ loop: 9
755
+ rotate: true
756
+ fresh: true
757
+ subagent: true
758
+ ---
759
+ Review and fix issues in this codebase.
760
+ ```
761
+
762
+ Each iteration gets fresh context, a different model, and its own thinking level. Convergence stops the loop when an iteration makes no file changes — use `converge: false` to guarantee every model gets at least one shot.
763
+
764
+ `thinking` pairing with `rotate: true`:
765
+
766
+ - Single value (`thinking: high`) — applied to every model.
767
+ - Comma-separated (`thinking: high, xhigh, off`) — positional, must match the number of models.
768
+ - Omitted — each iteration inherits the session default.
769
+
770
+ Without `loop`, `rotate` has no effect and comma-separated `model` keeps normal fallback behavior.
771
+
772
+ ## Chaining Templates
773
+
774
+ `/chain-prompts` runs multiple templates in sequence. Each step uses its own model, skill, and thinking level, while conversation context flows between them:
775
+
776
+ ```
777
+ /chain-prompts analyze-code -> fix-plan -> summarize -- src/main.ts
778
+ ```
779
+
780
+ This runs `analyze-code`, then `fix-plan` (which sees the analysis), then `summarize`. The ` -- ` separator marks shared args — everything after it is passed to each step as `$@`, unless a step has its own inline args:
781
+
782
+ ```
783
+ /chain-prompts analyze-code "error handling" -> fix-plan -> summarize -- src/main.ts
784
+ ```
785
+
786
+ Step 1 gets `"error handling"` as its args. Steps 2 and 3 fall back to the shared `"src/main.ts"`.
787
+
788
+ The chain captures your model and thinking level before starting and restores them when finished (or if any step fails).
789
+
790
+ ### Chain Templates
791
+
792
+ For reusable pipelines, put the chain in frontmatter:
793
+
794
+ ```markdown
795
+ ---
796
+ description: Review then clean up
797
+ chain: double-check --loop 2 -> deslop --loop 2
798
+ ---
799
+ ```
800
+
801
+ This registers the file's name as a command that runs `double-check` twice, then `deslop` twice. Per-step `--loop N` repeats that step before moving to the next, with per-step convergence (stops early if no changes, unless the step's template has `converge: false`).
802
+
803
+ Chain declarations also support parallel groups with `parallel(...)`:
804
+
805
+ ```markdown
806
+ ---
807
+ chain: parallel(scan-frontend, scan-backend) -> consolidate
808
+ ---
809
+ ```
810
+
811
+ Each entry inside `parallel(...)` runs as a delegated subagent task concurrently. Parallel entries can include per-step args (for example `parallel(scan-frontend, scan-backend "auth")`), but per-step `--loop` is not supported inside parallel groups. Nested `parallel(...)` is rejected. Parallel entries must be delegated templates (`subagent: ...` or runtime `--subagent` override). All entries in the same parallel group must resolve to the same `inheritContext` mode. Mixed `cwd` values are allowed normally, but when `worktree: true` is enabled they must all resolve to the same `cwd`.
812
+
813
+ Add `worktree: true` (or `--worktree` at runtime) so each parallel subagent runs in its own git worktree, avoiding file conflicts when agents edit concurrently:
814
+
815
+ ```markdown
816
+ ---
817
+ chain: parallel(scan-frontend, scan-backend) -> consolidate
818
+ worktree: true
819
+ ---
820
+ ```
821
+
822
+ `worktree` requires a chain with at least one `parallel()` step. The flag is passed to pi-subagents, which handles worktree creation and cleanup.
823
+
824
+ Steps with a `model` field use their own model. Steps without one inherit a snapshot of whatever model was active when the chain started — not the previous step's model. This keeps behavior deterministic regardless of what earlier steps do.
825
+
826
+ Chain templates support `loop`, `fresh`, `converge`, `restore`, `worktree`, and `cwd` in their frontmatter for controlling the overall execution:
827
+
828
+ ```markdown
829
+ ---
830
+ chain: analyze -> fix
831
+ loop: 3
832
+ fresh: true
833
+ converge: false
834
+ ---
835
+ ```
836
+
837
+ This runs the full analyze → fix chain 3 times, with fresh context between iterations and no early stopping. Chain nesting is not supported — steps can't reference other chain templates.
838
+
839
+ When a chain template sets `cwd`, it becomes the default delegated subprocess working directory for all delegated steps in that chain. Runtime `--cwd=<path>` overrides the chain template value.
840
+
841
+ ### Chain context for delegated steps
842
+
843
+ Delegated chain steps start fresh — they don't see what earlier steps did. Chain context prepends a compact summary of previous steps to each delegated task so later steps can build on earlier work.
844
+
845
+ Enable it chain-wide with `chainContext: summary` in frontmatter or `--chain-context` on the CLI:
846
+
847
+ ```markdown
848
+ ---
849
+ chain: analyze -> fix
850
+ chainContext: summary
851
+ ---
852
+ ```
853
+
854
+ ```
855
+ /chain-prompts analyze -> fix --chain-context
856
+ ```
857
+
858
+ To enable it for a single step, attach `--with-context` to that step name:
859
+
860
+ ```
861
+ /chain-prompts analyze -> reviewer --with-context -> summarize
862
+ ```
863
+
864
+ Here only `reviewer` receives the summary of `analyze`. The `summarize` step does not.
865
+
866
+ Steps using `inheritContext: true` already fork the full parent conversation and skip the summary preamble. `--with-context` is not supported inside `parallel(...)` groups. When a chain uses `loop`, summaries reset each iteration.
867
+
868
+ ### Parallel and looping from the CLI
869
+
870
+ Parallel groups work in `/chain-prompts` too:
871
+
872
+ ```
873
+ /chain-prompts parallel(scan-fe, scan-be) -> review
874
+ /chain-prompts parallel(scan-fe, scan-be) -> review --worktree
875
+ ```
876
+
877
+ Looping applies to the entire chain:
878
+
879
+ ```
880
+ /chain-prompts analyze -> fix --loop 3
881
+ /chain-prompts analyze -> fix --loop 3 --fresh
882
+ /chain-prompts analyze -> fix --loop 3 --no-converge
883
+ /chain-prompts analyze -> fix --loop
884
+ ```
885
+
886
+ Convergence applies across all steps in each iteration — if no step made file changes, the loop stops. Templates are re-read from disk between iterations, so edits take effect live.
887
+
888
+ ## Agent Tool
889
+
890
+ The agent can invoke prompt templates itself via a `run-prompt` tool. It's off by default:
891
+
892
+ ```
893
+ /prompt-tool on
894
+ ```
895
+
896
+ Once enabled, the agent sees `run-prompt` in its tool list:
897
+
898
+ ```
899
+ run-prompt({ command: "deslop --loop 5 --fresh" })
900
+ run-prompt({ command: "chain-prompts analyze -> fix --chain-context" })
901
+ run-prompt({ command: "chain-prompts analyze -> fix --loop 3" })
902
+ run-prompt({ command: "deslop --subagent" })
903
+ ```
904
+
905
+ The tool queues the command for execution after the agent's current turn ends. All loop, chain, and convergence features work the same as slash commands.
906
+
907
+ You can add guidance to steer when the agent reaches for it:
908
+
909
+ ```
910
+ /prompt-tool on Use run-prompt for iterative code improvement tasks
911
+ /prompt-tool guidance Use sparingly, only for multi-pass refinement
912
+ /prompt-tool guidance clear
913
+ /prompt-tool off
914
+ /prompt-tool # show current status
915
+ ```
916
+
917
+ Config persists across sessions in `~/.pi/agent/prompt-template-model.json`.
918
+
919
+ ## Autocomplete
920
+
921
+ Commands show their configuration in the autocomplete description:
922
+
923
+ ```
924
+ /debug-python Debug Python session [sonnet +tmux] (user)
925
+ /deep-analysis Deep code analysis [sonnet high] (user)
926
+ /save-progress Save progress doc [haiku|sonnet] (user)
927
+ /component Create React component [sonnet] (user:frontend)
928
+ ```
929
+
930
+ ## Subdirectories
931
+
932
+ Organize prompts in subdirectories for namespacing:
933
+
934
+ ```
935
+ ~/.pi/agent/prompts/
936
+ ├── quick.md → /quick (user)
937
+ ├── debug-python.md → /debug-python (user)
938
+ └── frontend/
939
+ ├── component.md → /component (user:frontend)
940
+ └── hook.md → /hook (user:frontend)
941
+ ```
942
+
943
+ The subdirectory shows as the source label in autocomplete. Command names are based on filename only. Duplicates within the same source layer are skipped with a warning, as are reserved names like `model`, `reload`, and `chain-prompts`.
944
+
945
+ ## Print Mode
946
+
947
+ These commands work in `pi -p` too:
948
+
949
+ ```bash
950
+ pi -p "/debug-python my code crashes on line 42"
951
+ ```
952
+
953
+ The model switches, skill is injected, the agent responds, and output goes to stdout. Useful for scripting or piping.
954
+
955
+ ## Examples
956
+
957
+ **Thinking levels** — max thinking for thorny analysis:
958
+
959
+ ```markdown
960
+ ---
961
+ description: Deep code analysis with extended thinking
962
+ model: claude-sonnet-4-20250514
963
+ thinking: high
964
+ ---
965
+ Analyze this code thoroughly, considering edge cases and potential issues: $@
966
+ ```
967
+
968
+ **Sticky mode switch** — switch models for the rest of the session:
969
+
970
+ ```markdown
971
+ ---
972
+ description: Switch to Haiku for this session
973
+ model: claude-haiku-4-5
974
+ restore: false
975
+ ---
976
+ Switched to Haiku. How can I help?
977
+ ```
978
+
979
+ **Cross-provider fallback** — try the same model on different providers:
980
+
981
+ ```markdown
982
+ ---
983
+ description: Quick analysis
984
+ model: anthropic/claude-haiku-4-5, openrouter/claude-haiku-4-5
985
+ ---
986
+ $@
987
+ ```
988
+
989
+ ## Release process
990
+
991
+ Releases are managed with [Release Please](https://github.com/googleapis/release-please) from conventional commits on `main`.
992
+
993
+ 1. Land normal commits such as `feat:`, `fix:`, `docs:`, or `chore:`.
994
+ 2. Release Please opens a release PR that updates `package.json`, `package-lock.json`, `CHANGELOG.md`, and the release manifest.
995
+ 3. Merge the release PR to create the GitHub Release/tag.
996
+ 4. The publish workflow verifies the tag matches `package.json`, runs the Node 24 test suite, checks production audit, verifies package contents, and publishes to npm with provenance through trusted publishing.
997
+
998
+ ## Limitations
999
+
1000
+ - Prompt files are reloaded on session start and whenever an extension-owned command runs. If you add a new prompt file mid-session, run any extension command (like `/chain-prompts`), start a new session, or reload pi to pick it up.
1001
+ - Model restore state is in-memory. Closing pi mid-response loses it.
1002
+ - In chains, model-less steps inherit the chain-start model snapshot, not the previous step's model. This is intentional for deterministic behavior.
1003
+ - Delegated `subagent` prompts require [pi-subagents](https://github.com/nicobailon/pi-subagents/).
1004
+ - `run-prompt` must be explicitly enabled with `/prompt-tool on`.