Compare commits

..

4 Commits

Author SHA1 Message Date
Jesse Vincent
b62616fc12 Release v6.0.2: stop shipping the evals submodule
It broke plugin installs for some users (#1778, #1774). The eval harness
now lives in its own repo, separate from the published plugin.
2026-06-16 22:42:19 -07:00
Jesse Vincent
a21956e48c Release v6.0.1: Codex fixes
- Brainstorm companion reads version from .codex-plugin/plugin.json when package.json is absent (PRI-2240)
- sync-to-codex script excludes .gitmodules and .pre-commit-config.yaml (PRI-1168)
2026-06-16 17:02:33 -07:00
Drew Ritter
29c0b1b7db fix: read Codex plugin version from manifest (PRI-2240) 2026-06-16 17:02:33 -07:00
Drew Ritter
cf32920d3a fix: exclude repo metadata from Codex sync (PRI-1168) 2026-06-16 17:02:33 -07:00
17 changed files with 108 additions and 34 deletions

View File

@@ -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": "6.0.0", "version": "6.0.2",
"source": "./", "source": "./",
"author": { "author": {
"name": "Jesse Vincent", "name": "Jesse Vincent",

View File

@@ -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": "6.0.0", "version": "6.0.2",
"author": { "author": {
"name": "Jesse Vincent", "name": "Jesse Vincent",
"email": "jesse@fsck.com" "email": "jesse@fsck.com"

View File

@@ -1,6 +1,6 @@
{ {
"name": "superpowers", "name": "superpowers",
"version": "6.0.0", "version": "6.0.2",
"description": "An agentic skills framework & software development methodology that works: planning, TDD, debugging, and collaboration workflows.", "description": "An agentic skills framework & software development methodology that works: planning, TDD, debugging, and collaboration workflows.",
"author": { "author": {
"name": "Jesse Vincent", "name": "Jesse Vincent",

View File

@@ -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": "6.0.0", "version": "6.0.2",
"author": { "author": {
"name": "Jesse Vincent", "name": "Jesse Vincent",
"email": "jesse@fsck.com" "email": "jesse@fsck.com"

9
.gitignore vendored
View File

@@ -7,8 +7,7 @@ node_modules/
inspo inspo
triage/ triage/
# Eval harness — drill ships its own gitignore at evals/.gitignore; # Eval harness lives in its own repository, cloned into evals/ for local
# these are belt-and-suspenders entries for tools that don't recurse. # development (see CLAUDE.md / README.md). It is not part of the published
evals/results/ # plugin, so the whole directory is ignored here.
evals/.venv/ evals/
evals/.env

3
.gitmodules vendored
View File

@@ -1,3 +0,0 @@
[submodule "evals"]
path = evals
url = git@github.com:prime-radiant-inc/superpowers-evals.git

View File

@@ -1,6 +1,6 @@
{ {
"name": "superpowers", "name": "superpowers",
"version": "6.0.0", "version": "6.0.2",
"description": "An agentic skills framework and software development methodology.", "description": "An agentic skills framework and software development methodology.",
"author": { "author": {
"name": "Jesse Vincent", "name": "Jesse Vincent",

View File

@@ -101,7 +101,7 @@ Skills are not prose — they are code that shapes agent behavior. If you modify
## Eval harness ## Eval harness
Skill-behavior evals live in the `evals/` submodule — after cloning, run `git submodule update --init evals`, then see `evals/README.md`. Drill (the harness) drives real tmux sessions of Claude Code / Codex / Gemini CLI and judges skill compliance with an LLM verifier. Plugin-infrastructure tests still live at `tests/`. Skill-behavior evals live in [superpowers-evals](https://github.com/prime-radiant-inc/superpowers-evals/), cloned into `evals/` see `evals/README.md` for setup. Drill (the harness) drives real tmux sessions of Claude Code / Codex / Gemini CLI and judges skill compliance with an LLM verifier. Plugin-infrastructure tests still live at `tests/`.
## Understand the Project Before Contributing ## Understand the Project Before Contributing

View File

@@ -262,7 +262,7 @@ The general contribution process for Superpowers is below. Keep in mind that we
4. Follow the `writing-skills` skill for creating and testing new and modified skills 4. Follow the `writing-skills` skill for creating and testing new and modified skills
5. Submit a PR, being sure to fill in the pull request template. 5. Submit a PR, being sure to fill in the pull request template.
Skill-behavior tests use the eval harness submodule at `evals/`. After cloning this repo, run `git submodule update --init evals`, then see `evals/README.md` for setup. Plugin-infrastructure tests live at `tests/` and run via the relevant `run-*.sh` or `npm test`. Skill-behavior tests use the drill eval harness from [superpowers-evals](https://github.com/prime-radiant-inc/superpowers-evals/), cloned into `evals/` see `evals/README.md` for setup. Plugin-infrastructure tests live at `tests/` and run via the relevant `run-*.sh` or `npm test`.
See `skills/writing-skills/SKILL.md` for the complete guide. See `skills/writing-skills/SKILL.md` for the complete guide.

View File

@@ -1,5 +1,18 @@
# Superpowers Release Notes # Superpowers Release Notes
## v6.0.2 (2026-06-16)
### Install Fixes
- **We no longer ship the `evals` submodule.** It broke plugin installs for some users, so the eval harness now lives in its own repo, separate from the published plugin. (#1778, #1774)
## v6.0.1 (2026-06-16)
### Codex Fixes
- **Version display in the brainstorm companion** — packaged Codex plugins ship without a root `package.json`, so the visual companion reported its version as "unknown". `readSuperpowersVersion()` now falls back to `.codex-plugin/plugin.json` when `package.json` is absent.
- **Cleaner Codex plugin sync** — the sync-to-codex script now excludes `.gitmodules` and `.pre-commit-config.yaml`, keeping repo metadata out of the packaged Codex plugin.
## v6.0.0 (2026-06-16) ## v6.0.0 (2026-06-16)
Superpowers 6.0 is a big release. The headline is a rewrite of how `subagent-driven-development` reviews each task — cheaper, stricter, and harder to game. Superpowers 6.0 is a big release. The headline is a rewrite of how `subagent-driven-development` reviews each task — cheaper, stricter, and harder to game.

1
evals

Submodule evals deleted from 70a245c36c

View File

@@ -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": "6.0.0", "version": "6.0.2",
"contextFileName": "GEMINI.md" "contextFileName": "GEMINI.md"
} }

View File

@@ -1,6 +1,6 @@
{ {
"name": "superpowers", "name": "superpowers",
"version": "6.0.0", "version": "6.0.2",
"description": "Superpowers skills and runtime bootstrap for coding agents", "description": "Superpowers skills and runtime bootstrap for coding agents",
"type": "module", "type": "module",
"main": ".opencode/plugins/superpowers.js", "main": ".opencode/plugins/superpowers.js",

View File

@@ -52,9 +52,11 @@ EXCLUDES=(
"/.gitattributes" "/.gitattributes"
"/.github/" "/.github/"
"/.gitignore" "/.gitignore"
"/.gitmodules"
"/.kimi-plugin/" "/.kimi-plugin/"
"/.opencode/" "/.opencode/"
"/.pi/" "/.pi/"
"/.pre-commit-config.yaml"
"/.version-bump.json" "/.version-bump.json"
"/.worktrees/" "/.worktrees/"
".DS_Store" ".DS_Store"

View File

@@ -206,14 +206,22 @@ const helperInjection = '<script>\n' + helperScript + '\n</script>';
// ========== Helper Functions ========== // ========== Helper Functions ==========
function readSuperpowersVersion() { function readSuperpowersVersion() {
try { const root = path.join(__dirname, '../../..');
const packageJson = JSON.parse( const manifests = [
fs.readFileSync(path.join(__dirname, '../../..', 'package.json'), 'utf-8') path.join(root, 'package.json'),
); path.join(root, '.codex-plugin/plugin.json')
return String(packageJson.version || 'unknown'); ];
} catch (e) {
return 'unknown'; for (const manifest of manifests) {
try {
const data = JSON.parse(fs.readFileSync(manifest, 'utf-8'));
if (data.version) return String(data.version);
} catch (e) {
// Packaged Codex plugins omit package.json; try the next manifest.
}
} }
return 'unknown';
} }
function isTruthyEnv(value) { function isTruthyEnv(value) {

View File

@@ -26,9 +26,9 @@ function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms)); return new Promise(resolve => setTimeout(resolve, ms));
} }
function startServer({ port, dir, env = {} }) { function startServer({ port, dir, env = {}, serverPath = SERVER_PATH }) {
cleanup(dir); cleanup(dir);
return spawn('node', [SERVER_PATH], { return spawn('node', [serverPath], {
env: { env: {
...process.env, ...process.env,
BRAINSTORM_PORT: String(port), BRAINSTORM_PORT: String(port),
@@ -74,6 +74,21 @@ function writeFragment(dir) {
fs.writeFileSync(path.join(contentDir, 'screen.html'), '<h2>Pick a layout</h2>'); fs.writeFileSync(path.join(contentDir, 'screen.html'), '<h2>Pick a layout</h2>');
} }
function createPackagedServerFixture(version) {
const root = fs.mkdtempSync(path.join('/tmp', 'superpowers-packaged-server-'));
const scriptDir = path.join(root, 'skills/brainstorming/scripts');
fs.cpSync(path.join(REPO_ROOT, 'skills/brainstorming/scripts'), scriptDir, { recursive: true });
fs.mkdirSync(path.join(root, '.codex-plugin'), { recursive: true });
fs.writeFileSync(
path.join(root, '.codex-plugin/plugin.json'),
JSON.stringify({ name: 'superpowers', version }, null, 2)
);
return {
root,
serverPath: path.join(scriptDir, 'server.cjs')
};
}
async function withServer(options, fn) { async function withServer(options, fn) {
const server = startServer(options); const server = startServer(options);
try { try {
@@ -104,13 +119,13 @@ async function test(name, fn) {
} }
} }
function assertBrandedWithLogo(html) { function assertBrandedWithLogo(html, version = PACKAGE_VERSION) {
assert( assert(
html.includes(`Superpowers v${PACKAGE_VERSION}`), html.includes(`Superpowers v${version}`),
'branding text should include dynamic package version' 'branding text should include dynamic package version'
); );
assert( assert(
!html.includes(`Superpowers v${PACKAGE_VERSION} by`), !html.includes(`Superpowers v${version} by`),
'branding text should not include "by" when the logo is visible' 'branding text should not include "by" when the logo is visible'
); );
assert( assert(
@@ -139,15 +154,15 @@ function assertBrandedWithLogo(html) {
); );
} }
function assertBrandedFallbackText(html) { function assertBrandedFallbackText(html, version = PACKAGE_VERSION) {
assert( assert(
html.includes(`Prime Radiant Superpowers v${PACKAGE_VERSION}`), html.includes(`Prime Radiant Superpowers v${version}`),
'disabled telemetry should keep plain text Prime Radiant/Superpowers branding' 'disabled telemetry should keep plain text Prime Radiant/Superpowers branding'
); );
} }
function assertTelemetryImage(html) { function assertTelemetryImage(html, version = PACKAGE_VERSION) {
const expectedUrl = `${ASSET_URL}?v=${encodeURIComponent(PACKAGE_VERSION)}`; const expectedUrl = `${ASSET_URL}?v=${encodeURIComponent(version)}`;
assert(html.includes(`src="${expectedUrl}"`), 'remote image should use the dedicated main-domain asset with only v='); assert(html.includes(`src="${expectedUrl}"`), 'remote image should use the dedicated main-domain asset with only v=');
assert(!html.includes('event='), 'remote image URL must not include event='); assert(!html.includes('event='), 'remote image URL must not include event=');
assert(!html.includes('surface='), 'remote image URL must not include surface='); assert(!html.includes('surface='), 'remote image URL must not include surface=');
@@ -255,6 +270,26 @@ async function main() {
}); });
}); });
await test('packaged Codex plugin reads version from .codex-plugin manifest', async () => {
const port = 3457;
const dir = '/tmp/brainstorm-branding-packaged-codex';
const packagedVersion = '7.8.9';
const fixture = createPackagedServerFixture(packagedVersion);
try {
await withServer({ port, dir, serverPath: fixture.serverPath }, async () => {
writeFragment(dir);
await sleep(300);
const html = await fetchHtml(port);
assertBrandedWithLogo(html, packagedVersion);
assertTelemetryImage(html, packagedVersion);
assert(!html.includes('Superpowers vunknown'), 'packaged plugin should not fall back to unknown version');
});
} finally {
cleanup(fixture.root);
}
});
await test('SUPERPOWERS_DISABLE_TELEMETRY=true omits remote image but keeps local branding', async () => { await test('SUPERPOWERS_DISABLE_TELEMETRY=true omits remote image but keeps local branding', async () => {
const port = 3453; const port = 3453;
const dir = '/tmp/brainstorm-branding-disabled'; const dir = '/tmp/brainstorm-branding-disabled';

View File

@@ -200,6 +200,23 @@ EOF
.private-journal/ .private-journal/
EOF EOF
cat > "$repo/.gitmodules" <<'EOF'
[submodule "evals"]
path = evals
url = git@example.com:example/evals.git
EOF
cat > "$repo/.pre-commit-config.yaml" <<'EOF'
repos:
- repo: local
hooks:
- id: evals-check
name: evals check
entry: echo evals
language: system
files: ^evals/
EOF
if [[ "$with_pure_ignored" == "1" ]]; then if [[ "$with_pure_ignored" == "1" ]]; then
cat >> "$repo/.gitignore" <<'EOF' cat >> "$repo/.gitignore" <<'EOF'
ignored-cache/ ignored-cache/
@@ -277,6 +294,8 @@ EOF
.codex-plugin/plugin.json \ .codex-plugin/plugin.json \
.kimi-plugin/plugin.json \ .kimi-plugin/plugin.json \
.gitignore \ .gitignore \
.gitmodules \
.pre-commit-config.yaml \
assets/app-icon.png \ assets/app-icon.png \
assets/superpowers-small.svg \ assets/superpowers-small.svg \
evals/drill/README.md \ evals/drill/README.md \
@@ -643,6 +662,8 @@ main() {
assert_not_contains "$preview_section" ".private-journal/leak.txt" "Preview excludes ignored untracked file" assert_not_contains "$preview_section" ".private-journal/leak.txt" "Preview excludes ignored untracked file"
assert_not_contains "$preview_section" "ignored-cache/" "Preview excludes pure ignored directories" assert_not_contains "$preview_section" "ignored-cache/" "Preview excludes pure ignored directories"
assert_not_contains "$preview_section" "evals/" "Preview excludes eval harness" assert_not_contains "$preview_section" "evals/" "Preview excludes eval harness"
assert_not_contains "$preview_section" ".gitmodules" "Preview excludes repo submodule metadata"
assert_not_contains "$preview_section" ".pre-commit-config.yaml" "Preview excludes repo pre-commit config"
assert_not_contains "$preview_output" "Overlay file (.codex-plugin/plugin.json) will be regenerated" "Preview omits overlay regeneration note" assert_not_contains "$preview_output" "Overlay file (.codex-plugin/plugin.json) will be regenerated" "Preview omits overlay regeneration note"
assert_not_contains "$preview_output" "Assets (superpowers-small.svg, app-icon.png) will be seeded from" "Preview omits assets seeding note" assert_not_contains "$preview_output" "Assets (superpowers-small.svg, app-icon.png) will be seeded from" "Preview omits assets seeding note"
assert_contains "$preview_section" "skills/example/SKILL.md" "Preview reflects dirty tracked destination file" assert_contains "$preview_section" "skills/example/SKILL.md" "Preview reflects dirty tracked destination file"