pi-superpowers 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.
Files changed (27) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +83 -0
  3. package/banner.jpg +0 -0
  4. package/extensions/plan-tracker.ts +324 -0
  5. package/package.json +29 -0
  6. package/skills/brainstorming/SKILL.md +55 -0
  7. package/skills/dispatching-parallel-agents/SKILL.md +184 -0
  8. package/skills/executing-plans/SKILL.md +86 -0
  9. package/skills/finishing-a-development-branch/SKILL.md +202 -0
  10. package/skills/receiving-code-review/SKILL.md +213 -0
  11. package/skills/requesting-code-review/SKILL.md +111 -0
  12. package/skills/requesting-code-review/code-reviewer.md +146 -0
  13. package/skills/subagent-driven-development/SKILL.md +249 -0
  14. package/skills/subagent-driven-development/code-quality-reviewer-prompt.md +20 -0
  15. package/skills/subagent-driven-development/implementer-prompt.md +78 -0
  16. package/skills/subagent-driven-development/spec-reviewer-prompt.md +61 -0
  17. package/skills/systematic-debugging/SKILL.md +298 -0
  18. package/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
  19. package/skills/systematic-debugging/condition-based-waiting.md +115 -0
  20. package/skills/systematic-debugging/defense-in-depth.md +122 -0
  21. package/skills/systematic-debugging/find-polluter.sh +63 -0
  22. package/skills/systematic-debugging/root-cause-tracing.md +169 -0
  23. package/skills/test-driven-development/SKILL.md +373 -0
  24. package/skills/test-driven-development/testing-anti-patterns.md +299 -0
  25. package/skills/using-git-worktrees/SKILL.md +217 -0
  26. package/skills/verification-before-completion/SKILL.md +139 -0
  27. package/skills/writing-plans/SKILL.md +118 -0
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 coctostan
4
+ Copyright (c) 2025 Jesse Vincent (original skill content from obra/superpowers)
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,83 @@
1
+ # pi-superpowers
2
+
3
+ ![pi-superpowers banner](banner.jpg)
4
+
5
+ Structured workflow skills for [pi](https://github.com/badlogic/pi-mono), adapted from [Superpowers](https://github.com/obra/superpowers) by Jesse Vincent.
6
+
7
+ Brainstorming → Planning → TDD → Debugging → Code Review → Finishing — as composable skills your coding agent loads on demand.
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ pi install git:github.com/coctostan/pi-superpowers
13
+ ```
14
+
15
+ Or add to `.pi/settings.json` (project-level) or `~/.pi/agent/settings.json` (global):
16
+
17
+ ```json
18
+ {
19
+ "packages": ["git:github.com/coctostan/pi-superpowers"]
20
+ }
21
+ ```
22
+
23
+ ## What's Inside
24
+
25
+ ### Skills
26
+
27
+ | Skill | Description | Invoke |
28
+ |-------|-------------|--------|
29
+ | **brainstorming** | Socratic design refinement — questions, alternatives, incremental validation | `/skill:brainstorming` |
30
+ | **writing-plans** | Detailed implementation plans with bite-sized TDD tasks | `/skill:writing-plans` |
31
+ | **executing-plans** | Batch execution with checkpoints for architect review | `/skill:executing-plans` |
32
+ | **subagent-driven-development** | Fresh subagent per task with two-stage review | `/skill:subagent-driven-development` |
33
+ | **test-driven-development** | RED-GREEN-REFACTOR cycle (includes anti-patterns reference) | `/skill:test-driven-development` |
34
+ | **systematic-debugging** | 4-phase root cause investigation | `/skill:systematic-debugging` |
35
+ | **verification-before-completion** | Evidence before claims, always | `/skill:verification-before-completion` |
36
+ | **requesting-code-review** | Pre-merge review with severity categories | `/skill:requesting-code-review` |
37
+ | **receiving-code-review** | Technical evaluation of review feedback | `/skill:receiving-code-review` |
38
+ | **dispatching-parallel-agents** | Concurrent subagent workflows | `/skill:dispatching-parallel-agents` |
39
+ | **using-git-worktrees** | Isolated development branches | `/skill:using-git-worktrees` |
40
+ | **finishing-a-development-branch** | Merge/PR decision workflow | `/skill:finishing-a-development-branch` |
41
+
42
+ ### Plan Tracker
43
+
44
+ The `plan_tracker` tool replaces file-based task tracking. It stores state in the session and shows progress in the TUI:
45
+
46
+ ```
47
+ Tasks: ✓✓→○○ (2/5) Task 3: Recovery modes
48
+ ```
49
+
50
+ Usage by the agent:
51
+ ```
52
+ plan_tracker({ action: "init", tasks: ["Task 1: Setup", "Task 2: Core", ...] })
53
+ plan_tracker({ action: "update", index: 0, status: "complete" })
54
+ plan_tracker({ action: "status" })
55
+ plan_tracker({ action: "clear" })
56
+ ```
57
+
58
+ ## The Workflow
59
+
60
+ 1. **Brainstorm** — `/skill:brainstorming` refines your idea into a design document
61
+ 2. **Isolate** — `/skill:using-git-worktrees` creates a clean workspace
62
+ 3. **Plan** — `/skill:writing-plans` breaks work into bite-sized TDD tasks
63
+ 4. **Execute** — `/skill:executing-plans` or `/skill:subagent-driven-development` works through the plan
64
+ 5. **Verify** — `/skill:verification-before-completion` proves it works
65
+ 6. **Review** — `/skill:requesting-code-review` catches issues
66
+ 7. **Finish** — `/skill:finishing-a-development-branch` merges or creates a PR
67
+
68
+ Each skill cross-references related skills so the agent knows what to use next.
69
+
70
+ ## Subagent Dispatch
71
+
72
+ Skills that reference subagent dispatch (subagent-driven-development, requesting-code-review, dispatching-parallel-agents) work with any dispatch mechanism:
73
+
74
+ - **With pi-superteam:** The agent uses the `team` tool automatically
75
+ - **Without pi-superteam:** Run `pi -p "prompt"` in another terminal, or use tmux panes for parallel tasks
76
+
77
+ ## Attribution
78
+
79
+ Skill content adapted from [Superpowers](https://github.com/obra/superpowers) by Jesse Vincent, licensed under MIT.
80
+
81
+ ## License
82
+
83
+ MIT — see [LICENSE](LICENSE) for details.
package/banner.jpg ADDED
Binary file
@@ -0,0 +1,324 @@
1
+ /**
2
+ * Plan Tracker Extension
3
+ *
4
+ * A native pi tool for tracking plan progress.
5
+ * State is stored in tool result details for proper branching support.
6
+ * Shows a persistent TUI widget above the editor.
7
+ */
8
+
9
+ import { StringEnum } from "@mariozechner/pi-ai";
10
+ import type { ExtensionAPI, ExtensionContext, Theme } from "@mariozechner/pi-coding-agent";
11
+ import { Text } from "@mariozechner/pi-tui";
12
+ import { Type, type Static } from "@sinclair/typebox";
13
+
14
+ type TaskStatus = "pending" | "in_progress" | "complete";
15
+
16
+ interface Task {
17
+ name: string;
18
+ status: TaskStatus;
19
+ }
20
+
21
+ interface PlanTrackerDetails {
22
+ action: "init" | "update" | "status" | "clear";
23
+ tasks: Task[];
24
+ error?: string;
25
+ }
26
+
27
+ const PlanTrackerParams = Type.Object({
28
+ action: StringEnum(["init", "update", "status", "clear"] as const, {
29
+ description: "Action to perform",
30
+ }),
31
+ tasks: Type.Optional(
32
+ Type.Array(Type.String(), {
33
+ description: "Task names (for init)",
34
+ })
35
+ ),
36
+ index: Type.Optional(
37
+ Type.Integer({
38
+ minimum: 0,
39
+ description: "Task index, 0-based (for update)",
40
+ })
41
+ ),
42
+ status: Type.Optional(
43
+ StringEnum(["pending", "in_progress", "complete"] as const, {
44
+ description: "New status (for update)",
45
+ })
46
+ ),
47
+ });
48
+
49
+ export type PlanTrackerInput = Static<typeof PlanTrackerParams>;
50
+
51
+ function formatWidget(tasks: Task[], theme: Theme): string {
52
+ if (tasks.length === 0) return "";
53
+
54
+ const complete = tasks.filter((t) => t.status === "complete").length;
55
+ const icons = tasks
56
+ .map((t) => {
57
+ switch (t.status) {
58
+ case "complete":
59
+ return theme.fg("success", "✓");
60
+ case "in_progress":
61
+ return theme.fg("warning", "→");
62
+ default:
63
+ return theme.fg("dim", "○");
64
+ }
65
+ })
66
+ .join("");
67
+
68
+ // Find current task (first in_progress, or first pending)
69
+ const current =
70
+ tasks.find((t) => t.status === "in_progress") ??
71
+ tasks.find((t) => t.status === "pending");
72
+ const currentName = current ? ` ${current.name}` : "";
73
+
74
+ return `${theme.fg("muted", "Tasks:")} ${icons} ${theme.fg("muted", `(${complete}/${tasks.length})`)}${currentName}`;
75
+ }
76
+
77
+ function formatStatus(tasks: Task[]): string {
78
+ if (tasks.length === 0) return "No plan active.";
79
+
80
+ const complete = tasks.filter((t) => t.status === "complete").length;
81
+ const inProgress = tasks.filter((t) => t.status === "in_progress").length;
82
+ const pending = tasks.filter((t) => t.status === "pending").length;
83
+
84
+ const lines: string[] = [];
85
+ lines.push(`Plan: ${complete}/${tasks.length} complete (${inProgress} in progress, ${pending} pending)`);
86
+ lines.push("");
87
+ for (let i = 0; i < tasks.length; i++) {
88
+ const t = tasks[i];
89
+ const icon =
90
+ t.status === "complete" ? "✓" : t.status === "in_progress" ? "→" : "○";
91
+ lines.push(` ${icon} [${i}] ${t.name}`);
92
+ }
93
+ return lines.join("\n");
94
+ }
95
+
96
+ export default function (pi: ExtensionAPI) {
97
+ let tasks: Task[] = [];
98
+
99
+ const reconstructState = (ctx: ExtensionContext) => {
100
+ tasks = [];
101
+ for (const entry of ctx.sessionManager.getBranch()) {
102
+ if (entry.type !== "message") continue;
103
+ const msg = entry.message;
104
+ if (msg.role !== "toolResult" || msg.toolName !== "plan_tracker") continue;
105
+ const details = msg.details as PlanTrackerDetails | undefined;
106
+ if (details && !details.error) {
107
+ tasks = details.tasks;
108
+ }
109
+ }
110
+ };
111
+
112
+ const updateWidget = (ctx: ExtensionContext) => {
113
+ if (!ctx.hasUI) return;
114
+ if (tasks.length === 0) {
115
+ ctx.ui.setWidget("plan_tracker", undefined);
116
+ } else {
117
+ ctx.ui.setWidget("plan_tracker", (_tui, theme) => {
118
+ return new Text(formatWidget(tasks, theme), 0, 0);
119
+ });
120
+ }
121
+ };
122
+
123
+ // Reconstruct state + widget on session events
124
+ for (const event of [
125
+ "session_start",
126
+ "session_switch",
127
+ "session_fork",
128
+ "session_tree",
129
+ ] as const) {
130
+ pi.on(event, async (_event, ctx) => {
131
+ reconstructState(ctx);
132
+ updateWidget(ctx);
133
+ });
134
+ }
135
+
136
+ pi.registerTool({
137
+ name: "plan_tracker",
138
+ label: "Plan Tracker",
139
+ description:
140
+ "Track implementation plan progress. Actions: init (set task list), update (change task status), status (show current state), clear (remove plan).",
141
+ parameters: PlanTrackerParams,
142
+
143
+ async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
144
+ switch (params.action) {
145
+ case "init": {
146
+ if (!params.tasks || params.tasks.length === 0) {
147
+ return {
148
+ content: [{ type: "text", text: "Error: tasks array required for init" }],
149
+ details: {
150
+ action: "init",
151
+ tasks: [...tasks],
152
+ error: "tasks required",
153
+ } as PlanTrackerDetails,
154
+ };
155
+ }
156
+ tasks = params.tasks.map((name) => ({ name, status: "pending" as TaskStatus }));
157
+ updateWidget(ctx);
158
+ return {
159
+ content: [
160
+ {
161
+ type: "text",
162
+ text: `Plan initialized with ${tasks.length} tasks.\n${formatStatus(tasks)}`,
163
+ },
164
+ ],
165
+ details: { action: "init", tasks: [...tasks] } as PlanTrackerDetails,
166
+ };
167
+ }
168
+
169
+ case "update": {
170
+ if (params.index === undefined || !params.status) {
171
+ return {
172
+ content: [
173
+ { type: "text", text: "Error: index and status required for update" },
174
+ ],
175
+ details: {
176
+ action: "update",
177
+ tasks: [...tasks],
178
+ error: "index and status required",
179
+ } as PlanTrackerDetails,
180
+ };
181
+ }
182
+ if (tasks.length === 0) {
183
+ return {
184
+ content: [{ type: "text", text: "Error: no plan active. Use init first." }],
185
+ details: {
186
+ action: "update",
187
+ tasks: [],
188
+ error: "no plan active",
189
+ } as PlanTrackerDetails,
190
+ };
191
+ }
192
+ if (params.index < 0 || params.index >= tasks.length) {
193
+ return {
194
+ content: [
195
+ {
196
+ type: "text",
197
+ text: `Error: index ${params.index} out of range (0-${tasks.length - 1})`,
198
+ },
199
+ ],
200
+ details: {
201
+ action: "update",
202
+ tasks: [...tasks],
203
+ error: `index ${params.index} out of range`,
204
+ } as PlanTrackerDetails,
205
+ };
206
+ }
207
+ tasks[params.index].status = params.status;
208
+ updateWidget(ctx);
209
+ return {
210
+ content: [
211
+ {
212
+ type: "text",
213
+ text: `Task ${params.index} "${tasks[params.index].name}" → ${params.status}\n${formatStatus(tasks)}`,
214
+ },
215
+ ],
216
+ details: { action: "update", tasks: [...tasks] } as PlanTrackerDetails,
217
+ };
218
+ }
219
+
220
+ case "status": {
221
+ return {
222
+ content: [{ type: "text", text: formatStatus(tasks) }],
223
+ details: { action: "status", tasks: [...tasks] } as PlanTrackerDetails,
224
+ };
225
+ }
226
+
227
+ case "clear": {
228
+ const count = tasks.length;
229
+ tasks = [];
230
+ updateWidget(ctx);
231
+ return {
232
+ content: [
233
+ {
234
+ type: "text",
235
+ text: count > 0 ? `Plan cleared (${count} tasks removed).` : "No plan was active.",
236
+ },
237
+ ],
238
+ details: { action: "clear", tasks: [] } as PlanTrackerDetails,
239
+ };
240
+ }
241
+
242
+ default:
243
+ return {
244
+ content: [{ type: "text", text: `Unknown action: ${params.action}` }],
245
+ details: {
246
+ action: "status",
247
+ tasks: [...tasks],
248
+ error: `unknown action`,
249
+ } as PlanTrackerDetails,
250
+ };
251
+ }
252
+ },
253
+
254
+ renderCall(args, theme) {
255
+ let text = theme.fg("toolTitle", theme.bold("plan_tracker "));
256
+ text += theme.fg("muted", args.action);
257
+ if (args.action === "update" && args.index !== undefined) {
258
+ text += ` ${theme.fg("accent", `[${args.index}]`)}`;
259
+ if (args.status) text += ` → ${theme.fg("dim", args.status)}`;
260
+ }
261
+ if (args.action === "init" && args.tasks) {
262
+ text += ` ${theme.fg("dim", `(${args.tasks.length} tasks)`)}`;
263
+ }
264
+ return new Text(text, 0, 0);
265
+ },
266
+
267
+ renderResult(result, _options, theme) {
268
+ const details = result.details as PlanTrackerDetails | undefined;
269
+ if (!details) {
270
+ const text = result.content[0];
271
+ return new Text(text?.type === "text" ? text.text : "", 0, 0);
272
+ }
273
+
274
+ if (details.error) {
275
+ return new Text(theme.fg("error", `Error: ${details.error}`), 0, 0);
276
+ }
277
+
278
+ const taskList = details.tasks;
279
+ switch (details.action) {
280
+ case "init":
281
+ return new Text(
282
+ theme.fg("success", "✓ ") +
283
+ theme.fg("muted", `Plan initialized with ${taskList.length} tasks`),
284
+ 0,
285
+ 0
286
+ );
287
+ case "update": {
288
+ const complete = taskList.filter((t) => t.status === "complete").length;
289
+ return new Text(
290
+ theme.fg("success", "✓ ") +
291
+ theme.fg("muted", `Updated (${complete}/${taskList.length} complete)`),
292
+ 0,
293
+ 0
294
+ );
295
+ }
296
+ case "status": {
297
+ if (taskList.length === 0) {
298
+ return new Text(theme.fg("dim", "No plan active"), 0, 0);
299
+ }
300
+ const complete = taskList.filter((t) => t.status === "complete").length;
301
+ let text = theme.fg("muted", `${complete}/${taskList.length} complete`);
302
+ for (const t of taskList) {
303
+ const icon =
304
+ t.status === "complete"
305
+ ? theme.fg("success", "✓")
306
+ : t.status === "in_progress"
307
+ ? theme.fg("warning", "→")
308
+ : theme.fg("dim", "○");
309
+ text += `\n${icon} ${theme.fg("muted", t.name)}`;
310
+ }
311
+ return new Text(text, 0, 0);
312
+ }
313
+ case "clear":
314
+ return new Text(
315
+ theme.fg("success", "✓ ") + theme.fg("muted", "Plan cleared"),
316
+ 0,
317
+ 0
318
+ );
319
+ default:
320
+ return new Text(theme.fg("dim", "Done"), 0, 0);
321
+ }
322
+ },
323
+ });
324
+ }
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "pi-superpowers",
3
+ "version": "0.1.0",
4
+ "description": "Superpowers workflow skills adapted for pi",
5
+ "keywords": ["pi-package"],
6
+ "license": "MIT",
7
+ "author": "coctostan",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/coctostan/pi-superpowers.git"
11
+ },
12
+ "files": [
13
+ "extensions/",
14
+ "skills/",
15
+ "banner.jpg",
16
+ "LICENSE",
17
+ "README.md"
18
+ ],
19
+ "pi": {
20
+ "extensions": ["extensions/plan-tracker.ts"],
21
+ "skills": ["skills"]
22
+ },
23
+ "peerDependencies": {
24
+ "@mariozechner/pi-ai": "*",
25
+ "@mariozechner/pi-coding-agent": "*",
26
+ "@mariozechner/pi-tui": "*",
27
+ "@sinclair/typebox": "*"
28
+ }
29
+ }
@@ -0,0 +1,55 @@
1
+ ---
2
+ name: brainstorming
3
+ description: "You MUST use this before any creative work - creating features, building components, adding functionality, or modifying behavior. Explores user intent, requirements and design before implementation."
4
+ ---
5
+
6
+ > **Related skills:** Consider `/skill:using-git-worktrees` to set up an isolated workspace, then `/skill:writing-plans` for implementation planning.
7
+
8
+ # Brainstorming Ideas Into Designs
9
+
10
+ ## Overview
11
+
12
+ Help turn ideas into fully formed designs and specs through natural collaborative dialogue.
13
+
14
+ Start by understanding the current project context, then ask questions one at a time to refine the idea. Once you understand what you're building, present the design in small sections (200-300 words), checking after each section whether it looks right so far.
15
+
16
+ ## The Process
17
+
18
+ **Understanding the idea:**
19
+ - Check out the current project state first (files, docs, recent commits)
20
+ - Ask questions one at a time to refine the idea
21
+ - Prefer multiple choice questions when possible, but open-ended is fine too
22
+ - Only one question per message - if a topic needs more exploration, break it into multiple questions
23
+ - Focus on understanding: purpose, constraints, success criteria
24
+
25
+ **Exploring approaches:**
26
+ - Propose 2-3 different approaches with trade-offs
27
+ - Present options conversationally with your recommendation and reasoning
28
+ - Lead with your recommended option and explain why
29
+
30
+ **Presenting the design:**
31
+ - Once you believe you understand what you're building, present the design
32
+ - Break it into sections of 200-300 words
33
+ - Ask after each section whether it looks right so far
34
+ - Cover: architecture, components, data flow, error handling, testing
35
+ - Be ready to go back and clarify if something doesn't make sense
36
+
37
+ ## After the Design
38
+
39
+ **Documentation:**
40
+ - Write the validated design to `docs/plans/YYYY-MM-DD-<topic>-design.md`
41
+ - Commit the design document to git
42
+
43
+ **Implementation (if continuing):**
44
+ - Ask: "Ready to set up for implementation?"
45
+ - Use `/skill:using-git-worktrees` to create isolated workspace
46
+ - Use `/skill:writing-plans` to create detailed implementation plan
47
+
48
+ ## Key Principles
49
+
50
+ - **One question at a time** - Don't overwhelm with multiple questions
51
+ - **Multiple choice preferred** - Easier to answer than open-ended when possible
52
+ - **YAGNI ruthlessly** - Remove unnecessary features from all designs
53
+ - **Explore alternatives** - Always propose 2-3 approaches before settling
54
+ - **Incremental validation** - Present design in sections, validate each
55
+ - **Be flexible** - Go back and clarify when something doesn't make sense