Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
{
"name": "superpowers",
"description": "Core skills library for Claude Code: TDD, debugging, collaboration patterns, and proven techniques",
"version": "6.1.1",
"version": "6.1.2",
"source": "./",
"author": {
"name": "Jesse Vincent",
Expand Down
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "superpowers",
"description": "Core skills library for Claude Code: TDD, debugging, collaboration patterns, and proven techniques",
"version": "6.1.1",
"version": "6.1.2",
"author": {
"name": "Jesse Vincent",
"email": "jesse@fsck.com"
Expand Down
50 changes: 50 additions & 0 deletions .github/workflows/fork-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Fork-side CI for heyi-co/superpowers.
# Upstream ships no .github/workflows, so this file is a clean fork addition
# with no sync conflict surface. It runs the fork-owned structural tests,
# the Codex packaging test, and shellcheck over fork-maintained shell.
name: fork-tests

# push is limited to the long-lived branches so a feature branch with an open
# PR runs once (pull_request), not twice, and tag pushes do not run at all.
# Shellcheck baseline validated with shellcheck 0.11.0; the runner's rolling
# version may surface new warnings after image upgrades.
on:
push:
branches: [main, dev]
pull_request:

jobs:
fork-tests:
# macos, not ubuntu: scripts/package-codex-plugin.sh (upstream code) uses
# bsdtar-only flags (--uid/--gid/--uname/--gname), so the packaging test
# can only run where bsdtar is the system tar. GNU tar compatibility is
# tracked in docs/superpowers/followups.md alongside upstream #1901/#1910.
runs-on: macos-latest
steps:
- uses: actions/checkout@v4

- name: Skill structural tests
run: |
bash tests/code-review-skill/test-code-review-integration.sh
bash tests/triaging-issues/test-triaging-issues-skill.sh
bash tests/decomposing-issues/test-decomposing-issues-skill.sh
bash tests/reconciling-issues/test-reconciling-issues-skill.sh
bash tests/working-from-issues/test-working-from-issues-skill.sh

- name: Codex package test
run: bash tests/codex/test-package-codex-plugin.sh

- name: Install shellcheck
run: command -v shellcheck >/dev/null || brew install shellcheck

- name: Shellcheck fork scripts and tests
run: |
shellcheck -S warning \
scripts/run-skill-evidence.sh \
scripts/package-codex-plugin.sh \
tests/code-review-skill/*.sh \
tests/triaging-issues/*.sh \
tests/decomposing-issues/*.sh \
tests/reconciling-issues/*.sh \
tests/working-from-issues/*.sh \
tests/codex/*.sh
8 changes: 8 additions & 0 deletions docs/superpowers/evidence/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ Prompts come verbatim from the skill's `pressure-scenarios.md`.

## Known limitations

- **GREEN transcript coverage is uneven.** Only `code-review` has committed
green transcripts (plus a no-skill control red). For the four
issue-workflow skills (`triaging-issues`, `decomposing-issues`,
`reconciling-issues`, `working-from-issues`) the committed transcripts are
RED baselines only; their green (skill-loaded) results in `evaluation.md`
are paraphrased rows annotated `paraphrased record, predates transcript
policy`. Backfilling green transcripts with the runner is tracked as
follow-up work.
- Transcripts dated 2026-07-02 predate the runner's path redaction and may
contain local home-directory paths or the operator's git identity from
session-internal commands (no credentials; verified at review). They are
Expand Down
127 changes: 127 additions & 0 deletions docs/superpowers/followups.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
# Follow-ups

This repository has GitHub issues disabled, so follow-up work is tracked
here. Add new entries at the bottom of the open list with a date and a
source; move finished entries to the Done section with the PR that closed
them. Entries are work items, not documentation — keep them short.

## Open

### 2026-07-06 · Backfill GREEN transcripts for the four issue-workflow skills

Source: 2026-07-06 fork evaluation.

Only `code-review` has committed green (skill-loaded) transcripts (8 green
plus a no-skill control red). `triaging-issues`, `decomposing-issues`,
`reconciling-issues`, and `working-from-issues` have RED baselines only;
their green results exist solely as paraphrased evaluation rows annotated
`paraphrased record, predates transcript policy`. The evidence tree's own
standard is transcript-or-it-didn't-happen. Scope: ~2 high-risk scenarios ×
2 harnesses per skill (~16 sessions) via `scripts/run-skill-evidence.sh`,
then replace the paraphrased rows and update the README disclosure.

### 2026-07-06 · code-review control baseline shows no failure

Source: 2026-07-06 fork evaluation.

The no-skill control found both planted bugs and emitted a JSON array; the
only delta vs the skill run was field naming. The current planted diff
(13 lines, 2 shallow bugs) proves schema compliance, not recall value, and
by the repo's own writing-skills standard a control that doesn't fail can't
justify the guidance. Author a harder planted diff (cross-file, async, or
removed-behavior bug) that the bare agent demonstrably misses.

### 2026-07-06 · Slim decomposing-issues: template-embedded instructions, quadruplicated rule, field bloat

Source: 2026-07-06 fork evaluation. Behavior-shaping; run pressure
scenarios before/after.

Three form problems: normative instructions live inside the output-template
fence (template-echo risk; writing-skills calls this form wrong), the
no-layer-split rule is stated four times (converge to one prose statement
plus one Red Flag), and the child-issue template carries 11 required fields
(`Release constraint` is never defined; `Parent coverage` overlaps `Covers
scope atoms`; SPIDR duplicates dimensions already listed).

### 2026-07-06 · reconciling-issues: undefined term, duplicated contract, misplaced red flag

Source: 2026-07-06 fork evaluation.

`needs-child-readback` is never defined in the skill that uses it; the
Parent Closure Contract semantics are written in both decomposing and
reconciling (pick one authority, reference from the other); the Red Flag
"Making working-from-issues own parent closure" polices another skill's
behavior and cannot be triggered by an agent running this one.

### 2026-07-06 · triaging-issues: axis overlap and undefined Confidence scale

Source: 2026-07-06 fork evaluation. Behavior-shaping; run pressure
scenarios before/after.

Classification and Actionability overlap heavily (`duplicate`,
`not-repo-owned`, security appear on both axes; legal combinations are
undefined; Classification's `unclear` has no actionability counterpart) —
converge to one axis plus modifiers. The `Confidence:` output field has no
defined scale, so its value cannot be verified.

### 2026-07-06 · Track upstream #1901/#1910; drop local packaging diff once merged

Source: 2026-07-06 fork evaluation (upstream survey).

The fork's changes to `scripts/package-codex-plugin.sh` and
`tests/codex/test-package-codex-plugin.sh` (worktree-safe git check, TZ=UTC
deterministic archives) correspond file-for-file to open upstream PRs
obra/superpowers#1901 and obra/superpowers#1910. Once upstream merges them,
verify semantic equivalence on the next sync and drop the local diff to
clear this conflict surface.

Related fact discovered by fork CI (2026-07-06): the script's tar.gz branch
uses bsdtar-only flags (`--uid/--gid/--uname/--gname`), so packaging only
works where bsdtar is the system tar (macOS). Fork CI runs on macos-latest
for this reason. If portability ever matters, GNU tar needs
`--owner=0 --group=0` instead — an upstream-shaped fix, not fork-local.

### 2026-07-06 · Upstream #1931/#1932/#1934 rewrite files carrying the fork's review-gate wiring

Source: 2026-07-06 fork evaluation (upstream survey).

obra's open skill-refactor PRs touch `requesting-code-review` and
`subagent-driven-development`, the two files carrying the fork's gate
wiring (P0-P2 blocking, code-review routing, dot-graph nodes). The first
sync after they merge will need a manual semantic replay of the fork
sections onto the new structure — a three-way merge will not resolve it —
followed by a rerun of `tests/code-review-skill/test-code-review-integration.sh`.

### 2026-07-06 · working-from-issues: wire branch finishing and persist triage artifacts

Source: 2026-07-06 fork evaluation. Behavior-shaping; run pressure
scenarios before/after.

The description promises "make a PR for" but no ready route reaches
`superpowers:finishing-a-development-branch`, and none of the four issue
skills reference `superpowers:using-git-worktrees` — debugging/docs-fix
paths edit the current branch directly. Triage Results, Issue
Decompositions, and Coverage Ledgers exist only in session output; define a
persistence path (for example `docs/superpowers/triage/<issue>.md`),
matching the brainstorming/writing-plans convention of committing
artifacts.

### 2026-07-06 · Run live evals for the 2026-07-06 behavior-shaping edits

Source: 2026-07-06 fork evaluation and the independent branch review of
`fix/eval-findings-2026-07-06`.

Three behavior-shaping edits shipped with structural tests and pressure
scenarios but no live session evidence: the Gate Semantics section
(circuit breaker, rerun label authority), the standing pre-authorization
escape hatch (including the vague-phrasing and repo-file negative cases;
reconciling/triaging/working-from have the shared prose but no scenarios of
their own yet), and the narrowed working-from-issues trigger (two
must-not-trigger negatives). Run the matching scenarios on both harnesses
with `scripts/run-skill-evidence.sh`, land transcripts under
`docs/superpowers/evidence/`, and add evaluation rows. Can be executed
together with the GREEN-transcript backfill entry.

## Done

(none yet)
6 changes: 6 additions & 0 deletions docs/superpowers/plans/2026-07-02-skill-evidence-and-style.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Skill Evidence Backfill and Code-Review Restyle Implementation Plan

> **Historical record (2026-07-02).** This plan is a dated snapshot and is not
> kept in sync with the tree. In particular, the runner script embedded in
> Task 1 reflects the version first landed; `scripts/run-skill-evidence.sh` is
> the live source of truth and has since gained session timeouts, atomic
> transcript writes, overwrite protection, and a `clean` subcommand.

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Backfill real RED-baseline evidence (with committed transcripts) for the four issue-workflow skills, fix the evaluation-record integrity defects, and restructure `skills/code-review` into a house-style shell plus a verbatim protocol file — per `docs/superpowers/specs/2026-07-02-skill-evidence-and-style-design.md`.
Expand Down
65 changes: 57 additions & 8 deletions scripts/run-skill-evidence.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,40 @@ REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
EVIDENCE_ROOT="$REPO_ROOT/docs/superpowers/evidence"
SCRATCH_ROOT="${SKILL_EVIDENCE_SCRATCH:-$HOME/.cache/skill-evidence-scratch}"
TODAY="$(date +%F)"
SESSION_TIMEOUT="${SKILL_EVIDENCE_TIMEOUT:-1800}"

usage() {
cat >&2 <<'USAGE'
Usage:
run-skill-evidence.sh preflight <claude|codex> <red|green>
run-skill-evidence.sh run <claude|codex> <red|green> <skill> <scenario-slug> <prompt-file>
run-skill-evidence.sh clean

RED = scratch config, plugin absent (baseline)
GREEN = scratch config with the working-tree plugin loaded (verification)
The transcript's repo-relative path is printed on the last stdout line.
Sessions are killed after SKILL_EVIDENCE_TIMEOUT seconds (default 1800).
clean removes the scratch root, including the credential copies seeded
into scratch config dirs; rerun any phase to reseed.
USAGE
exit 2
}

note() { echo "[run-skill-evidence] $*" >&2; }

TMP_TRANSCRIPT=""
trap '[[ -n "$TMP_TRANSCRIPT" ]] && rm -f "$TMP_TRANSCRIPT"' EXIT

with_timeout() { # run "$@" under SESSION_TIMEOUT; timeout exits 124/142
if command -v timeout >/dev/null 2>&1; then
timeout "$SESSION_TIMEOUT" "$@"
else
# macOS ships no timeout(1); perl is part of the base system.
perl -e 'alarm shift; exec @ARGV or die "exec failed: $!"' \
"$SESSION_TIMEOUT" "$@"
fi
}

make_workspace() {
local dir
dir="$(mktemp -d "${TMPDIR:-/tmp}/skill-evidence-ws.XXXXXX")"
Expand All @@ -42,6 +60,7 @@ claude_env_dir() { # $1 = red|green
local dir="$SCRATCH_ROOT/claude-$1"
if [[ ! -d "$dir" ]]; then
mkdir -p "$dir"
chmod 700 "$SCRATCH_ROOT" "$dir"
# Seed onboarding/user state so headless runs skip first-run prompts.
if [[ -f "$HOME/.claude.json" ]]; then
cp "$HOME/.claude.json" "$dir/.claude.json"
Expand All @@ -63,6 +82,7 @@ codex_env_dir() { # $1 = red|green
local dir="$SCRATCH_ROOT/codex-$1"
if [[ ! -d "$dir" ]]; then
mkdir -p "$dir"
chmod 700 "$SCRATCH_ROOT" "$dir"
# Codex keeps credentials in CODEX_HOME; seed auth only. No config.toml:
# the scratch env must not inherit plugin or marketplace configuration.
if [[ -f "$HOME/.codex/auth.json" ]]; then
Expand Down Expand Up @@ -104,6 +124,10 @@ harness_version() { # $1 = claude|codex
run_session() { # $1 harness, $2 phase, $3 prompt-file, $4 transcript-path
local harness="$1" phase="$2" prompt_file="$3" transcript="$4"
local ws cfg load_note version
command -v "$harness" >/dev/null 2>&1 || {
note "FATAL: $harness CLI not found in PATH"
exit 1
}
ws="$(make_workspace)"
version="$(harness_version "$harness")"

Expand All @@ -125,7 +149,11 @@ run_session() { # $1 harness, $2 phase, $3 prompt-file, $4 transcript-path
fi
fi

# Build the transcript in a same-directory temp file and mv it into place
# once complete, so an interrupted session never leaves a half-written
# file at the final path.
mkdir -p "$(dirname "$transcript")"
TMP_TRANSCRIPT="$(mktemp "$(dirname "$transcript")/.transcript.XXXXXX")"
{
echo "# Evidence transcript"
echo
Expand All @@ -145,35 +173,42 @@ run_session() { # $1 harness, $2 phase, $3 prompt-file, $4 transcript-path
echo "## Session output"
echo
echo '````text'
} > "$transcript"
} > "$TMP_TRANSCRIPT"

# Session output is redacted before it reaches the transcript: local
# home-directory paths become "~" so committed evidence does not carry
# operator paths. With pipefail, rc still reflects the session, not sed.
# Sessions run under with_timeout so a hung CLI cannot block forever
# (timeout exit codes 124/142 land in the transcript like any failure).
local rc=0
if [[ "$harness" == "claude" ]]; then
if [[ "$phase" == "green" ]]; then
( cd "$ws" && CLAUDE_CONFIG_DIR="$cfg" claude -p --output-format text \
( cd "$ws" && with_timeout env CLAUDE_CONFIG_DIR="$cfg" \
claude -p --output-format text \
--plugin-dir "$REPO_ROOT" < "$prompt_file" ) 2>&1 \
| sed "s|$HOME|~|g" >> "$transcript" || rc=$?
| sed "s|$HOME|~|g" >> "$TMP_TRANSCRIPT" || rc=$?
else
( cd "$ws" && CLAUDE_CONFIG_DIR="$cfg" claude -p --output-format text \
( cd "$ws" && with_timeout env CLAUDE_CONFIG_DIR="$cfg" \
claude -p --output-format text \
< "$prompt_file" ) 2>&1 \
| sed "s|$HOME|~|g" >> "$transcript" || rc=$?
| sed "s|$HOME|~|g" >> "$TMP_TRANSCRIPT" || rc=$?
fi
else
# Harden the session: run model-generated shell commands in a read-only
# sandbox (-s read-only) and disable account/MCP connectors (--disable apps,
# the current name for the connectors feature) so the session cannot reach
# external mutating tools such as the GitHub connector.
( cd "$ws" && CODEX_HOME="$cfg" codex exec -s read-only --disable apps - < "$prompt_file" ) 2>&1 \
| sed "s|$HOME|~|g" >> "$transcript" || rc=$?
( cd "$ws" && with_timeout env CODEX_HOME="$cfg" \
codex exec -s read-only --disable apps - < "$prompt_file" ) 2>&1 \
| sed "s|$HOME|~|g" >> "$TMP_TRANSCRIPT" || rc=$?
fi
{
echo '````'
echo
echo "- Exit code: $rc"
} >> "$transcript"
} >> "$TMP_TRANSCRIPT"
mv "$TMP_TRANSCRIPT" "$transcript"
TMP_TRANSCRIPT=""
if [[ "$rc" -ne 0 ]]; then
note "session exited non-zero ($rc); recorded in transcript"
fi
Expand Down Expand Up @@ -203,9 +238,23 @@ case "$cmd" in
harness="$2"; phase="$3"; skill="$4"; slug="$5"; prompt_file="$6"
[[ -f "$prompt_file" ]] || { note "prompt file not found: $prompt_file"; exit 1; }
transcript="$EVIDENCE_ROOT/$skill/$TODAY-$slug-$harness-$phase.md"
if [[ -e "$transcript" ]]; then
note "FATAL: transcript already exists: $transcript"
note "Evidence files are append-only history; rerun with a different scenario slug."
exit 1
fi
run_session "$harness" "$phase" "$prompt_file" "$transcript"
echo "docs/superpowers/evidence/$skill/$TODAY-$slug-$harness-$phase.md"
;;
clean)
[[ $# -eq 1 ]] || usage
if [[ -d "$SCRATCH_ROOT" ]]; then
rm -rf "$SCRATCH_ROOT"
note "removed scratch root (including seeded credential copies): $SCRATCH_ROOT"
else
note "nothing to clean: $SCRATCH_ROOT"
fi
;;
*)
usage
;;
Expand Down
Loading
Loading