@nmzpy/pi-ember-stack 0.1.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/ATTRIBUTION.md +9 -0
- package/README.md +63 -0
- package/package.json +50 -0
- package/src/pi-ember-stack.ts +983 -0
- package/src/questionnaire-tool.ts +287 -0
- package/src/subagent/LICENSE +21 -0
- package/src/subagent/README.md +52 -0
- package/src/subagent/agent-format.md +64 -0
- package/src/subagent/agents/architect.md +56 -0
- package/src/subagent/agents/coder.md +35 -0
- package/src/subagent/agents/general-purpose.md +13 -0
- package/src/subagent/agents/reviewer.md +36 -0
- package/src/subagent/agents/scout.md +44 -0
- package/src/subagent/agents/worker.md +15 -0
- package/src/subagent/extensions/agents.ts +223 -0
- package/src/subagent/extensions/index.ts +1218 -0
- package/src/subagent/extensions/model.ts +86 -0
- package/src/subagent/extensions/package.json +3 -0
- package/src/subagent/extensions/render.ts +278 -0
- package/src/subagent/extensions/runner.ts +317 -0
- package/src/subagent/extensions/service.ts +79 -0
- package/src/subagent/extensions/thread-viewer.ts +393 -0
- package/src/subagent/extensions/threads.ts +116 -0
- package/tsconfig.json +13 -0
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import { Type } from "typebox";
|
|
2
|
+
import {
|
|
3
|
+
Key,
|
|
4
|
+
Text,
|
|
5
|
+
matchesKey,
|
|
6
|
+
visibleWidth,
|
|
7
|
+
wrapTextWithAnsi,
|
|
8
|
+
} from "@earendil-works/pi-tui";
|
|
9
|
+
|
|
10
|
+
export interface QuestionnaireOption {
|
|
11
|
+
value: string;
|
|
12
|
+
label: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface QuestionnaireQuestion {
|
|
17
|
+
id: string;
|
|
18
|
+
label?: string;
|
|
19
|
+
prompt: string;
|
|
20
|
+
options: QuestionnaireOption[];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface QuestionnaireAnswer {
|
|
24
|
+
id: string;
|
|
25
|
+
value: string;
|
|
26
|
+
label: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface QuestionnaireResult {
|
|
30
|
+
answers: QuestionnaireAnswer[];
|
|
31
|
+
cancelled: boolean;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const QuestionnaireParams = Type.Object({
|
|
35
|
+
questions: Type.Array(Type.Object({
|
|
36
|
+
id: Type.String({ description: "Unique question identifier" }),
|
|
37
|
+
label: Type.Optional(Type.String({ description: "Short label for the question" })),
|
|
38
|
+
prompt: Type.String({ description: "The full question to show the user" }),
|
|
39
|
+
options: Type.Array(Type.Object({
|
|
40
|
+
value: Type.String({ description: "Value returned for this option" }),
|
|
41
|
+
label: Type.String({ description: "Option label shown to the user" }),
|
|
42
|
+
description: Type.Optional(
|
|
43
|
+
Type.String({ description: "Optional option explanation" }),
|
|
44
|
+
),
|
|
45
|
+
})),
|
|
46
|
+
})),
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
export async function askQuestionnaire(
|
|
50
|
+
ctx: any,
|
|
51
|
+
title: string,
|
|
52
|
+
questions: QuestionnaireQuestion[],
|
|
53
|
+
): Promise<QuestionnaireAnswer[] | undefined> {
|
|
54
|
+
if (!ctx.hasUI || questions.length === 0) return undefined;
|
|
55
|
+
|
|
56
|
+
const result = await ctx.ui.custom(
|
|
57
|
+
(
|
|
58
|
+
_tui: any,
|
|
59
|
+
theme: any,
|
|
60
|
+
_keybindings: any,
|
|
61
|
+
done: (result: QuestionnaireResult) => void,
|
|
62
|
+
) => {
|
|
63
|
+
let questionIndex = 0;
|
|
64
|
+
let optionIndex = 0;
|
|
65
|
+
let cachedLines: string[] | undefined;
|
|
66
|
+
const answers = new Map<string, QuestionnaireAnswer>();
|
|
67
|
+
|
|
68
|
+
function refresh(): void {
|
|
69
|
+
cachedLines = undefined;
|
|
70
|
+
_tui.requestRender();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function addWrapped(lines: string[], text: string, width: number): void {
|
|
74
|
+
lines.push(...wrapTextWithAnsi(text, width));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function addWrappedWithPrefix(
|
|
78
|
+
lines: string[],
|
|
79
|
+
prefix: string,
|
|
80
|
+
text: string,
|
|
81
|
+
width: number,
|
|
82
|
+
): void {
|
|
83
|
+
const prefixWidth = visibleWidth(prefix);
|
|
84
|
+
if (prefixWidth >= width) {
|
|
85
|
+
addWrapped(lines, `${prefix}${text}`, width);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const wrapped = wrapTextWithAnsi(text, width - prefixWidth);
|
|
89
|
+
const continuationPrefix = " ".repeat(prefixWidth);
|
|
90
|
+
for (let i = 0; i < wrapped.length; i++) {
|
|
91
|
+
lines.push(`${i === 0 ? prefix : continuationPrefix}${wrapped[i]}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function currentQuestion(): QuestionnaireQuestion {
|
|
96
|
+
return questions[questionIndex];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function render(width: number): string[] {
|
|
100
|
+
if (cachedLines) return cachedLines;
|
|
101
|
+
const renderWidth = Math.max(1, width);
|
|
102
|
+
const question = currentQuestion();
|
|
103
|
+
const lines: string[] = [theme.fg("accent", "─".repeat(renderWidth))];
|
|
104
|
+
addWrappedWithPrefix(
|
|
105
|
+
lines,
|
|
106
|
+
" ",
|
|
107
|
+
theme.fg("accent", theme.bold(title)),
|
|
108
|
+
renderWidth,
|
|
109
|
+
);
|
|
110
|
+
addWrappedWithPrefix(
|
|
111
|
+
lines,
|
|
112
|
+
" ",
|
|
113
|
+
theme.fg(
|
|
114
|
+
"muted",
|
|
115
|
+
`${questionIndex + 1}/${questions.length} ${question.label ?? ""}`,
|
|
116
|
+
),
|
|
117
|
+
renderWidth,
|
|
118
|
+
);
|
|
119
|
+
lines.push("");
|
|
120
|
+
addWrappedWithPrefix(lines, " ", theme.fg("text", question.prompt), renderWidth);
|
|
121
|
+
lines.push("");
|
|
122
|
+
|
|
123
|
+
for (let i = 0; i < question.options.length; i++) {
|
|
124
|
+
const option = question.options[i];
|
|
125
|
+
const selected = i === optionIndex;
|
|
126
|
+
const prefix = selected ? theme.fg("accent", "> ") : " ";
|
|
127
|
+
const color = selected ? "accent" : "text";
|
|
128
|
+
addWrappedWithPrefix(
|
|
129
|
+
lines,
|
|
130
|
+
prefix,
|
|
131
|
+
theme.fg(color, `${i + 1}. ${option.label}`),
|
|
132
|
+
renderWidth,
|
|
133
|
+
);
|
|
134
|
+
if (option.description) {
|
|
135
|
+
addWrappedWithPrefix(
|
|
136
|
+
lines,
|
|
137
|
+
" ",
|
|
138
|
+
theme.fg("muted", option.description),
|
|
139
|
+
renderWidth,
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
lines.push("");
|
|
145
|
+
addWrappedWithPrefix(
|
|
146
|
+
lines,
|
|
147
|
+
" ",
|
|
148
|
+
theme.fg("dim", "Up/Down navigate | Enter select | Left/Right revisit | Esc cancel"),
|
|
149
|
+
renderWidth,
|
|
150
|
+
);
|
|
151
|
+
lines.push(theme.fg("accent", "─".repeat(renderWidth)));
|
|
152
|
+
cachedLines = lines;
|
|
153
|
+
return lines;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function handleInput(data: string): void {
|
|
157
|
+
const question = currentQuestion();
|
|
158
|
+
if (matchesKey(data, Key.up)) {
|
|
159
|
+
optionIndex = Math.max(0, optionIndex - 1);
|
|
160
|
+
refresh();
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
if (matchesKey(data, Key.down)) {
|
|
164
|
+
optionIndex = Math.min(question.options.length - 1, optionIndex + 1);
|
|
165
|
+
refresh();
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
if (matchesKey(data, Key.left) && questionIndex > 0) {
|
|
169
|
+
questionIndex--;
|
|
170
|
+
optionIndex = 0;
|
|
171
|
+
refresh();
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
if (
|
|
175
|
+
matchesKey(data, Key.right) &&
|
|
176
|
+
answers.has(question.id) &&
|
|
177
|
+
questionIndex < questions.length - 1
|
|
178
|
+
) {
|
|
179
|
+
questionIndex++;
|
|
180
|
+
optionIndex = 0;
|
|
181
|
+
refresh();
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
if (matchesKey(data, Key.enter)) {
|
|
185
|
+
const option = question.options[optionIndex];
|
|
186
|
+
answers.set(question.id, {
|
|
187
|
+
id: question.id,
|
|
188
|
+
value: option.value,
|
|
189
|
+
label: option.label,
|
|
190
|
+
});
|
|
191
|
+
if (questionIndex === questions.length - 1) {
|
|
192
|
+
done({ answers: Array.from(answers.values()), cancelled: false });
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
questionIndex++;
|
|
196
|
+
optionIndex = 0;
|
|
197
|
+
refresh();
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
if (matchesKey(data, Key.escape)) {
|
|
201
|
+
done({ answers: [], cancelled: true });
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return { render, invalidate: refresh, handleInput };
|
|
206
|
+
},
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
return result.cancelled ? undefined : result.answers;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export function registerQuestionnaireTool(pi: any): void {
|
|
213
|
+
pi.registerTool({
|
|
214
|
+
name: "questionnaire",
|
|
215
|
+
label: "Questionnaire",
|
|
216
|
+
description: "Ask the user one or more decision questions inline before continuing.",
|
|
217
|
+
parameters: QuestionnaireParams,
|
|
218
|
+
executionMode: "sequential",
|
|
219
|
+
async execute(
|
|
220
|
+
_toolCallId: string,
|
|
221
|
+
params: { questions: QuestionnaireQuestion[] },
|
|
222
|
+
_signal: AbortSignal,
|
|
223
|
+
_onUpdate: unknown,
|
|
224
|
+
ctx: any,
|
|
225
|
+
) {
|
|
226
|
+
if (ctx.mode !== "tui") {
|
|
227
|
+
return {
|
|
228
|
+
content: [{
|
|
229
|
+
type: "text",
|
|
230
|
+
text: "Error: Questionnaire UI is only available in interactive mode.",
|
|
231
|
+
}],
|
|
232
|
+
details: { answers: [], cancelled: true },
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
if (
|
|
236
|
+
params.questions.length === 0 ||
|
|
237
|
+
params.questions.some((question) => question.options.length === 0)
|
|
238
|
+
) {
|
|
239
|
+
return {
|
|
240
|
+
content: [{
|
|
241
|
+
type: "text",
|
|
242
|
+
text: "Error: Questionnaire questions require at least one option.",
|
|
243
|
+
}],
|
|
244
|
+
details: { answers: [], cancelled: true },
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const answers = await askQuestionnaire(ctx, "Questionnaire", params.questions);
|
|
249
|
+
return {
|
|
250
|
+
content: [{
|
|
251
|
+
type: "text",
|
|
252
|
+
text: answers === undefined
|
|
253
|
+
? "User cancelled the questionnaire."
|
|
254
|
+
: answers.map((answer) => `${answer.id}: ${answer.label}`).join("\n"),
|
|
255
|
+
}],
|
|
256
|
+
details: { answers: answers ?? [], cancelled: answers === undefined },
|
|
257
|
+
};
|
|
258
|
+
},
|
|
259
|
+
renderCall(args: { questions?: QuestionnaireQuestion[] }, theme: any): any {
|
|
260
|
+
const count = args.questions?.length ?? 0;
|
|
261
|
+
return new Text(
|
|
262
|
+
theme.fg("toolTitle", theme.bold("questionnaire ")) +
|
|
263
|
+
theme.fg("muted", `${count} question${count === 1 ? "" : "s"}`),
|
|
264
|
+
0,
|
|
265
|
+
0,
|
|
266
|
+
);
|
|
267
|
+
},
|
|
268
|
+
renderResult(result: any, _options: unknown, theme: any): any {
|
|
269
|
+
const details = result.details as {
|
|
270
|
+
answers?: QuestionnaireAnswer[];
|
|
271
|
+
cancelled?: boolean;
|
|
272
|
+
} | undefined;
|
|
273
|
+
if (details?.cancelled) return new Text(theme.fg("warning", "Cancelled"), 0, 0);
|
|
274
|
+
const answers = details?.answers ?? [];
|
|
275
|
+
return new Text(
|
|
276
|
+
answers
|
|
277
|
+
.map((answer) => {
|
|
278
|
+
const label = `${answer.id}: ${answer.label}`;
|
|
279
|
+
return `${theme.fg("success", "Selected: ")}${theme.fg("accent", label)}`;
|
|
280
|
+
})
|
|
281
|
+
.join("\n"),
|
|
282
|
+
0,
|
|
283
|
+
0,
|
|
284
|
+
);
|
|
285
|
+
},
|
|
286
|
+
});
|
|
287
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) bacnh85
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# pi-subagent
|
|
2
|
+
|
|
3
|
+
Isolated in-process subagents for Pi. The `subagent` tool supports single, parallel (8 tasks, 4 concurrent), and chained execution; `/agent` opens inspectable child threads.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pi install npm:@bacnh85/pi-subagent
|
|
9
|
+
# local checkout
|
|
10
|
+
pi install ./pi-subagent
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Bundled roles
|
|
14
|
+
|
|
15
|
+
| Role | Model | Thinking | Tools |
|
|
16
|
+
| --- | --- | --- | --- |
|
|
17
|
+
| `scout` | parent model | low | read, grep, find, ls |
|
|
18
|
+
| `reviewer` | parent model | high | read, grep, find, ls |
|
|
19
|
+
| `worker` | parent model | medium | standard coding tools |
|
|
20
|
+
| `general-purpose` | parent model | off | standard coding tools |
|
|
21
|
+
|
|
22
|
+
Bundled roles inherit the parent model so they work with the account already active in Pi. User/project agent files may override `model` and `thinking`.
|
|
23
|
+
|
|
24
|
+
## Agent files
|
|
25
|
+
|
|
26
|
+
Create `~/.pi/agent/agents/*.md` or `.pi/agents/*.md`:
|
|
27
|
+
|
|
28
|
+
```markdown
|
|
29
|
+
---
|
|
30
|
+
name: scout-fast
|
|
31
|
+
description: Locate relevant files and symbols
|
|
32
|
+
tools: read, grep, find, ls
|
|
33
|
+
thinking: low
|
|
34
|
+
model: optional-provider/optional-model
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
Return concise evidence with file/symbol anchors.
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Project agents require confirmation when requested through the public tool. Definitions are cached with file-signature invalidation; `/subagent reload` clears the cache.
|
|
41
|
+
|
|
42
|
+
## Context and limits
|
|
43
|
+
|
|
44
|
+
Children use in-memory SDK sessions with no extensions, skills, prompt templates, or automatic `AGENTS.md` loading. The optional `instructions` argument passes a bounded 16 KB task/repository contract. Only Pi built-in tools are available; Serena, FFF, web, and Munin are not available in lean children.
|
|
45
|
+
|
|
46
|
+
Threads are session-memory only and are cleared when Pi replaces or reloads the session. Timeout and parent cancellation propagate to child sessions. Subagents cannot recursively invoke `subagent`.
|
|
47
|
+
|
|
48
|
+
## Extension contract
|
|
49
|
+
|
|
50
|
+
`pi-subagent` owns the `pi-subagent:run` event contract for one named-agent request. `pi-review` uses it for isolated review. Requests use an immediate boolean `accept()` claim and exactly one `respond()` callback; this suppresses duplicate responders while missing services and timeouts remain caller-controlled.
|
|
51
|
+
|
|
52
|
+
See [`agent-format.md`](./agent-format.md) for all frontmatter fields.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Agent Definition Format
|
|
2
|
+
|
|
3
|
+
Sub-agents are defined as Markdown files with YAML frontmatter.
|
|
4
|
+
|
|
5
|
+
## File Location
|
|
6
|
+
|
|
7
|
+
| Location | Scope |
|
|
8
|
+
|----------|-------|
|
|
9
|
+
| `~/.pi/agent/agents/*.md` | User-level (all projects) |
|
|
10
|
+
| `.pi/agents/*.md` | Project-level |
|
|
11
|
+
| `<package>/agents/*.md` | Bundled with pi-subagent |
|
|
12
|
+
|
|
13
|
+
Project agents override user agents with the same name when `agentScope: "both"`.
|
|
14
|
+
|
|
15
|
+
## Frontmatter Fields
|
|
16
|
+
|
|
17
|
+
```yaml
|
|
18
|
+
---
|
|
19
|
+
name: my-agent # Required. Unique identifier (kebab-case).
|
|
20
|
+
description: ... # Required. When to use this agent.
|
|
21
|
+
tools: read, grep, ... # Optional. Comma-separated tool names. Defaults to all.
|
|
22
|
+
model: provider/model # Optional. Defaults to parent's model.
|
|
23
|
+
thinking: low # Optional: off|minimal|low|medium|high|xhigh|max.
|
|
24
|
+
---
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Only `name` and `description` are required.
|
|
28
|
+
|
|
29
|
+
## Body
|
|
30
|
+
|
|
31
|
+
The body after frontmatter becomes the agent's **entire system prompt**. No pi defaults, no AGENTS.md files, no skills — only what you write here. Keep it focused.
|
|
32
|
+
|
|
33
|
+
## Available Tools
|
|
34
|
+
|
|
35
|
+
Built-in pi tool names: `read`, `bash`, `edit`, `write`, `grep`, `find`, `ls`
|
|
36
|
+
|
|
37
|
+
The `subagent` tool is never available to sub-agents (prevents accidental recursion). Sub-agents run at one level of delegation only; they cannot spawn further sub-agents.
|
|
38
|
+
|
|
39
|
+
Custom/extension tools are NOT available to sub-agents by default (each runs in an isolated in-memory session with no extensions).
|
|
40
|
+
|
|
41
|
+
## Model Resolution
|
|
42
|
+
|
|
43
|
+
Model IDs are resolved via `getModel("provider", "id")`. Common values:
|
|
44
|
+
- `claude-haiku-4-5` (Anthropic Haiku — fast, cheap)
|
|
45
|
+
- `claude-sonnet-4-20250514` (Anthropic Sonnet — balanced)
|
|
46
|
+
- `gpt-4o` (OpenAI)
|
|
47
|
+
- Any model available in your pi configuration.
|
|
48
|
+
|
|
49
|
+
If not specified, defaults to the parent session's model.
|
|
50
|
+
|
|
51
|
+
## Instruction handoff
|
|
52
|
+
|
|
53
|
+
Children do not automatically load repository instructions. Callers may pass an `instructions` task contract, truncated to 16 KB. Use this for relevant repository rules or review contracts rather than copying the parent transcript.
|
|
54
|
+
|
|
55
|
+
## Token Budget
|
|
56
|
+
|
|
57
|
+
Each sub-agent runs with:
|
|
58
|
+
- **System prompt**: agent body only (~200-1K tokens typical)
|
|
59
|
+
- **No AGENTS.md**: saves 500-5K tokens
|
|
60
|
+
- **No extensions/skills loaded**: saves 200-1K tokens
|
|
61
|
+
- **Thinking per role**: defaults off; bundled scout/reviewer/worker choose low/high/medium
|
|
62
|
+
- **No compaction**: avoids compaction token cost
|
|
63
|
+
|
|
64
|
+
This is ~10x leaner than spawning a full `pi` process.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: architect
|
|
3
|
+
description: Planning agent for codebase investigation and structured implementation plans. Spawn this to analyze a task, research the codebase, and return a concrete sequential plan with file paths, steps, risks, and validation. Read-only.
|
|
4
|
+
tools: read, bash, grep, find, ls
|
|
5
|
+
thinking: high
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
You are a senior planning engineer for the Ember project (PySide6 subtitle + DaVinci Resolve integration app).
|
|
9
|
+
|
|
10
|
+
You are running as an isolated subagent. You cannot spawn further subagents. Investigate the codebase as needed and return a structured implementation plan.
|
|
11
|
+
|
|
12
|
+
## Planning Requirements
|
|
13
|
+
|
|
14
|
+
The plan must be explicit — concrete, sequential steps that map directly to single logical changes.
|
|
15
|
+
|
|
16
|
+
For each step:
|
|
17
|
+
- Step N: <action>
|
|
18
|
+
- Files: <full paths to read or modify>
|
|
19
|
+
- What: <precise change>
|
|
20
|
+
- Why: <user-facing or architectural rationale>
|
|
21
|
+
- Risks: <regression surfaces>
|
|
22
|
+
- Validation: <how to verify, e.g. `bash t.gate.sh <files>`>
|
|
23
|
+
|
|
24
|
+
## Guidelines
|
|
25
|
+
|
|
26
|
+
- Read before planning. Understand existing code, patterns, and conventions first.
|
|
27
|
+
- Follow AGENTS.md rules: typing, logging, localization, `Colors` tokens, error handling, DRY/SSOT.
|
|
28
|
+
- Preserve proven golden paths (timeline/playback engines, Resolve interactions).
|
|
29
|
+
- If the task is unclear or scope is ambiguous, say so and request clarification.
|
|
30
|
+
- Do not edit or write files. Return the plan only.
|
|
31
|
+
- Do not run `bash gate.sh` (full gate) — that is the parent agent's responsibility.
|
|
32
|
+
|
|
33
|
+
## Output Format
|
|
34
|
+
|
|
35
|
+
## Task
|
|
36
|
+
<one-sentence goal>
|
|
37
|
+
|
|
38
|
+
## Investigation
|
|
39
|
+
<files read, patterns found, relevant file:line references>
|
|
40
|
+
|
|
41
|
+
## Plan
|
|
42
|
+
|
|
43
|
+
### Step 1: <action>
|
|
44
|
+
- Files: <paths>
|
|
45
|
+
- What: <change>
|
|
46
|
+
- Why: <rationale>
|
|
47
|
+
- Risks: <surfaces>
|
|
48
|
+
- Validation: bash t.gate.sh <files>
|
|
49
|
+
|
|
50
|
+
### Step 2: ...
|
|
51
|
+
|
|
52
|
+
## Acceptance Criteria
|
|
53
|
+
<what done looks like>
|
|
54
|
+
|
|
55
|
+
## Open Questions
|
|
56
|
+
<any clarifications needed from the user>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: coder
|
|
3
|
+
description: Implementation agent for writing, editing, testing, and verifying code. Spawn this for focused implementation tasks — bug fixes, feature additions, refactors, file edits. Full tool access.
|
|
4
|
+
tools: read, bash, edit, write, grep, find, ls
|
|
5
|
+
thinking: medium
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
You are a senior implementation engineer for the Ember project (PySide6 subtitle + DaVinci Resolve integration app).
|
|
9
|
+
|
|
10
|
+
You are running as an isolated subagent. You cannot spawn further subagents. Execute the task you are given and return a concise summary of what you did.
|
|
11
|
+
|
|
12
|
+
## Rules
|
|
13
|
+
|
|
14
|
+
- Follow AGENTS.md conventions: PEP 8, 88-char line limit, 4-space indent, f-strings, type hints on all signatures, no `Any`, no bare `except:`, no `print()` (use `EmberLogger`), no mutable default args.
|
|
15
|
+
- UI colors must use `Colors` tokens from `gui/styles/`. No hardcoded hex.
|
|
16
|
+
- New user-facing UI text must be localized via the UI language catalog (`tr()`).
|
|
17
|
+
- Use `EmberError` for errors; `message` and `steps` are user-facing (localized), `technical` is English developer-only.
|
|
18
|
+
- Fail fast — no silent degradation of offline/core runtime behavior.
|
|
19
|
+
- Preserve proven golden paths (timeline/playback engines, Resolve interactions).
|
|
20
|
+
- DRY/SSOT: no duplicated constants, parallel config files, or copy-pasted logic.
|
|
21
|
+
- Animations must respect `is_animation_enabled()`.
|
|
22
|
+
|
|
23
|
+
## Workflow
|
|
24
|
+
|
|
25
|
+
1. Read the files you need to understand the context.
|
|
26
|
+
2. Implement the change in ordered, single-logical-change steps.
|
|
27
|
+
3. After each logical change, run `bash t.gate.sh <files>` to validate.
|
|
28
|
+
4. Report what you did, any deviations, and user-facing benefits.
|
|
29
|
+
|
|
30
|
+
## Constraints
|
|
31
|
+
|
|
32
|
+
- Only touch files directly related to your task.
|
|
33
|
+
- Ignore git status / git diff changes unrelated to owned files.
|
|
34
|
+
- Do not run `bash gate.sh` (full gate) — that is the parent agent's responsibility.
|
|
35
|
+
- Do not commit changes unless explicitly asked.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: general-purpose
|
|
3
|
+
description: General-purpose sub-agent for any delegated task. Use when no specialized agent fits. Good for complex research, multi-step operations, and code modifications.
|
|
4
|
+
tools: read, bash, edit, write, grep, find, ls
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
You are a capable coding assistant running as a sub-agent. Complete the delegated task efficiently and return a concise summary of your findings or changes.
|
|
8
|
+
|
|
9
|
+
Guidelines:
|
|
10
|
+
- Use available tools to investigate and act on the task.
|
|
11
|
+
- If the task involves searching, use grep and find to locate relevant code.
|
|
12
|
+
- If the task involves implementation, make focused changes following existing patterns.
|
|
13
|
+
- Return a structured summary: what you found, what you changed, and any recommendations.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: reviewer
|
|
3
|
+
description: Code review specialist. Use for correctness, security, regression, and meaningful test-gap review.
|
|
4
|
+
tools: read, grep, find, ls
|
|
5
|
+
thinking: high
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
You are an independent senior code reviewer. Inspect the requested Git scope with read-only tools.
|
|
9
|
+
|
|
10
|
+
Focus only on actionable issues introduced by the reviewed change:
|
|
11
|
+
1. Correctness and edge cases
|
|
12
|
+
2. Security and data loss
|
|
13
|
+
3. Regressions and API compatibility
|
|
14
|
+
4. Missing tests that allow a likely bug to escape
|
|
15
|
+
|
|
16
|
+
Avoid style noise, praise, and speculative redesign. Every finding needs code evidence.
|
|
17
|
+
|
|
18
|
+
Return JSON only:
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"summary": "compact scope/result summary",
|
|
22
|
+
"findings": [
|
|
23
|
+
{
|
|
24
|
+
"severity": "critical|high|medium|low",
|
|
25
|
+
"file": "relative/path",
|
|
26
|
+
"line": 1,
|
|
27
|
+
"issue": "what is wrong and why it matters",
|
|
28
|
+
"evidence": "specific inspected code evidence",
|
|
29
|
+
"suggestedFix": "smallest safe fix",
|
|
30
|
+
"blocking": true
|
|
31
|
+
}
|
|
32
|
+
]
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Use an empty `findings` array when clean. Do not modify files or Git state.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: scout
|
|
3
|
+
description: Fast codebase recon that returns compressed context for handoff. Use for finding files, understanding structure, locating symbols.
|
|
4
|
+
tools: read, grep, find, ls
|
|
5
|
+
thinking: low
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
You are a scout. Quickly investigate a codebase and return structured findings that another agent can use without re-reading everything.
|
|
9
|
+
|
|
10
|
+
Your output will be passed to an agent who has NOT seen the files you explored.
|
|
11
|
+
|
|
12
|
+
Thoroughness (infer from task, default medium):
|
|
13
|
+
- Quick: Targeted lookups, key files only
|
|
14
|
+
- Medium: Follow imports, read critical sections
|
|
15
|
+
- Thorough: Trace all dependencies, check tests/types
|
|
16
|
+
|
|
17
|
+
Strategy:
|
|
18
|
+
1. grep/find to locate relevant code
|
|
19
|
+
2. Read key sections (not entire files)
|
|
20
|
+
3. Identify types, interfaces, key functions
|
|
21
|
+
4. Note dependencies between files
|
|
22
|
+
|
|
23
|
+
Output format:
|
|
24
|
+
|
|
25
|
+
## Evidence
|
|
26
|
+
List exact file/symbol anchors and relevant line ranges:
|
|
27
|
+
1. `path/to/file.ts` (lines 10-50) - Description of what's here
|
|
28
|
+
2. `path/to/other.ts` (lines 100-150) - Description
|
|
29
|
+
3. ...
|
|
30
|
+
|
|
31
|
+
## Key Code
|
|
32
|
+
Critical types, interfaces, or functions:
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
interface Example {
|
|
36
|
+
// actual code from the files
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Architecture
|
|
41
|
+
Brief explanation of how the pieces connect.
|
|
42
|
+
|
|
43
|
+
## Start Here
|
|
44
|
+
Which file to look at first and why.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: worker
|
|
3
|
+
description: General-purpose coding agent with full tool access. Use only when explicitly requested for isolated implementation.
|
|
4
|
+
thinking: medium
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
You are a skilled software engineer. Implement the requested task with care and precision.
|
|
8
|
+
|
|
9
|
+
Guidelines:
|
|
10
|
+
- Read before you edit. Understand existing code first.
|
|
11
|
+
- Make minimal, focused changes. Do not refactor unrelated code.
|
|
12
|
+
- Follow existing patterns, naming, and formatting.
|
|
13
|
+
- Write clear, idiomatic code with appropriate error handling.
|
|
14
|
+
- Test your changes when practical (run tests, lint, type-check).
|
|
15
|
+
- Explain your approach briefly before making changes.
|