mirror of
https://github.com/obra/superpowers.git
synced 2026-04-26 11:39:05 +08:00
Compare commits
8 Commits
fix/owner-
...
8b9a5da90b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8b9a5da90b | ||
|
|
04ff6660e8 | ||
|
|
471aa93a4c | ||
|
|
872172870d | ||
|
|
ed06287a8a | ||
|
|
5406747197 | ||
|
|
879940ba5e | ||
|
|
0f306f0d18 |
@@ -9,7 +9,7 @@
|
|||||||
{
|
{
|
||||||
"name": "superpowers",
|
"name": "superpowers",
|
||||||
"description": "Core skills library for Claude Code: TDD, debugging, collaboration patterns, and proven techniques",
|
"description": "Core skills library for Claude Code: TDD, debugging, collaboration patterns, and proven techniques",
|
||||||
"version": "5.0.5",
|
"version": "5.0.6",
|
||||||
"source": "./",
|
"source": "./",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Jesse Vincent",
|
"name": "Jesse Vincent",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "superpowers",
|
"name": "superpowers",
|
||||||
"description": "Core skills library for Claude Code: TDD, debugging, collaboration patterns, and proven techniques",
|
"description": "Core skills library for Claude Code: TDD, debugging, collaboration patterns, and proven techniques",
|
||||||
"version": "5.0.5",
|
"version": "5.0.6",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Jesse Vincent",
|
"name": "Jesse Vincent",
|
||||||
"email": "jesse@fsck.com"
|
"email": "jesse@fsck.com"
|
||||||
@@ -9,5 +9,12 @@
|
|||||||
"homepage": "https://github.com/obra/superpowers",
|
"homepage": "https://github.com/obra/superpowers",
|
||||||
"repository": "https://github.com/obra/superpowers",
|
"repository": "https://github.com/obra/superpowers",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"keywords": ["skills", "tdd", "debugging", "collaboration", "best-practices", "workflows"]
|
"keywords": [
|
||||||
|
"skills",
|
||||||
|
"tdd",
|
||||||
|
"debugging",
|
||||||
|
"collaboration",
|
||||||
|
"best-practices",
|
||||||
|
"workflows"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"name": "superpowers",
|
"name": "superpowers",
|
||||||
"displayName": "Superpowers",
|
"displayName": "Superpowers",
|
||||||
"description": "Core skills library: TDD, debugging, collaboration patterns, and proven techniques",
|
"description": "Core skills library: TDD, debugging, collaboration patterns, and proven techniques",
|
||||||
"version": "5.0.5",
|
"version": "5.0.6",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Jesse Vincent",
|
"name": "Jesse Vincent",
|
||||||
"email": "jesse@fsck.com"
|
"email": "jesse@fsck.com"
|
||||||
@@ -10,7 +10,14 @@
|
|||||||
"homepage": "https://github.com/obra/superpowers",
|
"homepage": "https://github.com/obra/superpowers",
|
||||||
"repository": "https://github.com/obra/superpowers",
|
"repository": "https://github.com/obra/superpowers",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"keywords": ["skills", "tdd", "debugging", "collaboration", "best-practices", "workflows"],
|
"keywords": [
|
||||||
|
"skills",
|
||||||
|
"tdd",
|
||||||
|
"debugging",
|
||||||
|
"collaboration",
|
||||||
|
"best-practices",
|
||||||
|
"workflows"
|
||||||
|
],
|
||||||
"skills": "./skills/",
|
"skills": "./skills/",
|
||||||
"agents": "./agents/",
|
"agents": "./agents/",
|
||||||
"commands": "./commands/",
|
"commands": "./commands/",
|
||||||
|
|||||||
@@ -68,8 +68,6 @@ When skills reference tools you don't have, substitute OpenCode equivalents:
|
|||||||
- \`Skill\` tool → OpenCode's native \`skill\` tool
|
- \`Skill\` tool → OpenCode's native \`skill\` tool
|
||||||
- \`Read\`, \`Write\`, \`Edit\`, \`Bash\` → Your native tools
|
- \`Read\`, \`Write\`, \`Edit\`, \`Bash\` → Your native tools
|
||||||
|
|
||||||
**Skills location:**
|
|
||||||
Superpowers skills are in \`${configDir}/skills/superpowers/\`
|
|
||||||
Use OpenCode's native \`skill\` tool to list and load skills.`;
|
Use OpenCode's native \`skill\` tool to list and load skills.`;
|
||||||
|
|
||||||
return `<EXTREMELY_IMPORTANT>
|
return `<EXTREMELY_IMPORTANT>
|
||||||
@@ -96,12 +94,19 @@ ${toolMapping}
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// Use system prompt transform to inject bootstrap (fixes #226 agent reset bug)
|
// Inject bootstrap into the first user message of each session.
|
||||||
'experimental.chat.system.transform': async (_input, output) => {
|
// Using a user message instead of a system message avoids:
|
||||||
|
// 1. Token bloat from system messages repeated every turn (#750)
|
||||||
|
// 2. Multiple system messages breaking Qwen and other models (#894)
|
||||||
|
'experimental.chat.messages.transform': async (_input, output) => {
|
||||||
const bootstrap = getBootstrapContent();
|
const bootstrap = getBootstrapContent();
|
||||||
if (bootstrap) {
|
if (!bootstrap || !output.messages.length) return;
|
||||||
(output.system ||= []).push(bootstrap);
|
const firstUser = output.messages.find(m => m.info.role === 'user');
|
||||||
}
|
if (!firstUser || !firstUser.parts.length) return;
|
||||||
|
// Only inject once
|
||||||
|
if (firstUser.parts.some(p => p.type === 'text' && p.text.includes('EXTREMELY_IMPORTANT'))) return;
|
||||||
|
const ref = firstUser.parts[0];
|
||||||
|
firstUser.parts.unshift({ ...ref, type: 'text', text: bootstrap });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -82,6 +82,13 @@ Fetch and follow instructions from https://raw.githubusercontent.com/obra/superp
|
|||||||
|
|
||||||
**Detailed docs:** [docs/README.opencode.md](docs/README.opencode.md)
|
**Detailed docs:** [docs/README.opencode.md](docs/README.opencode.md)
|
||||||
|
|
||||||
|
### GitHub Copilot CLI
|
||||||
|
|
||||||
|
```bash
|
||||||
|
copilot plugin marketplace add obra/superpowers-marketplace
|
||||||
|
copilot plugin install superpowers@superpowers-marketplace
|
||||||
|
```
|
||||||
|
|
||||||
### Gemini CLI
|
### Gemini CLI
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -1,5 +1,18 @@
|
|||||||
# Superpowers Release Notes
|
# Superpowers Release Notes
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
### GitHub Copilot CLI Support
|
||||||
|
|
||||||
|
- **SessionStart context injection** — Copilot CLI v1.0.11 added support for `additionalContext` in sessionStart hook output. The session-start hook now detects the `COPILOT_CLI` environment variable and emits the SDK-standard `{ "additionalContext": "..." }` format, giving Copilot CLI users the full superpowers bootstrap at session start. (Original fix by @culinablaz in PR #910)
|
||||||
|
- **Tool mapping** — added `references/copilot-tools.md` with the full Claude Code to Copilot CLI tool equivalence table
|
||||||
|
- **Skill and README updates** — added Copilot CLI to the `using-superpowers` skill's platform instructions and README installation section
|
||||||
|
|
||||||
|
### OpenCode Fixes
|
||||||
|
|
||||||
|
- **Skills path consistency** — the bootstrap text no longer advertises a misleading `configDir/skills/superpowers/` path that didn't match the runtime path. The agent should use the native `skill` tool, not navigate to files by path. Tests now use consistent paths derived from a single source of truth. (#847, #916)
|
||||||
|
- **Bootstrap as user message** — moved bootstrap injection from `experimental.chat.system.transform` to `experimental.chat.messages.transform`, prepending to the first user message instead of adding a system message. Avoids token bloat from system messages repeated every turn (#750) and fixes compatibility with Qwen and other models that break on multiple system messages (#894).
|
||||||
|
|
||||||
## v5.0.6 (2026-03-24)
|
## v5.0.6 (2026-03-24)
|
||||||
|
|
||||||
### Inline Self-Review Replaces Subagent Review Loops
|
### Inline Self-Review Replaces Subagent Review Loops
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "superpowers",
|
"name": "superpowers",
|
||||||
"description": "Core skills library: TDD, debugging, collaboration patterns, and proven techniques",
|
"description": "Core skills library: TDD, debugging, collaboration patterns, and proven techniques",
|
||||||
"version": "5.0.0",
|
"version": "5.0.6",
|
||||||
"contextFileName": "GEMINI.md"
|
"contextFileName": "GEMINI.md"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,23 +35,23 @@ warning_escaped=$(escape_for_json "$warning_message")
|
|||||||
session_context="<EXTREMELY_IMPORTANT>\nYou have superpowers.\n\n**Below is the full content of your 'superpowers:using-superpowers' skill - your introduction to using skills. For all other skills, use the 'Skill' tool:**\n\n${using_superpowers_escaped}\n\n${warning_escaped}\n</EXTREMELY_IMPORTANT>"
|
session_context="<EXTREMELY_IMPORTANT>\nYou have superpowers.\n\n**Below is the full content of your 'superpowers:using-superpowers' skill - your introduction to using skills. For all other skills, use the 'Skill' tool:**\n\n${using_superpowers_escaped}\n\n${warning_escaped}\n</EXTREMELY_IMPORTANT>"
|
||||||
|
|
||||||
# Output context injection as JSON.
|
# Output context injection as JSON.
|
||||||
# Cursor hooks expect additional_context.
|
# Cursor hooks expect additional_context (snake_case).
|
||||||
# Claude Code hooks expect hookSpecificOutput.additionalContext.
|
# Claude Code hooks expect hookSpecificOutput.additionalContext (nested).
|
||||||
# Claude Code reads BOTH fields without deduplication, so we must only
|
# Copilot CLI (v1.0.11+) and others expect additionalContext (top-level, SDK standard).
|
||||||
# emit the field consumed by the current platform to avoid double injection.
|
# Claude Code reads BOTH additional_context and hookSpecificOutput without
|
||||||
|
# deduplication, so we must emit only the field the current platform consumes.
|
||||||
#
|
#
|
||||||
# Uses printf instead of heredoc (cat <<EOF) to work around a bash 5.3+
|
# Uses printf instead of heredoc to work around bash 5.3+ heredoc hang.
|
||||||
# bug where heredoc variable expansion hangs when content exceeds ~512 bytes.
|
|
||||||
# See: https://github.com/obra/superpowers/issues/571
|
# See: https://github.com/obra/superpowers/issues/571
|
||||||
if [ -n "${CURSOR_PLUGIN_ROOT:-}" ]; then
|
if [ -n "${CURSOR_PLUGIN_ROOT:-}" ]; then
|
||||||
# Cursor sets CURSOR_PLUGIN_ROOT (may also set CLAUDE_PLUGIN_ROOT) — emit additional_context
|
# Cursor sets CURSOR_PLUGIN_ROOT (may also set CLAUDE_PLUGIN_ROOT)
|
||||||
printf '{\n "additional_context": "%s"\n}\n' "$session_context"
|
printf '{\n "additional_context": "%s"\n}\n' "$session_context"
|
||||||
elif [ -n "${CLAUDE_PLUGIN_ROOT:-}" ]; then
|
elif [ -n "${CLAUDE_PLUGIN_ROOT:-}" ] && [ -z "${COPILOT_CLI:-}" ]; then
|
||||||
# Claude Code sets CLAUDE_PLUGIN_ROOT — emit only hookSpecificOutput
|
# Claude Code sets CLAUDE_PLUGIN_ROOT without COPILOT_CLI
|
||||||
printf '{\n "hookSpecificOutput": {\n "hookEventName": "SessionStart",\n "additionalContext": "%s"\n }\n}\n' "$session_context"
|
printf '{\n "hookSpecificOutput": {\n "hookEventName": "SessionStart",\n "additionalContext": "%s"\n }\n}\n' "$session_context"
|
||||||
else
|
else
|
||||||
# Other platforms — emit additional_context as fallback
|
# Copilot CLI (sets COPILOT_CLI=1) or unknown platform — SDK standard format
|
||||||
printf '{\n "additional_context": "%s"\n}\n' "$session_context"
|
printf '{\n "additionalContext": "%s"\n}\n' "$session_context"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "superpowers",
|
"name": "superpowers",
|
||||||
"version": "5.0.4",
|
"version": "5.0.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": ".opencode/plugins/superpowers.js"
|
"main": ".opencode/plugins/superpowers.js"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,13 +29,15 @@ If CLAUDE.md, GEMINI.md, or AGENTS.md says "don't use TDD" and a skill says "alw
|
|||||||
|
|
||||||
**In Claude Code:** Use the `Skill` tool. When you invoke a skill, its content is loaded and presented to you—follow it directly. Never use the Read tool on skill files.
|
**In Claude Code:** Use the `Skill` tool. When you invoke a skill, its content is loaded and presented to you—follow it directly. Never use the Read tool on skill files.
|
||||||
|
|
||||||
|
**In Copilot CLI:** Use the `skill` tool. Skills are auto-discovered from installed plugins. The `skill` tool works the same as Claude Code's `Skill` tool.
|
||||||
|
|
||||||
**In Gemini CLI:** Skills activate via the `activate_skill` tool. Gemini loads skill metadata at session start and activates the full content on demand.
|
**In Gemini CLI:** Skills activate via the `activate_skill` tool. Gemini loads skill metadata at session start and activates the full content on demand.
|
||||||
|
|
||||||
**In other environments:** Check your platform's documentation for how skills are loaded.
|
**In other environments:** Check your platform's documentation for how skills are loaded.
|
||||||
|
|
||||||
## Platform Adaptation
|
## Platform Adaptation
|
||||||
|
|
||||||
Skills use Claude Code tool names. Non-CC platforms: see `references/codex-tools.md` (Codex) for tool equivalents. Gemini CLI users get the tool mapping loaded automatically via GEMINI.md.
|
Skills use Claude Code tool names. Non-CC platforms: see `references/copilot-tools.md` (Copilot CLI), `references/codex-tools.md` (Codex) for tool equivalents. Gemini CLI users get the tool mapping loaded automatically via GEMINI.md.
|
||||||
|
|
||||||
# Using Skills
|
# Using Skills
|
||||||
|
|
||||||
|
|||||||
52
skills/using-superpowers/references/copilot-tools.md
Normal file
52
skills/using-superpowers/references/copilot-tools.md
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
# Copilot CLI Tool Mapping
|
||||||
|
|
||||||
|
Skills use Claude Code tool names. When you encounter these in a skill, use your platform equivalent:
|
||||||
|
|
||||||
|
| Skill references | Copilot CLI equivalent |
|
||||||
|
|-----------------|----------------------|
|
||||||
|
| `Read` (file reading) | `view` |
|
||||||
|
| `Write` (file creation) | `create` |
|
||||||
|
| `Edit` (file editing) | `edit` |
|
||||||
|
| `Bash` (run commands) | `bash` |
|
||||||
|
| `Grep` (search file content) | `grep` |
|
||||||
|
| `Glob` (search files by name) | `glob` |
|
||||||
|
| `Skill` tool (invoke a skill) | `skill` |
|
||||||
|
| `WebFetch` | `web_fetch` |
|
||||||
|
| `Task` tool (dispatch subagent) | `task` (see [Agent types](#agent-types)) |
|
||||||
|
| Multiple `Task` calls (parallel) | Multiple `task` calls |
|
||||||
|
| Task status/output | `read_agent`, `list_agents` |
|
||||||
|
| `TodoWrite` (task tracking) | `sql` with built-in `todos` table |
|
||||||
|
| `WebSearch` | No equivalent — use `web_fetch` with a search engine URL |
|
||||||
|
| `EnterPlanMode` / `ExitPlanMode` | No equivalent — stay in the main session |
|
||||||
|
|
||||||
|
## Agent types
|
||||||
|
|
||||||
|
Copilot CLI's `task` tool accepts an `agent_type` parameter:
|
||||||
|
|
||||||
|
| Claude Code agent | Copilot CLI equivalent |
|
||||||
|
|-------------------|----------------------|
|
||||||
|
| `general-purpose` | `"general-purpose"` |
|
||||||
|
| `Explore` | `"explore"` |
|
||||||
|
| Named plugin agents (e.g. `superpowers:code-reviewer`) | Discovered automatically from installed plugins |
|
||||||
|
|
||||||
|
## Async shell sessions
|
||||||
|
|
||||||
|
Copilot CLI supports persistent async shell sessions, which have no direct Claude Code equivalent:
|
||||||
|
|
||||||
|
| Tool | Purpose |
|
||||||
|
|------|---------|
|
||||||
|
| `bash` with `async: true` | Start a long-running command in the background |
|
||||||
|
| `write_bash` | Send input to a running async session |
|
||||||
|
| `read_bash` | Read output from an async session |
|
||||||
|
| `stop_bash` | Terminate an async session |
|
||||||
|
| `list_bash` | List all active shell sessions |
|
||||||
|
|
||||||
|
## Additional Copilot CLI tools
|
||||||
|
|
||||||
|
| Tool | Purpose |
|
||||||
|
|------|---------|
|
||||||
|
| `store_memory` | Persist facts about the codebase for future sessions |
|
||||||
|
| `report_intent` | Update the UI status line with current intent |
|
||||||
|
| `sql` | Query the session's SQLite database (todos, metadata) |
|
||||||
|
| `fetch_copilot_cli_documentation` | Look up Copilot CLI documentation |
|
||||||
|
| GitHub MCP tools (`github-mcp-server-*`) | Native GitHub API access (issues, PRs, code search) |
|
||||||
@@ -7,30 +7,39 @@ set -euo pipefail
|
|||||||
REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||||
|
|
||||||
# Create temp home directory for isolation
|
# Create temp home directory for isolation
|
||||||
export TEST_HOME=$(mktemp -d)
|
export TEST_HOME
|
||||||
|
TEST_HOME=$(mktemp -d)
|
||||||
export HOME="$TEST_HOME"
|
export HOME="$TEST_HOME"
|
||||||
export XDG_CONFIG_HOME="$TEST_HOME/.config"
|
export XDG_CONFIG_HOME="$TEST_HOME/.config"
|
||||||
export OPENCODE_CONFIG_DIR="$TEST_HOME/.config/opencode"
|
export OPENCODE_CONFIG_DIR="$TEST_HOME/.config/opencode"
|
||||||
|
|
||||||
# Install plugin to test location
|
# Standard install layout:
|
||||||
mkdir -p "$HOME/.config/opencode/superpowers"
|
# $OPENCODE_CONFIG_DIR/superpowers/ ← package root
|
||||||
cp -r "$REPO_ROOT/lib" "$HOME/.config/opencode/superpowers/"
|
# $OPENCODE_CONFIG_DIR/superpowers/skills/ ← skills dir (../../skills from plugin)
|
||||||
cp -r "$REPO_ROOT/skills" "$HOME/.config/opencode/superpowers/"
|
# $OPENCODE_CONFIG_DIR/superpowers/.opencode/plugins/superpowers.js ← plugin file
|
||||||
|
# $OPENCODE_CONFIG_DIR/plugins/superpowers.js ← symlink OpenCode reads
|
||||||
|
|
||||||
# Copy plugin directory
|
SUPERPOWERS_DIR="$OPENCODE_CONFIG_DIR/superpowers"
|
||||||
mkdir -p "$HOME/.config/opencode/superpowers/.opencode/plugins"
|
SUPERPOWERS_SKILLS_DIR="$SUPERPOWERS_DIR/skills"
|
||||||
cp "$REPO_ROOT/.opencode/plugins/superpowers.js" "$HOME/.config/opencode/superpowers/.opencode/plugins/"
|
SUPERPOWERS_PLUGIN_FILE="$SUPERPOWERS_DIR/.opencode/plugins/superpowers.js"
|
||||||
|
|
||||||
# Register plugin via symlink
|
# Install skills
|
||||||
mkdir -p "$HOME/.config/opencode/plugins"
|
mkdir -p "$SUPERPOWERS_DIR"
|
||||||
ln -sf "$HOME/.config/opencode/superpowers/.opencode/plugins/superpowers.js" \
|
cp -r "$REPO_ROOT/skills" "$SUPERPOWERS_DIR/"
|
||||||
"$HOME/.config/opencode/plugins/superpowers.js"
|
|
||||||
|
# Install plugin
|
||||||
|
mkdir -p "$(dirname "$SUPERPOWERS_PLUGIN_FILE")"
|
||||||
|
cp "$REPO_ROOT/.opencode/plugins/superpowers.js" "$SUPERPOWERS_PLUGIN_FILE"
|
||||||
|
|
||||||
|
# Register plugin via symlink (what OpenCode actually reads)
|
||||||
|
mkdir -p "$OPENCODE_CONFIG_DIR/plugins"
|
||||||
|
ln -sf "$SUPERPOWERS_PLUGIN_FILE" "$OPENCODE_CONFIG_DIR/plugins/superpowers.js"
|
||||||
|
|
||||||
# Create test skills in different locations for testing
|
# Create test skills in different locations for testing
|
||||||
|
|
||||||
# Personal test skill
|
# Personal test skill
|
||||||
mkdir -p "$HOME/.config/opencode/skills/personal-test"
|
mkdir -p "$OPENCODE_CONFIG_DIR/skills/personal-test"
|
||||||
cat > "$HOME/.config/opencode/skills/personal-test/SKILL.md" <<'EOF'
|
cat > "$OPENCODE_CONFIG_DIR/skills/personal-test/SKILL.md" <<'EOF'
|
||||||
---
|
---
|
||||||
name: personal-test
|
name: personal-test
|
||||||
description: Test personal skill for verification
|
description: Test personal skill for verification
|
||||||
@@ -57,8 +66,11 @@ PROJECT_SKILL_MARKER_67890
|
|||||||
EOF
|
EOF
|
||||||
|
|
||||||
echo "Setup complete: $TEST_HOME"
|
echo "Setup complete: $TEST_HOME"
|
||||||
echo "Plugin installed to: $HOME/.config/opencode/superpowers/.opencode/plugins/superpowers.js"
|
echo "OPENCODE_CONFIG_DIR: $OPENCODE_CONFIG_DIR"
|
||||||
echo "Plugin registered at: $HOME/.config/opencode/plugins/superpowers.js"
|
echo "Superpowers dir: $SUPERPOWERS_DIR"
|
||||||
|
echo "Skills dir: $SUPERPOWERS_SKILLS_DIR"
|
||||||
|
echo "Plugin file: $SUPERPOWERS_PLUGIN_FILE"
|
||||||
|
echo "Plugin registered at: $OPENCODE_CONFIG_DIR/plugins/superpowers.js"
|
||||||
echo "Test project at: $TEST_HOME/test-project"
|
echo "Test project at: $TEST_HOME/test-project"
|
||||||
|
|
||||||
# Helper function for cleanup (call from tests or trap)
|
# Helper function for cleanup (call from tests or trap)
|
||||||
@@ -71,3 +83,6 @@ cleanup_test_env() {
|
|||||||
# Export for use in tests
|
# Export for use in tests
|
||||||
export -f cleanup_test_env
|
export -f cleanup_test_env
|
||||||
export REPO_ROOT
|
export REPO_ROOT
|
||||||
|
export SUPERPOWERS_DIR
|
||||||
|
export SUPERPOWERS_SKILLS_DIR
|
||||||
|
export SUPERPOWERS_PLUGIN_FILE
|
||||||
|
|||||||
@@ -13,17 +13,19 @@ source "$SCRIPT_DIR/setup.sh"
|
|||||||
# Trap to cleanup on exit
|
# Trap to cleanup on exit
|
||||||
trap cleanup_test_env EXIT
|
trap cleanup_test_env EXIT
|
||||||
|
|
||||||
|
plugin_link="$OPENCODE_CONFIG_DIR/plugins/superpowers.js"
|
||||||
|
|
||||||
# Test 1: Verify plugin file exists and is registered
|
# Test 1: Verify plugin file exists and is registered
|
||||||
echo "Test 1: Checking plugin registration..."
|
echo "Test 1: Checking plugin registration..."
|
||||||
if [ -L "$HOME/.config/opencode/plugins/superpowers.js" ]; then
|
if [ -L "$plugin_link" ]; then
|
||||||
echo " [PASS] Plugin symlink exists"
|
echo " [PASS] Plugin symlink exists"
|
||||||
else
|
else
|
||||||
echo " [FAIL] Plugin symlink not found at $HOME/.config/opencode/plugins/superpowers.js"
|
echo " [FAIL] Plugin symlink not found at $plugin_link"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Verify symlink target exists
|
# Verify symlink target exists
|
||||||
if [ -f "$(readlink -f "$HOME/.config/opencode/plugins/superpowers.js")" ]; then
|
if [ -f "$(readlink -f "$plugin_link")" ]; then
|
||||||
echo " [PASS] Plugin symlink target exists"
|
echo " [PASS] Plugin symlink target exists"
|
||||||
else
|
else
|
||||||
echo " [FAIL] Plugin symlink target does not exist"
|
echo " [FAIL] Plugin symlink target does not exist"
|
||||||
@@ -32,36 +34,44 @@ fi
|
|||||||
|
|
||||||
# Test 2: Verify skills directory is populated
|
# Test 2: Verify skills directory is populated
|
||||||
echo "Test 2: Checking skills directory..."
|
echo "Test 2: Checking skills directory..."
|
||||||
skill_count=$(find "$HOME/.config/opencode/superpowers/skills" -name "SKILL.md" | wc -l)
|
skill_count=$(find "$SUPERPOWERS_SKILLS_DIR" -name "SKILL.md" | wc -l)
|
||||||
if [ "$skill_count" -gt 0 ]; then
|
if [ "$skill_count" -gt 0 ]; then
|
||||||
echo " [PASS] Found $skill_count skills installed"
|
echo " [PASS] Found $skill_count skills"
|
||||||
else
|
else
|
||||||
echo " [FAIL] No skills found in installed location"
|
echo " [FAIL] No skills found in $SUPERPOWERS_SKILLS_DIR"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Test 4: Check using-superpowers skill exists (critical for bootstrap)
|
# Test 3: Check using-superpowers skill exists (critical for bootstrap)
|
||||||
echo "Test 4: Checking using-superpowers skill (required for bootstrap)..."
|
echo "Test 3: Checking using-superpowers skill (required for bootstrap)..."
|
||||||
if [ -f "$HOME/.config/opencode/superpowers/skills/using-superpowers/SKILL.md" ]; then
|
if [ -f "$SUPERPOWERS_SKILLS_DIR/using-superpowers/SKILL.md" ]; then
|
||||||
echo " [PASS] using-superpowers skill exists"
|
echo " [PASS] using-superpowers skill exists"
|
||||||
else
|
else
|
||||||
echo " [FAIL] using-superpowers skill not found (required for bootstrap)"
|
echo " [FAIL] using-superpowers skill not found (required for bootstrap)"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Test 5: Verify plugin JavaScript syntax (basic check)
|
# Test 4: Verify plugin JavaScript syntax (basic check)
|
||||||
echo "Test 5: Checking plugin JavaScript syntax..."
|
echo "Test 4: Checking plugin JavaScript syntax..."
|
||||||
plugin_file="$HOME/.config/opencode/superpowers/.opencode/plugins/superpowers.js"
|
if node --check "$SUPERPOWERS_PLUGIN_FILE" 2>/dev/null; then
|
||||||
if node --check "$plugin_file" 2>/dev/null; then
|
|
||||||
echo " [PASS] Plugin JavaScript syntax is valid"
|
echo " [PASS] Plugin JavaScript syntax is valid"
|
||||||
else
|
else
|
||||||
echo " [FAIL] Plugin has JavaScript syntax errors"
|
echo " [FAIL] Plugin has JavaScript syntax errors"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Test 5: Verify bootstrap text does not reference a hardcoded skills path
|
||||||
|
echo "Test 5: Checking bootstrap does not advertise a wrong skills path..."
|
||||||
|
if grep -q 'configDir}/skills/superpowers/' "$SUPERPOWERS_PLUGIN_FILE"; then
|
||||||
|
echo " [FAIL] Plugin still references old configDir skills path"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo " [PASS] Plugin does not advertise a misleading skills path"
|
||||||
|
fi
|
||||||
|
|
||||||
# Test 6: Verify personal test skill was created
|
# Test 6: Verify personal test skill was created
|
||||||
echo "Test 6: Checking test fixtures..."
|
echo "Test 6: Checking test fixtures..."
|
||||||
if [ -f "$HOME/.config/opencode/skills/personal-test/SKILL.md" ]; then
|
if [ -f "$OPENCODE_CONFIG_DIR/skills/personal-test/SKILL.md" ]; then
|
||||||
echo " [PASS] Personal test skill fixture created"
|
echo " [PASS] Personal test skill fixture created"
|
||||||
else
|
else
|
||||||
echo " [FAIL] Personal test skill fixture not found"
|
echo " [FAIL] Personal test skill fixture not found"
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ trap cleanup_test_env EXIT
|
|||||||
echo "Setting up priority test fixtures..."
|
echo "Setting up priority test fixtures..."
|
||||||
|
|
||||||
# 1. Create in superpowers location (lowest priority)
|
# 1. Create in superpowers location (lowest priority)
|
||||||
mkdir -p "$HOME/.config/opencode/superpowers/skills/priority-test"
|
mkdir -p "$SUPERPOWERS_SKILLS_DIR/priority-test"
|
||||||
cat > "$HOME/.config/opencode/superpowers/skills/priority-test/SKILL.md" <<'EOF'
|
cat > "$SUPERPOWERS_SKILLS_DIR/priority-test/SKILL.md" <<'EOF'
|
||||||
---
|
---
|
||||||
name: priority-test
|
name: priority-test
|
||||||
description: Superpowers version of priority test skill
|
description: Superpowers version of priority test skill
|
||||||
@@ -32,8 +32,8 @@ PRIORITY_MARKER_SUPERPOWERS_VERSION
|
|||||||
EOF
|
EOF
|
||||||
|
|
||||||
# 2. Create in personal location (medium priority)
|
# 2. Create in personal location (medium priority)
|
||||||
mkdir -p "$HOME/.config/opencode/skills/priority-test"
|
mkdir -p "$OPENCODE_CONFIG_DIR/skills/priority-test"
|
||||||
cat > "$HOME/.config/opencode/skills/priority-test/SKILL.md" <<'EOF'
|
cat > "$OPENCODE_CONFIG_DIR/skills/priority-test/SKILL.md" <<'EOF'
|
||||||
---
|
---
|
||||||
name: priority-test
|
name: priority-test
|
||||||
description: Personal version of priority test skill
|
description: Personal version of priority test skill
|
||||||
@@ -65,14 +65,14 @@ echo " Created priority-test skill in all three locations"
|
|||||||
echo ""
|
echo ""
|
||||||
echo "Test 1: Verifying test fixtures..."
|
echo "Test 1: Verifying test fixtures..."
|
||||||
|
|
||||||
if [ -f "$HOME/.config/opencode/superpowers/skills/priority-test/SKILL.md" ]; then
|
if [ -f "$SUPERPOWERS_SKILLS_DIR/priority-test/SKILL.md" ]; then
|
||||||
echo " [PASS] Superpowers version exists"
|
echo " [PASS] Superpowers version exists"
|
||||||
else
|
else
|
||||||
echo " [FAIL] Superpowers version missing"
|
echo " [FAIL] Superpowers version missing"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -f "$HOME/.config/opencode/skills/priority-test/SKILL.md" ]; then
|
if [ -f "$OPENCODE_CONFIG_DIR/skills/priority-test/SKILL.md" ]; then
|
||||||
echo " [PASS] Personal version exists"
|
echo " [PASS] Personal version exists"
|
||||||
else
|
else
|
||||||
echo " [FAIL] Personal version missing"
|
echo " [FAIL] Personal version missing"
|
||||||
|
|||||||
Reference in New Issue
Block a user