pi-subagents 0.14.1 → 0.15.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 +18 -0
- package/README.md +85 -4
- package/agent-management.ts +28 -7
- package/agent-manager-detail.ts +4 -1
- package/agent-manager-edit.ts +46 -6
- package/agent-manager.ts +28 -2
- package/agent-serializer.ts +6 -0
- package/agents/context-builder.md +24 -26
- package/agents/delegate.md +4 -1
- package/agents/planner.md +21 -15
- package/agents/researcher.md +23 -25
- package/agents/reviewer.md +22 -14
- package/agents/scout.md +24 -19
- package/agents/worker.md +20 -8
- package/agents.ts +121 -13
- package/async-execution.ts +18 -12
- package/async-job-tracker.ts +3 -3
- package/async-status.ts +3 -3
- package/chain-execution.ts +5 -5
- package/execution.ts +3 -3
- package/formatters.ts +14 -12
- package/index.ts +1 -1
- package/package.json +1 -1
- package/parallel-utils.ts +4 -15
- package/pi-args.ts +13 -6
- package/schemas.ts +1 -1
- package/settings.ts +2 -2
- package/slash-commands.ts +8 -8
- package/subagent-executor.ts +32 -19
- package/subagent-prompt-runtime.ts +67 -0
- package/subagent-runner.ts +3 -8
- package/utils.ts +6 -1
- package/worktree.ts +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.15.0] - 2026-04-16
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- Added `systemPromptMode` so subagents can replace Pi's base prompt with `--system-prompt` instead of always appending with `--append-system-prompt`, shipping the core of issue `#85` from @isvlasov.
|
|
9
|
+
- Added `inheritProjectContext` and `inheritSkills` so child runs can keep or strip inherited project instruction files (`AGENTS.md`, `CLAUDE.md`, etc.) and Pi's discovered skills block.
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
- Builtin subagents now default to `systemPromptMode: replace`, with builtin `delegate` staying on `append`.
|
|
13
|
+
- Builtin agents now inherit project-level instruction files by default unless the user overrides them.
|
|
14
|
+
- Builtin agent prompts were rewritten for the new prompt-assembly model, and builtin `reviewer` / `context-builder` tool lists now match their documented behaviors. This rounds out the prompt-assembly work merged in PR `#92`, which closed issue `#85`. Thanks @isvlasov.
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
- Cross-platform tests now avoid machine-specific Pi install paths, align homedir-sensitive settings discovery on Windows CI, and use deterministic async config-write failure fixtures.
|
|
18
|
+
- Request-level `cwd` handling is now consistent across management and execution paths. `subagent` requests that target a worktree or nested checkout now resolve project agents, project settings, and builtin agent overrides from the requested `cwd` instead of accidentally inheriting the parent session's repo. This fixes issue `#83`. Thanks @hakin19 for the report.
|
|
19
|
+
- Relative child `cwd` values now resolve from the already-selected request/shared `cwd` across sync runs, async/background runs, chain steps, and top-level parallel tasks. This fixes cases where values like `packages/app` were interpreted from the wrong base directory, which could break skill lookup, output paths, and child process spawning.
|
|
20
|
+
- Worktree parallel-mode validation now compares task-level `cwd` overrides after relative-path resolution, so equivalent paths like `.` no longer trigger false conflict errors against the shared worktree base.
|
|
21
|
+
- Internal TypeScript source imports in the touched runtime paths now consistently use `.ts` local specifiers, matching the repo's direct TypeScript runtime loading conventions and reducing drift between adjacent modules.
|
|
22
|
+
|
|
5
23
|
## [0.14.1] - 2026-04-14
|
|
6
24
|
|
|
7
25
|
### Fixed
|
package/README.md
CHANGED
|
@@ -51,10 +51,44 @@ You can also override selected builtin fields without copying the whole agent. B
|
|
|
51
51
|
- User scope: `~/.pi/agent/settings.json`
|
|
52
52
|
- Project scope: `.pi/settings.json`
|
|
53
53
|
|
|
54
|
-
Supported builtin override fields are `model`, `fallbackModels`, `thinking`, `skills`, `tools`, and `systemPrompt`. Project overrides beat user overrides.
|
|
54
|
+
Supported builtin override fields are `model`, `fallbackModels`, `thinking`, `systemPromptMode`, `inheritProjectContext`, `inheritSkills`, `skills`, `tools`, and `systemPrompt`. Project overrides beat user overrides.
|
|
55
|
+
|
|
56
|
+
**Overriding builtin defaults:**
|
|
57
|
+
|
|
58
|
+
All builtin agents inherit project instruction files (`AGENTS.md`, `CLAUDE.md`, etc.) by default. To make a builtin agent run without those project instructions:
|
|
59
|
+
|
|
60
|
+
**Via settings file** — add to `~/.pi/agent/settings.json` (user scope) or `.pi/settings.json` (project scope):
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"subagents": {
|
|
64
|
+
"agentOverrides": {
|
|
65
|
+
"reviewer": {
|
|
66
|
+
"inheritProjectContext": false
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Via `/agents` UI** — press `e` on any builtin agent (like `reviewer`), then toggle `inheritProjectContext` to `false` and save. This creates an override that you can edit or remove later without modifying the builtin definition itself.
|
|
74
|
+
|
|
75
|
+
Overridden builtins show badges like `[builtin+user]` or `[builtin+project]` to indicate they have customizations applied.
|
|
55
76
|
|
|
56
77
|
> **Note:** The `researcher` agent uses `web_search`, `fetch_content`, and `get_search_content` tools which require the [pi-web-access](https://github.com/nicobailon/pi-web-access) extension. Install it with `pi install npm:pi-web-access`.
|
|
57
78
|
|
|
79
|
+
### Prompt Assembly Philosophy
|
|
80
|
+
|
|
81
|
+
Subagents are designed to be **narrow and intentional**. Custom subagents default to seeing only what you explicitly give them — not Pi's entire base prompt, not your repo's `AGENTS.md`, and not the parent's discovered skills.
|
|
82
|
+
|
|
83
|
+
This prevents subtle bugs where a "simple" code review agent starts making decisions based on project architecture rules it shouldn't know about, or a focused research agent gets distracted by tool descriptions meant for the orchestrator.
|
|
84
|
+
|
|
85
|
+
Use inheritance flags to selectively add back context when you actually want it:
|
|
86
|
+
- **`inheritProjectContext: true`** — Keep Pi's inherited project-instructions block from project-level files like `AGENTS.md` and `CLAUDE.md`
|
|
87
|
+
- **`inheritSkills: true`** — Let the child use Pi's discovered skills catalog
|
|
88
|
+
- **`systemPromptMode: append`** — Add the agent's prompt to Pi's base instead of replacing it
|
|
89
|
+
|
|
90
|
+
Builtin agents ship a little differently: they all inherit project instruction files by default so they follow repo-specific rules out of the box. `delegate` is still the exception for `systemPromptMode` — it stays on `append` because its job is orchestration within the parent workflow, not isolated task execution.
|
|
91
|
+
|
|
58
92
|
**Agent frontmatter:**
|
|
59
93
|
|
|
60
94
|
```yaml
|
|
@@ -66,6 +100,9 @@ extensions: # absent=all, empty=none, csv=allowlist
|
|
|
66
100
|
model: claude-haiku-4-5
|
|
67
101
|
fallbackModels: openai/gpt-5-mini, anthropic/claude-sonnet-4 # optional ordered fallbacks
|
|
68
102
|
thinking: high # off, minimal, low, medium, high, xhigh
|
|
103
|
+
systemPromptMode: replace # replace by default, except builtin delegate
|
|
104
|
+
inheritProjectContext: false # custom agents default false; builtins opt into true
|
|
105
|
+
inheritSkills: false # strip Pi's discovered skills section
|
|
69
106
|
skill: safe-bash, chrome-devtools # comma-separated skills to inject
|
|
70
107
|
output: context.md # writes to {chain_dir}/context.md
|
|
71
108
|
defaultReads: context.md # comma-separated files to read
|
|
@@ -81,10 +118,51 @@ The `thinking` field sets a default extended thinking level for the agent. At ru
|
|
|
81
118
|
|
|
82
119
|
`fallbackModels` is an optional ordered list of backup models to try when the primary model fails with a provider/model-style error such as quota, auth, timeout, or provider/model unavailable. In markdown frontmatter, declare it as a comma-separated string. In management `config` objects, you can pass either a comma-separated string or a string array.
|
|
83
120
|
|
|
121
|
+
`systemPromptMode` — How the agent markdown body is passed to Pi:
|
|
122
|
+
- **`replace`** (default) — The agent's markdown body becomes the system prompt. Clean slate, no Pi base prompt baggage.
|
|
123
|
+
- **`append`** — The agent's prompt is appended to Pi's normal base prompt. Use this when you want Pi's full capabilities plus your extra instructions.
|
|
124
|
+
|
|
125
|
+
`inheritProjectContext` — Whether the child keeps Pi's inherited project-instructions block, built from project-level instruction files like `AGENTS.md` and `CLAUDE.md`:
|
|
126
|
+
- **`false`** (default) — Strip those inherited project-level instructions from the child's final system prompt. This does not remove repo access, cwd, tools, or the task itself; it only removes those inherited instructions.
|
|
127
|
+
- **`true`** — Keep those inherited project-level instructions. Use for specialists that should follow project-specific constraints and conventions.
|
|
128
|
+
|
|
129
|
+
`inheritSkills` — Whether the child keeps Pi's discovered skills section:
|
|
130
|
+
- **`false`** (default) — Skills catalog is stripped. Good for focused agents that shouldn't browse unrelated skills.
|
|
131
|
+
- **`true`** — Child sees the full skills list. Use for general-purpose assistants that might need varied tools.
|
|
132
|
+
|
|
133
|
+
The `skills` field still works independently — it injects specific skills directly into the agent prompt regardless of `inheritSkills`.
|
|
134
|
+
|
|
135
|
+
**Common Recipes**
|
|
136
|
+
|
|
137
|
+
| Goal | `systemPromptMode` | `inheritProjectContext` | `inheritSkills` |
|
|
138
|
+
|------|-------------------|------------------------|-----------------|
|
|
139
|
+
| Fully isolated specialist (custom-agent default) | `replace` | `false` | `false` |
|
|
140
|
+
| Specialist that should follow project instruction files | `replace` | `true` | `false` |
|
|
141
|
+
| Pi-plus-extensions | `append` | `true` | `true` |
|
|
142
|
+
|
|
143
|
+
- **Security auditor**: Fully isolated so it objectively checks for vulnerabilities without being biased by project conventions.
|
|
144
|
+
- **Architecture planner**: Repo-aware so it respects `AGENTS.md` constraints when making design decisions.
|
|
145
|
+
- **Generic helper**: Append mode with full inheritance so it behaves like a slightly-customized Pi.
|
|
146
|
+
|
|
84
147
|
Fallback resolution follows the same conservative model lookup as normal execution. Explicit `provider/model` values are used as-is. Bare model IDs first prefer the current session provider when that provider actually exposes the model, then fall back to a unique registry match. If a bare ID is still ambiguous, it stays bare.
|
|
85
148
|
|
|
86
149
|
Fallback is only used for provider/model availability failures. Ordinary task failures such as bad `bash` commands, missing files, or other tool/runtime errors do not trigger a model hop.
|
|
87
150
|
|
|
151
|
+
**Tool selection semantics**
|
|
152
|
+
|
|
153
|
+
The `tools` field controls builtin-tool allowlisting and a couple of related extension behaviors:
|
|
154
|
+
|
|
155
|
+
- `tools` **omitted** → `pi-subagents` does not pass `--tools`, so the child gets Pi's normal default builtin tools.
|
|
156
|
+
- `tools` **present** → listed builtin tool names become an explicit allowlist passed via `--tools`.
|
|
157
|
+
- `mcp:...` entries are split out of `tools` and forwarded as direct MCP tool selections.
|
|
158
|
+
- Path-like entries in `tools` (extension paths or file paths ending in `.ts` / `.js`) are treated as tool-extension paths, not builtin tool names.
|
|
159
|
+
|
|
160
|
+
This means:
|
|
161
|
+
|
|
162
|
+
- `tools` omitted + `extensions` omitted → child gets Pi's normal builtin tools and normal extension set.
|
|
163
|
+
- `tools: mcp:chrome-devtools` → child still gets Pi's default builtin tools, plus direct MCP tools from `chrome-devtools`.
|
|
164
|
+
- `tools: read, bash, mcp:chrome-devtools` → child is restricted to `read` and `bash` for builtin tools, plus direct MCP tools from `chrome-devtools`.
|
|
165
|
+
|
|
88
166
|
**Extension sandboxing**
|
|
89
167
|
|
|
90
168
|
Use `extensions` in frontmatter to control which extensions a subagent can access:
|
|
@@ -229,7 +307,7 @@ Press **Ctrl+Shift+A** or type `/agents` to open the Agents Manager overlay —
|
|
|
229
307
|
|--------|-------------|
|
|
230
308
|
| List | Browse all agents and chains with search/filter, scope badges, chain badges |
|
|
231
309
|
| Detail | View resolved prompt, frontmatter fields, recent run history, and active builtin override path |
|
|
232
|
-
| Edit | Edit fields with specialized pickers (model, thinking, skills, prompt editor) |
|
|
310
|
+
| Edit | Edit fields with specialized pickers and toggles (model, thinking, prompt mode, inherited context, inherited skills, prompt editor) |
|
|
233
311
|
| Chain Detail | View chain steps with flow visualization and dependency map |
|
|
234
312
|
| Parallel Builder | Build parallel execution slots, add same agent multiple times, per-slot task overrides |
|
|
235
313
|
| Task Input | Enter task and launch with optional skip-clarify toggle |
|
|
@@ -573,6 +651,9 @@ Agent definitions are not loaded into LLM context by default. Management actions
|
|
|
573
651
|
description: "Scans codebases for patterns and issues",
|
|
574
652
|
scope: "user",
|
|
575
653
|
systemPrompt: "You are a code scout...",
|
|
654
|
+
systemPromptMode: "replace",
|
|
655
|
+
inheritProjectContext: false,
|
|
656
|
+
inheritSkills: false,
|
|
576
657
|
model: "anthropic/claude-sonnet-4",
|
|
577
658
|
fallbackModels: ["openai/gpt-5-mini", "anthropic/claude-haiku-4-5"],
|
|
578
659
|
tools: "read, bash, mcp:github/search_repositories",
|
|
@@ -613,7 +694,7 @@ Agent definitions are not loaded into LLM context by default. Management actions
|
|
|
613
694
|
Notes:
|
|
614
695
|
- `create` uses `config.scope` (`"user"` or `"project"`), not `agentScope`.
|
|
615
696
|
- `update`/`delete` use `agentScope` only for scope disambiguation when the same name exists in both scopes.
|
|
616
|
-
- Agent config mapping: `reads -> defaultReads`, `progress -> defaultProgress`, `extensions` controls extension sandboxing, `maxSubagentDepth`
|
|
697
|
+
- Agent config mapping: `reads -> defaultReads`, `progress -> defaultProgress`, `extensions` controls extension sandboxing, `maxSubagentDepth`, `fallbackModels`, `systemPromptMode`, `inheritProjectContext`, and `inheritSkills` map directly to agent frontmatter, and `tools` supports `mcp:` entries that map to direct MCP tools.
|
|
617
698
|
- To clear any optional field, set it to `false` or `""` (e.g., `{ model: false }` or `{ skills: "" }`). Both work for all string-typed fields.
|
|
618
699
|
|
|
619
700
|
## Parameters
|
|
@@ -624,7 +705,7 @@ Notes:
|
|
|
624
705
|
| `task` | string | - | Task string (single mode) |
|
|
625
706
|
| `action` | string | - | Management action: `list`, `get`, `create`, `update`, `delete` |
|
|
626
707
|
| `chainName` | string | - | Chain name for management get/update/delete |
|
|
627
|
-
| `config` | object | - | Agent or chain config for management create/update. Agent configs also accept `fallbackModels` (comma-separated string or string array). |
|
|
708
|
+
| `config` | object | - | Agent or chain config for management create/update. Agent configs also accept `fallbackModels` (comma-separated string or string array), `systemPromptMode` (`append` or `replace`), `inheritProjectContext` (boolean), and `inheritSkills` (boolean). |
|
|
628
709
|
| `output` | `string \| false` | agent default | Override output file for single agent (absolute path as-is, relative path resolved against cwd) |
|
|
629
710
|
| `skill` | `string \| string[] \| false` | agent default | Override skills (comma-separated string, array, or false to disable) |
|
|
630
711
|
| `model` | string | agent default | Override model for single agent |
|
package/agent-management.ts
CHANGED
|
@@ -8,6 +8,9 @@ import {
|
|
|
8
8
|
type AgentSource,
|
|
9
9
|
type ChainConfig,
|
|
10
10
|
type ChainStepConfig,
|
|
11
|
+
defaultInheritProjectContext,
|
|
12
|
+
defaultInheritSkills,
|
|
13
|
+
defaultSystemPromptMode,
|
|
11
14
|
discoverAgentsAll,
|
|
12
15
|
} from "./agents.ts";
|
|
13
16
|
import { serializeAgent } from "./agent-serializer.ts";
|
|
@@ -244,6 +247,18 @@ function applyAgentConfig(target: AgentConfig, cfg: Record<string, unknown>): st
|
|
|
244
247
|
else if (typeof cfg.thinking === "string") target.thinking = cfg.thinking.trim() || undefined;
|
|
245
248
|
else return "config.thinking must be a string or false when provided.";
|
|
246
249
|
}
|
|
250
|
+
if (hasKey(cfg, "systemPromptMode")) {
|
|
251
|
+
if (cfg.systemPromptMode === "append" || cfg.systemPromptMode === "replace") target.systemPromptMode = cfg.systemPromptMode;
|
|
252
|
+
else return "config.systemPromptMode must be 'append' or 'replace' when provided.";
|
|
253
|
+
}
|
|
254
|
+
if (hasKey(cfg, "inheritProjectContext")) {
|
|
255
|
+
if (typeof cfg.inheritProjectContext !== "boolean") return "config.inheritProjectContext must be a boolean when provided.";
|
|
256
|
+
target.inheritProjectContext = cfg.inheritProjectContext;
|
|
257
|
+
}
|
|
258
|
+
if (hasKey(cfg, "inheritSkills")) {
|
|
259
|
+
if (typeof cfg.inheritSkills !== "boolean") return "config.inheritSkills must be a boolean when provided.";
|
|
260
|
+
target.inheritSkills = cfg.inheritSkills;
|
|
261
|
+
}
|
|
247
262
|
if (hasKey(cfg, "output")) {
|
|
248
263
|
if (cfg.output === false || cfg.output === "") target.output = undefined;
|
|
249
264
|
else if (typeof cfg.output === "string") target.output = cfg.output;
|
|
@@ -320,6 +335,9 @@ export function formatAgentDetail(agent: AgentConfig): string {
|
|
|
320
335
|
if (agent.fallbackModels?.length) lines.push(`Fallback models: ${agent.fallbackModels.join(", ")}`);
|
|
321
336
|
if (tools.length) lines.push(`Tools: ${tools.join(", ")}`);
|
|
322
337
|
if (agent.skills?.length) lines.push(`Skills: ${agent.skills.join(", ")}`);
|
|
338
|
+
lines.push(`System prompt mode: ${agent.systemPromptMode}`);
|
|
339
|
+
lines.push(`Inherit project context: ${agent.inheritProjectContext ? "true" : "false"}`);
|
|
340
|
+
lines.push(`Inherit skills: ${agent.inheritSkills ? "true" : "false"}`);
|
|
323
341
|
if (agent.extensions !== undefined) lines.push(`Extensions: ${agent.extensions.length ? agent.extensions.join(", ") : "(none)"}`);
|
|
324
342
|
if (agent.thinking) lines.push(`Thinking: ${agent.thinking}`);
|
|
325
343
|
if (agent.output) lines.push(`Output: ${agent.output}`);
|
|
@@ -418,7 +436,16 @@ export function handleCreate(params: ManagementParams, ctx: ManagementContext):
|
|
|
418
436
|
warnings.push(...chainStepWarnings(ctx, chain.steps));
|
|
419
437
|
return result([`Created chain '${name}' at ${targetPath}.`, ...warnings].join("\n"));
|
|
420
438
|
}
|
|
421
|
-
const agent: AgentConfig = {
|
|
439
|
+
const agent: AgentConfig = {
|
|
440
|
+
name,
|
|
441
|
+
description: cfg.description.trim(),
|
|
442
|
+
source: scope,
|
|
443
|
+
filePath: targetPath,
|
|
444
|
+
systemPrompt: "",
|
|
445
|
+
systemPromptMode: defaultSystemPromptMode(name),
|
|
446
|
+
inheritProjectContext: defaultInheritProjectContext(name),
|
|
447
|
+
inheritSkills: defaultInheritSkills(),
|
|
448
|
+
};
|
|
422
449
|
const applyError = applyAgentConfig(agent, cfg);
|
|
423
450
|
if (applyError) return result(applyError, true);
|
|
424
451
|
const mw = modelWarning(ctx, agent.model);
|
|
@@ -446,7 +473,6 @@ export function handleUpdate(params: ManagementParams, ctx: ManagementContext):
|
|
|
446
473
|
const target = targetOrError;
|
|
447
474
|
const updated: AgentConfig = { ...target };
|
|
448
475
|
const oldName = target.name;
|
|
449
|
-
// Validate all fields before any filesystem mutation
|
|
450
476
|
if (hasKey(cfg, "name") && (typeof cfg.name !== "string" || !cfg.name.trim())) return result("config.name must be a non-empty string when provided.", true);
|
|
451
477
|
if (hasKey(cfg, "description") && (typeof cfg.description !== "string" || !cfg.description.trim())) return result("config.description must be a non-empty string when provided.", true);
|
|
452
478
|
let newName: string | undefined;
|
|
@@ -456,7 +482,6 @@ export function handleUpdate(params: ManagementParams, ctx: ManagementContext):
|
|
|
456
482
|
}
|
|
457
483
|
const applyError = applyAgentConfig(updated, cfg);
|
|
458
484
|
if (applyError) return result(applyError, true);
|
|
459
|
-
// Apply name/description (validated above)
|
|
460
485
|
if (newName !== undefined) updated.name = newName;
|
|
461
486
|
if (hasKey(cfg, "description")) updated.description = (cfg.description as string).trim();
|
|
462
487
|
if (hasKey(cfg, "model")) {
|
|
@@ -471,7 +496,6 @@ export function handleUpdate(params: ManagementParams, ctx: ManagementContext):
|
|
|
471
496
|
const sw = skillsWarning(ctx.cwd, updated.skills);
|
|
472
497
|
if (sw) warnings.push(sw);
|
|
473
498
|
}
|
|
474
|
-
// Filesystem mutations last
|
|
475
499
|
if (updated.name !== oldName) {
|
|
476
500
|
const renamed = renamePath("agent", target.filePath, updated.name, target.source, ctx.cwd);
|
|
477
501
|
if (renamed.error) return result(renamed.error, true);
|
|
@@ -493,7 +517,6 @@ export function handleUpdate(params: ManagementParams, ctx: ManagementContext):
|
|
|
493
517
|
const target = targetOrError;
|
|
494
518
|
const updated: ChainConfig = { ...target, steps: [...target.steps] };
|
|
495
519
|
const oldName = target.name;
|
|
496
|
-
// Validate all fields before any filesystem mutation
|
|
497
520
|
if (hasKey(cfg, "name") && (typeof cfg.name !== "string" || !cfg.name.trim())) return result("config.name must be a non-empty string when provided.", true);
|
|
498
521
|
if (hasKey(cfg, "description") && (typeof cfg.description !== "string" || !cfg.description.trim())) return result("config.description must be a non-empty string when provided.", true);
|
|
499
522
|
let newName: string | undefined;
|
|
@@ -507,7 +530,6 @@ export function handleUpdate(params: ManagementParams, ctx: ManagementContext):
|
|
|
507
530
|
if (parsed.error) return result(parsed.error, true);
|
|
508
531
|
parsedSteps = parsed.steps!;
|
|
509
532
|
}
|
|
510
|
-
// Apply validated changes to in-memory object
|
|
511
533
|
if (newName !== undefined) updated.name = newName;
|
|
512
534
|
if (hasKey(cfg, "description")) updated.description = (cfg.description as string).trim();
|
|
513
535
|
if (parsedSteps) {
|
|
@@ -516,7 +538,6 @@ export function handleUpdate(params: ManagementParams, ctx: ManagementContext):
|
|
|
516
538
|
if (missing.length) warnings.push(`Warning: chain steps reference unknown agents: ${missing.join(", ")}.`);
|
|
517
539
|
warnings.push(...chainStepWarnings(ctx, updated.steps));
|
|
518
540
|
}
|
|
519
|
-
// Filesystem mutations last
|
|
520
541
|
if (updated.name !== oldName) {
|
|
521
542
|
const renamed = renamePath("chain", target.filePath, updated.name, target.source, ctx.cwd);
|
|
522
543
|
if (renamed.error) return result(renamed.error, true);
|
package/agent-manager-detail.ts
CHANGED
|
@@ -27,7 +27,7 @@ function renderFieldLine(
|
|
|
27
27
|
width: number,
|
|
28
28
|
theme: Theme,
|
|
29
29
|
): string {
|
|
30
|
-
const labelWidth =
|
|
30
|
+
const labelWidth = 12;
|
|
31
31
|
const labelText = theme.fg("dim", pad(label, labelWidth));
|
|
32
32
|
const available = Math.max(0, width - labelWidth);
|
|
33
33
|
return `${labelText}${truncateToWidth(value, available)}`;
|
|
@@ -61,6 +61,9 @@ function buildDetailLines(
|
|
|
61
61
|
const maxSubagentDepth = agent.maxSubagentDepth !== undefined ? String(agent.maxSubagentDepth) : "(default)";
|
|
62
62
|
|
|
63
63
|
lines.push(renderFieldLine("Model:", agent.model ?? "default", contentWidth, theme));
|
|
64
|
+
lines.push(renderFieldLine("Prompt mode:", agent.systemPromptMode, contentWidth, theme));
|
|
65
|
+
lines.push(renderFieldLine("Project ctx:", agent.inheritProjectContext ? "on" : "off", contentWidth, theme));
|
|
66
|
+
lines.push(renderFieldLine("Skills ctx:", agent.inheritSkills ? "on" : "off", contentWidth, theme));
|
|
64
67
|
if (agent.override) {
|
|
65
68
|
const overrideLabel = `${agent.override.scope} · ${formatPath(agent.override.path)}`;
|
|
66
69
|
lines.push(renderFieldLine("Override:", overrideLabel, contentWidth, theme));
|
package/agent-manager-edit.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Theme } from "@mariozechner/pi-coding-agent";
|
|
2
2
|
import { matchesKey, truncateToWidth } from "@mariozechner/pi-tui";
|
|
3
|
-
import type
|
|
3
|
+
import { defaultSystemPromptMode, type AgentConfig, type BuiltinAgentOverrideBase } from "./agents.ts";
|
|
4
4
|
import { createEditorState, ensureCursorVisible, getCursorDisplayPos, handleEditorInput, renderEditor, wrapText } from "./text-editor.ts";
|
|
5
5
|
import type { TextEditorState } from "./text-editor.ts";
|
|
6
6
|
import { pad, row, renderHeader, renderFooter, formatScrollInfo } from "./render-helpers.ts";
|
|
@@ -26,7 +26,7 @@ export interface CreateEditStateOptions {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
const THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh"] as const;
|
|
29
|
-
const FIELD_ORDER = ["name", "description", "model", "fallbackModels", "thinking", "tools", "extensions", "skills", "output", "reads", "progress", "interactive", "prompt"] as const;
|
|
29
|
+
const FIELD_ORDER = ["name", "description", "model", "fallbackModels", "thinking", "systemPromptMode", "inheritProjectContext", "inheritSkills", "tools", "extensions", "skills", "output", "reads", "progress", "interactive", "prompt"] as const;
|
|
30
30
|
type ThinkingLevel = typeof THINKING_LEVELS[number];
|
|
31
31
|
const PROMPT_VIEWPORT_HEIGHT = 16;
|
|
32
32
|
const MODEL_SELECTOR_HEIGHT = 10;
|
|
@@ -45,6 +45,9 @@ function fieldValueMatchesBase(field: EditField, state: EditState): boolean {
|
|
|
45
45
|
case "model": return state.draft.model === base.model;
|
|
46
46
|
case "fallbackModels": return arraysEqual(state.draft.fallbackModels, base.fallbackModels);
|
|
47
47
|
case "thinking": return state.draft.thinking === base.thinking;
|
|
48
|
+
case "systemPromptMode": return state.draft.systemPromptMode === base.systemPromptMode;
|
|
49
|
+
case "inheritProjectContext": return state.draft.inheritProjectContext === base.inheritProjectContext;
|
|
50
|
+
case "inheritSkills": return state.draft.inheritSkills === base.inheritSkills;
|
|
48
51
|
case "tools": return arraysEqual(toolList(state.draft), toolList(base));
|
|
49
52
|
case "skills": return arraysEqual(state.draft.skills, base.skills);
|
|
50
53
|
case "prompt": return state.draft.systemPrompt === base.systemPrompt;
|
|
@@ -59,6 +62,9 @@ function resetFieldToBase(field: EditField, state: EditState): void {
|
|
|
59
62
|
case "model": state.draft.model = base.model; break;
|
|
60
63
|
case "fallbackModels": state.draft.fallbackModels = base.fallbackModels ? [...base.fallbackModels] : undefined; break;
|
|
61
64
|
case "thinking": state.draft.thinking = base.thinking; break;
|
|
65
|
+
case "systemPromptMode": state.draft.systemPromptMode = base.systemPromptMode; break;
|
|
66
|
+
case "inheritProjectContext": state.draft.inheritProjectContext = base.inheritProjectContext; break;
|
|
67
|
+
case "inheritSkills": state.draft.inheritSkills = base.inheritSkills; break;
|
|
62
68
|
case "tools": state.draft.tools = base.tools ? [...base.tools] : undefined; state.draft.mcpDirectTools = base.mcpDirectTools ? [...base.mcpDirectTools] : undefined; break;
|
|
63
69
|
case "skills": state.draft.skills = base.skills ? [...base.skills] : undefined; break;
|
|
64
70
|
case "prompt": state.draft.systemPrompt = base.systemPrompt; state.promptEditor = createEditorState(base.systemPrompt); break;
|
|
@@ -83,6 +89,9 @@ function renderFieldValue(field: EditField, state: EditState): string {
|
|
|
83
89
|
case "model": return draft.model ?? "default";
|
|
84
90
|
case "fallbackModels": return draft.fallbackModels && draft.fallbackModels.length > 0 ? draft.fallbackModels.join(", ") : "";
|
|
85
91
|
case "thinking": return draft.thinking ?? "off";
|
|
92
|
+
case "systemPromptMode": return draft.systemPromptMode ?? defaultSystemPromptMode(draft.name);
|
|
93
|
+
case "inheritProjectContext": return draft.inheritProjectContext ? "on" : "off";
|
|
94
|
+
case "inheritSkills": return draft.inheritSkills ? "on" : "off";
|
|
86
95
|
case "tools": return formatTools(draft);
|
|
87
96
|
case "extensions": return draft.extensions !== undefined ? (draft.extensions.length > 0 ? draft.extensions.join(", ") : "") : "(all)";
|
|
88
97
|
case "skills": return draft.skills && draft.skills.length > 0 ? draft.skills.join(", ") : "";
|
|
@@ -101,12 +110,28 @@ function applyFieldValue(field: EditField, state: EditState, value: string): voi
|
|
|
101
110
|
case "description": draft.description = value.trim(); break;
|
|
102
111
|
case "model": draft.model = value.trim() || undefined; break;
|
|
103
112
|
case "fallbackModels": draft.fallbackModels = parseCommaList(value); break;
|
|
113
|
+
case "systemPromptMode": {
|
|
114
|
+
const trimmed = value.trim();
|
|
115
|
+
if (trimmed === "") {
|
|
116
|
+
draft.systemPromptMode = defaultSystemPromptMode(draft.name);
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
if (trimmed === "append" || trimmed === "replace") {
|
|
120
|
+
draft.systemPromptMode = trimmed;
|
|
121
|
+
}
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
104
124
|
case "tools": { const parsed = parseTools(value); draft.tools = parsed.tools; draft.mcpDirectTools = parsed.mcp; break; }
|
|
105
125
|
case "extensions": { const trimmed = value.trim(); draft.extensions = trimmed === "(all)" ? undefined : parseCommaList(trimmed) ?? []; break; }
|
|
106
126
|
case "skills": draft.skills = parseCommaList(value); break;
|
|
107
127
|
case "output": { const trimmed = value.trim(); draft.output = trimmed.length > 0 ? trimmed : undefined; break; }
|
|
108
128
|
case "reads": draft.defaultReads = parseCommaList(value); break;
|
|
109
|
-
case "
|
|
129
|
+
case "inheritProjectContext":
|
|
130
|
+
case "inheritSkills":
|
|
131
|
+
case "progress":
|
|
132
|
+
case "interactive":
|
|
133
|
+
case "prompt":
|
|
134
|
+
break;
|
|
110
135
|
}
|
|
111
136
|
}
|
|
112
137
|
|
|
@@ -231,13 +256,19 @@ export function handleEditInput(screen: EditScreen, state: EditState, data: stri
|
|
|
231
256
|
if (data === "m") { openModelPicker(state, models); return { nextScreen: "edit-field" }; }
|
|
232
257
|
if (data === "t") { openThinkingPicker(state); return { nextScreen: "edit-field" }; }
|
|
233
258
|
if (data === "s") { openSkillPicker(state, skills); return { nextScreen: "edit-field" }; }
|
|
234
|
-
if (data === " " && (field === "
|
|
259
|
+
if (data === " " && (field === "inheritProjectContext" || field === "inheritSkills" || field === "progress" || field === "interactive")) {
|
|
260
|
+
if (field === "inheritProjectContext") state.draft.inheritProjectContext = !state.draft.inheritProjectContext;
|
|
261
|
+
if (field === "inheritSkills") state.draft.inheritSkills = !state.draft.inheritSkills;
|
|
262
|
+
if (field === "progress") state.draft.defaultProgress = !state.draft.defaultProgress;
|
|
263
|
+
if (field === "interactive") state.draft.interactive = !state.draft.interactive;
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
235
266
|
if (matchesKey(data, "return")) {
|
|
236
267
|
if (field === "model") { openModelPicker(state, models); return { nextScreen: "edit-field" }; }
|
|
237
268
|
if (field === "thinking") { openThinkingPicker(state); return { nextScreen: "edit-field" }; }
|
|
238
269
|
if (field === "skills") { openSkillPicker(state, skills); return { nextScreen: "edit-field" }; }
|
|
239
270
|
if (field === "prompt") { state.promptEditor = createEditorState(state.draft.systemPrompt ?? ""); return { nextScreen: "edit-prompt" }; }
|
|
240
|
-
if (field === "progress" || field === "interactive") return;
|
|
271
|
+
if (field === "inheritProjectContext" || field === "inheritSkills" || field === "progress" || field === "interactive") return;
|
|
241
272
|
state.fieldMode = "text"; state.fieldEditor = createEditorState(renderFieldValue(field, state)); return { nextScreen: "edit-field" };
|
|
242
273
|
}
|
|
243
274
|
return;
|
|
@@ -304,8 +335,17 @@ export function renderEdit(screen: EditScreen, state: EditState, width: number,
|
|
|
304
335
|
for (let i = 0; i < state.fields.length; i++) {
|
|
305
336
|
const field = state.fields[i]!; if (field === "prompt") break;
|
|
306
337
|
const isFocused = i === state.fieldIndex; const prefix = isFocused ? theme.fg("accent", "▸ ") : " ";
|
|
307
|
-
const
|
|
338
|
+
const fieldLabel = field === "systemPromptMode"
|
|
339
|
+
? "Prompt Mode"
|
|
340
|
+
: field === "inheritProjectContext"
|
|
341
|
+
? "Project Ctx"
|
|
342
|
+
: field === "inheritSkills"
|
|
343
|
+
? "Skills Ctx"
|
|
344
|
+
: `${field[0]!.toUpperCase()}${field.slice(1)}`;
|
|
345
|
+
const rawLabel = pad(`${fieldLabel}:`, labelWidth);
|
|
308
346
|
const labelText = state.overrideBase && !fieldValueMatchesBase(field, state) ? theme.fg("accent", rawLabel) : rawLabel; let valueText = renderFieldValue(field, state);
|
|
347
|
+
if (field === "inheritProjectContext") { const toggle = state.draft.inheritProjectContext ? theme.fg("success", "[x]") : "[ ]"; valueText = `${toggle} ${state.draft.inheritProjectContext ? "on" : "off"}`; lines.push(row(` ${prefix}${labelText} ${pad(truncateToWidth(valueText, valueWidth), valueWidth)}`, width, theme)); continue; }
|
|
348
|
+
if (field === "inheritSkills") { const toggle = state.draft.inheritSkills ? theme.fg("success", "[x]") : "[ ]"; valueText = `${toggle} ${state.draft.inheritSkills ? "on" : "off"}`; lines.push(row(` ${prefix}${labelText} ${pad(truncateToWidth(valueText, valueWidth), valueWidth)}`, width, theme)); continue; }
|
|
309
349
|
if (field === "progress") { const toggle = state.draft.defaultProgress ? theme.fg("success", "[x]") : "[ ]"; valueText = `${toggle} ${state.draft.defaultProgress ? "on" : "off"}`; lines.push(row(` ${prefix}${labelText} ${pad(truncateToWidth(valueText, valueWidth), valueWidth)}`, width, theme)); continue; }
|
|
310
350
|
if (field === "interactive") { const toggle = state.draft.interactive ? theme.fg("success", "[x]") : "[ ]"; valueText = `${toggle} ${state.draft.interactive ? "on" : "off"}`; lines.push(row(` ${prefix}${labelText} ${pad(truncateToWidth(valueText, valueWidth), valueWidth)}`, width, theme)); continue; }
|
|
311
351
|
let displayValue = truncateToWidth(valueText, valueWidth);
|
package/agent-manager.ts
CHANGED
|
@@ -5,6 +5,9 @@ import type { Component, TUI } from "@mariozechner/pi-tui";
|
|
|
5
5
|
import { matchesKey, truncateToWidth, visibleWidth } from "@mariozechner/pi-tui";
|
|
6
6
|
import {
|
|
7
7
|
buildBuiltinOverrideConfig,
|
|
8
|
+
defaultInheritProjectContext,
|
|
9
|
+
defaultInheritSkills,
|
|
10
|
+
defaultSystemPromptMode,
|
|
8
11
|
discoverAgentsAll,
|
|
9
12
|
removeBuiltinAgentOverride,
|
|
10
13
|
saveBuiltinAgentOverride,
|
|
@@ -40,7 +43,7 @@ interface NameInputState { mode: "new-agent" | "clone-agent" | "clone-chain" | "
|
|
|
40
43
|
interface StatusMessage { text: string; type: "error" | "info"; }
|
|
41
44
|
interface OverrideScopeState { selectedScope: "user" | "project"; allowProject: boolean; }
|
|
42
45
|
|
|
43
|
-
const BUILTIN_OVERRIDE_FIELDS: EditField[] = ["model", "fallbackModels", "thinking", "tools", "skills", "prompt"];
|
|
46
|
+
const BUILTIN_OVERRIDE_FIELDS: EditField[] = ["model", "fallbackModels", "thinking", "systemPromptMode", "inheritProjectContext", "inheritSkills", "tools", "skills", "prompt"];
|
|
44
47
|
|
|
45
48
|
function cloneConfig(config: AgentConfig): AgentConfig {
|
|
46
49
|
return {
|
|
@@ -130,6 +133,9 @@ export class AgentManagerComponent implements Component {
|
|
|
130
133
|
model: entry.config.model,
|
|
131
134
|
fallbackModels: entry.config.fallbackModels ? [...entry.config.fallbackModels] : undefined,
|
|
132
135
|
thinking: entry.config.thinking,
|
|
136
|
+
systemPromptMode: entry.config.systemPromptMode,
|
|
137
|
+
inheritProjectContext: entry.config.inheritProjectContext,
|
|
138
|
+
inheritSkills: entry.config.inheritSkills,
|
|
133
139
|
systemPrompt: entry.config.systemPrompt,
|
|
134
140
|
skills: entry.config.skills ? [...entry.config.skills] : undefined,
|
|
135
141
|
tools: entry.config.tools ? [...entry.config.tools] : undefined,
|
|
@@ -233,6 +239,16 @@ export class AgentManagerComponent implements Component {
|
|
|
233
239
|
filePath = path.join(dir, `${edit.draft.name}.md`);
|
|
234
240
|
if (fs.existsSync(filePath)) { edit.error = "An agent with that name already exists."; return false; }
|
|
235
241
|
fs.mkdirSync(dir, { recursive: true });
|
|
242
|
+
} else if (edit.draft.name !== entry.config.name) {
|
|
243
|
+
const nextPath = path.join(path.dirname(filePath), `${edit.draft.name}.md`);
|
|
244
|
+
if (nextPath !== filePath && fs.existsSync(nextPath)) {
|
|
245
|
+
edit.error = "An agent with that name already exists.";
|
|
246
|
+
return false;
|
|
247
|
+
}
|
|
248
|
+
if (nextPath !== filePath) {
|
|
249
|
+
fs.renameSync(filePath, nextPath);
|
|
250
|
+
filePath = nextPath;
|
|
251
|
+
}
|
|
236
252
|
}
|
|
237
253
|
try { const toSave: AgentConfig = { ...edit.draft, filePath }; fs.writeFileSync(filePath, serializeAgent(toSave), "utf-8"); entry.config = cloneConfig(toSave); entry.isNew = false; edit.error = undefined; return true; }
|
|
238
254
|
catch (err) { edit.error = err instanceof Error ? err.message : "Failed to save agent."; return false; }
|
|
@@ -349,7 +365,17 @@ export class AgentManagerComponent implements Component {
|
|
|
349
365
|
baseConfig = cloneConfig(sourceEntry.config);
|
|
350
366
|
} else {
|
|
351
367
|
const templateConfig = state.template?.config ?? {};
|
|
352
|
-
baseConfig = {
|
|
368
|
+
baseConfig = {
|
|
369
|
+
name,
|
|
370
|
+
description: "Describe this agent",
|
|
371
|
+
systemPrompt: "",
|
|
372
|
+
systemPromptMode: defaultSystemPromptMode(name),
|
|
373
|
+
inheritProjectContext: defaultInheritProjectContext(name),
|
|
374
|
+
inheritSkills: defaultInheritSkills(),
|
|
375
|
+
source: state.scope,
|
|
376
|
+
filePath: "",
|
|
377
|
+
...templateConfig,
|
|
378
|
+
};
|
|
353
379
|
}
|
|
354
380
|
const dir = state.scope === "project" ? this.agentData.projectDir : this.agentData.userDir;
|
|
355
381
|
if (!dir) { state.error = "Project agents directory not found."; this.tui.requestRender(); return; }
|
package/agent-serializer.ts
CHANGED
|
@@ -8,6 +8,9 @@ export const KNOWN_FIELDS = new Set([
|
|
|
8
8
|
"model",
|
|
9
9
|
"fallbackModels",
|
|
10
10
|
"thinking",
|
|
11
|
+
"systemPromptMode",
|
|
12
|
+
"inheritProjectContext",
|
|
13
|
+
"inheritSkills",
|
|
11
14
|
"skill",
|
|
12
15
|
"skills",
|
|
13
16
|
"extensions",
|
|
@@ -40,6 +43,9 @@ export function serializeAgent(config: AgentConfig): string {
|
|
|
40
43
|
const fallbackModelsValue = joinComma(config.fallbackModels);
|
|
41
44
|
if (fallbackModelsValue) lines.push(`fallbackModels: ${fallbackModelsValue}`);
|
|
42
45
|
if (config.thinking && config.thinking !== "off") lines.push(`thinking: ${config.thinking}`);
|
|
46
|
+
lines.push(`systemPromptMode: ${config.systemPromptMode}`);
|
|
47
|
+
lines.push(`inheritProjectContext: ${config.inheritProjectContext ? "true" : "false"}`);
|
|
48
|
+
lines.push(`inheritSkills: ${config.inheritSkills ? "true" : "false"}`);
|
|
43
49
|
|
|
44
50
|
const skillsValue = joinComma(config.skills);
|
|
45
51
|
if (skillsValue) lines.push(`skills: ${skillsValue}`);
|
|
@@ -1,38 +1,36 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: context-builder
|
|
3
3
|
description: Analyzes requirements and codebase, generates context and meta-prompt
|
|
4
|
-
tools: read, grep, find, ls, bash, web_search
|
|
4
|
+
tools: read, grep, find, ls, bash, write, web_search
|
|
5
5
|
model: claude-sonnet-4-6
|
|
6
|
+
systemPromptMode: replace
|
|
7
|
+
inheritProjectContext: true
|
|
8
|
+
inheritSkills: false
|
|
6
9
|
output: context.md
|
|
7
10
|
---
|
|
8
11
|
|
|
9
|
-
You
|
|
12
|
+
You are a requirements-to-context subagent.
|
|
10
13
|
|
|
11
|
-
|
|
14
|
+
Analyze the user request against the codebase, gather the minimum high-value context, and produce structured handoff material for planning.
|
|
12
15
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
Working rules:
|
|
17
|
+
- Read the request carefully before touching the codebase.
|
|
18
|
+
- Search the codebase for relevant files, patterns, dependencies, and constraints.
|
|
19
|
+
- Use `web_search` only when the task depends on external APIs, libraries, or current best practices.
|
|
20
|
+
- Write the requested output files clearly and concretely.
|
|
21
|
+
- Prefer distilled, high-signal context over exhaustive dumps.
|
|
17
22
|
|
|
18
|
-
When running in a chain, generate two files in the
|
|
23
|
+
When running in a chain, expect to generate two files in the chain directory:
|
|
19
24
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
## Patterns Found
|
|
25
|
-
[existing patterns to follow]
|
|
26
|
-
## Dependencies
|
|
27
|
-
[libraries, APIs involved]
|
|
25
|
+
`context.md`
|
|
26
|
+
- relevant files with line numbers and key snippets
|
|
27
|
+
- important patterns already used in the codebase
|
|
28
|
+
- dependencies, constraints, and implementation risks
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
[recommended implementation strategy]
|
|
37
|
-
## Questions Resolved
|
|
38
|
-
[decisions made during analysis]
|
|
30
|
+
`meta-prompt.md`
|
|
31
|
+
- distilled requirements summary
|
|
32
|
+
- technical constraints
|
|
33
|
+
- suggested implementation approach
|
|
34
|
+
- resolved questions and assumptions
|
|
35
|
+
|
|
36
|
+
The goal is to hand the planner exactly enough code and requirement context to produce a strong implementation plan without having to rediscover the same ground.
|
package/agents/delegate.md
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: delegate
|
|
3
3
|
description: Lightweight subagent that inherits the parent model with no default reads
|
|
4
|
+
systemPromptMode: append
|
|
5
|
+
inheritProjectContext: true
|
|
6
|
+
inheritSkills: false
|
|
4
7
|
---
|
|
5
8
|
|
|
6
|
-
You are a delegated agent. Execute the assigned task using
|
|
9
|
+
You are a delegated agent. Execute the assigned task using the provided tools. Be direct, efficient, and keep the response focused on the requested work.
|
package/agents/planner.md
CHANGED
|
@@ -4,43 +4,49 @@ description: Creates implementation plans from context and requirements
|
|
|
4
4
|
tools: read, grep, find, ls, write
|
|
5
5
|
model: claude-opus-4-6
|
|
6
6
|
thinking: high
|
|
7
|
+
systemPromptMode: replace
|
|
8
|
+
inheritProjectContext: true
|
|
9
|
+
inheritSkills: false
|
|
7
10
|
output: plan.md
|
|
8
11
|
defaultReads: context.md
|
|
9
12
|
---
|
|
10
13
|
|
|
11
|
-
You are a planning
|
|
14
|
+
You are a planning subagent.
|
|
12
15
|
|
|
13
|
-
|
|
16
|
+
Your job is to turn requirements and code context into a concrete implementation plan. Do not make code changes. Read, analyze, and write the plan only.
|
|
14
17
|
|
|
15
|
-
|
|
18
|
+
Working rules:
|
|
19
|
+
- Read the provided context before planning.
|
|
20
|
+
- Read any additional code you need in order to make the plan concrete.
|
|
21
|
+
- Name exact files whenever you can.
|
|
22
|
+
- Prefer small, ordered, actionable tasks over vague phases.
|
|
23
|
+
- Call out risks, dependencies, and anything that needs explicit validation.
|
|
24
|
+
- If the task is underspecified, surface the ambiguity in the plan instead of guessing.
|
|
16
25
|
|
|
17
|
-
Output format (plan.md):
|
|
26
|
+
Output format (`plan.md`):
|
|
18
27
|
|
|
19
28
|
# Implementation Plan
|
|
20
29
|
|
|
21
30
|
## Goal
|
|
22
|
-
One sentence summary of
|
|
31
|
+
One sentence summary of the outcome.
|
|
23
32
|
|
|
24
33
|
## Tasks
|
|
25
|
-
Numbered steps, each small and actionable
|
|
34
|
+
Numbered steps, each small and actionable.
|
|
26
35
|
1. **Task 1**: Description
|
|
27
36
|
- File: `path/to/file.ts`
|
|
28
|
-
- Changes:
|
|
29
|
-
- Acceptance:
|
|
30
|
-
|
|
31
|
-
2. **Task 2**: Description
|
|
32
|
-
...
|
|
37
|
+
- Changes: what to modify
|
|
38
|
+
- Acceptance: how to verify
|
|
33
39
|
|
|
34
40
|
## Files to Modify
|
|
35
|
-
- `path/to/file.ts` - what changes
|
|
41
|
+
- `path/to/file.ts` - what changes there
|
|
36
42
|
|
|
37
|
-
## New Files
|
|
43
|
+
## New Files
|
|
38
44
|
- `path/to/new.ts` - purpose
|
|
39
45
|
|
|
40
46
|
## Dependencies
|
|
41
47
|
Which tasks depend on others.
|
|
42
48
|
|
|
43
49
|
## Risks
|
|
44
|
-
Anything to
|
|
50
|
+
Anything likely to go wrong, need clarification, or need careful verification.
|
|
45
51
|
|
|
46
|
-
Keep the plan concrete.
|
|
52
|
+
Keep the plan concrete. Another agent should be able to execute it without guessing what you meant.
|