Compare commits

..

20 Commits

Author SHA1 Message Date
Jesse Vincent
d525598b32 Add OpenCode native skills changes to release notes
Documents:
- Breaking change: switch to native skill tool
- Fix for agent reset bug (#226)
- Fix for Windows installation (#232)
2026-01-22 12:50:18 -08:00
Jesse Vincent
6491a1d9cf feat(opencode): use native skills and fix agent reset bug (#226)
- Replace custom use_skill/find_skills tools with OpenCode's native skill tool
- Use experimental.chat.system.transform hook instead of session.prompt
  (fixes #226 agent reset on first message)
- Symlink skills directory into ~/.config/opencode/skills/superpowers/
- Update installation docs with comprehensive Windows support:
  - Command Prompt, PowerShell, and Git Bash instructions
  - Proper symlink vs junction handling
  - Reinstall safety with cleanup steps
  - Verification commands for each shell
2026-01-22 12:50:18 -08:00
oribi
06dcd150ad fix: respect OPENCODE_CONFIG_DIR for personal skills lookup (#297)
* fix: respect OPENCODE_CONFIG_DIR for personal skills lookup

The plugin was hardcoded to look for personal skills in ~/.config/opencode/skills,
ignoring users who set OPENCODE_CONFIG_DIR to a custom path (e.g., for dotfiles management).

Now uses OPENCODE_CONFIG_DIR if set, falling back to the default path.

* fix: update help text to use dynamic paths

Use configDir and personalSkillsDir variables in help text so paths
are accurate when OPENCODE_CONFIG_DIR is set.

* fix: normalize OPENCODE_CONFIG_DIR before use

Handle edge cases where the env var might be:
- Empty or whitespace-only
- Using ~ for home directory (common in .env files)
- A relative path

Now trims, expands ~, and resolves to absolute path.
2026-01-22 12:47:18 -08:00
Vinicius da Motta
6354d817eb fix use_skill agent context (#290) 2026-01-22 12:47:18 -08:00
Jesse Vincent
2b8814f7d9 Add instruction priority hierarchy to using-superpowers skill
Clarifies that user instructions (CLAUDE.md, direct requests) always
take precedence over Superpowers skills, which in turn override
default system prompt behavior. Ensures users remain in control.

Also updates RELEASE-NOTES.md with unreleased changes including
the visual companion feature.
2026-01-19 21:03:40 -08:00
Jesse Vincent
b16369cae2 Use semantic filenames for visual companion screens
Server now watches directory for new .html files instead of a single
screen file. Claude writes to semantically named files like
platform.html, style.html, layout.html - each screen is a new file.

Benefits:
- No need to read before write (files are always new)
- Semantic filenames describe what's on screen
- History preserved in directory for debugging
- Server serves newest file by mtime automatically

Updated: index.js, start-server.sh, and all documentation.
2026-01-17 19:32:02 -08:00
Jesse Vincent
e9263c9754 docs: improve terminal UX for visual companion
- Never use cat/heredoc for HTML (dumps noise into terminal)
- Read screen_file first before Write tool to avoid errors
- Remind user of URL on every step, not just first
- Give text summary of what's on screen before they look
2026-01-17 18:55:05 -08:00
Jesse Vincent
de2e15242c refactor: simplify visual companion workflow, improve guidance
Scripts:
- Rename show-and-wait.sh -> wait-for-feedback.sh (just waits, no HTML piping)
- Remove wait-for-event.sh (used hanging tail -f)
- Workflow now: Write tool for HTML, wait-for-feedback.sh to block

Documentation rewrite:
- Broader "when to use" (UI, architecture, complex choices, spatial)
- Always ask user first before starting
- Scale fidelity to the question being asked
- Explain the question on each page
- Iterate before moving on - validate changes address feedback
- Use real content (Unsplash images) when it matters
2026-01-17 18:44:50 -08:00
Jesse Vincent
70c2d06c4e feat: add show-and-wait.sh helper, fix race condition
- New show-and-wait.sh combines write + wait into one command
- Uses polling instead of tail -f (which hangs on macOS)
- Docs updated: start watcher BEFORE writing screen to avoid race
- Reduces terminal noise by consolidating operations
2026-01-17 18:35:37 -08:00
Jesse Vincent
b98afbd74f fix: session isolation and blocking wait for visual companion
- Each session gets unique temp directory (/tmp/brainstorm-{pid}-{timestamp})
- Server outputs screen_dir and screen_file in startup JSON
- stop-server.sh takes screen_dir arg and cleans up session directory
- Document blocking TaskOutput pattern: 10-min timeouts, retry up to 3x,
  then prompt user "let me know when you want to continue"
2026-01-17 17:25:45 -08:00
Jesse Vincent
2a61167b02 feat: add visual companion for brainstorming skill
Adds browser-based mockup display to replace ASCII art during
brainstorming sessions. Key components:

- Frame template with OS-aware light/dark theming
- CSS helpers for options, cards, mockups, split views
- Server lifecycle scripts (start/stop with random high port)
- Event watcher using tail+grep for feedback loop
- Claude instructions for using the visual companion

The skill now asks users if they want browser mockups and only
runs in Claude Code environments.
2026-01-17 16:47:03 -08:00
Jesse Vincent
94d5f4a817 feat: add sendToClaude helper and wait-for-event tool
- Add sendToClaude() function to browser helper that shows confirmation
- Add wait-for-event.sh script for watching server output (tail -f | grep -m 1)
- Enables clean event-driven loop: background bash waits for event, completion triggers Claude's turn
2026-01-17 16:38:21 -08:00
Jesse Vincent
209fcec3b9 docs: add visual brainstorming implementation plan 2026-01-17 15:13:23 -08:00
Jesse Vincent
fccb5b4b8f fix: preserve original event type, use source field for wrapper 2026-01-17 13:11:53 -08:00
Jesse Vincent
15d0f2a8f6 fix: correct visual companion documentation issues 2026-01-17 13:08:18 -08:00
Jesse Vincent
cc585ad4d5 feat: add visual companion to brainstorming skill 2026-01-17 13:06:12 -08:00
Jesse Vincent
7e86703081 test: add brainstorm server integration tests 2026-01-17 13:03:04 -08:00
Jesse Vincent
c536926f03 fix: ensure user-event type is preserved in WebSocket message output
The spread operator order was causing incoming event types to overwrite
the user-event type marker.
2026-01-17 13:03:01 -08:00
Jesse Vincent
333eaa3281 feat: add browser helper library for event capture 2026-01-17 12:59:17 -08:00
Jesse Vincent
74a55c0bf4 feat: add brainstorm server foundation
Create the initial server for the visual brainstorming companion:
- Express server with WebSocket support for browser communication
- File watcher (chokidar) to detect screen.html changes
- Auto-injects helper.js into served HTML for event capture
- Binds to localhost only (127.0.0.1) for security
- Outputs JSON events to stdout for Claude consumption
2026-01-17 12:56:11 -08:00
59 changed files with 1012 additions and 2301 deletions

View File

@@ -9,7 +9,7 @@
{
"name": "superpowers",
"description": "Core skills library for Claude Code: TDD, debugging, collaboration patterns, and proven techniques",
"version": "4.2.0",
"version": "4.0.3",
"source": "./",
"author": {
"name": "Jesse Vincent",

View File

@@ -1,7 +1,7 @@
{
"name": "superpowers",
"description": "Core skills library for Claude Code: TDD, debugging, collaboration patterns, and proven techniques",
"version": "4.2.0",
"version": "4.0.3",
"author": {
"name": "Jesse Vincent",
"email": "jesse@fsck.com"

View File

@@ -1,67 +1,35 @@
# Installing Superpowers for Codex
Enable superpowers skills in Codex via native skill discovery. Just clone and symlink.
## Prerequisites
- Git
Quick setup to enable superpowers skills in Codex.
## Installation
1. **Clone the superpowers repository:**
1. **Clone superpowers repository**:
```bash
git clone https://github.com/obra/superpowers.git ~/.codex/superpowers
mkdir -p ~/.codex/superpowers
cd ~/.codex/superpowers
git clone https://github.com/obra/superpowers.git .
```
2. **Create the skills symlink:**
2. **Create personal skills directory**:
```bash
mkdir -p ~/.agents/skills
ln -s ~/.codex/superpowers/skills ~/.agents/skills/superpowers
mkdir -p ~/.codex/skills
```
**Windows (PowerShell):**
```powershell
New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.agents\skills"
cmd /c mklink /J "$env:USERPROFILE\.agents\skills\superpowers" "$env:USERPROFILE\.codex\superpowers\skills"
3. **Update ~/.codex/AGENTS.md** to include this superpowers section:
```markdown
## Superpowers System
<EXTREMELY_IMPORTANT>
You have superpowers. Superpowers teach you new skills and capabilities. RIGHT NOW run: `~/.codex/superpowers/.codex/superpowers-codex bootstrap` and follow the instructions it returns.
</EXTREMELY_IMPORTANT>
```
3. **Restart Codex** (quit and relaunch the CLI) to discover the skills.
## Migrating from old bootstrap
If you installed superpowers before native skill discovery, you need to:
1. **Update the repo:**
```bash
cd ~/.codex/superpowers && git pull
```
2. **Create the skills symlink** (step 2 above) — this is the new discovery mechanism.
3. **Remove the old bootstrap block** from `~/.codex/AGENTS.md` — any block referencing `superpowers-codex bootstrap` is no longer needed.
4. **Restart Codex.**
## Verify
## Verification
Test the installation:
```bash
ls -la ~/.agents/skills/superpowers
~/.codex/superpowers/.codex/superpowers-codex bootstrap
```
You should see a symlink (or junction on Windows) pointing to your superpowers skills directory.
## Updating
```bash
cd ~/.codex/superpowers && git pull
```
Skills update instantly through the symlink.
## Uninstalling
```bash
rm ~/.agents/skills/superpowers
```
Optionally delete the clone: `rm -rf ~/.codex/superpowers`.
You should see skill listings and bootstrap instructions. The system is now ready for use.

View File

@@ -0,0 +1,33 @@
# Superpowers Bootstrap for Codex
<EXTREMELY_IMPORTANT>
You have superpowers.
**Tool for running skills:**
- `~/.codex/superpowers/.codex/superpowers-codex use-skill <skill-name>`
**Tool Mapping for Codex:**
When skills reference tools you don't have, substitute your equivalent tools:
- `TodoWrite``update_plan` (your planning/task tracking tool)
- `Task` tool with subagents → Tell the user that subagents aren't available in Codex yet and you'll do the work the subagent would do
- `Skill` tool → `~/.codex/superpowers/.codex/superpowers-codex use-skill` command (already available)
- `Read`, `Write`, `Edit`, `Bash` → Use your native tools with similar functions
**Skills naming:**
- Superpowers skills: `superpowers:skill-name` (from ~/.codex/superpowers/skills/)
- Personal skills: `skill-name` (from ~/.codex/skills/)
- Personal skills override superpowers skills when names match
**Critical Rules:**
- Before ANY task, review the skills list (shown below)
- If a relevant skill exists, you MUST use `~/.codex/superpowers/.codex/superpowers-codex use-skill` to load it
- Announce: "I've read the [Skill Name] skill and I'm using it to [purpose]"
- Skills with checklists require `update_plan` todos for each item
- NEVER skip mandatory workflows (brainstorming before coding, TDD, systematic debugging)
**Skills location:**
- Superpowers skills: ~/.codex/superpowers/skills/
- Personal skills: ~/.codex/skills/ (override superpowers when names match)
IF A SKILL APPLIES TO YOUR TASK, YOU DO NOT HAVE A CHOICE. YOU MUST USE IT.
</EXTREMELY_IMPORTANT>

267
.codex/superpowers-codex Executable file
View File

@@ -0,0 +1,267 @@
#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
const os = require('os');
const skillsCore = require('../lib/skills-core');
// Paths
const homeDir = os.homedir();
const superpowersSkillsDir = path.join(homeDir, '.codex', 'superpowers', 'skills');
const personalSkillsDir = path.join(homeDir, '.codex', 'skills');
const bootstrapFile = path.join(homeDir, '.codex', 'superpowers', '.codex', 'superpowers-bootstrap.md');
const superpowersRepoDir = path.join(homeDir, '.codex', 'superpowers');
// Utility functions
function printSkill(skillPath, sourceType) {
const skillFile = path.join(skillPath, 'SKILL.md');
const relPath = sourceType === 'personal'
? path.relative(personalSkillsDir, skillPath)
: path.relative(superpowersSkillsDir, skillPath);
// Print skill name with namespace
if (sourceType === 'personal') {
console.log(relPath.replace(/\\/g, '/')); // Personal skills are not namespaced
} else {
console.log(`superpowers:${relPath.replace(/\\/g, '/')}`); // Superpowers skills get superpowers namespace
}
// Extract and print metadata
const { name, description } = skillsCore.extractFrontmatter(skillFile);
if (description) console.log(` ${description}`);
console.log('');
}
// Commands
function runFindSkills() {
console.log('Available skills:');
console.log('==================');
console.log('');
const foundSkills = new Set();
// Find personal skills first (these take precedence)
const personalSkills = skillsCore.findSkillsInDir(personalSkillsDir, 'personal', 2);
for (const skill of personalSkills) {
const relPath = path.relative(personalSkillsDir, skill.path);
foundSkills.add(relPath);
printSkill(skill.path, 'personal');
}
// Find superpowers skills (only if not already found in personal)
const superpowersSkills = skillsCore.findSkillsInDir(superpowersSkillsDir, 'superpowers', 1);
for (const skill of superpowersSkills) {
const relPath = path.relative(superpowersSkillsDir, skill.path);
if (!foundSkills.has(relPath)) {
printSkill(skill.path, 'superpowers');
}
}
console.log('Usage:');
console.log(' superpowers-codex use-skill <skill-name> # Load a specific skill');
console.log('');
console.log('Skill naming:');
console.log(' Superpowers skills: superpowers:skill-name (from ~/.codex/superpowers/skills/)');
console.log(' Personal skills: skill-name (from ~/.codex/skills/)');
console.log(' Personal skills override superpowers skills when names match.');
console.log('');
console.log('Note: All skills are disclosed at session start via bootstrap.');
}
function runBootstrap() {
console.log('# Superpowers Bootstrap for Codex');
console.log('# ================================');
console.log('');
// Check for updates (with timeout protection)
if (skillsCore.checkForUpdates(superpowersRepoDir)) {
console.log('## Update Available');
console.log('');
console.log('⚠️ Your superpowers installation is behind the latest version.');
console.log('To update, run: `cd ~/.codex/superpowers && git pull`');
console.log('');
console.log('---');
console.log('');
}
// Show the bootstrap instructions
if (fs.existsSync(bootstrapFile)) {
console.log('## Bootstrap Instructions:');
console.log('');
try {
const content = fs.readFileSync(bootstrapFile, 'utf8');
console.log(content);
} catch (error) {
console.log(`Error reading bootstrap file: ${error.message}`);
}
console.log('');
console.log('---');
console.log('');
}
// Run find-skills to show available skills
console.log('## Available Skills:');
console.log('');
runFindSkills();
console.log('');
console.log('---');
console.log('');
// Load the using-superpowers skill automatically
console.log('## Auto-loading superpowers:using-superpowers skill:');
console.log('');
runUseSkill('superpowers:using-superpowers');
console.log('');
console.log('---');
console.log('');
console.log('# Bootstrap Complete!');
console.log('# You now have access to all superpowers skills.');
console.log('# Use "superpowers-codex use-skill <skill>" to load and apply skills.');
console.log('# Remember: If a skill applies to your task, you MUST use it!');
}
function runUseSkill(skillName) {
if (!skillName) {
console.log('Usage: superpowers-codex use-skill <skill-name>');
console.log('Examples:');
console.log(' superpowers-codex use-skill superpowers:brainstorming # Load superpowers skill');
console.log(' superpowers-codex use-skill brainstorming # Load personal skill (or superpowers if not found)');
console.log(' superpowers-codex use-skill my-custom-skill # Load personal skill');
return;
}
// Handle namespaced skill names
let actualSkillPath;
let forceSuperpowers = false;
if (skillName.startsWith('superpowers:')) {
// Remove the superpowers: namespace prefix
actualSkillPath = skillName.substring('superpowers:'.length);
forceSuperpowers = true;
} else {
actualSkillPath = skillName;
}
// Remove "skills/" prefix if present
if (actualSkillPath.startsWith('skills/')) {
actualSkillPath = actualSkillPath.substring('skills/'.length);
}
// Function to find skill file
function findSkillFile(searchPath) {
// Check for exact match with SKILL.md
const skillMdPath = path.join(searchPath, 'SKILL.md');
if (fs.existsSync(skillMdPath)) {
return skillMdPath;
}
// Check for direct SKILL.md file
if (searchPath.endsWith('SKILL.md') && fs.existsSync(searchPath)) {
return searchPath;
}
return null;
}
let skillFile = null;
// If superpowers: namespace was used, only check superpowers skills
if (forceSuperpowers) {
if (fs.existsSync(superpowersSkillsDir)) {
const superpowersPath = path.join(superpowersSkillsDir, actualSkillPath);
skillFile = findSkillFile(superpowersPath);
}
} else {
// First check personal skills directory (takes precedence)
if (fs.existsSync(personalSkillsDir)) {
const personalPath = path.join(personalSkillsDir, actualSkillPath);
skillFile = findSkillFile(personalPath);
if (skillFile) {
console.log(`# Loading personal skill: ${actualSkillPath}`);
console.log(`# Source: ${skillFile}`);
console.log('');
}
}
// If not found in personal, check superpowers skills
if (!skillFile && fs.existsSync(superpowersSkillsDir)) {
const superpowersPath = path.join(superpowersSkillsDir, actualSkillPath);
skillFile = findSkillFile(superpowersPath);
if (skillFile) {
console.log(`# Loading superpowers skill: superpowers:${actualSkillPath}`);
console.log(`# Source: ${skillFile}`);
console.log('');
}
}
}
// If still not found, error
if (!skillFile) {
console.log(`Error: Skill not found: ${actualSkillPath}`);
console.log('');
console.log('Available skills:');
runFindSkills();
return;
}
// Extract frontmatter and content using shared core functions
let content, frontmatter;
try {
const fullContent = fs.readFileSync(skillFile, 'utf8');
const { name, description } = skillsCore.extractFrontmatter(skillFile);
content = skillsCore.stripFrontmatter(fullContent);
frontmatter = { name, description };
} catch (error) {
console.log(`Error reading skill file: ${error.message}`);
return;
}
// Display skill header with clean info
const displayName = forceSuperpowers ? `superpowers:${actualSkillPath}` :
(skillFile.includes(personalSkillsDir) ? actualSkillPath : `superpowers:${actualSkillPath}`);
const skillDirectory = path.dirname(skillFile);
console.log(`# ${frontmatter.name || displayName}`);
if (frontmatter.description) {
console.log(`# ${frontmatter.description}`);
}
console.log(`# Skill-specific tools and reference files live in ${skillDirectory}`);
console.log('# ============================================');
console.log('');
// Display the skill content (without frontmatter)
console.log(content);
}
// Main CLI
const command = process.argv[2];
const arg = process.argv[3];
switch (command) {
case 'bootstrap':
runBootstrap();
break;
case 'use-skill':
runUseSkill(arg);
break;
case 'find-skills':
runFindSkills();
break;
default:
console.log('Superpowers for Codex');
console.log('Usage:');
console.log(' superpowers-codex bootstrap # Run complete bootstrap with all skills');
console.log(' superpowers-codex use-skill <skill-name> # Load a specific skill');
console.log(' superpowers-codex find-skills # List all available skills');
console.log('');
console.log('Examples:');
console.log(' superpowers-codex bootstrap');
console.log(' superpowers-codex use-skill superpowers:brainstorming');
console.log(' superpowers-codex use-skill my-custom-skill');
break;
}

17
.gitattributes vendored
View File

@@ -1,17 +0,0 @@
# Ensure shell scripts always have LF line endings
*.sh text eol=lf
# Ensure the polyglot wrapper keeps LF (it's parsed by both cmd and bash)
*.cmd text eol=lf
# Common text files
*.md text eol=lf
*.json text eol=lf
*.js text eol=lf
*.mjs text eol=lf
*.ts text eol=lf
# Explicitly mark binary files
*.png binary
*.jpg binary
*.gif binary

2
.gitignore vendored
View File

@@ -2,5 +2,3 @@
.private-journal/
.claude/
node_modules/
inspo
triage/

View File

@@ -3,13 +3,15 @@
## Prerequisites
- [OpenCode.ai](https://opencode.ai) installed
- Node.js installed
- Git installed
## Installation Steps
### 1. Clone Superpowers
### 1. Install Superpowers
```bash
mkdir -p ~/.config/opencode/superpowers
git clone https://github.com/obra/superpowers.git ~/.config/opencode/superpowers
```
@@ -18,43 +20,32 @@ git clone https://github.com/obra/superpowers.git ~/.config/opencode/superpowers
Create a symlink so OpenCode discovers the plugin:
```bash
mkdir -p ~/.config/opencode/plugins
rm -f ~/.config/opencode/plugins/superpowers.js
ln -s ~/.config/opencode/superpowers/.opencode/plugins/superpowers.js ~/.config/opencode/plugins/superpowers.js
mkdir -p ~/.config/opencode/plugin
ln -sf ~/.config/opencode/superpowers/.opencode/plugin/superpowers.js ~/.config/opencode/plugin/superpowers.js
```
### 3. Symlink Skills
### 3. Restart OpenCode
Create a symlink so OpenCode's native skill tool discovers superpowers skills:
Restart OpenCode. The plugin will automatically inject superpowers context via the chat.message hook.
```bash
mkdir -p ~/.config/opencode/skills
rm -rf ~/.config/opencode/skills/superpowers
ln -s ~/.config/opencode/superpowers/skills ~/.config/opencode/skills/superpowers
```
### 4. Restart OpenCode
Restart OpenCode. The plugin will automatically inject superpowers context.
Verify by asking: "do you have superpowers?"
You should see superpowers is active when you ask "do you have superpowers?"
## Usage
### Finding Skills
Use OpenCode's native `skill` tool to list available skills:
Use the `find_skills` tool to list all available skills:
```
use skill tool to list skills
use find_skills tool
```
### Loading a Skill
Use OpenCode's native `skill` tool to load a specific skill:
Use the `use_skill` tool to load a specific skill:
```
use skill tool to load superpowers/brainstorming
use use_skill tool with skill_name: "superpowers:brainstorming"
```
### Personal Skills
@@ -78,11 +69,36 @@ description: Use when [condition] - [what it does]
[Your skill content here]
```
Personal skills override superpowers skills with the same name.
### Project Skills
Create project-specific skills in `.opencode/skills/` within your project.
Create project-specific skills in your OpenCode project:
**Skill Priority:** Project skills > Personal skills > Superpowers skills
```bash
# In your OpenCode project
mkdir -p .opencode/skills/my-project-skill
```
Create `.opencode/skills/my-project-skill/SKILL.md`:
```markdown
---
name: my-project-skill
description: Use when [condition] - [what it does]
---
# My Project Skill
[Your skill content here]
```
**Skill Priority:** Project skills override personal skills, which override superpowers skills.
**Skill Naming:**
- `project:skill-name` - Force project skill lookup
- `skill-name` - Searches project → personal → superpowers
- `superpowers:skill-name` - Force superpowers skill lookup
## Updating
@@ -95,25 +111,25 @@ git pull
### Plugin not loading
1. Check plugin symlink: `ls -l ~/.config/opencode/plugins/superpowers.js`
2. Check source exists: `ls ~/.config/opencode/superpowers/.opencode/plugins/superpowers.js`
3. Check OpenCode logs for errors
1. Check plugin file exists: `ls ~/.config/opencode/superpowers/.opencode/plugin/superpowers.js`
2. Check OpenCode logs for errors
3. Verify Node.js is installed: `node --version`
### Skills not found
1. Check skills symlink: `ls -l ~/.config/opencode/skills/superpowers`
2. Verify it points to: `~/.config/opencode/superpowers/skills`
3. Use `skill` tool to list what's discovered
1. Verify skills directory exists: `ls ~/.config/opencode/superpowers/skills`
2. Use `find_skills` tool to see what's discovered
3. Check file structure: each skill should have a `SKILL.md` file
### Tool mapping
### Tool mapping issues
When skills reference Claude Code tools:
- `TodoWrite``update_plan`
- `Task` with subagents → `@mention` syntax
- `Skill` tool → OpenCode's native `skill` tool
- File operations → your native tools
When a skill references a Claude Code tool you don't have:
- `TodoWrite` use `update_plan`
- `Task` with subagents → use `@mention` syntax to invoke OpenCode subagents
- `Skill` → use `use_skill` tool
- File operations → use your native tools
## Getting Help
- Report issues: https://github.com/obra/superpowers/issues
- Full documentation: https://github.com/obra/superpowers/blob/main/docs/README.opencode.md
- Documentation: https://github.com/obra/superpowers

View File

@@ -44,7 +44,18 @@ Then install the plugin from this marketplace:
### Verify Installation
Start a new session and ask Claude to help with something that would trigger a skill (e.g., "help me plan this feature" or "let's debug this issue"). Claude should automatically invoke the relevant superpowers skill.
Check that commands appear:
```bash
/help
```
```
# Should see:
# /superpowers:brainstorm - Interactive design refinement
# /superpowers:write-plan - Create implementation plan
# /superpowers:execute-plan - Execute plan in batches
```
### Codex

View File

@@ -4,25 +4,6 @@
### Breaking Changes
**Specs and plans directory restructured**
- Specs (brainstorming output) now go to `docs/superpowers/specs/YYYY-MM-DD-<topic>-design.md`
- Plans (writing-plans output) now go to `docs/superpowers/plans/YYYY-MM-DD-<feature-name>.md`
- User preferences for spec/plan locations override these defaults
- Migration: move existing files from `docs/plans/` to new locations if desired
**Brainstorming → writing-plans transition enforced**
- After design approval, brainstorming now requires using writing-plans skill
- Platform planning features (e.g., EnterPlanMode) should not be used
- Direct implementation without writing-plans is not allowed
**Subagent-driven development now mandatory on capable harnesses**
- On harnesses with subagent support (Claude Code), subagent-driven-development is now required after plan approval
- No longer offers a choice between subagent-driven and executing-plans
- Executing-plans is only used on harnesses without subagent capability
**OpenCode: Switched to native skills system**
Superpowers for OpenCode now uses OpenCode's native `skill` tool instead of custom `use_skill`/`find_skills` tools. This is a cleaner integration that works with OpenCode's built-in skill discovery.
@@ -55,28 +36,6 @@ Components:
The visual companion is opt-in and falls back gracefully to terminal-only operation.
### Bug Fixes
**Fixed Windows hook execution for Claude Code 2.1.x**
Claude Code 2.1.x changed how hooks execute on Windows: it now auto-detects `.sh` files in commands and prepends `bash `. This broke the polyglot wrapper pattern because `bash "run-hook.cmd" session-start.sh` tries to execute the .cmd file as a bash script.
Fix: hooks.json now calls session-start.sh directly. Claude Code 2.1.x handles the bash invocation automatically. Also added .gitattributes to enforce LF line endings for shell scripts (fixes CRLF issues on Windows checkout).
**Brainstorming visual companion: reduced token cost and improved persistence**
The visual companion now generates much smaller HTML per screen. The server automatically wraps bare content fragments in the frame template (header, CSS theme, feedback footer, interactive JS), so Claude writes only the content portion (~30 lines instead of ~260). Full HTML documents are still served as-is when Claude needs complete control.
Other improvements:
- `toggleSelect`/`send`/`selectedChoice` moved from inline template script to `helper.js` (auto-injected)
- `start-server.sh --project-dir` persists mockups under `.superpowers/brainstorm/` instead of `/tmp`
- `stop-server.sh` only deletes ephemeral `/tmp` sessions, preserving persistent ones
- Dark mode fix: `sendToClaude` confirmation page now uses CSS variables instead of hardcoded colors
- Skill restructured: SKILL.md is minimal (prompt + pointer); all visual companion details in progressive disclosure doc (`visual-companion.md`)
- Prompt to user now notes the feature is new, token-intensive, and can be slow
- Deleted redundant `CLAUDE-INSTRUCTIONS.md` (content folded into `visual-companion.md`)
- Test fixes: correct env var (`BRAINSTORM_DIR`), polling-based startup wait, new tests for frame wrapping
### Improvements
**Instruction priority clarified in using-superpowers**
@@ -89,120 +48,6 @@ Added explicit instruction priority hierarchy to prevent conflicts with user pre
This ensures users remain in control. If CLAUDE.md says "don't use TDD" and a skill says "always use TDD," CLAUDE.md wins.
## v4.2.0 (2026-02-05)
### Breaking Changes
**Codex: Replaced bootstrap CLI with native skill discovery**
The `superpowers-codex` bootstrap CLI, Windows `.cmd` wrapper, and related bootstrap content file have been removed. Codex now uses native skill discovery via `~/.agents/skills/superpowers/` symlink, so the old `use_skill`/`find_skills` CLI tools are no longer needed.
Installation is now just clone + symlink (documented in INSTALL.md). No Node.js dependency required. The old `~/.codex/skills/` path is deprecated.
### Fixes
**Windows: Fixed Claude Code 2.1.x hook execution (#331)**
Claude Code 2.1.x changed how hooks execute on Windows: it now auto-detects `.sh` files in commands and prepends `bash`. This broke the polyglot wrapper pattern because `bash "run-hook.cmd" session-start.sh` tries to execute the `.cmd` file as a bash script.
Fix: hooks.json now calls session-start.sh directly. Claude Code 2.1.x handles the bash invocation automatically. Also added .gitattributes to enforce LF line endings for shell scripts (fixes CRLF issues on Windows checkout).
**Windows: SessionStart hook runs async to prevent terminal freeze (#404, #413, #414, #419)**
The synchronous SessionStart hook blocked the TUI from entering raw mode on Windows, freezing all keyboard input. Running the hook async prevents the freeze while still injecting superpowers context.
**Windows: Fixed O(n^2) `escape_for_json` performance**
The character-by-character loop using `${input:$i:1}` was O(n^2) in bash due to substring copy overhead. On Windows Git Bash this took 60+ seconds. Replaced with bash parameter substitution (`${s//old/new}`) which runs each pattern as a single C-level pass — 7x faster on macOS, dramatically faster on Windows.
**Codex: Fixed Windows/PowerShell invocation (#285, #243)**
- Windows doesn't respect shebangs, so directly invoking the extensionless `superpowers-codex` script triggered an "Open with" dialog. All invocations now prefixed with `node`.
- Fixed `~/` path expansion on Windows — PowerShell doesn't expand `~` when passed as an argument to `node`. Changed to `$HOME` which expands correctly in both bash and PowerShell.
**Codex: Fixed path resolution in installer**
Used `fileURLToPath()` instead of manual URL pathname parsing to correctly handle paths with spaces and special characters on all platforms.
**Codex: Fixed stale skills path in writing-skills**
Updated `~/.codex/skills/` reference (deprecated) to `~/.agents/skills/` for native discovery.
### Improvements
**Worktree isolation now required before implementation**
Added `using-git-worktrees` as a required skill for both `subagent-driven-development` and `executing-plans`. Implementation workflows now explicitly require setting up an isolated worktree before starting work, preventing accidental work directly on main.
**Main branch protection softened to require explicit consent**
Instead of prohibiting main branch work entirely, the skills now allow it with explicit user consent. More flexible while still ensuring users are aware of the implications.
**Simplified installation verification**
Removed `/help` command check and specific slash command list from verification steps. Skills are primarily invoked by describing what you want to do, not by running specific commands.
**Codex: Clarified subagent tool mapping in bootstrap**
Improved documentation of how Codex tools map to Claude Code equivalents for subagent workflows.
### Tests
- Added worktree requirement test for subagent-driven-development
- Added main branch red flag warning test
- Fixed case sensitivity in skill recognition test assertions
---
## v4.1.1 (2026-01-23)
### Fixes
**OpenCode: Standardized on `plugins/` directory per official docs (#343)**
OpenCode's official documentation uses `~/.config/opencode/plugins/` (plural). Our docs previously used `plugin/` (singular). While OpenCode accepts both forms, we've standardized on the official convention to avoid confusion.
Changes:
- Renamed `.opencode/plugin/` to `.opencode/plugins/` in repo structure
- Updated all installation docs (INSTALL.md, README.opencode.md) across all platforms
- Updated test scripts to match
**OpenCode: Fixed symlink instructions (#339, #342)**
- Added explicit `rm` before `ln -s` (fixes "file already exists" errors on reinstall)
- Added missing skills symlink step that was absent from INSTALL.md
- Updated from deprecated `use_skill`/`find_skills` to native `skill` tool references
---
## v4.1.0 (2026-01-23)
### Breaking Changes
**OpenCode: Switched to native skills system**
Superpowers for OpenCode now uses OpenCode's native `skill` tool instead of custom `use_skill`/`find_skills` tools. This is a cleaner integration that works with OpenCode's built-in skill discovery.
**Migration required:** Skills must be symlinked to `~/.config/opencode/skills/superpowers/` (see updated installation docs).
### Fixes
**OpenCode: Fixed agent reset on session start (#226)**
The previous bootstrap injection method using `session.prompt({ noReply: true })` caused OpenCode to reset the selected agent to "build" on first message. Now uses `experimental.chat.system.transform` hook which modifies the system prompt directly without side effects.
**OpenCode: Fixed Windows installation (#232)**
- Removed dependency on `skills-core.js` (eliminates broken relative imports when file is copied instead of symlinked)
- Added comprehensive Windows installation docs for cmd.exe, PowerShell, and Git Bash
- Documented proper symlink vs junction usage for each platform
**Claude Code: Fixed Windows hook execution for Claude Code 2.1.x**
Claude Code 2.1.x changed how hooks execute on Windows: it now auto-detects `.sh` files in commands and prepends `bash `. This broke the polyglot wrapper pattern because `bash "run-hook.cmd" session-start.sh` tries to execute the .cmd file as a bash script.
Fix: hooks.json now calls session-start.sh directly. Claude Code 2.1.x handles the bash invocation automatically. Also added .gitattributes to enforce LF line endings for shell scripts (fixes CRLF issues on Windows checkout).
---
## v4.0.3 (2025-12-26)

View File

@@ -1,6 +1,6 @@
# Superpowers for Codex
Guide for using Superpowers with OpenAI Codex via native skill discovery.
Complete guide for using Superpowers with OpenAI Codex.
## Quick Install
@@ -14,59 +14,63 @@ Fetch and follow instructions from https://raw.githubusercontent.com/obra/superp
### Prerequisites
- OpenAI Codex CLI
- Git
- OpenAI Codex access
- Shell access to install files
### Steps
### Installation Steps
1. Clone the repo:
```bash
git clone https://github.com/obra/superpowers.git ~/.codex/superpowers
```
#### 1. Clone Superpowers
2. Create the skills symlink:
```bash
mkdir -p ~/.agents/skills
ln -s ~/.codex/superpowers/skills ~/.agents/skills/superpowers
```
3. Restart Codex.
### Windows
Use a junction instead of a symlink (works without Developer Mode):
```powershell
New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.agents\skills"
cmd /c mklink /J "$env:USERPROFILE\.agents\skills\superpowers" "$env:USERPROFILE\.codex\superpowers\skills"
```bash
mkdir -p ~/.codex/superpowers
git clone https://github.com/obra/superpowers.git ~/.codex/superpowers
```
## How It Works
#### 2. Install Bootstrap
Codex has native skill discovery — it scans `~/.agents/skills/` at startup, parses SKILL.md frontmatter, and loads skills on demand. Superpowers skills are made visible through a single symlink:
The bootstrap file is included in the repository at `.codex/superpowers-bootstrap.md`. Codex will automatically use it from the cloned location.
#### 3. Verify Installation
Tell Codex:
```
~/.agents/skills/superpowers/ → ~/.codex/superpowers/skills/
Run ~/.codex/superpowers/.codex/superpowers-codex find-skills to show available skills
```
The `using-superpowers` skill is discovered automatically and enforces skill usage discipline — no additional configuration needed.
You should see a list of available skills with descriptions.
## Usage
Skills are discovered automatically. Codex activates them when:
- You mention a skill by name (e.g., "use brainstorming")
- The task matches a skill's description
- The `using-superpowers` skill directs Codex to use one
### Finding Skills
```
Run ~/.codex/superpowers/.codex/superpowers-codex find-skills
```
### Loading a Skill
```
Run ~/.codex/superpowers/.codex/superpowers-codex use-skill superpowers:brainstorming
```
### Bootstrap All Skills
```
Run ~/.codex/superpowers/.codex/superpowers-codex bootstrap
```
This loads the complete bootstrap with all skill information.
### Personal Skills
Create your own skills in `~/.agents/skills/`:
Create your own skills in `~/.codex/skills/`:
```bash
mkdir -p ~/.agents/skills/my-skill
mkdir -p ~/.codex/skills/my-skill
```
Create `~/.agents/skills/my-skill/SKILL.md`:
Create `~/.codex/skills/my-skill/SKILL.md`:
```markdown
---
@@ -79,42 +83,71 @@ description: Use when [condition] - [what it does]
[Your skill content here]
```
The `description` field is how Codex decides when to activate a skill automatically — write it as a clear trigger condition.
Personal skills override superpowers skills with the same name.
## Architecture
### Codex CLI Tool
**Location:** `~/.codex/superpowers/.codex/superpowers-codex`
A Node.js CLI script that provides three commands:
- `bootstrap` - Load complete bootstrap with all skills
- `use-skill <name>` - Load a specific skill
- `find-skills` - List all available skills
### Shared Core Module
**Location:** `~/.codex/superpowers/lib/skills-core.js`
The Codex implementation uses the shared `skills-core` module (ES module format) for skill discovery and parsing. This is the same module used by the OpenCode plugin, ensuring consistent behavior across platforms.
### Tool Mapping
Skills written for Claude Code are adapted for Codex with these mappings:
- `TodoWrite``update_plan`
- `Task` with subagents → Tell user subagents aren't available, do work directly
- `Skill` tool → `~/.codex/superpowers/.codex/superpowers-codex use-skill`
- File operations → Native Codex tools
## Updating
```bash
cd ~/.codex/superpowers && git pull
cd ~/.codex/superpowers
git pull
```
Skills update instantly through the symlink.
## Uninstalling
```bash
rm ~/.agents/skills/superpowers
```
**Windows (PowerShell):**
```powershell
Remove-Item "$env:USERPROFILE\.agents\skills\superpowers"
```
Optionally delete the clone: `rm -rf ~/.codex/superpowers` (Windows: `Remove-Item -Recurse -Force "$env:USERPROFILE\.codex\superpowers"`).
## Troubleshooting
### Skills not showing up
### Skills not found
1. Verify the symlink: `ls -la ~/.agents/skills/superpowers`
2. Check skills exist: `ls ~/.codex/superpowers/skills`
3. Restart Codex — skills are discovered at startup
1. Verify installation: `ls ~/.codex/superpowers/skills`
2. Check CLI works: `~/.codex/superpowers/.codex/superpowers-codex find-skills`
3. Verify skills have SKILL.md files
### Windows junction issues
### CLI script not executable
Junctions normally work without special permissions. If creation fails, try running PowerShell as administrator.
```bash
chmod +x ~/.codex/superpowers/.codex/superpowers-codex
```
### Node.js errors
The CLI script requires Node.js. Verify:
```bash
node --version
```
Should show v14 or higher (v18+ recommended for ES module support).
## Getting Help
- Report issues: https://github.com/obra/superpowers/issues
- Main documentation: https://github.com/obra/superpowers
- Blog post: https://blog.fsck.com/2025/10/27/skills-for-openai-codex/
## Note
Codex support is experimental and may require refinement based on user feedback. If you encounter issues, please report them on GitHub.

View File

@@ -7,7 +7,7 @@ Complete guide for using Superpowers with [OpenCode.ai](https://opencode.ai).
Tell OpenCode:
```
Clone https://github.com/obra/superpowers to ~/.config/opencode/superpowers, then create directory ~/.config/opencode/plugins, then symlink ~/.config/opencode/superpowers/.opencode/plugins/superpowers.js to ~/.config/opencode/plugins/superpowers.js, then symlink ~/.config/opencode/superpowers/skills to ~/.config/opencode/skills/superpowers, then restart opencode.
Clone https://github.com/obra/superpowers to ~/.config/opencode/superpowers, then create directory ~/.config/opencode/plugin, then symlink ~/.config/opencode/superpowers/.opencode/plugin/superpowers.js to ~/.config/opencode/plugin/superpowers.js, then symlink ~/.config/opencode/superpowers/skills to ~/.config/opencode/skills/superpowers, then restart opencode.
```
## Manual Installation
@@ -28,23 +28,19 @@ else
fi
# 2. Create directories
mkdir -p ~/.config/opencode/plugins ~/.config/opencode/skills
mkdir -p ~/.config/opencode/plugin ~/.config/opencode/skills
# 3. Remove old symlinks/directories if they exist
rm -f ~/.config/opencode/plugins/superpowers.js
rm -rf ~/.config/opencode/skills/superpowers
# 3. Create symlinks (safe for reinstalls - ln -sf overwrites)
ln -sf ~/.config/opencode/superpowers/.opencode/plugin/superpowers.js ~/.config/opencode/plugin/superpowers.js
ln -sf ~/.config/opencode/superpowers/skills ~/.config/opencode/skills/superpowers
# 4. Create symlinks
ln -s ~/.config/opencode/superpowers/.opencode/plugins/superpowers.js ~/.config/opencode/plugins/superpowers.js
ln -s ~/.config/opencode/superpowers/skills ~/.config/opencode/skills/superpowers
# 5. Restart OpenCode
# 4. Restart OpenCode
```
#### Verify Installation
```bash
ls -l ~/.config/opencode/plugins/superpowers.js
ls -l ~/.config/opencode/plugin/superpowers.js
ls -l ~/.config/opencode/skills/superpowers
```
@@ -69,15 +65,15 @@ Run as Administrator, or with Developer Mode enabled:
git clone https://github.com/obra/superpowers.git "%USERPROFILE%\.config\opencode\superpowers"
:: 2. Create directories
mkdir "%USERPROFILE%\.config\opencode\plugins" 2>nul
mkdir "%USERPROFILE%\.config\opencode\plugin" 2>nul
mkdir "%USERPROFILE%\.config\opencode\skills" 2>nul
:: 3. Remove existing links (safe for reinstalls)
del "%USERPROFILE%\.config\opencode\plugins\superpowers.js" 2>nul
del "%USERPROFILE%\.config\opencode\plugin\superpowers.js" 2>nul
rmdir "%USERPROFILE%\.config\opencode\skills\superpowers" 2>nul
:: 4. Create plugin symlink (requires Developer Mode or Admin)
mklink "%USERPROFILE%\.config\opencode\plugins\superpowers.js" "%USERPROFILE%\.config\opencode\superpowers\.opencode\plugins\superpowers.js"
mklink "%USERPROFILE%\.config\opencode\plugin\superpowers.js" "%USERPROFILE%\.config\opencode\superpowers\.opencode\plugin\superpowers.js"
:: 5. Create skills junction (works without special privileges)
mklink /J "%USERPROFILE%\.config\opencode\skills\superpowers" "%USERPROFILE%\.config\opencode\superpowers\skills"
@@ -94,15 +90,15 @@ Run as Administrator, or with Developer Mode enabled:
git clone https://github.com/obra/superpowers.git "$env:USERPROFILE\.config\opencode\superpowers"
# 2. Create directories
New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.config\opencode\plugins"
New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.config\opencode\plugin"
New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.config\opencode\skills"
# 3. Remove existing links (safe for reinstalls)
Remove-Item "$env:USERPROFILE\.config\opencode\plugins\superpowers.js" -Force -ErrorAction SilentlyContinue
Remove-Item "$env:USERPROFILE\.config\opencode\plugin\superpowers.js" -Force -ErrorAction SilentlyContinue
Remove-Item "$env:USERPROFILE\.config\opencode\skills\superpowers" -Force -ErrorAction SilentlyContinue
# 4. Create plugin symlink (requires Developer Mode or Admin)
New-Item -ItemType SymbolicLink -Path "$env:USERPROFILE\.config\opencode\plugins\superpowers.js" -Target "$env:USERPROFILE\.config\opencode\superpowers\.opencode\plugins\superpowers.js"
New-Item -ItemType SymbolicLink -Path "$env:USERPROFILE\.config\opencode\plugin\superpowers.js" -Target "$env:USERPROFILE\.config\opencode\superpowers\.opencode\plugin\superpowers.js"
# 5. Create skills junction (works without special privileges)
New-Item -ItemType Junction -Path "$env:USERPROFILE\.config\opencode\skills\superpowers" -Target "$env:USERPROFILE\.config\opencode\superpowers\skills"
@@ -119,14 +115,14 @@ Note: Git Bash's native `ln` command copies files instead of creating symlinks.
git clone https://github.com/obra/superpowers.git ~/.config/opencode/superpowers
# 2. Create directories
mkdir -p ~/.config/opencode/plugins ~/.config/opencode/skills
mkdir -p ~/.config/opencode/plugin ~/.config/opencode/skills
# 3. Remove existing links (safe for reinstalls)
rm -f ~/.config/opencode/plugins/superpowers.js 2>/dev/null
rm -f ~/.config/opencode/plugin/superpowers.js 2>/dev/null
rm -rf ~/.config/opencode/skills/superpowers 2>/dev/null
# 4. Create plugin symlink (requires Developer Mode or Admin)
cmd //c "mklink \"$(cygpath -w ~/.config/opencode/plugins/superpowers.js)\" \"$(cygpath -w ~/.config/opencode/superpowers/.opencode/plugins/superpowers.js)\""
cmd //c "mklink \"$(cygpath -w ~/.config/opencode/plugin/superpowers.js)\" \"$(cygpath -w ~/.config/opencode/superpowers/.opencode/plugin/superpowers.js)\""
# 5. Create skills junction (works without special privileges)
cmd //c "mklink /J \"$(cygpath -w ~/.config/opencode/skills/superpowers)\" \"$(cygpath -w ~/.config/opencode/superpowers/skills)\""
@@ -142,13 +138,13 @@ If running OpenCode inside WSL, use the [macOS / Linux](#macos--linux) instructi
**Command Prompt:**
```cmd
dir /AL "%USERPROFILE%\.config\opencode\plugins"
dir /AL "%USERPROFILE%\.config\opencode\plugin"
dir /AL "%USERPROFILE%\.config\opencode\skills"
```
**PowerShell:**
```powershell
Get-ChildItem "$env:USERPROFILE\.config\opencode\plugins" | Where-Object { $_.LinkType }
Get-ChildItem "$env:USERPROFILE\.config\opencode\plugin" | Where-Object { $_.LinkType }
Get-ChildItem "$env:USERPROFILE\.config\opencode\skills" | Where-Object { $_.LinkType }
```
@@ -258,7 +254,7 @@ Skills written for Claude Code are automatically adapted for OpenCode. The boots
### Plugin Structure
**Location:** `~/.config/opencode/superpowers/.opencode/plugins/superpowers.js`
**Location:** `~/.config/opencode/superpowers/.opencode/plugin/superpowers.js`
**Components:**
- `experimental.chat.system.transform` hook for bootstrap injection
@@ -283,8 +279,8 @@ Restart OpenCode to load the updates.
### Plugin not loading
1. Check plugin exists: `ls ~/.config/opencode/superpowers/.opencode/plugins/superpowers.js`
2. Check symlink/junction: `ls -l ~/.config/opencode/plugins/` (macOS/Linux) or `dir /AL %USERPROFILE%\.config\opencode\plugins` (Windows)
1. Check plugin exists: `ls ~/.config/opencode/superpowers/.opencode/plugin/superpowers.js`
2. Check symlink/junction: `ls -l ~/.config/opencode/plugin/` (macOS/Linux) or `dir /AL %USERPROFILE%\.config\opencode\plugin` (Windows)
3. Check OpenCode logs: `opencode run "test" --print-logs --log-level DEBUG`
4. Look for plugin loading message in logs

View File

@@ -1,301 +0,0 @@
# Document Review System Implementation Plan
> **For Claude:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan.
**Goal:** Add spec and plan document review loops to the brainstorming and writing-plans skills.
**Architecture:** Create reviewer prompt templates in each skill directory. Modify skill files to add review loops after document creation. Use Task tool with general-purpose subagent for reviewer dispatch.
**Tech Stack:** Markdown skill files, subagent dispatch via Task tool
**Spec:** docs/superpowers/specs/2026-01-22-document-review-system-design.md
---
## Chunk 1: Spec Document Reviewer
This chunk adds the spec document reviewer to the brainstorming skill.
### Task 1: Create Spec Document Reviewer Prompt Template
**Files:**
- Create: `skills/brainstorming/spec-document-reviewer-prompt.md`
- [ ] **Step 1:** Create the reviewer prompt template file
```markdown
# Spec Document Reviewer Prompt Template
Use this template when dispatching a spec document reviewer subagent.
**Purpose:** Verify the spec is complete, consistent, and ready for implementation planning.
**Dispatch after:** Spec document is written to docs/superpowers/specs/
```
Task tool (general-purpose):
description: "Review spec document"
prompt: |
You are a spec document reviewer. Verify this spec is complete and ready for planning.
**Spec to review:** [SPEC_FILE_PATH]
## What to Check
| Category | What to Look For |
|----------|------------------|
| Completeness | TODOs, placeholders, "TBD", incomplete sections |
| Coverage | Missing error handling, edge cases, integration points |
| Consistency | Internal contradictions, conflicting requirements |
| Clarity | Ambiguous requirements |
| YAGNI | Unrequested features, over-engineering |
## CRITICAL
Look especially hard for:
- Any TODO markers or placeholder text
- Sections saying "to be defined later" or "will spec when X is done"
- Sections noticeably less detailed than others
## Output Format
## Spec Review
**Status:** ✅ Approved | ❌ Issues Found
**Issues (if any):**
- [Section X]: [specific issue] - [why it matters]
**Recommendations (advisory):**
- [suggestions that don't block approval]
```
**Reviewer returns:** Status, Issues (if any), Recommendations
```
- [ ] **Step 2:** Verify the file was created correctly
Run: `cat skills/brainstorming/spec-document-reviewer-prompt.md | head -20`
Expected: Shows the header and purpose section
- [ ] **Step 3:** Commit
```bash
git add skills/brainstorming/spec-document-reviewer-prompt.md
git commit -m "feat: add spec document reviewer prompt template"
```
---
### Task 2: Add Review Loop to Brainstorming Skill
**Files:**
- Modify: `skills/brainstorming/SKILL.md`
- [ ] **Step 1:** Read the current brainstorming skill
Run: `cat skills/brainstorming/SKILL.md`
- [ ] **Step 2:** Add the review loop section after "After the Design"
Find the "After the Design" section and add a new "Spec Review Loop" section after documentation but before implementation:
```markdown
**Spec Review Loop:**
After writing the spec document:
1. Dispatch spec-document-reviewer subagent (see spec-document-reviewer-prompt.md)
2. If ❌ Issues Found:
- Fix the issues in the spec document
- Re-dispatch reviewer
- Repeat until ✅ Approved
3. If ✅ Approved: proceed to implementation setup
**Review loop guidance:**
- Same agent that wrote the spec fixes it (preserves context)
- If loop exceeds 5 iterations, surface to human for guidance
- Reviewers are advisory - explain disagreements if you believe feedback is incorrect
```
- [ ] **Step 3:** Verify the changes
Run: `grep -A 15 "Spec Review Loop" skills/brainstorming/SKILL.md`
Expected: Shows the new review loop section
- [ ] **Step 4:** Commit
```bash
git add skills/brainstorming/SKILL.md
git commit -m "feat: add spec review loop to brainstorming skill"
```
---
## Chunk 2: Plan Document Reviewer
This chunk adds the plan document reviewer to the writing-plans skill.
### Task 3: Create Plan Document Reviewer Prompt Template
**Files:**
- Create: `skills/writing-plans/plan-document-reviewer-prompt.md`
- [ ] **Step 1:** Create the reviewer prompt template file
```markdown
# Plan Document Reviewer Prompt Template
Use this template when dispatching a plan document reviewer subagent.
**Purpose:** Verify the plan chunk is complete, matches the spec, and has proper task decomposition.
**Dispatch after:** Each plan chunk is written
```
Task tool (general-purpose):
description: "Review plan chunk N"
prompt: |
You are a plan document reviewer. Verify this plan chunk is complete and ready for implementation.
**Plan chunk to review:** [PLAN_FILE_PATH] - Chunk N only
**Spec for reference:** [SPEC_FILE_PATH]
## What to Check
| Category | What to Look For |
|----------|------------------|
| Completeness | TODOs, placeholders, incomplete tasks, missing steps |
| Spec Alignment | Chunk covers relevant spec requirements, no scope creep |
| Task Decomposition | Tasks atomic, clear boundaries, steps actionable |
| Task Syntax | Checkbox syntax (`- [ ]`) on tasks and steps |
| Chunk Size | Each chunk under 1000 lines |
## CRITICAL
Look especially hard for:
- Any TODO markers or placeholder text
- Steps that say "similar to X" without actual content
- Incomplete task definitions
- Missing verification steps or expected outputs
## Output Format
## Plan Review - Chunk N
**Status:** ✅ Approved | ❌ Issues Found
**Issues (if any):**
- [Task X, Step Y]: [specific issue] - [why it matters]
**Recommendations (advisory):**
- [suggestions that don't block approval]
```
**Reviewer returns:** Status, Issues (if any), Recommendations
```
- [ ] **Step 2:** Verify the file was created
Run: `cat skills/writing-plans/plan-document-reviewer-prompt.md | head -20`
Expected: Shows the header and purpose section
- [ ] **Step 3:** Commit
```bash
git add skills/writing-plans/plan-document-reviewer-prompt.md
git commit -m "feat: add plan document reviewer prompt template"
```
---
### Task 4: Add Review Loop to Writing-Plans Skill
**Files:**
- Modify: `skills/writing-plans/SKILL.md`
- [ ] **Step 1:** Read current skill file
Run: `cat skills/writing-plans/SKILL.md`
- [ ] **Step 2:** Add chunk-by-chunk review section
Add before the "Execution Handoff" section:
```markdown
## Plan Review Loop
After completing each chunk of the plan:
1. Dispatch plan-document-reviewer subagent for the current chunk
- Provide: chunk content, path to spec document
2. If ❌ Issues Found:
- Fix the issues in the chunk
- Re-dispatch reviewer for that chunk
- Repeat until ✅ Approved
3. If ✅ Approved: proceed to next chunk (or execution handoff if last chunk)
**Chunk boundaries:** Use `## Chunk N: <name>` headings to delimit chunks. Each chunk should be ≤1000 lines and logically self-contained.
```
- [ ] **Step 3:** Update task syntax examples to use checkboxes
Change the Task Structure section to show checkbox syntax:
```markdown
### Task N: [Component Name]
- [ ] **Step 1:** Write the failing test
- File: `tests/path/test.py`
...
```
- [ ] **Step 4:** Verify the review loop section was added
Run: `grep -A 15 "Plan Review Loop" skills/writing-plans/SKILL.md`
Expected: Shows the new review loop section
- [ ] **Step 5:** Verify the task syntax examples were updated
Run: `grep -A 5 "Task N:" skills/writing-plans/SKILL.md`
Expected: Shows checkbox syntax `### Task N:`
- [ ] **Step 6:** Commit
```bash
git add skills/writing-plans/SKILL.md
git commit -m "feat: add plan review loop and checkbox syntax to writing-plans skill"
```
---
## Chunk 3: Update Plan Document Header
This chunk updates the plan document header template to reference the new checkbox syntax requirements.
### Task 5: Update Plan Header Template in Writing-Plans Skill
**Files:**
- Modify: `skills/writing-plans/SKILL.md`
- [ ] **Step 1:** Read current plan header template
Run: `grep -A 20 "Plan Document Header" skills/writing-plans/SKILL.md`
- [ ] **Step 2:** Update the header template to reference checkbox syntax
The plan header should note that tasks and steps use checkbox syntax. Update the header comment:
```markdown
> **For Claude:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Tasks and steps use checkbox (`- [ ]`) syntax for tracking.
```
- [ ] **Step 3:** Verify the change
Run: `grep -A 5 "For Claude:" skills/writing-plans/SKILL.md`
Expected: Shows updated header with checkbox syntax mention
- [ ] **Step 4:** Commit
```bash
git add skills/writing-plans/SKILL.md
git commit -m "docs: update plan header to reference checkbox syntax"
```

View File

@@ -1,136 +0,0 @@
# Document Review System Design
## Overview
Add two new review stages to the superpowers workflow:
1. **Spec Document Review** - After brainstorming, before writing-plans
2. **Plan Document Review** - After writing-plans, before implementation
Both follow the iterative loop pattern used by implementation reviews.
## Spec Document Reviewer
**Purpose:** Verify the spec is complete, consistent, and ready for implementation planning.
**Location:** `skills/brainstorming/spec-document-reviewer-prompt.md`
**What it checks for:**
| Category | What to Look For |
|----------|------------------|
| Completeness | TODOs, placeholders, "TBD", incomplete sections |
| Coverage | Missing error handling, edge cases, integration points |
| Consistency | Internal contradictions, conflicting requirements |
| Clarity | Ambiguous requirements |
| YAGNI | Unrequested features, over-engineering |
**Output format:**
```
## Spec Review
**Status:** Approved | Issues Found
**Issues (if any):**
- [Section X]: [issue] - [why it matters]
**Recommendations (advisory):**
- [suggestions that don't block approval]
```
**Review loop:** Issues found -> brainstorming agent fixes -> re-review -> repeat until approved.
**Dispatch mechanism:** Use the Task tool with `subagent_type: general-purpose`. The reviewer prompt template provides the full prompt. The brainstorming skill's controller dispatches the reviewer.
## Plan Document Reviewer
**Purpose:** Verify the plan is complete, matches the spec, and has proper task decomposition.
**Location:** `skills/writing-plans/plan-document-reviewer-prompt.md`
**What it checks for:**
| Category | What to Look For |
|----------|------------------|
| Completeness | TODOs, placeholders, incomplete tasks |
| Spec Alignment | Plan covers spec requirements, no scope creep |
| Task Decomposition | Tasks atomic, clear boundaries |
| Task Syntax | Checkbox syntax on tasks and steps |
| Chunk Size | Each chunk under 1000 lines |
**Chunk definition:** A chunk is a logical grouping of tasks within the plan document, delimited by `## Chunk N: <name>` headings. The writing-plans skill creates these boundaries based on logical phases (e.g., "Foundation", "Core Features", "Integration"). Each chunk should be self-contained enough to review independently.
**Spec alignment verification:** The reviewer receives both:
1. The plan document (or current chunk)
2. The path to the spec document for reference
The reviewer reads both and compares requirements coverage.
**Output format:** Same as spec reviewer, but scoped to the current chunk.
**Review process (chunk-by-chunk):**
1. Writing-plans creates chunk N
2. Controller dispatches plan-document-reviewer with chunk N content and spec path
3. Reviewer reads chunk and spec, returns verdict
4. If issues: writing-plans agent fixes chunk N, goto step 2
5. If approved: proceed to chunk N+1
6. Repeat until all chunks approved
**Dispatch mechanism:** Same as spec reviewer - Task tool with `subagent_type: general-purpose`.
## Updated Workflow
```
brainstorming -> spec -> SPEC REVIEW LOOP -> writing-plans -> plan -> PLAN REVIEW LOOP -> implementation
```
**Spec Review Loop:**
1. Spec complete
2. Dispatch reviewer
3. If issues: fix -> goto 2
4. If approved: proceed
**Plan Review Loop:**
1. Chunk N complete
2. Dispatch reviewer for chunk N
3. If issues: fix -> goto 2
4. If approved: next chunk or implementation
## Markdown Task Syntax
Tasks and steps use checkbox syntax:
```markdown
- [ ] ### Task 1: Name
- [ ] **Step 1:** Description
- File: path
- Command: cmd
```
## Error Handling
**Review loop termination:**
- No hard iteration limit - loops continue until reviewer approves
- If loop exceeds 5 iterations, the controller should surface this to the human for guidance
- The human can choose to: continue iterating, approve with known issues, or abort
**Disagreement handling:**
- Reviewers are advisory - they flag issues but don't block
- If the agent believes reviewer feedback is incorrect, it should explain why in its fix
- If disagreement persists after 3 iterations on the same issue, surface to human
**Malformed reviewer output:**
- Controller should validate reviewer output has required fields (Status, Issues if applicable)
- If malformed, re-dispatch reviewer with a note about expected format
- After 2 malformed responses, surface to human
## Files to Change
**New files:**
- `skills/brainstorming/spec-document-reviewer-prompt.md`
- `skills/writing-plans/plan-document-reviewer-prompt.md`
**Modified files:**
- `skills/brainstorming/SKILL.md` - add review loop after spec written
- `skills/writing-plans/SKILL.md` - add chunk-by-chunk review loop, update task syntax examples

View File

@@ -6,8 +6,7 @@
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/session-start.sh",
"async": true
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/run-hook.cmd\" session-start.sh"
}
]
}

View File

@@ -1,30 +1,6 @@
: << 'CMDBLOCK'
@echo off
REM ============================================================================
REM DEPRECATED: This polyglot wrapper is no longer used as of Claude Code 2.1.x
REM ============================================================================
REM
REM Claude Code 2.1.x changed the Windows execution model for hooks:
REM
REM Before (2.0.x): Hooks ran with shell:true, using the system default shell.
REM This wrapper provided cross-platform compatibility by
REM being both a valid .cmd file (Windows) and bash script.
REM
REM After (2.1.x): Claude Code now auto-detects .sh files in hook commands
REM and prepends "bash " on Windows. This broke the wrapper
REM because the command:
REM "run-hook.cmd" session-start.sh
REM became:
REM bash "run-hook.cmd" session-start.sh
REM ...and bash cannot execute a .cmd file.
REM
REM The fix: hooks.json now calls session-start.sh directly. Claude Code 2.1.x
REM handles the bash invocation automatically on Windows.
REM
REM This file is kept for reference and potential backward compatibility.
REM ============================================================================
REM
REM Original purpose: Polyglot wrapper to run .sh scripts cross-platform
REM Polyglot wrapper: runs .sh scripts cross-platform
REM Usage: run-hook.cmd <script-name> [args...]
REM The script should be in the same directory as this wrapper

View File

@@ -17,17 +17,23 @@ fi
# Read using-superpowers content
using_superpowers_content=$(cat "${PLUGIN_ROOT}/skills/using-superpowers/SKILL.md" 2>&1 || echo "Error reading using-superpowers skill")
# Escape string for JSON embedding using bash parameter substitution.
# Each ${s//old/new} is a single C-level pass - orders of magnitude
# faster than the character-by-character loop this replaces.
# Escape outputs for JSON using pure bash
escape_for_json() {
local s="$1"
s="${s//\\/\\\\}"
s="${s//\"/\\\"}"
s="${s//$'\n'/\\n}"
s="${s//$'\r'/\\r}"
s="${s//$'\t'/\\t}"
printf '%s' "$s"
local input="$1"
local output=""
local i char
for (( i=0; i<${#input}; i++ )); do
char="${input:$i:1}"
case "$char" in
$'\\') output+='\\' ;;
'"') output+='\"' ;;
$'\n') output+='\n' ;;
$'\r') output+='\r' ;;
$'\t') output+='\t' ;;
*) output+="$char" ;;
esac
done
printf '%s' "$output"
}
using_superpowers_escaped=$(escape_for_json "$using_superpowers_content")

View File

@@ -0,0 +1,212 @@
# Visual Companion Instructions for Claude
This document explains how to use the brainstorm visual companion to show mockups, designs, and options to users without resorting to ASCII art.
## When to Use
Use the visual companion when you need to show:
- **UI mockups** - layouts, navigation patterns, component designs
- **Design comparisons** - "Which of these 3 approaches works better?"
- **Interactive prototypes** - clickable wireframes
- **Visual choices** - anything where seeing beats describing
**Don't use it for:** simple text questions, code review, or when the user prefers terminal-only interaction.
## Lifecycle
```bash
# Start server (returns JSON with URL and session directory)
${CLAUDE_PLUGIN_ROOT}/lib/brainstorm-server/start-server.sh
# Returns: {"type":"server-started","port":52341,"url":"http://localhost:52341",
# "screen_dir":"/tmp/brainstorm-12345-1234567890"}
# Save screen_dir from response!
# Tell user to open the URL in their browser
# For each screen:
# 1. Start watcher in background FIRST (avoids race condition)
${CLAUDE_PLUGIN_ROOT}/lib/brainstorm-server/wait-for-feedback.sh $SCREEN_DIR
# 2. Write HTML to a NEW file in screen_dir (e.g., platform.html, style.html)
# Server automatically serves the newest file by modification time
# 3. Call TaskOutput(task_id, block=true, timeout=600000) to wait for feedback
# When done, stop server (pass screen_dir)
${CLAUDE_PLUGIN_ROOT}/lib/brainstorm-server/stop-server.sh $SCREEN_DIR
```
## File Naming
- **Use semantic names**: `platform.html`, `visual-style.html`, `layout.html`, `controls.html`
- **Never reuse filenames** - each screen must be a new file
- **For iterations**: append version suffix like `layout-v2.html`, `layout-v3.html`
- Server automatically serves the newest `.html` file by modification time
## Writing Screens
Copy the frame template structure but replace `#claude-content` with your content:
```html
<div id="claude-content">
<h2>Your Question</h2>
<p class="subtitle">Brief context</p>
<!-- Your content here -->
</div>
```
The frame template (`frame-template.html`) includes CSS for:
- OS-aware light/dark theming
- Fixed header and feedback footer
- Common UI patterns (see below)
## CSS Helper Classes
### Options (A/B/C choices)
```html
<div class="options">
<div class="option" data-choice="a" onclick="toggleSelect(this)">
<div class="letter">A</div>
<div class="content">
<h3>Option Title</h3>
<p>Description of this option</p>
</div>
</div>
<!-- More options... -->
</div>
```
### Cards (visual designs)
```html
<div class="cards">
<div class="card" data-choice="design1" onclick="toggleSelect(this)">
<div class="card-image">
<!-- Put mockup content here -->
</div>
<div class="card-body">
<h3>Design Name</h3>
<p>Brief description</p>
</div>
</div>
</div>
```
### Mockup Container
```html
<div class="mockup">
<div class="mockup-header">Preview: Dashboard Layout</div>
<div class="mockup-body">
<!-- Your mockup HTML -->
</div>
</div>
```
### Split View (side-by-side)
```html
<div class="split">
<div class="mockup"><!-- Left side --></div>
<div class="mockup"><!-- Right side --></div>
</div>
```
### Pros/Cons
```html
<div class="pros-cons">
<div class="pros">
<h4>Pros</h4>
<ul>
<li>Benefit one</li>
<li>Benefit two</li>
</ul>
</div>
<div class="cons">
<h4>Cons</h4>
<ul>
<li>Drawback one</li>
<li>Drawback two</li>
</ul>
</div>
</div>
```
### Inline Mockup Elements
```html
<div class="mock-nav">Logo | Home | About | Contact</div>
<div style="display: flex;">
<div class="mock-sidebar">Navigation</div>
<div class="mock-content">Main content area</div>
</div>
<button class="mock-button">Action Button</button>
<input class="mock-input" placeholder="Input field">
```
## User Feedback
When the user clicks Send, you receive JSON like:
```json
{"choice": "a", "feedback": "I like this but make the header smaller"}
```
- `choice` - which option/card they selected (from `data-choice` attribute)
- `feedback` - any notes they typed
## Example: Design Comparison
```html
<div id="claude-content">
<h2>Which blog layout works better?</h2>
<p class="subtitle">Consider readability and visual hierarchy</p>
<div class="cards">
<div class="card" data-choice="classic" onclick="toggleSelect(this)">
<div class="card-image">
<div style="padding: 1rem;">
<div class="mock-nav">Blog Title</div>
<div style="padding: 1rem;">
<h3 style="margin-bottom: 0.5rem;">Post Title</h3>
<p style="color: var(--text-secondary); font-size: 0.9rem;">
Content preview text goes here...
</p>
</div>
</div>
</div>
<div class="card-body">
<h3>Classic Layout</h3>
<p>Traditional blog with posts in a single column</p>
</div>
</div>
<div class="card" data-choice="magazine" onclick="toggleSelect(this)">
<div class="card-image">
<div style="padding: 1rem;">
<div class="mock-nav">Blog Title</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem; padding: 0.5rem;">
<div class="placeholder" style="padding: 1rem;">Featured</div>
<div class="placeholder" style="padding: 0.5rem;">Post</div>
</div>
</div>
</div>
<div class="card-body">
<h3>Magazine Layout</h3>
<p>Grid-based with featured posts</p>
</div>
</div>
</div>
</div>
```
## Tips
1. **Keep mockups simple** - Focus on layout and structure, not pixel-perfect design
2. **Use placeholders** - The `.placeholder` class works great for content areas
3. **Label clearly** - Use `.mockup-header` to explain what each mockup shows
4. **Limit choices** - 2-4 options is ideal; more gets overwhelming
5. **Provide context** - Use `.subtitle` to explain what you're asking
6. **Regenerate fully** - Write the complete HTML each turn; don't try to patch

View File

@@ -232,5 +232,28 @@
</div>
</div>
<script>
let selectedChoice = null;
function toggleSelect(el) {
const container = el.closest('.options') || el.closest('.cards');
if (container) {
container.querySelectorAll('.option, .card').forEach(o => o.classList.remove('selected'));
}
el.classList.add('selected');
selectedChoice = el.dataset.choice;
}
function send() {
const feedbackEl = document.getElementById('feedback');
const feedback = feedbackEl.value.trim();
const payload = {};
if (selectedChoice) payload.choice = selectedChoice;
if (feedback) payload.feedback = feedback;
if (Object.keys(payload).length === 0) return;
brainstorm.sendToClaude(payload);
feedbackEl.value = '';
}
</script>
</body>
</html>

View File

@@ -7,6 +7,7 @@
ws = new WebSocket(WS_URL);
ws.onopen = () => {
// Send any queued events
eventQueue.forEach(e => ws.send(JSON.stringify(e)));
eventQueue = [];
};
@@ -19,11 +20,12 @@
};
ws.onclose = () => {
// Reconnect after 1 second
setTimeout(connect, 1000);
};
}
function sendEvent(event) {
function send(event) {
event.timestamp = Date.now();
if (ws && ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify(event));
@@ -40,12 +42,9 @@
// Don't capture regular link navigation
if (target.tagName === 'A' && !target.dataset.choice) return;
// Don't capture the Send feedback button (handled by send())
if (target.id === 'send-feedback') return;
e.preventDefault();
sendEvent({
send({
type: 'click',
text: target.textContent.trim(),
choice: target.dataset.choice || null,
@@ -62,7 +61,7 @@
const data = {};
formData.forEach((value, key) => { data[key] = value; });
sendEvent({
send({
type: 'submit',
formId: form.id || null,
formName: form.name || null,
@@ -78,60 +77,37 @@
clearTimeout(inputTimeout);
inputTimeout = setTimeout(() => {
sendEvent({
send({
type: 'input',
name: target.name || null,
id: target.id || null,
value: target.value,
inputType: target.type || target.tagName.toLowerCase()
});
}, 500);
}, 500); // 500ms debounce
});
// Send to Claude - triggers feedback delivery
// Send to Claude - triggers server to exit and return all events
function sendToClaude(feedback) {
sendEvent({
send({
type: 'send-to-claude',
feedback: feedback || null
});
// Show themed confirmation page
// Show confirmation to user
document.body.innerHTML = `
<div style="display: flex; align-items: center; justify-content: center; height: 100vh; font-family: system-ui, -apple-system, BlinkMacSystemFont, sans-serif; background: var(--bg-primary, #f5f5f7);">
<div style="text-align: center; color: var(--text-secondary, #86868b);">
<h2 style="color: var(--text-primary, #1d1d1f); margin-bottom: 0.5rem;">Sent to Claude</h2>
<div style="display: flex; align-items: center; justify-content: center; height: 100vh; font-family: system-ui, sans-serif;">
<div style="text-align: center; color: #666;">
<h2 style="color: #333;">Sent to Claude</h2>
<p>Return to the terminal to see Claude's response.</p>
</div>
</div>
`;
}
// Frame UI: selection tracking and feedback send
window.selectedChoice = null;
window.toggleSelect = function(el) {
const container = el.closest('.options') || el.closest('.cards');
if (container) {
container.querySelectorAll('.option, .card').forEach(o => o.classList.remove('selected'));
}
el.classList.add('selected');
window.selectedChoice = el.dataset.choice;
};
window.send = function() {
const feedbackEl = document.getElementById('feedback');
const feedback = feedbackEl ? feedbackEl.value.trim() : '';
const payload = {};
if (window.selectedChoice) payload.choice = window.selectedChoice;
if (feedback) payload.feedback = feedback;
if (Object.keys(payload).length === 0) return;
sendToClaude(payload);
if (feedbackEl) feedbackEl.value = '';
};
// Expose API for explicit use
// Expose for explicit use if needed
window.brainstorm = {
send: sendEvent,
choice: (value, metadata = {}) => sendEvent({ type: 'choice', value, ...metadata }),
send: send,
choice: (value, metadata = {}) => send({ type: 'choice', value, ...metadata }),
sendToClaude: sendToClaude
};

View File

@@ -5,32 +5,15 @@ const chokidar = require('chokidar');
const fs = require('fs');
const path = require('path');
// Use provided port or pick a random high port (49152-65535)
const PORT = process.env.BRAINSTORM_PORT || (49152 + Math.floor(Math.random() * 16383));
const SCREEN_DIR = process.env.BRAINSTORM_DIR || '/tmp/brainstorm';
// Ensure screen directory exists
if (!fs.existsSync(SCREEN_DIR)) {
fs.mkdirSync(SCREEN_DIR, { recursive: true });
}
// Load frame template and helper script once at startup
const frameTemplate = fs.readFileSync(path.join(__dirname, 'frame-template.html'), 'utf-8');
const helperScript = fs.readFileSync(path.join(__dirname, 'helper.js'), 'utf-8');
const helperInjection = `<script>\n${helperScript}\n</script>`;
// Detect whether content is a full HTML document or a bare fragment
function isFullDocument(html) {
const trimmed = html.trimStart().toLowerCase();
return trimmed.startsWith('<!doctype') || trimmed.startsWith('<html');
}
// Wrap a content fragment in the frame template
function wrapInFrame(content) {
return frameTemplate.replace(
/(<div id="claude-content">)[\s\S]*?(<\/div>\s*<\/div>\s*<div class="feedback-footer">)/,
`$1\n ${content}\n $2`
);
}
// Find the newest .html file in the directory by mtime
function getNewestScreen() {
const files = fs.readdirSync(SCREEN_DIR)
@@ -45,6 +28,7 @@ function getNewestScreen() {
return files.length > 0 ? files[0].path : null;
}
// Default waiting page (served when no screens exist yet)
const WAITING_PAGE = `<!DOCTYPE html>
<html>
<head>
@@ -65,6 +49,7 @@ const app = express();
const server = http.createServer(app);
const wss = new WebSocket.Server({ server });
// Track connected browsers for reload notifications
const clients = new Set();
wss.on('connection', (ws) => {
@@ -72,6 +57,7 @@ wss.on('connection', (ws) => {
ws.on('close', () => clients.delete(ws));
ws.on('message', (data) => {
// User interaction event - write to stdout for Claude
const event = JSON.parse(data.toString());
console.log(JSON.stringify({ source: 'user-event', ...event }));
});
@@ -80,30 +66,27 @@ wss.on('connection', (ws) => {
// Serve newest screen with helper.js injected
app.get('/', (req, res) => {
const screenFile = getNewestScreen();
let html;
let html = screenFile ? fs.readFileSync(screenFile, 'utf-8') : WAITING_PAGE;
if (!screenFile) {
html = WAITING_PAGE;
} else {
const raw = fs.readFileSync(screenFile, 'utf-8');
html = isFullDocument(raw) ? raw : wrapInFrame(raw);
}
// Inject helper script before </body>
const helperScript = fs.readFileSync(path.join(__dirname, 'helper.js'), 'utf-8');
const injection = `<script>\n${helperScript}\n</script>`;
// Inject helper script
if (html.includes('</body>')) {
html = html.replace('</body>', `${helperInjection}\n</body>`);
html = html.replace('</body>', `${injection}\n</body>`);
} else {
html += helperInjection;
html += injection;
}
res.type('html').send(html);
});
// Watch for new or changed .html files
// Watch for new or changed .html files in the directory
chokidar.watch(SCREEN_DIR, { ignoreInitial: true })
.on('add', (filePath) => {
if (filePath.endsWith('.html')) {
console.log(JSON.stringify({ type: 'screen-added', file: filePath }));
// Notify all browsers to reload
clients.forEach(ws => {
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({ type: 'reload' }));

View File

@@ -1,40 +1,16 @@
#!/bin/bash
# Start the brainstorm server and output connection info
# Usage: start-server.sh [--project-dir <path>]
# Usage: start-server.sh
#
# Starts server on a random high port, outputs JSON with URL.
# Each session gets its own directory to avoid conflicts.
#
# Options:
# --project-dir <path> Store session files under <path>/.superpowers/brainstorm/
# instead of /tmp. Files persist after server stops.
# Starts server on a random high port, outputs JSON with URL
# Each session gets its own temp directory to avoid conflicts
# Server runs in background, PID saved for cleanup
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
# Parse arguments
PROJECT_DIR=""
while [[ $# -gt 0 ]]; do
case "$1" in
--project-dir)
PROJECT_DIR="$2"
shift 2
;;
*)
echo "{\"error\": \"Unknown argument: $1\"}"
exit 1
;;
esac
done
# Generate unique session directory
SESSION_ID="$$-$(date +%s)"
if [[ -n "$PROJECT_DIR" ]]; then
SCREEN_DIR="${PROJECT_DIR}/.superpowers/brainstorm/${SESSION_ID}"
else
SCREEN_DIR="/tmp/brainstorm-${SESSION_ID}"
fi
SCREEN_DIR="/tmp/brainstorm-${SESSION_ID}"
PID_FILE="${SCREEN_DIR}/.server.pid"
LOG_FILE="${SCREEN_DIR}/.server.log"
@@ -57,6 +33,7 @@ echo "$SERVER_PID" > "$PID_FILE"
# Wait for server-started message (check log file)
for i in {1..50}; do
if grep -q "server-started" "$LOG_FILE" 2>/dev/null; then
# Extract and output the server-started line
grep "server-started" "$LOG_FILE" | head -1
exit 0
fi

View File

@@ -1,10 +1,6 @@
#!/bin/bash
# Stop the brainstorm server and clean up
# Stop the brainstorm server and clean up session directory
# Usage: stop-server.sh <screen_dir>
#
# Kills the server process. Only deletes session directory if it's
# under /tmp (ephemeral). Persistent directories (.superpowers/) are
# kept so mockups can be reviewed later.
SCREEN_DIR="$1"
@@ -18,13 +14,8 @@ PID_FILE="${SCREEN_DIR}/.server.pid"
if [[ -f "$PID_FILE" ]]; then
pid=$(cat "$PID_FILE")
kill "$pid" 2>/dev/null
rm -f "$PID_FILE" "${SCREEN_DIR}/.server.log"
# Only delete ephemeral /tmp directories
if [[ "$SCREEN_DIR" == /tmp/* ]]; then
rm -rf "$SCREEN_DIR"
fi
# Clean up session directory
rm -rf "$SCREEN_DIR"
echo '{"status": "stopped"}'
else
echo '{"status": "not_running"}'

View File

@@ -5,6 +5,8 @@ description: "You MUST use this before any creative work - creating features, bu
# Brainstorming Ideas Into Designs
## Overview
Help turn ideas into fully formed designs and specs through natural collaborative dialogue.
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,9 +15,7 @@ Start by understanding the current project context, then ask questions one at a
**Understanding the idea:**
- Check out the current project state first (files, docs, recent commits)
- Before asking detailed questions, assess scope: if the request describes multiple independent subsystems (e.g., "build a platform with chat, file storage, billing, and analytics"), flag this immediately. Don't spend questions refining details of a project that needs to be decomposed first.
- If the project is too large for a single spec, help the user decompose into sub-projects: what are the independent pieces, how do they relate, what order should they be built? Then brainstorm the first sub-project through the normal design flow. Each sub-project gets its own spec → plan → implementation cycle.
- For appropriately-scoped projects, ask questions one at a time to refine the idea
- Ask questions one at a time to refine the idea
- Prefer multiple choice questions when possible, but open-ended is fine too
- Only one question per message - if a topic needs more exploration, break it into multiple questions
- Focus on understanding: purpose, constraints, success criteria
@@ -32,35 +32,17 @@ Start by understanding the current project context, then ask questions one at a
- Cover: architecture, components, data flow, error handling, testing
- Be ready to go back and clarify if something doesn't make sense
**Design for isolation and clarity:**
- Break the system into smaller units that each have one clear purpose, communicate through well-defined interfaces, and can be understood and tested independently
- For each unit, you should be able to answer: what does it do, how do you use it, and what does it depend on?
- Can someone understand what a unit does without reading its internals? Can you change the internals without breaking consumers? If not, the boundaries need work.
- Smaller, well-bounded units are also easier for you to work with - you reason better about code you can hold in context at once, and your edits are more reliable when files are focused. When a file grows large, that's often a signal that it's doing too much.
**Working in existing codebases:**
- Explore the current structure before proposing changes. Follow existing patterns.
- Where existing code has problems that affect the work (e.g., a file that's grown too large, unclear boundaries, tangled responsibilities), include targeted improvements as part of the design - the way a good developer improves code they're working in.
- Don't propose unrelated refactoring. Stay focused on what serves the current goal.
## After the Design
**Documentation:**
- Write the validated design (spec) to `docs/superpowers/specs/YYYY-MM-DD-<topic>-design.md`
- (User preferences for spec location override this default)
- Write the validated design to `docs/plans/YYYY-MM-DD-<topic>-design.md`
- Use elements-of-style:writing-clearly-and-concisely skill if available
- Commit the design document to git
**Spec Review Loop:**
After writing the spec document:
1. Dispatch spec-document-reviewer subagent (see spec-document-reviewer-prompt.md)
2. If Issues Found: fix, re-dispatch, repeat until Approved
3. If loop exceeds 5 iterations, surface to human for guidance
**Implementation (if continuing):**
When the user approves the design and wants to build:
1. **Invoke `superpowers:writing-plans` using the Skill tool.** Not EnterPlanMode. Not plan mode. Not direct implementation. The Skill tool.
2. After the plan is written, use superpowers:using-git-worktrees to create an isolated workspace for implementation.
- Ask: "Ready to set up for implementation?"
- Use superpowers:using-git-worktrees to create isolated workspace
- Use superpowers:writing-plans to create detailed implementation plan
## Key Principles
@@ -73,10 +55,83 @@ When the user approves the design and wants to build:
## Visual Companion (Claude Code Only)
A browser-based visual companion for showing mockups, diagrams, and options during brainstorming. Use it whenever visual representation would make feedback easier than text descriptions alone.
A browser-based visual companion for showing mockups, diagrams, and options. Use it whenever visual representation makes feedback easier. **Only works in Claude Code.**
**When the topic involves visual decisions, ask:**
> "This involves some visual decisions. I can show mockups in a browser window so you can see options and give feedback visually. This feature is still new — it can be token-intensive and a bit slow, but it works well for layout, design, and architecture questions. Want to try it? (Requires opening a local URL)"
### When to Use
If they agree, read the detailed guide before proceeding:
`${CLAUDE_PLUGIN_ROOT}/skills/brainstorming/visual-companion.md`
Use the visual companion when seeing beats describing:
- **UI mockups** - layouts, navigation, component designs
- **Architecture diagrams** - system components, data flow, relationships
- **Complex choices** - multi-option decisions with visual trade-offs
- **Design polish** - when the question is about look and feel
- **Spatial relationships** - file structures, database schemas, state machines
**Always ask first:**
> "This involves some visual decisions. Would you like me to show mockups in a browser window? (Requires opening a local URL)"
Only proceed if they agree. Otherwise, describe options in text.
### How to Use Effectively
**Scale fidelity to the question.** If you're asking about layout structure, simple wireframes suffice. If you're asking about visual polish, show polish. Match the mockup's detail level to what you're trying to learn.
**Explain the question on each page.** Don't just show options—state what decision you're seeking. "Which layout feels more professional?" not just "Pick one."
**Iterate before moving on.** If feedback changes the current screen, update it and show again. Validate that your changes address their feedback before proceeding to the next question.
**Limit choices to 2-4 options.** More gets overwhelming. If you have more alternatives, narrow them down first or group them.
**Use real content when it matters.** For a photography portfolio, use actual images (Unsplash). For a blog, use realistic text. Placeholder content obscures design issues.
### Starting a Session
```bash
# Start server (creates unique session directory)
${CLAUDE_PLUGIN_ROOT}/lib/brainstorm-server/start-server.sh
# Returns: {"type":"server-started","port":52341,"url":"http://localhost:52341",
# "screen_dir":"/tmp/brainstorm-12345"}
```
Save `screen_dir` from the response. Tell user to open the URL.
### The Loop
1. **Start watcher first** (background bash) - avoids race condition:
```bash
${CLAUDE_PLUGIN_ROOT}/lib/brainstorm-server/wait-for-feedback.sh $SCREEN_DIR
```
2. **Write HTML** to a new file in `screen_dir`:
- Use semantic filenames: `platform.html`, `visual-style.html`, `layout.html`
- **Never reuse filenames** - each screen gets a fresh file
- Use Write tool - **never use cat/heredoc** (dumps noise into terminal)
- Server automatically serves the newest file
3. **Tell user what to expect:**
- Remind them of the URL (every step, not just first)
- Give a brief text summary of what's on screen (e.g., "Showing 3 layout options for the homepage")
- This lets them know what to look for before switching to browser
4. **Wait for feedback** - call `TaskOutput(task_id, block=true, timeout=600000)`
- If timeout, call TaskOutput again (watcher still running)
- After 3 timeouts (30 min), say "Let me know when you want to continue"
5. **Process feedback** - returns JSON like `{"choice": "a", "feedback": "make header smaller"}`
6. **Iterate or advance** - if feedback changes current screen, write a new file (e.g., `layout-v2.html`). Only move to next question when current step is validated.
7. Repeat until done.
### Cleaning Up
```bash
${CLAUDE_PLUGIN_ROOT}/lib/brainstorm-server/stop-server.sh $SCREEN_DIR
```
### Resources
- Frame template: `${CLAUDE_PLUGIN_ROOT}/lib/brainstorm-server/frame-template.html`
- CSS classes: `.options`, `.cards`, `.mockup`, `.split`, `.pros-cons`
- Detailed examples: `${CLAUDE_PLUGIN_ROOT}/lib/brainstorm-server/CLAUDE-INSTRUCTIONS.md`
- Quick reference: `${CLAUDE_PLUGIN_ROOT}/skills/brainstorming/visual-companion.md`

View File

@@ -1,50 +0,0 @@
# Spec Document Reviewer Prompt Template
Use this template when dispatching a spec document reviewer subagent.
**Purpose:** Verify the spec is complete, consistent, and ready for implementation planning.
**Dispatch after:** Spec document is written to docs/superpowers/specs/
```
Task tool (general-purpose):
description: "Review spec document"
prompt: |
You are a spec document reviewer. Verify this spec is complete and ready for planning.
**Spec to review:** [SPEC_FILE_PATH]
## What to Check
| Category | What to Look For |
|----------|------------------|
| Completeness | TODOs, placeholders, "TBD", incomplete sections |
| Coverage | Missing error handling, edge cases, integration points |
| Consistency | Internal contradictions, conflicting requirements |
| Clarity | Ambiguous requirements |
| YAGNI | Unrequested features, over-engineering |
| Scope | Focused enough for a single plan — not covering multiple independent subsystems |
| Architecture | Units with clear boundaries, well-defined interfaces, independently understandable and testable |
## CRITICAL
Look especially hard for:
- Any TODO markers or placeholder text
- Sections saying "to be defined later" or "will spec when X is done"
- Sections noticeably less detailed than others
- Units that lack clear boundaries or interfaces — can you understand what each unit does without reading its internals?
## Output Format
## Spec Review
**Status:** ✅ Approved | ❌ Issues Found
**Issues (if any):**
- [Section X]: [specific issue] - [why it matters]
**Recommendations (advisory):**
- [suggestions that don't block approval]
```
**Reviewer returns:** Status, Issues (if any), Recommendations

View File

@@ -1,97 +1,62 @@
# Visual Companion Guide
# Visual Companion Reference
Browser-based visual brainstorming companion for showing mockups, diagrams, and options.
Quick reference for the browser-based visual brainstorming companion.
## When to Use
## Files
Use the visual companion when seeing beats describing:
- **UI mockups** — layouts, navigation, component designs
- **Architecture diagrams** — system components, data flow, relationships
- **Complex choices** — multi-option decisions with visual trade-offs
- **Design polish** — when the question is about look and feel
- **Spatial relationships** — file structures, database schemas, state machines
| File | Purpose |
|------|---------|
| `lib/brainstorm-server/start-server.sh` | Start server, outputs JSON with URL and session paths |
| `lib/brainstorm-server/stop-server.sh` | Stop server and clean up session directory |
| `lib/brainstorm-server/wait-for-feedback.sh` | Wait for user feedback (polling-based) |
| `lib/brainstorm-server/frame-template.html` | Base HTML template with CSS |
| `lib/brainstorm-server/CLAUDE-INSTRUCTIONS.md` | Detailed usage guide |
Don't use it for simple text questions, code review, or when the user prefers terminal-only interaction.
## How It Works
The server watches a directory for HTML files and serves the newest one to the browser. You write HTML content, the user sees it in their browser, clicks options or types feedback, and you receive their response as JSON.
**Content fragments vs full documents:** If your HTML file starts with `<!DOCTYPE` or `<html`, the server serves it as-is (just injects the helper script). Otherwise, the server automatically wraps your content in the frame template — adding the header, CSS theme, feedback footer, and all interactive infrastructure. **Write content fragments by default.** Only write full documents when you need complete control over the page.
## Starting a Session
## Quick Start
```bash
# Start server with persistence (mockups saved to project)
${CLAUDE_PLUGIN_ROOT}/lib/brainstorm-server/start-server.sh --project-dir /path/to/project
# 1. Start server
${CLAUDE_PLUGIN_ROOT}/lib/brainstorm-server/start-server.sh
# Returns: {"screen_dir":"/tmp/brainstorm-xxx","url":"http://localhost:PORT"}
# Returns: {"type":"server-started","port":52341,"url":"http://localhost:52341",
# "screen_dir":"/path/to/project/.superpowers/brainstorm/12345-1706000000"}
# 2. Start watcher FIRST (background bash) - avoids race condition
${CLAUDE_PLUGIN_ROOT}/lib/brainstorm-server/wait-for-feedback.sh $SCREEN_DIR
# 3. Write HTML to a NEW file in screen_dir (e.g., platform.html, style.html)
# Never reuse filenames - server serves newest file automatically
# 4. Call TaskOutput(task_id, block=true, timeout=600000)
# If timeout, call again. After 3 timeouts (30 min), prompt user.
# Returns: {"choice":"a","feedback":"user notes"}
# 5. Iterate or advance - write new file if feedback changes it (e.g., style-v2.html)
# 6. Clean up when done
${CLAUDE_PLUGIN_ROOT}/lib/brainstorm-server/stop-server.sh $SCREEN_DIR
```
Save `screen_dir` from the response. Tell user to open the URL.
## Key Principles
**Note:** Pass the project root as `--project-dir` so mockups persist in `.superpowers/brainstorm/` and survive server restarts. Without it, files go to `/tmp` and get cleaned up. Remind the user to add `.superpowers/` to `.gitignore` if it's not already there.
- **Always ask first** before starting visual companion
- **Scale fidelity to the question** - wireframes for layout, polish for polish questions
- **Explain the question** on each page - what decision are you seeking?
- **Iterate before advancing** - if feedback changes current screen, write new version
- **2-4 options max** per screen
## The Loop
## File Naming
1. **Start watcher first** (background bash) — avoids race condition:
```bash
${CLAUDE_PLUGIN_ROOT}/lib/brainstorm-server/wait-for-feedback.sh $SCREEN_DIR
```
- **Use semantic names**: `platform.html`, `visual-style.html`, `layout.html`, `controls.html`
- **Never reuse filenames** - each screen is a new file
- **For iterations**: append version suffix like `layout-v2.html`, `layout-v3.html`
- Server automatically serves the newest file by modification time
2. **Write HTML** to a new file in `screen_dir`:
- Use semantic filenames: `platform.html`, `visual-style.html`, `layout.html`
- **Never reuse filenames** — each screen gets a fresh file
- Use Write tool — **never use cat/heredoc** (dumps noise into terminal)
- Server automatically serves the newest file
## Terminal UX
3. **Tell user what to expect:**
- Remind them of the URL (every step, not just first)
- Give a brief text summary of what's on screen (e.g., "Showing 3 layout options for the homepage")
- **Never use cat/heredoc for HTML** - dumps noise into terminal. Use Write tool instead.
- **Remind user of URL** on every step, not just the first
- **Give text summary** of what's on screen before they look (e.g., "Showing 3 API structure options")
4. **Wait for feedback** — call `TaskOutput(task_id, block=true, timeout=600000)`
- If timeout, call TaskOutput again (watcher still running)
- After 3 timeouts (30 min), say "Let me know when you want to continue"
5. **Process feedback** — returns JSON like `{"choice": "a", "feedback": "make header smaller"}`
6. **Iterate or advance** — if feedback changes current screen, write a new file (e.g., `layout-v2.html`). Only move to the next question when the current step is validated.
7. Repeat until done.
## Writing Content Fragments
Write just the content that goes inside the page. The server wraps it in the frame template automatically (header, theme CSS, feedback footer, interactive JS).
**Minimal example:**
```html
<h2>Which layout works better?</h2>
<p class="subtitle">Consider readability and visual hierarchy</p>
<div class="options">
<div class="option" data-choice="a" onclick="toggleSelect(this)">
<div class="letter">A</div>
<div class="content">
<h3>Single Column</h3>
<p>Clean, focused reading experience</p>
</div>
</div>
<div class="option" data-choice="b" onclick="toggleSelect(this)">
<div class="letter">B</div>
<div class="content">
<h3>Two Column</h3>
<p>Sidebar navigation with main content</p>
</div>
</div>
</div>
```
That's it. No `<html>`, no CSS, no `<script>` tags needed. The server provides all of that.
## CSS Classes Available
The frame template provides these CSS classes for your content:
## CSS Classes
### Options (A/B/C choices)
```html
@@ -109,8 +74,8 @@ The frame template provides these CSS classes for your content:
### Cards (visual designs)
```html
<div class="cards">
<div class="card" data-choice="design1" onclick="toggleSelect(this)">
<div class="card-image"><!-- mockup content --></div>
<div class="card" data-choice="x" onclick="toggleSelect(this)">
<div class="card-image"><!-- mockup --></div>
<div class="card-body">
<h3>Name</h3>
<p>Description</p>
@@ -122,82 +87,44 @@ The frame template provides these CSS classes for your content:
### Mockup container
```html
<div class="mockup">
<div class="mockup-header">Preview: Dashboard Layout</div>
<div class="mockup-body"><!-- your mockup HTML --></div>
<div class="mockup-header">Label</div>
<div class="mockup-body"><!-- content --></div>
</div>
```
### Split view (side-by-side)
### Split view
```html
<div class="split">
<div class="mockup"><!-- left --></div>
<div class="mockup"><!-- right --></div>
<div><!-- left --></div>
<div><!-- right --></div>
</div>
```
### Pros/Cons
```html
<div class="pros-cons">
<div class="pros"><h4>Pros</h4><ul><li>Benefit</li></ul></div>
<div class="cons"><h4>Cons</h4><ul><li>Drawback</li></ul></div>
<div class="pros"><h4>Pros</h4><ul><li>...</li></ul></div>
<div class="cons"><h4>Cons</h4><ul><li>...</li></ul></div>
</div>
```
### Mock elements (wireframe building blocks)
### Mock elements
```html
<div class="mock-nav">Logo | Home | About | Contact</div>
<div style="display: flex;">
<div class="mock-sidebar">Navigation</div>
<div class="mock-content">Main content area</div>
</div>
<button class="mock-button">Action Button</button>
<input class="mock-input" placeholder="Input field">
<div class="mock-nav">Nav items</div>
<div class="mock-sidebar">Sidebar</div>
<div class="mock-content">Content</div>
<button class="mock-button">Button</button>
<input class="mock-input" placeholder="Input">
<div class="placeholder">Placeholder area</div>
```
### Typography and sections
- `h2` — page title
- `h3` — section heading
- `.subtitle` — secondary text below title
- `.section` — content block with bottom margin
- `.label` — small uppercase label text
## User Feedback Format
```json
{
"choice": "option-id",
"feedback": "user notes"
"choice": "option-id", // from data-choice attribute
"feedback": "user notes" // from feedback textarea
}
```
Both fields are optional user may select without notes, or send notes without a selection.
## Design Tips
- **Scale fidelity to the question** — wireframes for layout, polish for polish questions
- **Explain the question on each page** — "Which layout feels more professional?" not just "Pick one"
- **Iterate before advancing** — if feedback changes current screen, write a new version
- **2-4 options max** per screen
- **Use real content when it matters** — for a photography portfolio, use actual images (Unsplash). Placeholder content obscures design issues.
- **Keep mockups simple** — focus on layout and structure, not pixel-perfect design
## File Naming
- Use semantic names: `platform.html`, `visual-style.html`, `layout.html`
- Never reuse filenames — each screen must be a new file
- For iterations: append version suffix like `layout-v2.html`, `layout-v3.html`
- Server serves newest file by modification time
## Cleaning Up
```bash
${CLAUDE_PLUGIN_ROOT}/lib/brainstorm-server/stop-server.sh $SCREEN_DIR
```
If the session used `--project-dir`, mockup files persist in `.superpowers/brainstorm/` for later reference. Only `/tmp` sessions get deleted on stop.
## Reference
- Frame template (CSS reference): `${CLAUDE_PLUGIN_ROOT}/lib/brainstorm-server/frame-template.html`
- Helper script (JS API): `${CLAUDE_PLUGIN_ROOT}/lib/brainstorm-server/helper.js`
Both fields are optional - user may select without notes, or send notes without selection.

View File

@@ -74,11 +74,3 @@ After all tasks complete and verified:
- Reference skills when plan says to
- Between batches: just report and wait
- Stop when blocked, don't guess
- Never start implementation on main/master branch without explicit user consent
## Integration
**Required workflow skills:**
- **superpowers:using-git-worktrees** - REQUIRED: Set up isolated workspace before starting
- **superpowers:writing-plans** - Creates the plan this skill executes
- **superpowers:finishing-a-development-branch** - Complete development after all tasks

View File

@@ -58,7 +58,7 @@ HEAD_SHA=$(git rev-parse HEAD)
[Dispatch superpowers:code-reviewer subagent]
WHAT_WAS_IMPLEMENTED: Verification and repair functions for conversation index
PLAN_OR_REQUIREMENTS: Task 2 from docs/superpowers/plans/deployment-plan.md
PLAN_OR_REQUIREMENTS: Task 2 from docs/plans/deployment-plan.md
BASE_SHA: a7981ec
HEAD_SHA: 3df7661
DESCRIPTION: Added verifyIndex() and repairIndex() with 4 issue types

View File

@@ -82,39 +82,6 @@ digraph process {
}
```
## Model Selection
Use the least powerful model that can handle each role to conserve cost and increase speed.
**Mechanical implementation tasks** (isolated functions, clear specs, 1-2 files): use a fast, cheap model. Most implementation tasks are mechanical when the plan is well-specified.
**Integration and judgment tasks** (multi-file coordination, pattern matching, debugging): use a standard model.
**Architecture, design, and review tasks**: use the most capable available model.
**Task complexity signals:**
- Touches 1-2 files with a complete spec → cheap model
- Touches multiple files with integration concerns → standard model
- Requires design judgment or broad codebase understanding → most capable model
## Handling Implementer Status
Implementer subagents report one of four statuses. Handle each appropriately:
**DONE:** Proceed to spec compliance review.
**DONE_WITH_CONCERNS:** The implementer completed the work but flagged doubts. Read the concerns before proceeding. If the concerns are about correctness or scope, address them before review. If they're observations (e.g., "this file is getting large"), note them and proceed to review.
**NEEDS_CONTEXT:** The implementer needs information that wasn't provided. Provide the missing context and re-dispatch.
**BLOCKED:** The implementer cannot complete the task. Assess the blocker:
1. If it's a context problem, provide more context and re-dispatch with the same model
2. If the task requires more reasoning, re-dispatch with a more capable model
3. If the task is too large, break it into smaller pieces
4. If the plan itself is wrong, escalate to the human
**Never** ignore an escalation or force the same model to retry without changes. If the implementer said it's stuck, something needs to change.
## Prompt Templates
- `./implementer-prompt.md` - Dispatch implementer subagent
@@ -126,7 +93,7 @@ Implementer subagents report one of four statuses. Handle each appropriately:
```
You: I'm using Subagent-Driven Development to execute this plan.
[Read plan file once: docs/superpowers/plans/feature-plan.md]
[Read plan file once: docs/plans/feature-plan.md]
[Extract all 5 tasks with full text and context]
[Create TodoWrite with all tasks]
@@ -232,7 +199,6 @@ Done!
## Red Flags
**Never:**
- Start implementation on main/master branch without explicit user consent
- Skip reviews (spec compliance OR code quality)
- Proceed with unfixed issues
- Dispatch multiple implementation subagents in parallel (conflicts)
@@ -263,7 +229,6 @@ Done!
## Integration
**Required workflow skills:**
- **superpowers:using-git-worktrees** - REQUIRED: Set up isolated workspace before starting
- **superpowers:writing-plans** - Creates the plan this skill executes
- **superpowers:requesting-code-review** - Code review template for reviewer subagents
- **superpowers:finishing-a-development-branch** - Complete development after all tasks

View File

@@ -17,10 +17,4 @@ Task tool (superpowers:code-reviewer):
DESCRIPTION: [task summary]
```
**In addition to standard code quality concerns, the reviewer should check:**
- Does each file have one clear responsibility with a well-defined interface?
- Are units decomposed so they can be understood and tested independently?
- Is the implementation following the file structure from the plan?
- Did this implementation create new files that are already large, or significantly grow existing files? (Don't flag pre-existing file sizes — focus on what this change contributed.)
**Code reviewer returns:** Strengths, Issues (Critical/Important/Minor), Assessment

View File

@@ -41,36 +41,6 @@ Task tool (general-purpose):
**While you work:** If you encounter something unexpected or unclear, **ask questions**.
It's always OK to pause and clarify. Don't guess or make assumptions.
## Code Organization
You reason best about code you can hold in context at once, and your edits are more
reliable when files are focused. Keep this in mind:
- Follow the file structure defined in the plan
- Each file should have one clear responsibility with a well-defined interface
- If a file you're creating is growing beyond the plan's intent, stop and report
it as DONE_WITH_CONCERNS — don't split files on your own without plan guidance
- If an existing file you're modifying is already large or tangled, work carefully
and note it as a concern in your report
- In existing codebases, follow established patterns. Improve code you're touching
the way a good developer would, but don't restructure things outside your task.
## When You're in Over Your Head
It is always OK to stop and say "this is too hard for me." Bad work is worse than
no work. You will not be penalized for escalating.
**STOP and escalate when:**
- The task requires architectural decisions with multiple valid approaches
- You need to understand code beyond what was provided and can't find clarity
- You feel uncertain about whether your approach is correct
- The task involves restructuring existing code in ways the plan didn't anticipate
- You've been reading file after file trying to understand the system without progress
**How to escalate:** Report back with status BLOCKED or NEEDS_CONTEXT. Describe
specifically what you're stuck on, what you've tried, and what kind of help you need.
The controller can provide more context, re-dispatch with a more capable model,
or break the task into smaller pieces.
## Before Reporting Back: Self-Review
Review your work with fresh eyes. Ask yourself:
@@ -100,14 +70,9 @@ Task tool (general-purpose):
## Report Format
When done, report:
- **Status:** DONE | DONE_WITH_CONCERNS | BLOCKED | NEEDS_CONTEXT
- What you implemented (or what you attempted, if blocked)
- What you implemented
- What you tested and test results
- Files changed
- Self-review findings (if any)
- Any issues or concerns
Use DONE_WITH_CONCERNS if you completed the work but have doubts about correctness.
Use BLOCKED if you cannot complete the task. Use NEEDS_CONTEXT if you need
information that wasn't provided. Never silently produce work you're unsure about.
```

View File

@@ -210,9 +210,8 @@ Ready to implement auth feature
**Called by:**
- **brainstorming** (Phase 4) - REQUIRED when design is approved and implementation follows
- **subagent-driven-development** - REQUIRED before executing any tasks
- **executing-plans** - REQUIRED before executing any tasks
- Any skill needing isolated workspace
**Pairs with:**
- **finishing-a-development-branch** - REQUIRED for cleanup after work complete
- **executing-plans** or **subagent-driven-development** - Work happens in this worktree

View File

@@ -73,7 +73,6 @@ These thoughts mean STOP—you're rationalizing:
| "I'll just do this one thing first" | Check BEFORE doing anything. |
| "This feels productive" | Undisciplined action wastes time. Skills prevent this. |
| "I know what that means" | Knowing the concept ≠ using the skill. Invoke it. |
| "I should use EnterPlanMode / plan mode" | If a loaded skill specifies the next step, follow the skill. EnterPlanMode is a platform default — skills override defaults. |
## Skill Priority

View File

@@ -1,6 +1,6 @@
---
name: writing-plans
description: Use when you have a spec or requirements for a multi-step task, before touching code. After brainstorming, ALWAYS use this — not EnterPlanMode or plan mode.
description: Use when you have a spec or requirements for a multi-step task, before touching code
---
# Writing Plans
@@ -13,25 +13,9 @@ Assume they are a skilled developer, but know almost nothing about our toolset o
**Announce at start:** "I'm using the writing-plans skill to create the implementation plan."
**Context:** This runs in the main workspace after brainstorming, while context is fresh. The worktree is created afterward for implementation.
**Context:** This should be run in a dedicated worktree (created by brainstorming skill).
**Save plans to:** `docs/superpowers/plans/YYYY-MM-DD-<feature-name>.md`
- (User preferences for plan location override this default)
## Scope Check
If the spec covers multiple independent subsystems, it should have been broken into sub-project specs during brainstorming. If it wasn't, suggest breaking this into separate plans — one per subsystem. Each plan should produce working, testable software on its own.
## File Structure
Before defining tasks, map out which files will be created or modified and what each one is responsible for. This is where decomposition decisions get locked in.
- Design units with clear boundaries and well-defined interfaces. Each file should have one clear responsibility.
- You reason best about code you can hold in context at once, and your edits are more reliable when files are focused. Prefer smaller, focused files over large ones that do too much.
- Files that change together should live together. Split by responsibility, not by technical layer.
- In existing codebases, follow established patterns. If the codebase uses large files, don't unilaterally restructure - but if a file you're modifying has grown unwieldy, including a split in the plan is reasonable.
This structure informs the task decomposition. Each task should produce self-contained changes that make sense independently.
**Save plans to:** `docs/plans/YYYY-MM-DD-<feature-name>.md`
## Bite-Sized Task Granularity
@@ -49,7 +33,7 @@ This structure informs the task decomposition. Each task should produce self-con
```markdown
# [Feature Name] Implementation Plan
> **For Claude:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
**Goal:** [One sentence describing what this builds]
@@ -70,7 +54,7 @@ This structure informs the task decomposition. Each task should produce self-con
- Modify: `exact/path/to/existing.py:123-145`
- Test: `tests/exact/path/to/test.py`
- [ ] **Step 1: Write the failing test**
**Step 1: Write the failing test**
```python
def test_specific_behavior():
@@ -78,24 +62,24 @@ def test_specific_behavior():
assert result == expected
```
- [ ] **Step 2: Run test to verify it fails**
**Step 2: Run test to verify it fails**
Run: `pytest tests/path/test.py::test_name -v`
Expected: FAIL with "function not defined"
- [ ] **Step 3: Write minimal implementation**
**Step 3: Write minimal implementation**
```python
def function(input):
return expected
```
- [ ] **Step 4: Run test to verify it passes**
**Step 4: Run test to verify it passes**
Run: `pytest tests/path/test.py::test_name -v`
Expected: PASS
- [ ] **Step 5: Commit**
**Step 5: Commit**
```bash
git add tests/path/test.py src/path/file.py
@@ -110,38 +94,23 @@ git commit -m "feat: add specific feature"
- Reference relevant skills with @ syntax
- DRY, YAGNI, TDD, frequent commits
## Plan Review Loop
After completing each chunk of the plan:
1. Dispatch plan-document-reviewer subagent (see plan-document-reviewer-prompt.md) for the current chunk
- Provide: chunk content, path to spec document
2. If ❌ Issues Found:
- Fix the issues in the chunk
- Re-dispatch reviewer for that chunk
- Repeat until ✅ Approved
3. If ✅ Approved: proceed to next chunk (or execution handoff if last chunk)
**Chunk boundaries:** Use `## Chunk N: <name>` headings to delimit chunks. Each chunk should be ≤1000 lines and logically self-contained.
**Review loop guidance:**
- Same agent that wrote the plan fixes it (preserves context)
- If loop exceeds 5 iterations, surface to human for guidance
- Reviewers are advisory - explain disagreements if you believe feedback is incorrect
## Execution Handoff
After saving the plan:
After saving the plan, offer execution choice:
**"Plan complete and saved to `docs/superpowers/plans/<filename>.md`. Ready to execute?"**
**"Plan complete and saved to `docs/plans/<filename>.md`. Two execution options:**
**Execution path depends on harness capabilities:**
**1. Subagent-Driven (this session)** - I dispatch fresh subagent per task, review between tasks, fast iteration
**If harness has subagents (Claude Code, etc.):**
- **REQUIRED:** Use superpowers:subagent-driven-development
- Do NOT offer a choice - subagent-driven is the standard approach
- Fresh subagent per task + two-stage review
**2. Parallel Session (separate)** - Open new session with executing-plans, batch execution with checkpoints
**If harness does NOT have subagents:**
- Execute plan in current session using superpowers:executing-plans
- Batch execution with checkpoints for review
**Which approach?"**
**If Subagent-Driven chosen:**
- **REQUIRED SUB-SKILL:** Use superpowers:subagent-driven-development
- Stay in this session
- Fresh subagent per task + code review
**If Parallel Session chosen:**
- Guide them to open new session in worktree
- **REQUIRED SUB-SKILL:** New session uses superpowers:executing-plans

View File

@@ -1,52 +0,0 @@
# Plan Document Reviewer Prompt Template
Use this template when dispatching a plan document reviewer subagent.
**Purpose:** Verify the plan chunk is complete, matches the spec, and has proper task decomposition.
**Dispatch after:** Each plan chunk is written
```
Task tool (general-purpose):
description: "Review plan chunk N"
prompt: |
You are a plan document reviewer. Verify this plan chunk is complete and ready for implementation.
**Plan chunk to review:** [PLAN_FILE_PATH] - Chunk N only
**Spec for reference:** [SPEC_FILE_PATH]
## What to Check
| Category | What to Look For |
|----------|------------------|
| Completeness | TODOs, placeholders, incomplete tasks, missing steps |
| Spec Alignment | Chunk covers relevant spec requirements, no scope creep |
| Task Decomposition | Tasks atomic, clear boundaries, steps actionable |
| File Structure | Files have clear single responsibilities, split by responsibility not layer |
| File Size | Would any new or modified file likely grow large enough to be hard to reason about as a whole? |
| Task Syntax | Checkbox syntax (`- [ ]`) on steps for tracking |
| Chunk Size | Each chunk under 1000 lines |
## CRITICAL
Look especially hard for:
- Any TODO markers or placeholder text
- Steps that say "similar to X" without actual content
- Incomplete task definitions
- Missing verification steps or expected outputs
- Files planned to hold multiple responsibilities or likely to grow unwieldy
## Output Format
## Plan Review - Chunk N
**Status:** Approved | Issues Found
**Issues (if any):**
- [Task X, Step Y]: [specific issue] - [why it matters]
**Recommendations (advisory):**
- [suggestions that don't block approval]
```
**Reviewer returns:** Status, Issues (if any), Recommendations

View File

@@ -9,7 +9,7 @@ description: Use when creating new skills, editing existing skills, or verifying
**Writing skills IS Test-Driven Development applied to process documentation.**
**Personal skills live in agent-specific directories (`~/.claude/skills` for Claude Code, `~/.agents/skills/` for Codex)**
**Personal skills live in agent-specific directories (`~/.claude/skills` for Claude Code, `~/.codex/skills` for Codex)**
You write test cases (pressure scenarios with subagents), watch them fail (baseline behavior), write the skill (documentation), watch tests pass (agents comply), and refactor (close loopholes).

View File

@@ -7,11 +7,12 @@ const assert = require('assert');
const SERVER_PATH = path.join(__dirname, '../../lib/brainstorm-server/index.js');
const TEST_PORT = 3334;
const TEST_DIR = '/tmp/brainstorm-test';
const TEST_SCREEN = '/tmp/brainstorm-test/screen.html';
// Clean up test directory
function cleanup() {
if (fs.existsSync(TEST_DIR)) {
fs.rmSync(TEST_DIR, { recursive: true });
if (fs.existsSync(path.dirname(TEST_SCREEN))) {
fs.rmSync(path.dirname(TEST_SCREEN), { recursive: true });
}
}
@@ -29,29 +30,19 @@ async function fetch(url) {
});
}
function startServer() {
return spawn('node', [SERVER_PATH], {
env: { ...process.env, BRAINSTORM_PORT: TEST_PORT, BRAINSTORM_DIR: TEST_DIR }
});
}
async function runTests() {
cleanup();
fs.mkdirSync(TEST_DIR, { recursive: true });
const server = startServer();
// Start server
const server = spawn('node', [SERVER_PATH], {
env: { ...process.env, BRAINSTORM_PORT: TEST_PORT, BRAINSTORM_SCREEN: TEST_SCREEN }
});
let stdout = '';
let stderr = '';
server.stdout.on('data', (data) => { stdout += data.toString(); });
server.stderr.on('data', (data) => { stderr += data.toString(); });
server.stderr.on('data', (data) => { console.error('Server stderr:', data.toString()); });
// Wait for server to start (up to 3 seconds)
for (let i = 0; i < 30; i++) {
if (stdout.includes('server-started')) break;
await sleep(100);
}
if (stderr) console.error('Server stderr:', stderr);
await sleep(1000); // Wait for server to start
try {
// Test 1: Server starts and outputs JSON
@@ -60,17 +51,17 @@ async function runTests() {
assert(stdout.includes(TEST_PORT.toString()), 'Should include port');
console.log(' PASS');
// Test 2: GET / returns waiting page with helper injected when no screens exist
console.log('Test 2: Serves waiting page with helper injected');
// Test 2: GET / returns HTML with helper injected
console.log('Test 2: Serves HTML with helper injected');
const res = await fetch(`http://localhost:${TEST_PORT}/`);
assert.strictEqual(res.status, 200);
assert(res.body.includes('Waiting for Claude'), 'Should show waiting message');
assert(res.body.includes('brainstorm'), 'Should include brainstorm content');
assert(res.body.includes('WebSocket'), 'Should have helper.js injected');
console.log(' PASS');
// Test 3: WebSocket connection and event relay
console.log('Test 3: WebSocket relays events to stdout');
stdout = '';
stdout = ''; // Reset stdout capture
const ws = new WebSocket(`ws://localhost:${TEST_PORT}`);
await new Promise(resolve => ws.on('open', resolve));
@@ -93,61 +84,14 @@ async function runTests() {
if (msg.type === 'reload') gotReload = true;
});
fs.writeFileSync(path.join(TEST_DIR, 'test-screen.html'), '<html><body>Full doc</body></html>');
// Modify the screen file
fs.writeFileSync(TEST_SCREEN, '<html><body>Updated</body></html>');
await sleep(500);
assert(gotReload, 'Should send reload message on file change');
ws2.close();
console.log(' PASS');
// Test 5: Full HTML document served as-is (not wrapped)
console.log('Test 5: Full HTML document served without frame wrapping');
const fullDoc = '<!DOCTYPE html>\n<html><head><title>Custom</title></head><body><h1>Custom Page</h1></body></html>';
fs.writeFileSync(path.join(TEST_DIR, 'full-doc.html'), fullDoc);
await sleep(300);
const fullRes = await fetch(`http://localhost:${TEST_PORT}/`);
assert(fullRes.body.includes('<h1>Custom Page</h1>'), 'Should contain original content');
assert(fullRes.body.includes('WebSocket'), 'Should still inject helper.js');
// Should NOT have the frame template's feedback footer
assert(!fullRes.body.includes('feedback-footer') || fullDoc.includes('feedback-footer'),
'Should not wrap full documents in frame template');
console.log(' PASS');
// Test 6: Bare HTML fragment gets wrapped in frame template
console.log('Test 6: Content fragment wrapped in frame template');
const fragment = '<h2>Pick a layout</h2>\n<p class="subtitle">Choose one</p>\n<div class="options"><div class="option" data-choice="a"><div class="letter">A</div><div class="content"><h3>Simple</h3></div></div></div>';
fs.writeFileSync(path.join(TEST_DIR, 'fragment.html'), fragment);
await sleep(300);
const fragRes = await fetch(`http://localhost:${TEST_PORT}/`);
// Should have the frame template structure
assert(fragRes.body.includes('feedback-footer'), 'Fragment should get feedback footer from frame');
assert(fragRes.body.includes('Brainstorm Companion'), 'Fragment should get header from frame');
assert(fragRes.body.includes('--bg-primary'), 'Fragment should get theme CSS from frame');
// Should have the original content inside
assert(fragRes.body.includes('Pick a layout'), 'Fragment content should be present');
assert(fragRes.body.includes('data-choice="a"'), 'Fragment content should be intact');
// Should have helper.js injected
assert(fragRes.body.includes('WebSocket'), 'Fragment should have helper.js injected');
console.log(' PASS');
// Test 7: Helper.js includes toggleSelect and send functions
console.log('Test 7: Helper.js provides toggleSelect and send');
const helperContent = fs.readFileSync(
path.join(__dirname, '../../lib/brainstorm-server/helper.js'), 'utf-8'
);
assert(helperContent.includes('toggleSelect'), 'helper.js should define toggleSelect');
assert(helperContent.includes('send'), 'helper.js should define send function');
assert(helperContent.includes('selectedChoice'), 'helper.js should track selectedChoice');
console.log(' PASS');
// Test 8: sendToClaude confirmation uses CSS variables (dark mode support)
console.log('Test 8: sendToClaude confirmation respects theming');
assert(!helperContent.includes('color: #666'), 'Should not use hardcoded light-mode colors');
assert(!helperContent.includes('color: #333'), 'Should not use hardcoded light-mode colors');
console.log(' PASS');
console.log('\nAll tests passed!');
} finally {

View File

@@ -58,7 +58,6 @@ while [[ $# -gt 0 ]]; do
echo ""
echo "Tests:"
echo " test-subagent-driven-development.sh Test skill loading and requirements"
echo " test-brainstorm-handoff.sh Test brainstorm→writing-plans handoff"
echo ""
echo "Integration Tests (use --integration):"
echo " test-subagent-driven-development-integration.sh Full workflow execution"
@@ -75,7 +74,6 @@ done
# List of skill tests to run (fast unit tests)
tests=(
"test-subagent-driven-development.sh"
"test-brainstorm-handoff.sh"
)
# Integration tests (slow, full execution)

View File

@@ -1,330 +0,0 @@
#!/usr/bin/env bash
# Test: Brainstorm-to-plan handoff (end-to-end)
#
# Full brainstorming flow that builds enough context distance to reproduce
# the EnterPlanMode failure. Simulates a real brainstorming session with
# multiple turns of Q&A before the "build it" moment.
#
# This test takes 5-10 minutes to run.
#
# PASS: Skill tool invoked with "writing-plans" AND EnterPlanMode NOT invoked
# FAIL: EnterPlanMode invoked OR writing-plans not invoked
#
# Usage:
# ./test-brainstorm-handoff-e2e.sh # With fix (expects PASS)
# ./test-brainstorm-handoff-e2e.sh --without-fix # Strip fix, reproduce failure
# ./test-brainstorm-handoff-e2e.sh --verbose # Show full output
#
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PLUGIN_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
# Parse flags
VERBOSE=false
WITHOUT_FIX=false
while [[ $# -gt 0 ]]; do
case $1 in
--verbose|-v) VERBOSE=true; shift ;;
--without-fix) WITHOUT_FIX=true; shift ;;
*) echo "Unknown flag: $1"; exit 1 ;;
esac
done
TIMESTAMP=$(date +%s)
OUTPUT_DIR="/tmp/superpowers-tests/${TIMESTAMP}/brainstorm-handoff-e2e"
mkdir -p "$OUTPUT_DIR"
echo "=== Brainstorm-to-Plan Handoff E2E Test ==="
echo "Mode: $([ "$WITHOUT_FIX" = true ] && echo "WITHOUT FIX (expect failure)" || echo "WITH FIX (expect pass)")"
echo "Output: $OUTPUT_DIR"
echo "This test takes 5-10 minutes."
echo ""
# --- Project Setup ---
PROJECT_DIR="$OUTPUT_DIR/project"
mkdir -p "$PROJECT_DIR/src" "$PROJECT_DIR/test"
cat > "$PROJECT_DIR/package.json" << 'PROJ_EOF'
{
"name": "my-express-app",
"version": "1.0.0",
"type": "module",
"scripts": {
"start": "node src/index.js",
"test": "vitest run"
},
"dependencies": {
"express": "^4.18.0",
"better-sqlite3": "^9.0.0"
},
"devDependencies": {
"vitest": "^1.0.0",
"supertest": "^6.0.0"
}
}
PROJ_EOF
cat > "$PROJECT_DIR/src/index.js" << 'PROJ_EOF'
import express from 'express';
const app = express();
app.use(express.json());
app.get('/health', (req, res) => res.json({ status: 'ok' }));
const PORT = process.env.PORT || 3000;
if (process.env.NODE_ENV !== 'test') {
app.listen(PORT, () => console.log(`Listening on ${PORT}`));
}
export default app;
PROJ_EOF
cd "$PROJECT_DIR"
git init -q
git add -A
git commit -q -m "Initial commit"
# --- Plugin Setup ---
EFFECTIVE_PLUGIN_DIR="$PLUGIN_DIR"
if [ "$WITHOUT_FIX" = true ]; then
echo "Creating plugin copy without the handoff fix..."
EFFECTIVE_PLUGIN_DIR="$OUTPUT_DIR/plugin-without-fix"
cp -R "$PLUGIN_DIR" "$EFFECTIVE_PLUGIN_DIR"
python3 << PYEOF
import pathlib
# Strip fix from brainstorming SKILL.md
p = pathlib.Path('$EFFECTIVE_PLUGIN_DIR/skills/brainstorming/SKILL.md')
content = p.read_text()
content = content.replace(
'**Implementation (if continuing):**\nWhen the user approves the design and wants to build:\n1. **Invoke \`superpowers:writing-plans\` using the Skill tool.** Not EnterPlanMode. Not plan mode. Not direct implementation. The Skill tool.\n2. After the plan is written, use superpowers:using-git-worktrees to create an isolated workspace for implementation.',
'**Implementation (if continuing):**\n- Ask: "Ready to set up for implementation?"\n- Use superpowers:using-git-worktrees to create isolated workspace\n- **REQUIRED:** Use superpowers:writing-plans to create detailed implementation plan'
)
p.write_text(content)
# Strip fix from using-superpowers
p = pathlib.Path('$EFFECTIVE_PLUGIN_DIR/skills/using-superpowers/SKILL.md')
lines = p.read_text().splitlines(keepends=True)
lines = [l for l in lines if 'I should use EnterPlanMode' not in l]
p.write_text(''.join(lines))
# Strip fix from writing-plans
p = pathlib.Path('$EFFECTIVE_PLUGIN_DIR/skills/writing-plans/SKILL.md')
content = p.read_text()
content = content.replace(
'description: Use when you have a spec or requirements for a multi-step task, before touching code. After brainstorming, ALWAYS use this — not EnterPlanMode or plan mode.',
'description: Use when you have a spec or requirements for a multi-step task, before touching code'
)
content = content.replace(
'**Context:** This runs in the main workspace after brainstorming, while context is fresh. The worktree is created afterward for implementation.',
'**Context:** This should be run in a dedicated worktree (created by brainstorming skill).'
)
p.write_text(content)
PYEOF
echo "Plugin copy created."
echo ""
fi
# --- Helper ---
run_turn() {
local turn_num="$1"
local prompt="$2"
local max_turns="$3"
local label="$4"
local continue_flag="${5:-}"
local log_file="$OUTPUT_DIR/turn${turn_num}.json"
echo ">>> Turn $turn_num: $label"
local cmd="timeout 300 claude -p \"$prompt\""
cmd="$cmd --plugin-dir \"$EFFECTIVE_PLUGIN_DIR\""
cmd="$cmd --dangerously-skip-permissions"
cmd="$cmd --max-turns $max_turns"
cmd="$cmd --output-format stream-json"
if [ -n "$continue_flag" ]; then
cmd="$cmd --continue"
fi
eval "$cmd" > "$log_file" 2>&1 || true
echo " Done."
if [ "$VERBOSE" = true ]; then
echo " ---"
grep '"type":"assistant"' "$log_file" 2>/dev/null | tail -1 | \
jq -r '.message.content[0].text // empty' 2>/dev/null | \
head -c 600 || true
echo ""
echo " ---"
fi
echo "$log_file"
}
# --- Run Full Brainstorming Flow ---
cd "$PROJECT_DIR"
# Turn 1: Start brainstorming - this loads the skill and begins Q&A
T1=$(run_turn 1 \
"I want to add URL shortening to this Express app. Help me think through the design." \
5 "Starting brainstorming")
# Turn 2: Answer first question (whatever it is) generically
T2=$(run_turn 2 \
"Good question. Here is what I want: POST /api/shorten that takes a URL and returns a short code. GET /:code that redirects. GET /api/stats/:code for click tracking. Random 6-char alphanumeric codes. SQLite storage using better-sqlite3 which is already in package.json. No auth needed." \
5 "Answering first question" --continue)
# Turn 3: Agree with recommendations
T3=$(run_turn 3 \
"Yes, that sounds right. Go with your recommendation." \
5 "Agreeing with recommendation" --continue)
# Turn 4: Continue agreeing
T4=$(run_turn 4 \
"Looks good. I agree with that approach." \
5 "Continuing to agree" --continue)
# Turn 5: Push toward completion
T5=$(run_turn 5 \
"Perfect. I am happy with all of that. Please wrap up the design and write the spec." \
8 "Requesting spec write-up" --continue)
# Turn 6: Approve the spec
T6=$(run_turn 6 \
"The spec looks great. I approve it." \
5 "Approving spec" --continue)
# Turn 7: THE CRITICAL MOMENT - "build it"
T7=$(run_turn 7 \
"Yes, build it." \
5 "Critical handoff: build it" --continue)
# Turn 8: Safety net in case turn 7 asked a follow-up
T8=$(run_turn 8 \
"Yes. Go ahead and build it now." \
5 "Safety net: build it" --continue)
echo ""
# --- Assertions ---
echo "=== Results ==="
echo ""
# Combine all logs
ALL_LOGS="$OUTPUT_DIR/all-turns.json"
cat "$OUTPUT_DIR"/turn*.json > "$ALL_LOGS" 2>/dev/null
# Check handoff turns (6-8, where approval + "build it" happens)
HANDOFF_LOGS="$OUTPUT_DIR/handoff-turns.json"
cat "$OUTPUT_DIR/turn6.json" "$OUTPUT_DIR/turn7.json" "$OUTPUT_DIR/turn8.json" > "$HANDOFF_LOGS" 2>/dev/null
# Detection: writing-plans skill invoked in handoff turns?
HAS_WRITING_PLANS=false
if grep -q '"name":"Skill"' "$HANDOFF_LOGS" 2>/dev/null && grep -q 'writing-plans' "$HANDOFF_LOGS" 2>/dev/null; then
HAS_WRITING_PLANS=true
fi
# Detection: EnterPlanMode invoked in handoff turns?
HAS_ENTER_PLAN_MODE=false
if grep -q '"name":"EnterPlanMode"' "$HANDOFF_LOGS" 2>/dev/null; then
HAS_ENTER_PLAN_MODE=true
fi
# Also check across ALL turns (might happen earlier)
HAS_ENTER_PLAN_MODE_ANYWHERE=false
if grep -q '"name":"EnterPlanMode"' "$ALL_LOGS" 2>/dev/null; then
HAS_ENTER_PLAN_MODE_ANYWHERE=true
fi
# Report
echo "Skills invoked (all turns):"
grep -o '"skill":"[^"]*"' "$ALL_LOGS" 2>/dev/null | sort -u || echo " (none)"
echo ""
echo "Skills invoked (handoff turns 6-8):"
grep -o '"skill":"[^"]*"' "$HANDOFF_LOGS" 2>/dev/null | sort -u || echo " (none)"
echo ""
echo "Tools invoked in handoff turns (6-8):"
grep -o '"name":"[A-Z][^"]*"' "$HANDOFF_LOGS" 2>/dev/null | sort | uniq -c | sort -rn | head -10 || echo " (none)"
echo ""
if [ "$HAS_ENTER_PLAN_MODE_ANYWHERE" = true ]; then
echo "WARNING: EnterPlanMode was invoked somewhere in the conversation."
echo "Turns containing EnterPlanMode:"
for f in "$OUTPUT_DIR"/turn*.json; do
if grep -q '"name":"EnterPlanMode"' "$f" 2>/dev/null; then
echo " $(basename "$f")"
fi
done
echo ""
fi
# Determine result
PASSED=false
if [ "$WITHOUT_FIX" = true ]; then
echo "--- Without-Fix Mode (reproducing failure) ---"
if [ "$HAS_ENTER_PLAN_MODE" = true ] || [ "$HAS_ENTER_PLAN_MODE_ANYWHERE" = true ]; then
echo "REPRODUCED: Claude used EnterPlanMode (the bug we're fixing)"
PASSED=true
elif [ "$HAS_WRITING_PLANS" = true ]; then
echo "NOT REPRODUCED: Claude used writing-plans even without the fix"
echo "(The old guidance was sufficient in this run)"
PASSED=false
else
echo "INCONCLUSIVE: Claude used neither writing-plans nor EnterPlanMode"
echo "The brainstorming flow may not have reached the handoff point."
PASSED=false
fi
else
echo "--- With-Fix Mode (verifying fix) ---"
if [ "$HAS_WRITING_PLANS" = true ] && [ "$HAS_ENTER_PLAN_MODE_ANYWHERE" = false ]; then
echo "PASS: Claude used writing-plans skill (correct handoff)"
PASSED=true
elif [ "$HAS_ENTER_PLAN_MODE_ANYWHERE" = true ]; then
echo "FAIL: Claude used EnterPlanMode instead of writing-plans"
PASSED=false
elif [ "$HAS_WRITING_PLANS" = true ] && [ "$HAS_ENTER_PLAN_MODE_ANYWHERE" = true ]; then
echo "FAIL: Claude used BOTH writing-plans AND EnterPlanMode"
PASSED=false
else
echo "INCONCLUSIVE: Claude used neither writing-plans nor EnterPlanMode"
echo "The brainstorming flow may not have reached the handoff."
echo "Check logs to see where the conversation stopped."
PASSED=false
fi
fi
echo ""
# Show what happened in each turn
echo "Turn-by-turn summary:"
for i in 1 2 3 4 5 6 7 8; do
local_log="$OUTPUT_DIR/turn${i}.json"
if [ -f "$local_log" ]; then
local_skills=$(grep -o '"skill":"[^"]*"' "$local_log" 2>/dev/null | tr '\n' ' ' || true)
local_tools=$(grep -o '"name":"EnterPlanMode\|"name":"Skill"' "$local_log" 2>/dev/null | tr '\n' ' ' || true)
local_size=$(wc -c < "$local_log" | tr -d ' ')
printf " Turn %d: %s bytes" "$i" "$local_size"
[ -n "$local_skills" ] && printf " | skills: %s" "$local_skills"
[ -n "$local_tools" ] && printf " | tools: %s" "$local_tools"
echo ""
fi
done
echo ""
echo "Logs: $OUTPUT_DIR"
echo ""
if [ "$PASSED" = true ]; then
exit 0
else
exit 1
fi

View File

@@ -1,317 +0,0 @@
#!/usr/bin/env bash
# Test: Brainstorm-to-plan handoff
#
# Verifies that after brainstorming, Claude invokes the writing-plans skill
# instead of using EnterPlanMode.
#
# The failure mode this catches:
# User says "build it" after brainstorming -> Claude calls EnterPlanMode
# (because the system prompt's planning guidance overpowers the brainstorming
# skill's instructions, which were loaded many turns ago)
#
# PASS: Skill tool invoked with "writing-plans" AND EnterPlanMode NOT invoked
# FAIL: EnterPlanMode invoked OR writing-plans not invoked
#
# Usage:
# ./test-brainstorm-handoff.sh # Normal test (expects PASS)
# ./test-brainstorm-handoff.sh --without-fix # Strip fix, reproduce failure
# ./test-brainstorm-handoff.sh --verbose # Show full output
#
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PLUGIN_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
# Parse flags
VERBOSE=false
WITHOUT_FIX=false
while [[ $# -gt 0 ]]; do
case $1 in
--verbose|-v) VERBOSE=true; shift ;;
--without-fix) WITHOUT_FIX=true; shift ;;
*) echo "Unknown flag: $1"; exit 1 ;;
esac
done
TIMESTAMP=$(date +%s)
OUTPUT_DIR="/tmp/superpowers-tests/${TIMESTAMP}/brainstorm-handoff"
mkdir -p "$OUTPUT_DIR"
echo "=== Brainstorm-to-Plan Handoff Test ==="
echo "Mode: $([ "$WITHOUT_FIX" = true ] && echo "WITHOUT FIX (expect failure)" || echo "WITH FIX (expect pass)")"
echo "Output: $OUTPUT_DIR"
echo ""
# --- Project Setup ---
PROJECT_DIR="$OUTPUT_DIR/project"
mkdir -p "$PROJECT_DIR/src"
mkdir -p "$PROJECT_DIR/docs/superpowers/specs"
cat > "$PROJECT_DIR/package.json" << 'PROJ_EOF'
{
"name": "my-express-app",
"version": "1.0.0",
"type": "module",
"dependencies": {
"express": "^4.18.0",
"better-sqlite3": "^9.0.0"
}
}
PROJ_EOF
cat > "$PROJECT_DIR/src/index.js" << 'PROJ_EOF'
import express from 'express';
const app = express();
app.use(express.json());
app.get('/health', (req, res) => res.json({ status: 'ok' }));
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Listening on ${PORT}`));
PROJ_EOF
# Pre-create a spec document (simulating completed brainstorming)
cat > "$PROJECT_DIR/docs/superpowers/specs/2025-01-15-url-shortener-design.md" << 'SPEC_EOF'
# URL Shortener Design Spec
## Overview
Add URL shortening capability to the existing Express.js API.
## Features
- POST /api/shorten accepts { url } and returns { shortCode, shortUrl }
- GET /:code redirects to the original URL (302)
- GET /api/stats/:code returns { clicks, createdAt, originalUrl }
## Technical Design
### Database
Single SQLite table via better-sqlite3:
```sql
CREATE TABLE urls (
id INTEGER PRIMARY KEY AUTOINCREMENT,
short_code TEXT UNIQUE NOT NULL,
original_url TEXT NOT NULL,
clicks INTEGER DEFAULT 0,
created_at TEXT DEFAULT (datetime('now'))
);
CREATE INDEX idx_short_code ON urls(short_code);
```
### File Structure
- `src/index.js` — modified to mount new routes
- `src/db.js` — database initialization and query functions
- `src/shorten.js` — route handlers for all three endpoints
- `src/code-generator.js` — random 6-char alphanumeric code generation
### Code Generation
Random 6-character alphanumeric codes using crypto.randomBytes.
Check for collisions and retry (astronomically unlikely with 36^6 space).
### Validation
- URL must be present and start with http:// or https://
- Return 400 with { error: "..." } for invalid input
### Error Handling
- 404 with { error: "Not found" } for unknown short codes
- 500 with { error: "Internal server error" } for database failures
## Decisions
- 302 redirects (not 301) so browsers don't cache and we always track clicks
- Database path configurable via DATABASE_PATH env var, defaults to ./data/urls.db
- No auth, no custom codes, no expiry — keeping it simple
SPEC_EOF
# Initialize git so brainstorming can inspect project state
cd "$PROJECT_DIR"
git init -q
git add -A
git commit -q -m "Initial commit with URL shortener spec"
# --- Plugin Setup ---
EFFECTIVE_PLUGIN_DIR="$PLUGIN_DIR"
if [ "$WITHOUT_FIX" = true ]; then
echo "Creating plugin copy without the handoff fix..."
EFFECTIVE_PLUGIN_DIR="$OUTPUT_DIR/plugin-without-fix"
cp -R "$PLUGIN_DIR" "$EFFECTIVE_PLUGIN_DIR"
# Strip fix from brainstorming SKILL.md: revert to old implementation section
python3 << PYEOF
import pathlib
p = pathlib.Path('$EFFECTIVE_PLUGIN_DIR/skills/brainstorming/SKILL.md')
content = p.read_text()
content = content.replace(
'**Implementation (if continuing):**\nWhen the user approves the design and wants to build:\n1. **Invoke \`superpowers:writing-plans\` using the Skill tool.** Not EnterPlanMode. Not plan mode. Not direct implementation. The Skill tool.\n2. After the plan is written, use superpowers:using-git-worktrees to create an isolated workspace for implementation.',
'**Implementation (if continuing):**\n- Ask: "Ready to set up for implementation?"\n- Use superpowers:using-git-worktrees to create isolated workspace\n- **REQUIRED:** Use superpowers:writing-plans to create detailed implementation plan'
)
p.write_text(content)
PYEOF
# Strip fix from using-superpowers: remove EnterPlanMode red flag
python3 << PYEOF
import pathlib
p = pathlib.Path('$EFFECTIVE_PLUGIN_DIR/skills/using-superpowers/SKILL.md')
lines = p.read_text().splitlines(keepends=True)
lines = [l for l in lines if 'I should use EnterPlanMode' not in l]
p.write_text(''.join(lines))
PYEOF
# Strip fix from writing-plans: revert description and context
python3 << PYEOF
import pathlib
p = pathlib.Path('$EFFECTIVE_PLUGIN_DIR/skills/writing-plans/SKILL.md')
content = p.read_text()
content = content.replace(
'description: Use when you have a spec or requirements for a multi-step task, before touching code. After brainstorming, ALWAYS use this — not EnterPlanMode or plan mode.',
'description: Use when you have a spec or requirements for a multi-step task, before touching code'
)
content = content.replace(
'**Context:** This runs in the main workspace after brainstorming, while context is fresh. The worktree is created afterward for implementation.',
'**Context:** This should be run in a dedicated worktree (created by brainstorming skill).'
)
p.write_text(content)
PYEOF
echo "Plugin copy created at $EFFECTIVE_PLUGIN_DIR"
echo ""
fi
# --- Run Conversation ---
cd "$PROJECT_DIR"
# Turn 1: Load brainstorming and establish that we finished the design
# The key is that brainstorming gets loaded into context, and we're at the handoff point
echo ">>> Turn 1: Loading brainstorming skill and establishing context..."
TURN1_LOG="$OUTPUT_DIR/turn1.json"
TURN1_PROMPT='I want to add URL shortening to this Express app. I already have the full design worked out and written to docs/superpowers/specs/2025-01-15-url-shortener-design.md. Please read the spec.'
timeout 300 claude -p "$TURN1_PROMPT" \
--plugin-dir "$EFFECTIVE_PLUGIN_DIR" \
--dangerously-skip-permissions \
--max-turns 5 \
--output-format stream-json \
> "$TURN1_LOG" 2>&1 || true
echo "Turn 1 complete."
if [ "$VERBOSE" = true ]; then
echo "---"
grep '"type":"assistant"' "$TURN1_LOG" | tail -1 | jq -r '.message.content[0].text // empty' 2>/dev/null | head -c 800 || true
echo ""
echo "---"
fi
echo ""
# Turn 2: Approve and ask to build - this is the critical handoff moment
echo ">>> Turn 2: 'The spec is done. Build it.' (critical handoff)..."
TURN2_LOG="$OUTPUT_DIR/turn2.json"
TURN2_PROMPT='The spec is complete and I am happy with the design. Build it.'
timeout 300 claude -p "$TURN2_PROMPT" \
--continue \
--plugin-dir "$EFFECTIVE_PLUGIN_DIR" \
--dangerously-skip-permissions \
--max-turns 5 \
--output-format stream-json \
> "$TURN2_LOG" 2>&1 || true
echo "Turn 2 complete."
if [ "$VERBOSE" = true ]; then
echo "---"
grep '"type":"assistant"' "$TURN2_LOG" | tail -1 | jq -r '.message.content[0].text // empty' 2>/dev/null | head -c 800 || true
echo ""
echo "---"
fi
echo ""
# --- Assertions ---
echo "=== Results ==="
echo ""
# Combine all turn logs for analysis
ALL_LOGS="$OUTPUT_DIR/all-turns.json"
cat "$TURN1_LOG" "$TURN2_LOG" > "$ALL_LOGS"
# Detection: writing-plans skill invoked?
HAS_WRITING_PLANS=false
if grep -q '"name":"Skill"' "$ALL_LOGS" 2>/dev/null && grep -q 'writing-plans' "$ALL_LOGS" 2>/dev/null; then
HAS_WRITING_PLANS=true
fi
# Detection: EnterPlanMode invoked?
HAS_ENTER_PLAN_MODE=false
if grep -q '"name":"EnterPlanMode"' "$ALL_LOGS" 2>/dev/null; then
HAS_ENTER_PLAN_MODE=true
fi
# Report what skills were invoked
echo "Skills invoked:"
grep -o '"skill":"[^"]*"' "$ALL_LOGS" 2>/dev/null | sort -u || echo " (none)"
echo ""
echo "Notable tools invoked:"
grep -o '"name":"[A-Z][^"]*"' "$ALL_LOGS" 2>/dev/null | sort | uniq -c | sort -rn | head -10 || echo " (none)"
echo ""
# Determine result
PASSED=false
if [ "$WITHOUT_FIX" = true ]; then
# In without-fix mode, we EXPECT the failure (EnterPlanMode)
echo "--- Without-Fix Mode (reproducing failure) ---"
if [ "$HAS_ENTER_PLAN_MODE" = true ]; then
echo "REPRODUCED: Claude used EnterPlanMode (the bug we're fixing)"
PASSED=true
elif [ "$HAS_WRITING_PLANS" = true ]; then
echo "NOT REPRODUCED: Claude used writing-plans even without the fix"
echo "(The model may have followed the old guidance anyway)"
PASSED=false
else
echo "INCONCLUSIVE: Claude used neither writing-plans nor EnterPlanMode"
echo "The brainstorming flow may not have reached the handoff point."
PASSED=false
fi
else
# Normal mode: expect writing-plans, not EnterPlanMode
echo "--- With-Fix Mode (verifying fix) ---"
if [ "$HAS_WRITING_PLANS" = true ] && [ "$HAS_ENTER_PLAN_MODE" = false ]; then
echo "PASS: Claude used writing-plans skill (correct handoff)"
PASSED=true
elif [ "$HAS_ENTER_PLAN_MODE" = true ]; then
echo "FAIL: Claude used EnterPlanMode instead of writing-plans"
PASSED=false
elif [ "$HAS_WRITING_PLANS" = true ] && [ "$HAS_ENTER_PLAN_MODE" = true ]; then
echo "FAIL: Claude used BOTH writing-plans AND EnterPlanMode"
PASSED=false
else
echo "INCONCLUSIVE: Claude used neither writing-plans nor EnterPlanMode"
echo "The brainstorming flow may not have reached the handoff point."
echo "Check logs - brainstorming may still be asking questions."
PASSED=false
fi
fi
echo ""
# Show the critical turn 2 response
echo "Turn 2 response (first 500 chars):"
grep '"type":"assistant"' "$TURN2_LOG" 2>/dev/null | tail -1 | \
jq -r '.message.content[0].text // .message.content' 2>/dev/null | \
head -c 500 || echo " (could not extract)"
echo ""
echo ""
echo "Logs:"
echo " Turn 1: $TURN1_LOG"
echo " Turn 2: $TURN2_LOG"
echo " Combined: $ALL_LOGS"
echo ""
if [ "$PASSED" = true ]; then
exit 0
else
exit 1
fi

View File

@@ -1,177 +0,0 @@
#!/usr/bin/env bash
# Integration Test: Document Review System
# Actually runs spec/plan review and verifies reviewers catch issues
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
source "$SCRIPT_DIR/test-helpers.sh"
echo "========================================"
echo " Integration Test: Document Review System"
echo "========================================"
echo ""
echo "This test verifies the document review system by:"
echo " 1. Creating a spec with intentional errors"
echo " 2. Running the spec document reviewer"
echo " 3. Verifying the reviewer catches the errors"
echo ""
# Create test project
TEST_PROJECT=$(create_test_project)
echo "Test project: $TEST_PROJECT"
# Trap to cleanup
trap "cleanup_test_project $TEST_PROJECT" EXIT
cd "$TEST_PROJECT"
# Create directory structure
mkdir -p docs/superpowers/specs
# Create a spec document WITH INTENTIONAL ERRORS for the reviewer to catch
cat > docs/superpowers/specs/test-feature-design.md <<'EOF'
# Test Feature Design
## Overview
This is a test feature that does something useful.
## Requirements
1. The feature should work correctly
2. It should be fast
3. TODO: Add more requirements here
## Architecture
The feature will use a simple architecture with:
- A frontend component
- A backend service
- Error handling will be specified later once we understand the failure modes better
## Data Flow
Data flows from the frontend to the backend.
## Testing Strategy
Tests will be written to cover the main functionality.
EOF
# Initialize git repo
git init --quiet
git config user.email "test@test.com"
git config user.name "Test User"
git add .
git commit -m "Initial commit with test spec" --quiet
echo ""
echo "Created test spec with intentional errors:"
echo " - TODO placeholder in Requirements section"
echo " - 'specified later' deferral in Architecture section"
echo ""
echo "Running spec document reviewer..."
echo ""
# Run Claude to review the spec
OUTPUT_FILE="$TEST_PROJECT/claude-output.txt"
PROMPT="You are testing the spec document reviewer.
Read the spec-document-reviewer-prompt.md template in skills/brainstorming/ to understand the review format.
Then review the spec at $TEST_PROJECT/docs/superpowers/specs/test-feature-design.md using the criteria from that template.
Look for:
- TODOs, placeholders, 'TBD', incomplete sections
- Sections saying 'to be defined later' or 'will spec when X is done'
- Sections noticeably less detailed than others
Output your review in the format specified in the template."
echo "================================================================================"
cd "$SCRIPT_DIR/../.." && timeout 120 claude -p "$PROMPT" --permission-mode bypassPermissions 2>&1 | tee "$OUTPUT_FILE" || {
echo ""
echo "================================================================================"
echo "EXECUTION FAILED (exit code: $?)"
exit 1
}
echo "================================================================================"
echo ""
echo "Analyzing reviewer output..."
echo ""
# Verification tests
FAILED=0
echo "=== Verification Tests ==="
echo ""
# Test 1: Reviewer found the TODO
echo "Test 1: Reviewer found TODO..."
if grep -qi "TODO" "$OUTPUT_FILE" && grep -qi "requirements\|Requirements" "$OUTPUT_FILE"; then
echo " [PASS] Reviewer identified TODO in Requirements section"
else
echo " [FAIL] Reviewer did not identify TODO"
FAILED=$((FAILED + 1))
fi
echo ""
# Test 2: Reviewer found the "specified later" deferral
echo "Test 2: Reviewer found 'specified later' deferral..."
if grep -qi "specified later\|later\|defer\|incomplete\|error handling" "$OUTPUT_FILE"; then
echo " [PASS] Reviewer identified deferred content"
else
echo " [FAIL] Reviewer did not identify deferred content"
FAILED=$((FAILED + 1))
fi
echo ""
# Test 3: Reviewer output includes Issues section
echo "Test 3: Review output format..."
if grep -qi "issues\|Issues" "$OUTPUT_FILE"; then
echo " [PASS] Review includes Issues section"
else
echo " [FAIL] Review missing Issues section"
FAILED=$((FAILED + 1))
fi
echo ""
# Test 4: Reviewer did NOT approve (found issues)
echo "Test 4: Reviewer verdict..."
if grep -qi "Issues Found\|❌\|not approved\|issues found" "$OUTPUT_FILE"; then
echo " [PASS] Reviewer correctly found issues (not approved)"
elif grep -qi "Approved\|✅" "$OUTPUT_FILE" && ! grep -qi "Issues Found\|❌" "$OUTPUT_FILE"; then
echo " [FAIL] Reviewer incorrectly approved spec with errors"
FAILED=$((FAILED + 1))
else
echo " [PASS] Reviewer identified problems (ambiguous format but found issues)"
fi
echo ""
# Summary
echo "========================================"
echo " Test Summary"
echo "========================================"
echo ""
if [ $FAILED -eq 0 ]; then
echo "STATUS: PASSED"
echo "All verification tests passed!"
echo ""
echo "The spec document reviewer correctly:"
echo " ✓ Found TODO placeholder"
echo " ✓ Found 'specified later' deferral"
echo " ✓ Produced properly formatted review"
echo " ✓ Did not approve spec with errors"
exit 0
else
echo "STATUS: FAILED"
echo "Failed $FAILED verification tests"
echo ""
echo "Output saved to: $OUTPUT_FILE"
echo ""
echo "Review the output to see what went wrong."
exit 1
fi

View File

@@ -143,7 +143,7 @@ cleanup_test_project() {
create_test_plan() {
local project_dir="$1"
local plan_name="${2:-test-plan}"
local plan_file="$project_dir/docs/superpowers/plans/$plan_name.md"
local plan_file="$project_dir/docs/plans/$plan_name.md"
mkdir -p "$(dirname "$plan_file")"

View File

@@ -42,10 +42,10 @@ cat > package.json <<'EOF'
}
EOF
mkdir -p src test docs/superpowers/plans
mkdir -p src test docs/plans
# Create a simple implementation plan
cat > docs/superpowers/plans/implementation-plan.md <<'EOF'
cat > docs/plans/implementation-plan.md <<'EOF'
# Test Implementation Plan
This is a minimal plan to test the subagent-driven-development workflow.
@@ -121,7 +121,7 @@ OUTPUT_FILE="$TEST_PROJECT/claude-output.txt"
# Create prompt file
cat > "$TEST_PROJECT/prompt.txt" <<'EOF'
I want you to execute the implementation plan at docs/superpowers/plans/implementation-plan.md using the subagent-driven-development skill.
I want you to execute the implementation plan at docs/plans/implementation-plan.md using the subagent-driven-development skill.
IMPORTANT: Follow the skill exactly. I will be verifying that you:
1. Read the plan once at the beginning
@@ -136,7 +136,7 @@ EOF
# Note: We use a longer timeout since this is integration testing
# Use --allowed-tools to enable tool usage in headless mode
# IMPORTANT: Run from superpowers directory so local dev skills are available
PROMPT="Change to directory $TEST_PROJECT and then execute the implementation plan at docs/superpowers/plans/implementation-plan.md using the subagent-driven-development skill.
PROMPT="Change to directory $TEST_PROJECT and then execute the implementation plan at docs/plans/implementation-plan.md using the subagent-driven-development skill.
IMPORTANT: Follow the skill exactly. I will be verifying that you:
1. Read the plan once at the beginning

View File

@@ -14,7 +14,7 @@ echo "Test 1: Skill loading..."
output=$(run_claude "What is the subagent-driven-development skill? Describe its key steps briefly." 30)
if assert_contains "$output" "subagent-driven-development\|Subagent-Driven Development\|Subagent Driven" "Skill is recognized"; then
if assert_contains "$output" "subagent-driven-development" "Skill is recognized"; then
: # pass
else
exit 1
@@ -136,30 +136,4 @@ fi
echo ""
# Test 8: Verify worktree requirement
echo "Test 8: Worktree requirement..."
output=$(run_claude "What workflow skills are required before using subagent-driven-development? List any prerequisites or required skills." 30)
if assert_contains "$output" "using-git-worktrees\|worktree" "Mentions worktree requirement"; then
: # pass
else
exit 1
fi
echo ""
# Test 9: Verify main branch warning
echo "Test 9: Main branch red flag..."
output=$(run_claude "In subagent-driven-development, is it okay to start implementation directly on the main branch?" 30)
if assert_contains "$output" "worktree\|feature.*branch\|not.*main\|never.*main\|avoid.*main\|don't.*main\|consent\|permission" "Warns against main branch"; then
: # pass
else
exit 1
fi
echo ""
echo "=== All subagent-driven-development skill tests passed ==="

View File

@@ -1,3 +1,3 @@
The plan is done. docs/superpowers/plans/auth-system.md has everything.
The plan is done. docs/plans/auth-system.md has everything.
Do subagent-driven development on this - start with Task 1, dispatch a subagent, then we'll review.

View File

@@ -1,4 +1,4 @@
Great, the plan is complete. I've saved it to docs/superpowers/plans/auth-system.md.
Great, the plan is complete. I've saved it to docs/plans/auth-system.md.
Here's a summary of what we designed:
- Task 1: Add User Model with email/password fields

View File

@@ -1,5 +1,5 @@
[Previous assistant message]:
Plan complete and saved to docs/superpowers/plans/auth-system.md.
Plan complete and saved to docs/plans/auth-system.md.
Two execution options:
1. Subagent-Driven (this session) - I dispatch a fresh subagent per task, review between tasks, fast iteration within this conversation

View File

@@ -1,4 +1,4 @@
I have my implementation plan ready at docs/superpowers/plans/auth-system.md.
I have my implementation plan ready at docs/plans/auth-system.md.
I want to use subagent-driven-development to execute it. That means:
- Dispatch a fresh subagent for each task in the plan

View File

@@ -1,3 +1,3 @@
I have a plan at docs/superpowers/plans/auth-system.md that's ready to implement.
I have a plan at docs/plans/auth-system.md that's ready to implement.
subagent-driven-development, please

View File

@@ -1,3 +1,3 @@
Plan is at docs/superpowers/plans/auth-system.md.
Plan is at docs/plans/auth-system.md.
subagent-driven-development, please. Don't waste time - just read the plan and start dispatching subagents immediately.

View File

@@ -12,7 +12,7 @@ OUTPUT_DIR="/tmp/superpowers-tests/${TIMESTAMP}/explicit-skill-requests/claude-d
mkdir -p "$OUTPUT_DIR"
PROJECT_DIR="$OUTPUT_DIR/project"
mkdir -p "$PROJECT_DIR/docs/superpowers/plans"
mkdir -p "$PROJECT_DIR/docs/plans"
echo "=== Test: Claude Describes SDD First ==="
echo "Output dir: $OUTPUT_DIR"
@@ -21,7 +21,7 @@ echo ""
cd "$PROJECT_DIR"
# Create a plan
cat > "$PROJECT_DIR/docs/superpowers/plans/auth-system.md" << 'EOF'
cat > "$PROJECT_DIR/docs/plans/auth-system.md" << 'EOF'
# Auth System Implementation Plan
## Task 1: Add User Model
@@ -36,7 +36,7 @@ EOF
# Turn 1: Have Claude describe execution options including SDD
echo ">>> Turn 1: Ask Claude to describe execution options..."
claude -p "I have a plan at docs/superpowers/plans/auth-system.md. Tell me about my options for executing it, including what subagent-driven-development means and how it works." \
claude -p "I have a plan at docs/plans/auth-system.md. Tell me about my options for executing it, including what subagent-driven-development means and how it works." \
--model haiku \
--plugin-dir "$PLUGIN_DIR" \
--dangerously-skip-permissions \

View File

@@ -12,7 +12,7 @@ OUTPUT_DIR="/tmp/superpowers-tests/${TIMESTAMP}/explicit-skill-requests/extended
mkdir -p "$OUTPUT_DIR"
PROJECT_DIR="$OUTPUT_DIR/project"
mkdir -p "$PROJECT_DIR/docs/superpowers/plans"
mkdir -p "$PROJECT_DIR/docs/plans"
echo "=== Extended Multi-Turn Test ==="
echo "Output dir: $OUTPUT_DIR"

View File

@@ -12,7 +12,7 @@ OUTPUT_DIR="/tmp/superpowers-tests/${TIMESTAMP}/explicit-skill-requests/haiku"
mkdir -p "$OUTPUT_DIR"
PROJECT_DIR="$OUTPUT_DIR/project"
mkdir -p "$PROJECT_DIR/docs/superpowers/plans"
mkdir -p "$PROJECT_DIR/docs/plans"
mkdir -p "$PROJECT_DIR/.claude"
echo "=== Haiku Model Test with User CLAUDE.md ==="
@@ -31,7 +31,7 @@ else
fi
# Create a dummy plan file
cat > "$PROJECT_DIR/docs/superpowers/plans/auth-system.md" << 'EOF'
cat > "$PROJECT_DIR/docs/plans/auth-system.md" << 'EOF'
# Auth System Implementation Plan
## Task 1: Add User Model

View File

@@ -16,7 +16,7 @@ mkdir -p "$OUTPUT_DIR"
# Create project directory (conversation is cwd-based)
PROJECT_DIR="$OUTPUT_DIR/project"
mkdir -p "$PROJECT_DIR/docs/superpowers/plans"
mkdir -p "$PROJECT_DIR/docs/plans"
echo "=== Multi-Turn Explicit Skill Request Test ==="
echo "Output dir: $OUTPUT_DIR"
@@ -27,7 +27,7 @@ echo ""
cd "$PROJECT_DIR"
# Create a dummy plan file
cat > "$PROJECT_DIR/docs/superpowers/plans/auth-system.md" << 'EOF'
cat > "$PROJECT_DIR/docs/plans/auth-system.md" << 'EOF'
# Auth System Implementation Plan
## Task 1: Add User Model
@@ -59,7 +59,7 @@ echo ""
# Turn 2: Continue with more planning detail
echo ">>> Turn 2: Continuing planning..."
TURN2_LOG="$OUTPUT_DIR/turn2.json"
claude -p "Good analysis. I've already written the plan to docs/superpowers/plans/auth-system.md. Now I'm ready to implement. What are my options for execution?" \
claude -p "Good analysis. I've already written the plan to docs/plans/auth-system.md. Now I'm ready to implement. What are my options for execution?" \
--continue \
--plugin-dir "$PLUGIN_DIR" \
--dangerously-skip-permissions \

View File

@@ -43,10 +43,10 @@ cp "$PROMPT_FILE" "$OUTPUT_DIR/prompt.txt"
# Create a minimal project directory for the test
PROJECT_DIR="$OUTPUT_DIR/project"
mkdir -p "$PROJECT_DIR/docs/superpowers/plans"
mkdir -p "$PROJECT_DIR/docs/plans"
# Create a dummy plan file for mid-conversation tests
cat > "$PROJECT_DIR/docs/superpowers/plans/auth-system.md" << 'EOF'
cat > "$PROJECT_DIR/docs/plans/auth-system.md" << 'EOF'
# Auth System Implementation Plan
## Task 1: Add User Model

View File

@@ -18,13 +18,13 @@ cp -r "$REPO_ROOT/lib" "$HOME/.config/opencode/superpowers/"
cp -r "$REPO_ROOT/skills" "$HOME/.config/opencode/superpowers/"
# Copy plugin directory
mkdir -p "$HOME/.config/opencode/superpowers/.opencode/plugins"
cp "$REPO_ROOT/.opencode/plugins/superpowers.js" "$HOME/.config/opencode/superpowers/.opencode/plugins/"
mkdir -p "$HOME/.config/opencode/superpowers/.opencode/plugin"
cp "$REPO_ROOT/.opencode/plugin/superpowers.js" "$HOME/.config/opencode/superpowers/.opencode/plugin/"
# Register plugin via symlink
mkdir -p "$HOME/.config/opencode/plugins"
ln -sf "$HOME/.config/opencode/superpowers/.opencode/plugins/superpowers.js" \
"$HOME/.config/opencode/plugins/superpowers.js"
mkdir -p "$HOME/.config/opencode/plugin"
ln -sf "$HOME/.config/opencode/superpowers/.opencode/plugin/superpowers.js" \
"$HOME/.config/opencode/plugin/superpowers.js"
# Create test skills in different locations for testing
@@ -57,8 +57,8 @@ PROJECT_SKILL_MARKER_67890
EOF
echo "Setup complete: $TEST_HOME"
echo "Plugin installed to: $HOME/.config/opencode/superpowers/.opencode/plugins/superpowers.js"
echo "Plugin registered at: $HOME/.config/opencode/plugins/superpowers.js"
echo "Plugin installed to: $HOME/.config/opencode/superpowers/.opencode/plugin/superpowers.js"
echo "Plugin registered at: $HOME/.config/opencode/plugin/superpowers.js"
echo "Test project at: $TEST_HOME/test-project"
# Helper function for cleanup (call from tests or trap)

View File

@@ -15,15 +15,15 @@ trap cleanup_test_env EXIT
# Test 1: Verify plugin file exists and is registered
echo "Test 1: Checking plugin registration..."
if [ -L "$HOME/.config/opencode/plugins/superpowers.js" ]; then
if [ -L "$HOME/.config/opencode/plugin/superpowers.js" ]; then
echo " [PASS] Plugin symlink exists"
else
echo " [FAIL] Plugin symlink not found at $HOME/.config/opencode/plugins/superpowers.js"
echo " [FAIL] Plugin symlink not found at $HOME/.config/opencode/plugin/superpowers.js"
exit 1
fi
# Verify symlink target exists
if [ -f "$(readlink -f "$HOME/.config/opencode/plugins/superpowers.js")" ]; then
if [ -f "$(readlink -f "$HOME/.config/opencode/plugin/superpowers.js")" ]; then
echo " [PASS] Plugin symlink target exists"
else
echo " [FAIL] Plugin symlink target does not exist"
@@ -60,7 +60,7 @@ fi
# Test 5: Verify plugin JavaScript syntax (basic check)
echo "Test 5: Checking plugin JavaScript syntax..."
plugin_file="$HOME/.config/opencode/superpowers/.opencode/plugins/superpowers.js"
plugin_file="$HOME/.config/opencode/superpowers/.opencode/plugin/superpowers.js"
if node --check "$plugin_file" 2>/dev/null; then
echo " [PASS] Plugin JavaScript syntax is valid"
else

View File

@@ -1 +1 @@
I have a plan document at docs/superpowers/plans/2024-01-15-auth-system.md that needs to be executed. Please implement it.
I have a plan document at docs/plans/2024-01-15-auth-system.md that needs to be executed. Please implement it.