@aprimediet/minion 1.0.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/LICENSE +21 -0
- package/README.md +92 -0
- package/agents/code-reviewer.md +23 -0
- package/agents/code-simplifier.md +12 -0
- package/agents/comment-analyzer.md +12 -0
- package/agents/debugger.md +19 -0
- package/agents/docs-writer.md +10 -0
- package/agents/explore.md +23 -0
- package/agents/general-purpose.md +20 -0
- package/agents/plan.md +20 -0
- package/agents/pr-test-analyzer.md +17 -0
- package/agents/silent-failure-hunter.md +14 -0
- package/agents/test-writer.md +10 -0
- package/agents/type-design-analyzer.md +13 -0
- package/agents.ts +223 -0
- package/index.ts +146 -0
- package/minion.json +17 -0
- package/package.json +36 -0
- package/project.ts +170 -0
- package/prompts/implement-and-review.md +10 -0
- package/prompts/implement.md +10 -0
- package/prompts/review.md +11 -0
- package/prompts/scout-and-plan.md +9 -0
- package/subagent.ts +766 -0
- package/tasks.ts +380 -0
- package/todo.ts +149 -0
package/index.ts
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @aprimediet/minion
|
|
3
|
+
*
|
|
4
|
+
* Claude-Code-style delegation for the pi coding agent:
|
|
5
|
+
* - todo_write (TodoWrite) + /todos
|
|
6
|
+
* - subagent (Task: single / parallel / chain, isolated pi subprocesses)
|
|
7
|
+
* - a bundled library of 12 specialized agents, with per-agent model config
|
|
8
|
+
*
|
|
9
|
+
* Agents are bundled inside the extension and loaded directly (no install step).
|
|
10
|
+
* The default model map (minion.json) is copied into ~/.pi/agent/ on first run.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import * as fs from "node:fs";
|
|
14
|
+
import * as path from "node:path";
|
|
15
|
+
import { type ExtensionAPI, type ExtensionContext, CONFIG_DIR_NAME, getAgentDir } from "@earendil-works/pi-coding-agent";
|
|
16
|
+
import { buildDelegationSystemPrompt, bundledAgentsDir, bundledModelsFile, setDefaultAgentModel } from "./agents.ts";
|
|
17
|
+
import { ensureProject, resolveProject } from "./project.ts";
|
|
18
|
+
import { registerSubagentTool } from "./subagent.ts";
|
|
19
|
+
import { buildResumePrompt, getTask, listTasks, registerTaskTool, renderBoard } from "./tasks.ts";
|
|
20
|
+
import { registerTodoTool } from "./todo.ts";
|
|
21
|
+
|
|
22
|
+
function copyAgentFiles(srcDir: string, destDir: string): { copied: number; skipped: number } {
|
|
23
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
24
|
+
let copied = 0;
|
|
25
|
+
let skipped = 0;
|
|
26
|
+
for (const name of fs.readdirSync(srcDir)) {
|
|
27
|
+
if (!name.endsWith(".md")) continue;
|
|
28
|
+
const dest = path.join(destDir, name);
|
|
29
|
+
if (fs.existsSync(dest)) {
|
|
30
|
+
skipped++;
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
fs.copyFileSync(path.join(srcDir, name), dest);
|
|
34
|
+
copied++;
|
|
35
|
+
}
|
|
36
|
+
return { copied, skipped };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export default function minionExtension(pi: ExtensionAPI): void {
|
|
40
|
+
registerTodoTool(pi);
|
|
41
|
+
registerSubagentTool(pi);
|
|
42
|
+
registerTaskTool(pi);
|
|
43
|
+
|
|
44
|
+
pi.registerFlag("default-agent-model", {
|
|
45
|
+
description: "Fallback model for subagents with no configured/frontmatter model",
|
|
46
|
+
type: "string",
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// Seed the per-agent model config into ~/.pi/agent/minion.json on first run (idempotent), and
|
|
50
|
+
// create the project workspace (~/.pi/projects/<id>/ + the cwd marker), keeping cwd clean.
|
|
51
|
+
pi.on("session_start", async (_e, ctx: ExtensionContext) => {
|
|
52
|
+
const flag = pi.getFlag("default-agent-model");
|
|
53
|
+
if (typeof flag === "string" && flag) setDefaultAgentModel(flag);
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
const target = path.join(getAgentDir(), "minion.json");
|
|
57
|
+
if (!fs.existsSync(target)) {
|
|
58
|
+
const src = bundledModelsFile();
|
|
59
|
+
if (fs.existsSync(src)) {
|
|
60
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
61
|
+
fs.copyFileSync(src, target);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
} catch {
|
|
65
|
+
/* non-fatal */
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
try {
|
|
69
|
+
await ensureProject(ctx.cwd);
|
|
70
|
+
} catch {
|
|
71
|
+
/* non-fatal */
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// Make pi aware, every turn, that it can delegate and which subagents exist — by appending a
|
|
76
|
+
// "Subagent delegation" section (with the live agent list) to the system prompt. Rebuilt per
|
|
77
|
+
// turn from base options, so it stays in sync with bundled/user/project agent changes.
|
|
78
|
+
// Also surface unfinished board tasks each turn so the agent resumes them by delegating to the
|
|
79
|
+
// designated agent (subagent + taskId). This is the "check status → delegate" behavior.
|
|
80
|
+
pi.on("before_agent_start", async (event, ctx) => {
|
|
81
|
+
const parts = [buildDelegationSystemPrompt(ctx.cwd), buildResumePrompt(ctx.cwd)].filter(Boolean);
|
|
82
|
+
if (parts.length === 0) return undefined;
|
|
83
|
+
return { systemPrompt: `${event.systemPrompt}\n\n${parts.join("\n\n")}` };
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Optional convenience: export the bundled agents (and model config) for editing / native use.
|
|
87
|
+
pi.registerCommand("minion", {
|
|
88
|
+
description: "minion: 'install-agents [--project]' exports the bundled agents for editing",
|
|
89
|
+
handler: async (args, ctx: ExtensionContext) => {
|
|
90
|
+
const tokens = (args ?? "").trim().split(/\s+/).filter(Boolean);
|
|
91
|
+
const sub = tokens[0];
|
|
92
|
+
if (sub !== "install-agents") {
|
|
93
|
+
if (ctx.hasUI) ctx.ui.notify("Usage: /minion install-agents [--project]", "info");
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const toProject = tokens.includes("--project");
|
|
97
|
+
const destAgents = toProject
|
|
98
|
+
? path.join(ctx.cwd, CONFIG_DIR_NAME, "agents")
|
|
99
|
+
: path.join(getAgentDir(), "agents");
|
|
100
|
+
if (ctx.hasUI) {
|
|
101
|
+
const ok = await ctx.ui.confirm(
|
|
102
|
+
"Export bundled agents?",
|
|
103
|
+
`Copy the 12 bundled agents to:\n${destAgents}\n(existing files are kept, not overwritten)`,
|
|
104
|
+
);
|
|
105
|
+
if (!ok) return;
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
const { copied, skipped } = copyAgentFiles(bundledAgentsDir(), destAgents);
|
|
109
|
+
// Also drop the model config in the matching scope if absent.
|
|
110
|
+
const modelsTarget = toProject
|
|
111
|
+
? path.join(ctx.cwd, CONFIG_DIR_NAME, "minion.json")
|
|
112
|
+
: path.join(getAgentDir(), "minion.json");
|
|
113
|
+
if (!fs.existsSync(modelsTarget) && fs.existsSync(bundledModelsFile())) {
|
|
114
|
+
fs.mkdirSync(path.dirname(modelsTarget), { recursive: true });
|
|
115
|
+
fs.copyFileSync(bundledModelsFile(), modelsTarget);
|
|
116
|
+
}
|
|
117
|
+
if (ctx.hasUI) ctx.ui.notify(`Exported ${copied} agent(s), skipped ${skipped} existing → ${destAgents}`, "info");
|
|
118
|
+
} catch (err) {
|
|
119
|
+
if (ctx.hasUI) ctx.ui.notify(`Export failed: ${(err as Error).message}`, "error");
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// View the persistent kanban board for this project.
|
|
125
|
+
pi.registerCommand("tasks", {
|
|
126
|
+
description: "tasks: show the project kanban board ('/tasks all' includes done/cancelled; '/tasks <id>' shows one)",
|
|
127
|
+
handler: async (args, ctx: ExtensionContext) => {
|
|
128
|
+
if (!ctx.hasUI) return;
|
|
129
|
+
const tokens = (args ?? "").trim().split(/\s+/).filter(Boolean);
|
|
130
|
+
const project = resolveProject(ctx.cwd);
|
|
131
|
+
if (tokens[0] && tokens[0] !== "all") {
|
|
132
|
+
const t = getTask(project.tasksDir, tokens[0]);
|
|
133
|
+
ctx.ui.notify(
|
|
134
|
+
t
|
|
135
|
+
? `${t.id} [${t.status}]${t.agent ? ` @${t.agent}` : ""}\n${t.title}\n\nInstruction:\n${t.instruction || "(none)"}`
|
|
136
|
+
: `No task ${tokens[0]}.`,
|
|
137
|
+
t ? "info" : "error",
|
|
138
|
+
);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
const all = listTasks(project.tasksDir);
|
|
142
|
+
const shown = tokens[0] === "all" ? all : all.filter((t) => t.status !== "done" && t.status !== "cancelled");
|
|
143
|
+
ctx.ui.notify(`Board (${project.id}):\n${renderBoard(shown)}`, "info");
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
}
|
package/minion.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"models": {
|
|
3
|
+
"*": "claude-sonnet-4-6",
|
|
4
|
+
"general-purpose": "claude-sonnet-4-6",
|
|
5
|
+
"explore": "claude-haiku-4-5",
|
|
6
|
+
"plan": "claude-sonnet-4-6",
|
|
7
|
+
"code-reviewer": "claude-opus-4-8",
|
|
8
|
+
"code-simplifier": "claude-sonnet-4-6",
|
|
9
|
+
"silent-failure-hunter": "claude-sonnet-4-6",
|
|
10
|
+
"type-design-analyzer": "claude-opus-4-8",
|
|
11
|
+
"comment-analyzer": "claude-haiku-4-5",
|
|
12
|
+
"pr-test-analyzer": "claude-sonnet-4-6",
|
|
13
|
+
"debugger": "claude-sonnet-4-6",
|
|
14
|
+
"test-writer": "claude-sonnet-4-6",
|
|
15
|
+
"docs-writer": "claude-haiku-4-5"
|
|
16
|
+
}
|
|
17
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@aprimediet/minion",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "TodoWrite + subagent/Task + a bundled library of 12 specialized agents for the pi coding agent.",
|
|
6
|
+
"keywords": ["pi-package"],
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/aprimediet/pi-minion.git"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/aprimediet/pi-minion/issues"
|
|
14
|
+
},
|
|
15
|
+
"homepage": "https://github.com/aprimediet/pi-minion#readme",
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public",
|
|
18
|
+
"registry": "https://registry.npmjs.org/"
|
|
19
|
+
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"prepublishOnly": "node -e \"const pkg=require('./package.json'); if(!pkg.files||pkg.files.length===0){console.error('files field empty — abort');process.exit(1)}; console.log('Publishing '+pkg.name+'@'+pkg.version+' with files:', pkg.files)\"",
|
|
22
|
+
"pack:dry": "npm pack --dry-run"
|
|
23
|
+
},
|
|
24
|
+
"pi": {
|
|
25
|
+
"extensions": ["./index.ts"],
|
|
26
|
+
"prompts": ["./prompts"]
|
|
27
|
+
},
|
|
28
|
+
"files": ["*.ts", "minion.json", "agents/**", "prompts/**", "README.md", "LICENSE"],
|
|
29
|
+
"peerDependencies": {
|
|
30
|
+
"@earendil-works/pi-coding-agent": "*",
|
|
31
|
+
"@earendil-works/pi-agent-core": "*",
|
|
32
|
+
"@earendil-works/pi-ai": "*",
|
|
33
|
+
"@earendil-works/pi-tui": "*",
|
|
34
|
+
"typebox": "*"
|
|
35
|
+
}
|
|
36
|
+
}
|
package/project.ts
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project identity + path layout for minion's persistent delegation/task board.
|
|
3
|
+
*
|
|
4
|
+
* The working tree stays clean: the only artifact written into <cwd>/.pi is a single identifier
|
|
5
|
+
* file `<project-id>.md`. Tasks, todos and delegation records live globally under
|
|
6
|
+
* ~/.pi/projects/<project-id>/.
|
|
7
|
+
*
|
|
8
|
+
* IMPORTANT: this is intentionally COMPATIBLE with @aprimediet/memory's project.ts — same id
|
|
9
|
+
* algorithm (`<slug>-<sha1(root)[:8]>`), same marker format (`pi-project: true` + `id`), same
|
|
10
|
+
* detection. So both extensions share ONE cwd marker and ONE ~/.pi/projects/<id>/ workspace.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import * as crypto from "node:crypto";
|
|
14
|
+
import * as fs from "node:fs";
|
|
15
|
+
import * as path from "node:path";
|
|
16
|
+
import { CONFIG_DIR_NAME, getAgentDir, parseFrontmatter, withFileMutationQueue } from "@earendil-works/pi-coding-agent";
|
|
17
|
+
|
|
18
|
+
export interface ProjectPaths {
|
|
19
|
+
id: string;
|
|
20
|
+
root: string;
|
|
21
|
+
configDir: string; // <root>/.pi
|
|
22
|
+
markerPath: string; // <root>/.pi/<id>.md
|
|
23
|
+
globalDir: string; // ~/.pi/projects/<id>
|
|
24
|
+
tasksDir: string; // <globalDir>/tasks
|
|
25
|
+
todosDir: string; // <globalDir>/todos
|
|
26
|
+
delegationsDir: string; // <globalDir>/delegations
|
|
27
|
+
projectJson: string; // <globalDir>/project.json
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function piHome(): string {
|
|
31
|
+
return path.dirname(getAgentDir()); // getAgentDir() === ~/.pi/agent
|
|
32
|
+
}
|
|
33
|
+
export function projectsRoot(): string {
|
|
34
|
+
return path.join(piHome(), "projects");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function slug(name: string): string {
|
|
38
|
+
const s = name
|
|
39
|
+
.toLowerCase()
|
|
40
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
41
|
+
.replace(/^-+|-+$/g, "")
|
|
42
|
+
.slice(0, 40);
|
|
43
|
+
return s || "project";
|
|
44
|
+
}
|
|
45
|
+
function pathHash(abs: string): string {
|
|
46
|
+
return crypto.createHash("sha1").update(abs).digest("hex").slice(0, 8);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function findProjectRoot(cwd: string): string {
|
|
50
|
+
let dir = cwd;
|
|
51
|
+
for (;;) {
|
|
52
|
+
if (fs.existsSync(path.join(dir, CONFIG_DIR_NAME)) || fs.existsSync(path.join(dir, ".git"))) return dir;
|
|
53
|
+
const parent = path.dirname(dir);
|
|
54
|
+
if (parent === dir) return cwd;
|
|
55
|
+
dir = parent;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function readMarker(configDir: string): { id: string; file: string } | null {
|
|
60
|
+
if (!fs.existsSync(configDir)) return null;
|
|
61
|
+
let names: string[];
|
|
62
|
+
try {
|
|
63
|
+
names = fs.readdirSync(configDir).filter((n) => n.endsWith(".md"));
|
|
64
|
+
} catch {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
for (const name of names) {
|
|
68
|
+
const file = path.join(configDir, name);
|
|
69
|
+
try {
|
|
70
|
+
const { frontmatter } = parseFrontmatter<Record<string, string>>(fs.readFileSync(file, "utf-8"));
|
|
71
|
+
if (frontmatter && String(frontmatter["pi-project"]) === "true" && frontmatter.id) return { id: frontmatter.id, file };
|
|
72
|
+
} catch {
|
|
73
|
+
/* not a marker */
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function pathsForId(id: string, root: string, configDir: string, markerPath: string): ProjectPaths {
|
|
80
|
+
const globalDir = path.join(projectsRoot(), id);
|
|
81
|
+
return {
|
|
82
|
+
id,
|
|
83
|
+
root,
|
|
84
|
+
configDir,
|
|
85
|
+
markerPath,
|
|
86
|
+
globalDir,
|
|
87
|
+
tasksDir: path.join(globalDir, "tasks"),
|
|
88
|
+
todosDir: path.join(globalDir, "todos"),
|
|
89
|
+
delegationsDir: path.join(globalDir, "delegations"),
|
|
90
|
+
projectJson: path.join(globalDir, "project.json"),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Resolve project identity for a cwd (read-only — creates nothing). */
|
|
95
|
+
export function resolveProject(cwd: string): ProjectPaths {
|
|
96
|
+
const root = findProjectRoot(cwd);
|
|
97
|
+
const configDir = path.join(root, CONFIG_DIR_NAME);
|
|
98
|
+
const existing = readMarker(configDir);
|
|
99
|
+
const id = existing?.id ?? `${slug(path.basename(root))}-${pathHash(root)}`;
|
|
100
|
+
const markerPath = existing?.file ?? path.join(configDir, `${id}.md`);
|
|
101
|
+
return pathsForId(id, root, configDir, markerPath);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function markerBody(id: string, createdISO: string): string {
|
|
105
|
+
return [
|
|
106
|
+
"---",
|
|
107
|
+
"pi-project: true",
|
|
108
|
+
`id: ${id}`,
|
|
109
|
+
`created: ${createdISO}`,
|
|
110
|
+
"---",
|
|
111
|
+
"# pi project",
|
|
112
|
+
"",
|
|
113
|
+
"This file marks this directory as a pi project. To keep your working tree clean, pi",
|
|
114
|
+
"extensions store their per-project data globally — NOT here — under:",
|
|
115
|
+
"",
|
|
116
|
+
` ~/.pi/projects/${id}/`,
|
|
117
|
+
"",
|
|
118
|
+
"minion stores here:",
|
|
119
|
+
"- `tasks/` persistent kanban task cards (delegation board)",
|
|
120
|
+
"- `todos/` in-session todo snapshots",
|
|
121
|
+
"- `delegations/` full records of every subagent delegation",
|
|
122
|
+
"",
|
|
123
|
+
"Managed by pi extensions (@aprimediet/minion, @aprimediet/memory). Safe to commit",
|
|
124
|
+
"(stable id) and safe to delete (recreated).",
|
|
125
|
+
"",
|
|
126
|
+
].join("\n");
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** Create the global directory structure + the cwd marker (idempotent). */
|
|
130
|
+
export async function ensureProject(cwd: string): Promise<ProjectPaths> {
|
|
131
|
+
const p = resolveProject(cwd);
|
|
132
|
+
const nowISO = new Date().toISOString();
|
|
133
|
+
|
|
134
|
+
for (const dir of [p.tasksDir, p.todosDir, p.delegationsDir]) fs.mkdirSync(dir, { recursive: true });
|
|
135
|
+
|
|
136
|
+
if (!fs.existsSync(p.markerPath)) {
|
|
137
|
+
fs.mkdirSync(p.configDir, { recursive: true });
|
|
138
|
+
await withFileMutationQueue(p.markerPath, async () => {
|
|
139
|
+
const tmp = `${p.markerPath}.tmp`;
|
|
140
|
+
await fs.promises.writeFile(tmp, markerBody(p.id, nowISO), { encoding: "utf-8", mode: 0o644 });
|
|
141
|
+
await fs.promises.rename(tmp, p.markerPath);
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// project.json — shared with the memory extension; preserve unknown keys, just update ours.
|
|
146
|
+
try {
|
|
147
|
+
let meta: Record<string, unknown> = {};
|
|
148
|
+
try {
|
|
149
|
+
meta = JSON.parse(fs.readFileSync(p.projectJson, "utf-8")) as Record<string, unknown>;
|
|
150
|
+
} catch {
|
|
151
|
+
/* first run */
|
|
152
|
+
}
|
|
153
|
+
meta.id = p.id;
|
|
154
|
+
meta.name = meta.name ?? path.basename(p.root);
|
|
155
|
+
const paths = Array.isArray(meta.paths) ? (meta.paths as string[]) : [];
|
|
156
|
+
if (!paths.includes(p.root)) paths.push(p.root);
|
|
157
|
+
meta.paths = paths;
|
|
158
|
+
meta.created = meta.created ?? nowISO;
|
|
159
|
+
meta.lastSeen = nowISO;
|
|
160
|
+
await withFileMutationQueue(p.projectJson, async () => {
|
|
161
|
+
const tmp = `${p.projectJson}.tmp`;
|
|
162
|
+
await fs.promises.writeFile(tmp, JSON.stringify(meta, null, 2), { encoding: "utf-8", mode: 0o600 });
|
|
163
|
+
await fs.promises.rename(tmp, p.projectJson);
|
|
164
|
+
});
|
|
165
|
+
} catch {
|
|
166
|
+
/* non-fatal */
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return p;
|
|
170
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: general-purpose implements, code-reviewer reviews, general-purpose applies the feedback
|
|
3
|
+
---
|
|
4
|
+
Use the `subagent` tool with the `chain` parameter for: $@
|
|
5
|
+
|
|
6
|
+
1. First, use the "general-purpose" agent to implement: $@
|
|
7
|
+
2. Then, use the "code-reviewer" agent to review the implementation from the previous step (use the {previous} placeholder).
|
|
8
|
+
3. Finally, use the "general-purpose" agent to apply the feedback from the review (use the {previous} placeholder).
|
|
9
|
+
|
|
10
|
+
Execute this as a chain, passing output between steps via {previous}.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Full implementation workflow — explore gathers context, plan designs, general-purpose implements
|
|
3
|
+
---
|
|
4
|
+
Use the `subagent` tool with the `chain` parameter to execute this workflow for: $@
|
|
5
|
+
|
|
6
|
+
1. First, use the "explore" agent to find all code relevant to: $@
|
|
7
|
+
2. Then, use the "plan" agent to create an implementation plan for "$@" using the context from the previous step (use the {previous} placeholder).
|
|
8
|
+
3. Finally, use the "general-purpose" agent to implement the plan from the previous step (use the {previous} placeholder).
|
|
9
|
+
|
|
10
|
+
Execute this as a single chain, passing output between steps via {previous}.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Multi-perspective review of the current changes (code-reviewer + silent-failure-hunter + type-design-analyzer)
|
|
3
|
+
---
|
|
4
|
+
Use the `subagent` tool with the `tasks` parameter to review the current changes in parallel, focusing on: $@
|
|
5
|
+
|
|
6
|
+
Run these three agents concurrently, each on the current diff for "$@":
|
|
7
|
+
- "code-reviewer" — bugs, style, guideline violations
|
|
8
|
+
- "silent-failure-hunter" — swallowed errors / bad fallbacks
|
|
9
|
+
- "type-design-analyzer" — type-design weaknesses
|
|
10
|
+
|
|
11
|
+
Then synthesize their findings into one prioritized review (Critical → Warning → Suggestion), de-duplicating overlaps.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Explore gathers context, plan creates an implementation plan (no implementation)
|
|
3
|
+
---
|
|
4
|
+
Use the `subagent` tool with the `chain` parameter for: $@
|
|
5
|
+
|
|
6
|
+
1. First, use the "explore" agent to find all code relevant to: $@
|
|
7
|
+
2. Then, use the "plan" agent to create an implementation plan for "$@" using the context from the previous step (use the {previous} placeholder).
|
|
8
|
+
|
|
9
|
+
Execute this as a chain, passing output between steps via {previous}. Do NOT implement — just return the plan.
|