superpowers-opencode-fork-dev-test 1.0.2 → 1.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/.opencode/plugins/superpowers.js +203 -129
- package/package.json +3 -2
- package/skills/brainstorming/SKILL.md +54 -0
- package/skills/dispatching-parallel-agents/SKILL.md +180 -0
- package/skills/executing-plans/SKILL.md +76 -0
- package/skills/finishing-a-development-branch/SKILL.md +200 -0
- package/skills/receiving-code-review/SKILL.md +213 -0
- package/skills/requesting-code-review/SKILL.md +105 -0
- package/skills/requesting-code-review/code-reviewer.md +146 -0
- package/skills/subagent-driven-development/SKILL.md +240 -0
- package/skills/subagent-driven-development/code-quality-reviewer-prompt.md +20 -0
- package/skills/subagent-driven-development/implementer-prompt.md +78 -0
- package/skills/subagent-driven-development/spec-reviewer-prompt.md +61 -0
- package/skills/systematic-debugging/CREATION-LOG.md +119 -0
- package/skills/systematic-debugging/SKILL.md +296 -0
- package/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
- package/skills/systematic-debugging/condition-based-waiting.md +115 -0
- package/skills/systematic-debugging/defense-in-depth.md +122 -0
- package/skills/systematic-debugging/find-polluter.sh +63 -0
- package/skills/systematic-debugging/root-cause-tracing.md +169 -0
- package/skills/systematic-debugging/test-academic.md +14 -0
- package/skills/systematic-debugging/test-pressure-1.md +58 -0
- package/skills/systematic-debugging/test-pressure-2.md +68 -0
- package/skills/systematic-debugging/test-pressure-3.md +69 -0
- package/skills/test-driven-development/SKILL.md +371 -0
- package/skills/test-driven-development/testing-anti-patterns.md +299 -0
- package/skills/using-git-worktrees/SKILL.md +217 -0
- package/skills/using-superpowers/SKILL.md +87 -0
- package/skills/verification-before-completion/SKILL.md +139 -0
- package/skills/writing-plans/SKILL.md +116 -0
- package/skills/writing-skills/SKILL.md +655 -0
- package/skills/writing-skills/anthropic-best-practices.md +1150 -0
- package/skills/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
- package/skills/writing-skills/graphviz-conventions.dot +172 -0
- package/skills/writing-skills/persuasion-principles.md +187 -0
- package/skills/writing-skills/render-graphs.js +168 -0
- package/skills/writing-skills/testing-skills-with-subagents.md +384 -0
|
@@ -47,21 +47,38 @@ const normalizePath = (p, homeDir) => {
|
|
|
47
47
|
};
|
|
48
48
|
|
|
49
49
|
export const SuperpowersPlugin = async ({ client, directory }) => {
|
|
50
|
+
console.log('[superpowers DEBUG] Plugin loading...');
|
|
51
|
+
console.log('[superpowers DEBUG] __dirname:', __dirname);
|
|
52
|
+
console.log('[superpowers DEBUG] Platform:', os.platform());
|
|
53
|
+
console.log('[superpowers DEBUG] Client name:', client?.app?.name);
|
|
54
|
+
console.log('[superpowers DEBUG] Directory:', directory);
|
|
55
|
+
|
|
50
56
|
const homeDir = os.homedir();
|
|
51
57
|
const superpowersSkillsDir = path.resolve(__dirname, '../../skills');
|
|
52
58
|
const envConfigDir = normalizePath(process.env.OPENCODE_CONFIG_DIR, homeDir);
|
|
53
59
|
const configDir = envConfigDir || path.join(homeDir, '.config/opencode');
|
|
54
60
|
|
|
61
|
+
console.log('[superpowers DEBUG] Home dir:', homeDir);
|
|
62
|
+
console.log('[superpowers DEBUG] Config dir:', configDir);
|
|
63
|
+
console.log('[superpowers DEBUG] Skills dir:', superpowersSkillsDir);
|
|
64
|
+
|
|
55
65
|
// Helper to generate bootstrap content
|
|
56
66
|
const getBootstrapContent = () => {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
67
|
+
try {
|
|
68
|
+
// Try to load using-superpowers skill
|
|
69
|
+
const skillPath = path.join(superpowersSkillsDir, 'using-superpowers', 'SKILL.md');
|
|
70
|
+
console.log('[superpowers DEBUG] Looking for bootstrap skill at:', skillPath);
|
|
60
71
|
|
|
61
|
-
|
|
62
|
-
|
|
72
|
+
if (!fs.existsSync(skillPath)) {
|
|
73
|
+
console.log('[superpowers DEBUG] Bootstrap skill not found at:', skillPath);
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
63
76
|
|
|
64
|
-
|
|
77
|
+
console.log('[superpowers DEBUG] Found bootstrap skill, reading content...');
|
|
78
|
+
const fullContent = fs.readFileSync(skillPath, 'utf8');
|
|
79
|
+
const { content } = extractAndStripFrontmatter(fullContent);
|
|
80
|
+
|
|
81
|
+
const toolMapping = `**Tool Mapping for OpenCode:**
|
|
65
82
|
When skills reference tools you don't have, substitute OpenCode equivalents:
|
|
66
83
|
- \`TodoWrite\` → \`update_plan\`
|
|
67
84
|
- \`Task\` tool with subagents → Use OpenCode's subagent system (@mention)
|
|
@@ -72,7 +89,8 @@ When skills reference tools you don't have, substitute OpenCode equivalents:
|
|
|
72
89
|
Superpowers skills are in \`${configDir}/skills/superpowers/\`
|
|
73
90
|
Use OpenCode's native \`skill\` tool to list and load skills.`;
|
|
74
91
|
|
|
75
|
-
|
|
92
|
+
console.log('[superpowers DEBUG] Bootstrap content generated successfully');
|
|
93
|
+
return `<EXTREMELY_IMPORTANT>
|
|
76
94
|
You have superpowers.
|
|
77
95
|
|
|
78
96
|
**IMPORTANT: The using-superpowers skill content is included below. It is ALREADY LOADED - you are currently following it. Do NOT use the skill tool to load "using-superpowers" again - that would be redundant.**
|
|
@@ -81,6 +99,10 @@ ${content}
|
|
|
81
99
|
|
|
82
100
|
${toolMapping}
|
|
83
101
|
</EXTREMELY_IMPORTANT>`;
|
|
102
|
+
} catch (error) {
|
|
103
|
+
console.error('[superpowers DEBUG] Error generating bootstrap content:', error);
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
84
106
|
};
|
|
85
107
|
|
|
86
108
|
// Platform detection: only run on Linux or macOS
|
|
@@ -150,156 +172,208 @@ ${toolMapping}
|
|
|
150
172
|
|
|
151
173
|
// Autoinstall handler - entry point for all autoinstall logic
|
|
152
174
|
const handleAutoinstall = async () => {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
175
|
+
console.log('[superpowers DEBUG] handleAutoinstall called');
|
|
176
|
+
console.log('[superpowers DEBUG] Platform:', platform);
|
|
177
|
+
console.log('[superpowers DEBUG] isOpencode:', isOpencode);
|
|
178
|
+
console.log('[superpowers DEBUG] isSupportedPlatform:', isSupportedPlatform);
|
|
158
179
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
180
|
+
try {
|
|
181
|
+
// Exit early on unsupported platforms
|
|
182
|
+
if (!isSupportedPlatform) {
|
|
183
|
+
console.log('[superpowers DEBUG] Skipping autoinstall - unsupported platform:', platform);
|
|
184
|
+
client.app.log('superpowers: Skipping autoinstall - unsupported platform:', platform);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
164
187
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
client.app.log('superpowers: Config directory:', configDir);
|
|
170
|
-
|
|
171
|
-
const superpowersDir = path.join(configDir, 'superpowers');
|
|
172
|
-
const pluginSymlinkPath = path.join(configDir, 'plugins/superpowers.js');
|
|
173
|
-
const skillsSymlinkPath = path.join(configDir, 'skills/superpowers');
|
|
174
|
-
const targetPluginPath = path.join(superpowersDir, '.opencode/plugins/superpowers.js');
|
|
175
|
-
const targetSkillsPath = path.join(superpowersDir, 'skills');
|
|
176
|
-
|
|
177
|
-
// Task 4: Implement git clone if not exists
|
|
178
|
-
if (!fs.existsSync(superpowersDir)) {
|
|
179
|
-
client.app.log('superpowers: Superpowers directory not found, cloning repository...');
|
|
180
|
-
try {
|
|
181
|
-
await $`git clone git+https://github.com/obra/superpowers.git ${superpowersDir}`;
|
|
182
|
-
client.app.log('superpowers: Successfully cloned superpowers repository');
|
|
183
|
-
} catch (error) {
|
|
184
|
-
if (error.message.includes('git')) {
|
|
185
|
-
client.app.log('superpowers: Error: Git is not installed. Please install git to continue.');
|
|
186
|
-
} else {
|
|
187
|
-
client.app.log('superpowers: Failed to clone repository:', error.message);
|
|
188
|
-
}
|
|
188
|
+
// Exit early if not running in OpenCode
|
|
189
|
+
if (!isOpencode) {
|
|
190
|
+
console.log('[superpowers DEBUG] Skipping autoinstall - not running in OpenCode');
|
|
191
|
+
client.app.log('superpowers: Skipping autoinstall - not running in OpenCode');
|
|
189
192
|
return;
|
|
190
193
|
}
|
|
191
|
-
} else {
|
|
192
|
-
client.app.log('superpowers: Superpowers directory exists at', superpowersDir);
|
|
193
|
-
}
|
|
194
194
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
195
|
+
// Read configuration from directory/opencode.json
|
|
196
|
+
const config = readConfig();
|
|
197
|
+
|
|
198
|
+
console.log('[superpowers DEBUG] Autoinstall starting...');
|
|
199
|
+
console.log('[superpowers DEBUG] Config directory:', configDir);
|
|
200
|
+
client.app.log('superpowers: Autoinstall starting...');
|
|
201
|
+
client.app.log('superpowers: Config directory:', configDir);
|
|
202
|
+
|
|
203
|
+
const superpowersDir = path.join(configDir, 'superpowers');
|
|
204
|
+
const pluginSymlinkPath = path.join(configDir, 'plugins/superpowers.js');
|
|
205
|
+
const skillsSymlinkPath = path.join(configDir, 'skills/superpowers');
|
|
206
|
+
const targetPluginPath = path.join(superpowersDir, '.opencode/plugins/superpowers.js');
|
|
207
|
+
const targetSkillsPath = path.join(superpowersDir, 'skills');
|
|
208
|
+
|
|
209
|
+
console.log('[superpowers DEBUG] superpowersDir:', superpowersDir);
|
|
210
|
+
console.log('[superpowers DEBUG] Plugin symlink path:', pluginSymlinkPath);
|
|
211
|
+
console.log('[superpowers DEBUG] Skills symlink path:', skillsSymlinkPath);
|
|
212
|
+
|
|
213
|
+
// Task 4: Implement git clone if not exists
|
|
214
|
+
if (!fs.existsSync(superpowersDir)) {
|
|
215
|
+
console.log('[superpowers DEBUG] Superpowers directory not found, cloning...');
|
|
216
|
+
client.app.log('superpowers: Superpowers directory not found, cloning repository...');
|
|
217
|
+
try {
|
|
218
|
+
await $`git clone git+https://github.com/obra/superpowers.git ${superpowersDir}`;
|
|
219
|
+
console.log('[superpowers DEBUG] Successfully cloned repository');
|
|
220
|
+
client.app.log('superpowers: Successfully cloned superpowers repository');
|
|
221
|
+
} catch (error) {
|
|
222
|
+
console.error('[superpowers DEBUG] Clone error:', error);
|
|
223
|
+
if (error.message.includes('git')) {
|
|
224
|
+
client.app.log('superpowers: Error: Git is not installed. Please install git to continue.');
|
|
225
|
+
} else {
|
|
226
|
+
client.app.log('superpowers: Failed to clone repository:', error.message);
|
|
227
|
+
}
|
|
228
|
+
return;
|
|
202
229
|
}
|
|
203
|
-
}
|
|
204
|
-
|
|
230
|
+
} else {
|
|
231
|
+
console.log('[superpowers DEBUG] Superpowers directory exists:', superpowersDir);
|
|
232
|
+
client.app.log('superpowers: Superpowers directory exists at', superpowersDir);
|
|
205
233
|
}
|
|
206
234
|
|
|
207
|
-
//
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
235
|
+
// Task 5: Implement symlink creation/removal (idempotent)
|
|
236
|
+
const createSymlink = (source, target) => {
|
|
237
|
+
console.log('[superpowers DEBUG] Creating symlink:', target, '→', source);
|
|
238
|
+
try {
|
|
239
|
+
// Remove existing symlink or file if it exists
|
|
240
|
+
if (fs.existsSync(target) || fs.lstatSync(target).isSymbolicLink()) {
|
|
241
|
+
console.log('[superpowers DEBUG] Removing existing symlink at:', target);
|
|
242
|
+
client.app.log('superpowers: Removing existing symlink at', target);
|
|
243
|
+
fs.unlinkSync(target);
|
|
244
|
+
}
|
|
245
|
+
} catch (error) {
|
|
246
|
+
// Ignore errors if target doesn't exist
|
|
247
|
+
console.log('[superpowers DEBUG] Error checking/removing existing symlink:', error.message);
|
|
248
|
+
}
|
|
213
249
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
fs.
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
};
|
|
250
|
+
// Ensure parent directory exists
|
|
251
|
+
const parentDir = path.dirname(target);
|
|
252
|
+
if (!fs.existsSync(parentDir)) {
|
|
253
|
+
console.log('[superpowers DEBUG] Creating parent directory:', parentDir);
|
|
254
|
+
client.app.log('superpowers: Creating parent directory', parentDir);
|
|
255
|
+
fs.mkdirSync(parentDir, { recursive: true });
|
|
256
|
+
}
|
|
222
257
|
|
|
223
|
-
|
|
224
|
-
|
|
258
|
+
// Create symlink
|
|
259
|
+
try {
|
|
260
|
+
fs.symlinkSync(source, target);
|
|
261
|
+
console.log('[superpowers DEBUG] Successfully created symlink');
|
|
262
|
+
client.app.log('superpowers: Created symlink', target, '→', source);
|
|
263
|
+
} catch (error) {
|
|
264
|
+
console.error('[superpowers DEBUG] Symlink creation error:', error);
|
|
265
|
+
client.app.log('superpowers: Failed to create symlink', target, '→', source, ':', error.message);
|
|
266
|
+
}
|
|
267
|
+
};
|
|
225
268
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
if (!fs.existsSync(gitDir)) {
|
|
231
|
-
client.app.log('superpowers: Not a git repository, skipping update check');
|
|
232
|
-
return;
|
|
233
|
-
}
|
|
269
|
+
console.log('[superpowers DEBUG] Creating plugin symlink...');
|
|
270
|
+
createSymlink(targetPluginPath, pluginSymlinkPath);
|
|
271
|
+
console.log('[superpowers DEBUG] Creating skills symlink...');
|
|
272
|
+
createSymlink(targetSkillsPath, skillsSymlinkPath);
|
|
234
273
|
|
|
235
|
-
//
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
}
|
|
274
|
+
// Task 6: Implement update detection and pull
|
|
275
|
+
const checkForUpdates = async () => {
|
|
276
|
+
console.log('[superpowers DEBUG] Checking for updates...');
|
|
277
|
+
const gitDir = path.join(superpowersDir, '.git');
|
|
240
278
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
279
|
+
if (!fs.existsSync(gitDir)) {
|
|
280
|
+
console.log('[superpowers DEBUG] Not a git repository, skipping update check');
|
|
281
|
+
client.app.log('superpowers: Not a git repository, skipping update check');
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
245
284
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
285
|
+
// Check for manual install
|
|
286
|
+
if (isManualInstall(superpowersDir)) {
|
|
287
|
+
console.log('[superpowers DEBUG] Manual install detected, skipping auto-update');
|
|
288
|
+
client.app.log('superpowers: Manual installation detected, skipping auto-update');
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
249
291
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
292
|
+
// Check autoupdate config
|
|
293
|
+
if (!config.superpowers.autoupdate) {
|
|
294
|
+
console.log('[superpowers DEBUG] Auto-update disabled in config');
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
if (config.superpowers.autoupdate_notify) {
|
|
299
|
+
console.log('[superpowers DEBUG] Checking for updates...');
|
|
300
|
+
client.app.log('superpowers: Checking for updates...');
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
try {
|
|
304
|
+
// Git fetch with timeout
|
|
305
|
+
await Promise.race([
|
|
306
|
+
$`git -C ${superpowersDir} fetch origin`,
|
|
307
|
+
new Promise((_, reject) =>
|
|
308
|
+
setTimeout(() => reject(new Error('Timeout')), 30000)
|
|
309
|
+
)
|
|
310
|
+
]);
|
|
311
|
+
|
|
312
|
+
// Check if local branch is behind remote
|
|
313
|
+
const localRev = await $`git -C ${superpowersDir} rev-parse HEAD`;
|
|
314
|
+
const remoteRev = await $`git -C ${superpowersDir} rev-parse @{u}`;
|
|
315
|
+
|
|
316
|
+
if (localRev.stdout.trim() !== remoteRev.stdout.trim()) {
|
|
272
317
|
if (config.superpowers.autoupdate_notify) {
|
|
273
|
-
|
|
318
|
+
console.log('[superpowers DEBUG] Updates available, pulling...');
|
|
319
|
+
client.app.log('superpowers: Updates available, pulling changes...');
|
|
320
|
+
}
|
|
321
|
+
await $`git -C ${superpowersDir} pull`;
|
|
322
|
+
|
|
323
|
+
// Get the current version/tag
|
|
324
|
+
try {
|
|
325
|
+
const tag = await $`git -C ${superpowersDir} describe --tags --abbrev=0 2>/dev/null`;
|
|
326
|
+
if (config.superpowers.autoupdate_notify) {
|
|
327
|
+
console.log('[superpowers DEBUG] Updated to version:', tag.stdout.trim());
|
|
328
|
+
client.app.log('superpowers: Updated to version:', tag.stdout.trim());
|
|
329
|
+
}
|
|
330
|
+
} catch {
|
|
331
|
+
if (config.superpowers.autoupdate_notify) {
|
|
332
|
+
console.log('[superpowers DEBUG] Updated successfully (no tag)');
|
|
333
|
+
client.app.log('superpowers: Updated successfully (no tag available)');
|
|
334
|
+
}
|
|
274
335
|
}
|
|
275
|
-
}
|
|
336
|
+
} else {
|
|
276
337
|
if (config.superpowers.autoupdate_notify) {
|
|
277
|
-
|
|
338
|
+
console.log('[superpowers DEBUG] Already up to date');
|
|
339
|
+
client.app.log('superpowers: Already up to date');
|
|
278
340
|
}
|
|
279
341
|
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
|
|
342
|
+
} catch (error) {
|
|
343
|
+
console.error('[superpowers DEBUG] Update check error:', error);
|
|
344
|
+
if (error.message === 'Timeout') {
|
|
345
|
+
client.app.log('superpowers: Update check timed out, continuing...');
|
|
346
|
+
} else {
|
|
347
|
+
client.app.log('superpowers: Update check failed:', error.message);
|
|
283
348
|
}
|
|
284
349
|
}
|
|
285
|
-
}
|
|
286
|
-
if (error.message === 'Timeout') {
|
|
287
|
-
client.app.log('superpowers: Update check timed out, continuing...');
|
|
288
|
-
} else {
|
|
289
|
-
client.app.log('superpowers: Update check failed:', error.message);
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
};
|
|
350
|
+
};
|
|
293
351
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
352
|
+
// Run update check in background (non-blocking)
|
|
353
|
+
console.log('[superpowers DEBUG] Scheduling update check...');
|
|
354
|
+
setImmediate(() => {
|
|
355
|
+
checkForUpdates();
|
|
356
|
+
});
|
|
357
|
+
console.log('[superpowers DEBUG] Autoinstall completed successfully');
|
|
358
|
+
} catch (error) {
|
|
359
|
+
console.error('[superpowers ERROR] Fatal error in handleAutoinstall:', error);
|
|
360
|
+
console.error('[superpowers ERROR] Stack:', error.stack);
|
|
361
|
+
if (client?.app?.log) {
|
|
362
|
+
client.app.log('superpowers: Fatal error:', error.message);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
298
365
|
};
|
|
299
366
|
|
|
300
367
|
return {
|
|
301
368
|
// Autoinstall entry point - triggers on new sessions
|
|
302
369
|
'session.created': async () => {
|
|
370
|
+
console.log('[superpowers DEBUG] session.created hook fired');
|
|
371
|
+
await handleAutoinstall();
|
|
372
|
+
},
|
|
373
|
+
|
|
374
|
+
// Alternative hook - try session.start as well
|
|
375
|
+
'session.start': async () => {
|
|
376
|
+
console.log('[superpowers DEBUG] session.start hook fired');
|
|
303
377
|
await handleAutoinstall();
|
|
304
378
|
},
|
|
305
379
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "superpowers-opencode-fork-dev-test",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Superpowers plugin for OpenCode.ai - Complete software development workflow with composable skills",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": ".opencode/plugins/superpowers.js",
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
}
|
|
12
12
|
},
|
|
13
13
|
"files": [
|
|
14
|
-
".opencode/plugins/superpowers.js"
|
|
14
|
+
".opencode/plugins/superpowers.js",
|
|
15
|
+
"skills/**/*"
|
|
15
16
|
],
|
|
16
17
|
"scripts": {
|
|
17
18
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
@@ -0,0 +1,54 @@
|
|
|
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
|
+
# Brainstorming Ideas Into Designs
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
Help turn ideas into fully formed designs and specs through natural collaborative dialogue.
|
|
11
|
+
|
|
12
|
+
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.
|
|
13
|
+
|
|
14
|
+
## The Process
|
|
15
|
+
|
|
16
|
+
**Understanding the idea:**
|
|
17
|
+
- Check out the current project state first (files, docs, recent commits)
|
|
18
|
+
- Ask questions one at a time to refine the idea
|
|
19
|
+
- Prefer multiple choice questions when possible, but open-ended is fine too
|
|
20
|
+
- Only one question per message - if a topic needs more exploration, break it into multiple questions
|
|
21
|
+
- Focus on understanding: purpose, constraints, success criteria
|
|
22
|
+
|
|
23
|
+
**Exploring approaches:**
|
|
24
|
+
- Propose 2-3 different approaches with trade-offs
|
|
25
|
+
- Present options conversationally with your recommendation and reasoning
|
|
26
|
+
- Lead with your recommended option and explain why
|
|
27
|
+
|
|
28
|
+
**Presenting the design:**
|
|
29
|
+
- Once you believe you understand what you're building, present the design
|
|
30
|
+
- Break it into sections of 200-300 words
|
|
31
|
+
- Ask after each section whether it looks right so far
|
|
32
|
+
- Cover: architecture, components, data flow, error handling, testing
|
|
33
|
+
- Be ready to go back and clarify if something doesn't make sense
|
|
34
|
+
|
|
35
|
+
## After the Design
|
|
36
|
+
|
|
37
|
+
**Documentation:**
|
|
38
|
+
- Write the validated design to `docs/plans/YYYY-MM-DD-<topic>-design.md`
|
|
39
|
+
- Use elements-of-style:writing-clearly-and-concisely skill if available
|
|
40
|
+
- Commit the design document to git
|
|
41
|
+
|
|
42
|
+
**Implementation (if continuing):**
|
|
43
|
+
- Ask: "Ready to set up for implementation?"
|
|
44
|
+
- Use superpowers:using-git-worktrees to create isolated workspace
|
|
45
|
+
- Use superpowers:writing-plans to create detailed implementation plan
|
|
46
|
+
|
|
47
|
+
## Key Principles
|
|
48
|
+
|
|
49
|
+
- **One question at a time** - Don't overwhelm with multiple questions
|
|
50
|
+
- **Multiple choice preferred** - Easier to answer than open-ended when possible
|
|
51
|
+
- **YAGNI ruthlessly** - Remove unnecessary features from all designs
|
|
52
|
+
- **Explore alternatives** - Always propose 2-3 approaches before settling
|
|
53
|
+
- **Incremental validation** - Present design in sections, validate each
|
|
54
|
+
- **Be flexible** - Go back and clarify when something doesn't make sense
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dispatching-parallel-agents
|
|
3
|
+
description: Use when facing 2+ independent tasks that can be worked on without shared state or sequential dependencies
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Dispatching Parallel Agents
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
When you have multiple unrelated failures (different test files, different subsystems, different bugs), investigating them sequentially wastes time. Each investigation is independent and can happen in parallel.
|
|
11
|
+
|
|
12
|
+
**Core principle:** Dispatch one agent per independent problem domain. Let them work concurrently.
|
|
13
|
+
|
|
14
|
+
## When to Use
|
|
15
|
+
|
|
16
|
+
```dot
|
|
17
|
+
digraph when_to_use {
|
|
18
|
+
"Multiple failures?" [shape=diamond];
|
|
19
|
+
"Are they independent?" [shape=diamond];
|
|
20
|
+
"Single agent investigates all" [shape=box];
|
|
21
|
+
"One agent per problem domain" [shape=box];
|
|
22
|
+
"Can they work in parallel?" [shape=diamond];
|
|
23
|
+
"Sequential agents" [shape=box];
|
|
24
|
+
"Parallel dispatch" [shape=box];
|
|
25
|
+
|
|
26
|
+
"Multiple failures?" -> "Are they independent?" [label="yes"];
|
|
27
|
+
"Are they independent?" -> "Single agent investigates all" [label="no - related"];
|
|
28
|
+
"Are they independent?" -> "Can they work in parallel?" [label="yes"];
|
|
29
|
+
"Can they work in parallel?" -> "Parallel dispatch" [label="yes"];
|
|
30
|
+
"Can they work in parallel?" -> "Sequential agents" [label="no - shared state"];
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**Use when:**
|
|
35
|
+
- 3+ test files failing with different root causes
|
|
36
|
+
- Multiple subsystems broken independently
|
|
37
|
+
- Each problem can be understood without context from others
|
|
38
|
+
- No shared state between investigations
|
|
39
|
+
|
|
40
|
+
**Don't use when:**
|
|
41
|
+
- Failures are related (fix one might fix others)
|
|
42
|
+
- Need to understand full system state
|
|
43
|
+
- Agents would interfere with each other
|
|
44
|
+
|
|
45
|
+
## The Pattern
|
|
46
|
+
|
|
47
|
+
### 1. Identify Independent Domains
|
|
48
|
+
|
|
49
|
+
Group failures by what's broken:
|
|
50
|
+
- File A tests: Tool approval flow
|
|
51
|
+
- File B tests: Batch completion behavior
|
|
52
|
+
- File C tests: Abort functionality
|
|
53
|
+
|
|
54
|
+
Each domain is independent - fixing tool approval doesn't affect abort tests.
|
|
55
|
+
|
|
56
|
+
### 2. Create Focused Agent Tasks
|
|
57
|
+
|
|
58
|
+
Each agent gets:
|
|
59
|
+
- **Specific scope:** One test file or subsystem
|
|
60
|
+
- **Clear goal:** Make these tests pass
|
|
61
|
+
- **Constraints:** Don't change other code
|
|
62
|
+
- **Expected output:** Summary of what you found and fixed
|
|
63
|
+
|
|
64
|
+
### 3. Dispatch in Parallel
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
// In Claude Code / AI environment
|
|
68
|
+
Task("Fix agent-tool-abort.test.ts failures")
|
|
69
|
+
Task("Fix batch-completion-behavior.test.ts failures")
|
|
70
|
+
Task("Fix tool-approval-race-conditions.test.ts failures")
|
|
71
|
+
// All three run concurrently
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### 4. Review and Integrate
|
|
75
|
+
|
|
76
|
+
When agents return:
|
|
77
|
+
- Read each summary
|
|
78
|
+
- Verify fixes don't conflict
|
|
79
|
+
- Run full test suite
|
|
80
|
+
- Integrate all changes
|
|
81
|
+
|
|
82
|
+
## Agent Prompt Structure
|
|
83
|
+
|
|
84
|
+
Good agent prompts are:
|
|
85
|
+
1. **Focused** - One clear problem domain
|
|
86
|
+
2. **Self-contained** - All context needed to understand the problem
|
|
87
|
+
3. **Specific about output** - What should the agent return?
|
|
88
|
+
|
|
89
|
+
```markdown
|
|
90
|
+
Fix the 3 failing tests in src/agents/agent-tool-abort.test.ts:
|
|
91
|
+
|
|
92
|
+
1. "should abort tool with partial output capture" - expects 'interrupted at' in message
|
|
93
|
+
2. "should handle mixed completed and aborted tools" - fast tool aborted instead of completed
|
|
94
|
+
3. "should properly track pendingToolCount" - expects 3 results but gets 0
|
|
95
|
+
|
|
96
|
+
These are timing/race condition issues. Your task:
|
|
97
|
+
|
|
98
|
+
1. Read the test file and understand what each test verifies
|
|
99
|
+
2. Identify root cause - timing issues or actual bugs?
|
|
100
|
+
3. Fix by:
|
|
101
|
+
- Replacing arbitrary timeouts with event-based waiting
|
|
102
|
+
- Fixing bugs in abort implementation if found
|
|
103
|
+
- Adjusting test expectations if testing changed behavior
|
|
104
|
+
|
|
105
|
+
Do NOT just increase timeouts - find the real issue.
|
|
106
|
+
|
|
107
|
+
Return: Summary of what you found and what you fixed.
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Common Mistakes
|
|
111
|
+
|
|
112
|
+
**❌ Too broad:** "Fix all the tests" - agent gets lost
|
|
113
|
+
**✅ Specific:** "Fix agent-tool-abort.test.ts" - focused scope
|
|
114
|
+
|
|
115
|
+
**❌ No context:** "Fix the race condition" - agent doesn't know where
|
|
116
|
+
**✅ Context:** Paste the error messages and test names
|
|
117
|
+
|
|
118
|
+
**❌ No constraints:** Agent might refactor everything
|
|
119
|
+
**✅ Constraints:** "Do NOT change production code" or "Fix tests only"
|
|
120
|
+
|
|
121
|
+
**❌ Vague output:** "Fix it" - you don't know what changed
|
|
122
|
+
**✅ Specific:** "Return summary of root cause and changes"
|
|
123
|
+
|
|
124
|
+
## When NOT to Use
|
|
125
|
+
|
|
126
|
+
**Related failures:** Fixing one might fix others - investigate together first
|
|
127
|
+
**Need full context:** Understanding requires seeing entire system
|
|
128
|
+
**Exploratory debugging:** You don't know what's broken yet
|
|
129
|
+
**Shared state:** Agents would interfere (editing same files, using same resources)
|
|
130
|
+
|
|
131
|
+
## Real Example from Session
|
|
132
|
+
|
|
133
|
+
**Scenario:** 6 test failures across 3 files after major refactoring
|
|
134
|
+
|
|
135
|
+
**Failures:**
|
|
136
|
+
- agent-tool-abort.test.ts: 3 failures (timing issues)
|
|
137
|
+
- batch-completion-behavior.test.ts: 2 failures (tools not executing)
|
|
138
|
+
- tool-approval-race-conditions.test.ts: 1 failure (execution count = 0)
|
|
139
|
+
|
|
140
|
+
**Decision:** Independent domains - abort logic separate from batch completion separate from race conditions
|
|
141
|
+
|
|
142
|
+
**Dispatch:**
|
|
143
|
+
```
|
|
144
|
+
Agent 1 → Fix agent-tool-abort.test.ts
|
|
145
|
+
Agent 2 → Fix batch-completion-behavior.test.ts
|
|
146
|
+
Agent 3 → Fix tool-approval-race-conditions.test.ts
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**Results:**
|
|
150
|
+
- Agent 1: Replaced timeouts with event-based waiting
|
|
151
|
+
- Agent 2: Fixed event structure bug (threadId in wrong place)
|
|
152
|
+
- Agent 3: Added wait for async tool execution to complete
|
|
153
|
+
|
|
154
|
+
**Integration:** All fixes independent, no conflicts, full suite green
|
|
155
|
+
|
|
156
|
+
**Time saved:** 3 problems solved in parallel vs sequentially
|
|
157
|
+
|
|
158
|
+
## Key Benefits
|
|
159
|
+
|
|
160
|
+
1. **Parallelization** - Multiple investigations happen simultaneously
|
|
161
|
+
2. **Focus** - Each agent has narrow scope, less context to track
|
|
162
|
+
3. **Independence** - Agents don't interfere with each other
|
|
163
|
+
4. **Speed** - 3 problems solved in time of 1
|
|
164
|
+
|
|
165
|
+
## Verification
|
|
166
|
+
|
|
167
|
+
After agents return:
|
|
168
|
+
1. **Review each summary** - Understand what changed
|
|
169
|
+
2. **Check for conflicts** - Did agents edit same code?
|
|
170
|
+
3. **Run full suite** - Verify all fixes work together
|
|
171
|
+
4. **Spot check** - Agents can make systematic errors
|
|
172
|
+
|
|
173
|
+
## Real-World Impact
|
|
174
|
+
|
|
175
|
+
From debugging session (2025-10-03):
|
|
176
|
+
- 6 failures across 3 files
|
|
177
|
+
- 3 agents dispatched in parallel
|
|
178
|
+
- All investigations completed concurrently
|
|
179
|
+
- All fixes integrated successfully
|
|
180
|
+
- Zero conflicts between agent changes
|