Files
superpowers/tests/claude-code/test-sdd-workspace.sh
Drew Ritter cdcadda4be refactor(sdd): platform-owned dispatch hints — shared scripts carry no Codex literals
Responds to maintainer review of this branch: the dispatch-hint lines
were hardcoded Codex strings inside shared skill tooling that every
harness runs.

The per-role hint lines now live in a platform-owned data file,
skills/using-superpowers/references/codex-dispatch.hints, and the
task-brief/review-package scripts only relay the current role's line.
The relay is suppressed when CLAUDECODE is set (Claude Code's dispatch
templates already carry model selection) and on any harness with no
hints file; unknown harnesses fail toward printing, because a silent
no-op in the environment that needs the hint is the failure mode this
mechanism exists to prevent. Printing at the moment of dispatch is
load-bearing: skill text loaded at session start does not survive
context compaction, but script output reprints every round.

codex-tools.md's SDD dispatch section shrinks to the behavioral rules
(fork_turns: "none" always; copy the printed hint verbatim; reviewer
tier never exceeds implementer tier; no effort bumps; the <=0.144
inheritance fallback) and points at the hints file for values.

Tests cover the relay path, the per-role efforts, and the new
CLAUDECODE suppression case.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 15:31:50 -07:00

258 lines
9.3 KiB
Bash
Executable File

#!/usr/bin/env bash
# Tests for the SDD workspace: scripts/sdd-workspace resolves a self-ignoring,
# PER-PLAN working-tree directory for SDD artifacts, and the SDD scripts write
# into their plan's directory.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
SDD_SCRIPTS="$REPO_ROOT/skills/subagent-driven-development/scripts"
FAILURES=0
TEST_ROOT=""
pass() { echo " [PASS] $1"; }
fail() {
echo " [FAIL] $1"
FAILURES=$((FAILURES + 1))
}
cleanup() {
if [[ -n "$TEST_ROOT" && -d "$TEST_ROOT" ]]; then
rm -rf "$TEST_ROOT"
fi
}
main() {
echo "=== Test: sdd-workspace ==="
TEST_ROOT="$(mktemp -d)"
trap cleanup EXIT
# Resolve repo to its physical path so string comparisons match the
# helper's output (git rev-parse --show-toplevel resolves symlinks; on
# macOS mktemp lives under /var -> /private/var).
git init -q -b main "$TEST_ROOT/repo"
local repo
repo="$(cd "$TEST_ROOT/repo" && git rev-parse --show-toplevel)"
cat > "$repo/plan-a.md" <<'PLAN'
# Plan A
## Task 1: First thing
Do the first thing.
PLAN
cat > "$repo/plan-b.md" <<'PLAN'
# Plan B
## Task 1: Other thing
Do the other thing.
PLAN
# --- argument validation ---
local rc=0
(cd "$repo" && "$SDD_SCRIPTS/sdd-workspace" >/dev/null 2>&1) || rc=$?
if [[ "$rc" -eq 2 ]]; then
pass "sdd-workspace without a plan errors with exit 2"
else
fail "sdd-workspace without a plan errors with exit 2"
echo " exit: $rc"
fi
rc=0
(cd "$repo" && "$SDD_SCRIPTS/sdd-workspace" no-such-plan.md >/dev/null 2>&1) || rc=$?
if [[ "$rc" -eq 2 ]]; then
pass "sdd-workspace with a missing plan file errors with exit 2"
else
fail "sdd-workspace with a missing plan file errors with exit 2"
echo " exit: $rc"
fi
# --- per-plan resolution ---
local dir_a dir_b
dir_a="$(cd "$repo" && "$SDD_SCRIPTS/sdd-workspace" plan-a.md)"
dir_b="$(cd "$repo" && "$SDD_SCRIPTS/sdd-workspace" plan-b.md)"
if [[ "$dir_a" == "$repo/.superpowers/sdd/plan-a" ]]; then
pass "prints <repo-root>/.superpowers/sdd/<plan-basename>"
else
fail "prints <repo-root>/.superpowers/sdd/<plan-basename>"
echo " got: $dir_a"
fi
if [[ "$dir_a" != "$dir_b" && -d "$dir_a" && -d "$dir_b" ]]; then
pass "two plans resolve to two distinct directories"
else
fail "two plans resolve to two distinct directories"
echo " a: $dir_a"
echo " b: $dir_b"
fi
if [[ -f "$repo/.superpowers/sdd/.gitignore" && "$(cat "$repo/.superpowers/sdd/.gitignore")" == "*" ]]; then
pass "self-ignoring .gitignore created at .superpowers/sdd/ with '*'"
else
fail "self-ignoring .gitignore created at .superpowers/sdd/ with '*'"
fi
printf 'x\n' > "$dir_a/artifact.md"
local status
status="$(cd "$repo" && git status --porcelain)"
# plan-a.md/plan-b.md are intentionally untracked fixture files; only the
# workspace must be invisible.
if [[ "$status" != *".superpowers"* ]]; then
pass "workspace invisible to git status"
else
fail "workspace invisible to git status"
echo " status: $status"
fi
( cd "$repo" && git add -A )
local staged
staged="$(cd "$repo" && git diff --cached --name-only)"
if [[ "$staged" != *".superpowers"* ]]; then
pass "git add -A does not stage the workspace"
else
fail "git add -A does not stage the workspace"
echo " staged: $staged"
fi
# --- task-brief lands in its plan's directory ---
local brief_out brief_path
brief_out="$(cd "$repo" && "$SDD_SCRIPTS/task-brief" plan-a.md 1)"
brief_path="$(printf '%s\n' "$brief_out" | sed -n 's/^wrote \(.*\): [0-9][0-9]* lines$/\1/p')"
if [[ "$brief_path" == "$repo/.superpowers/sdd/plan-a/task-1-brief.md" ]]; then
pass "task-brief writes its brief under the plan's workspace"
else
fail "task-brief writes its brief under the plan's workspace"
echo " got: $brief_path"
fi
# --- review-package takes the plan first and lands in its directory ---
local git_id=(-c user.email=t@example.com -c user.name=t -c commit.gpgsign=false)
( cd "$repo" \
&& git "${git_id[@]}" commit -qm c1 \
&& printf 'y\n' > f && git add f \
&& git "${git_id[@]}" commit -qm c2 )
local rp_out rp_path
rp_out="$(cd "$repo" && "$SDD_SCRIPTS/review-package" plan-a.md HEAD~1 HEAD)"
rp_path="$(printf '%s\n' "$rp_out" | sed -n 's/^wrote \(.*\): [0-9].*$/\1/p')"
case "$rp_path" in
"$repo/.superpowers/sdd/plan-a/review-"*.diff)
pass "review-package writes its diff under the plan's workspace" ;;
*)
fail "review-package writes its diff under the plan's workspace"
echo " got: $rp_path"
;;
esac
rc=0
(cd "$repo" && "$SDD_SCRIPTS/review-package" HEAD~1 HEAD >/dev/null 2>&1) || rc=$?
if [[ "$rc" -eq 2 ]]; then
pass "review-package without a plan errors with exit 2"
else
fail "review-package without a plan errors with exit 2"
echo " exit: $rc"
fi
local rp_explicit
rp_explicit="$(cd "$repo" && "$SDD_SCRIPTS/review-package" plan-a.md HEAD~1 HEAD "$TEST_ROOT/explicit.diff")"
if [[ -s "$TEST_ROOT/explicit.diff" && "$rp_explicit" == *"$TEST_ROOT/explicit.diff"* ]]; then
pass "review-package honors an explicit OUTFILE"
else
fail "review-package honors an explicit OUTFILE"
echo " got: $rp_explicit"
fi
# --- platform dispatch hints ride the script output (suppressed on CC) ---
local brief_hint
brief_hint="$(cd "$repo" && env -u CLAUDECODE "$SDD_SCRIPTS/task-brief" plan-a.md 1)"
if [[ "$brief_hint" == *"dispatch (spawn_agent): fork_turns=none model=gpt-5.6-terra reasoning_effort=high"* ]]; then
pass "task-brief relays the implementer dispatch hint off Claude Code"
else
fail "task-brief relays the implementer dispatch hint off Claude Code"
echo " got: $brief_hint"
fi
local rp_hint
rp_hint="$(cd "$repo" && env -u CLAUDECODE "$SDD_SCRIPTS/review-package" plan-a.md HEAD~1 HEAD)"
if [[ "$rp_hint" == *"dispatch (spawn_agent): fork_turns=none model=gpt-5.6-terra reasoning_effort=high"* ]]; then
pass "review-package relays the default-role hint off Claude Code"
else
fail "review-package relays the default-role hint off Claude Code"
echo " got: $rp_hint"
fi
local rp_rereview
rp_rereview="$(cd "$repo" && env -u CLAUDECODE "$SDD_SCRIPTS/review-package" --role re-review plan-a.md HEAD~1 HEAD)"
if [[ "$rp_rereview" == *"dispatch (spawn_agent): fork_turns=none model=gpt-5.6-terra reasoning_effort=medium"* ]]; then
pass "review-package --role re-review relays the medium-effort hint"
else
fail "review-package --role re-review relays the medium-effort hint"
echo " got: $rp_rereview"
fi
local rp_final
rp_final="$(cd "$repo" && env -u CLAUDECODE "$SDD_SCRIPTS/review-package" --role final-review plan-a.md HEAD~1 HEAD)"
if [[ "$rp_final" == *"dispatch (spawn_agent): fork_turns=none model=gpt-5.6-terra reasoning_effort=high"* ]]; then
pass "review-package --role final-review relays the high-effort hint"
else
fail "review-package --role final-review relays the high-effort hint"
echo " got: $rp_final"
fi
local brief_cc rp_cc
brief_cc="$(cd "$repo" && CLAUDECODE=1 "$SDD_SCRIPTS/task-brief" plan-a.md 1)"
rp_cc="$(cd "$repo" && CLAUDECODE=1 "$SDD_SCRIPTS/review-package" plan-a.md HEAD~1 HEAD)"
if [[ "$brief_cc" != *"dispatch (spawn_agent)"* && "$rp_cc" != *"dispatch (spawn_agent)"* ]]; then
pass "dispatch hints are suppressed under Claude Code (CLAUDECODE set)"
else
fail "dispatch hints are suppressed under Claude Code (CLAUDECODE set)"
echo " brief: $brief_cc"
echo " rp: $rp_cc"
fi
rc=0
(cd "$repo" && "$SDD_SCRIPTS/review-package" --role bogus plan-a.md HEAD~1 HEAD >/dev/null 2>&1) || rc=$?
if [[ "$rc" -eq 2 ]]; then
pass "review-package rejects an unknown --role with exit 2"
else
fail "review-package rejects an unknown --role with exit 2"
echo " exit: $rc"
fi
# --- Worktree isolation: a linked worktree resolves its own workspace ---
local wt="$TEST_ROOT/wt"
( cd "$repo" && git worktree add -q "$wt" -b wt-feature )
local wt_root wt_dir
wt_root="$(cd "$wt" && git rev-parse --show-toplevel)"
wt_dir="$(cd "$wt" && "$SDD_SCRIPTS/sdd-workspace" plan-a.md)"
if [[ "$wt_dir" == "$wt_root/.superpowers/sdd/plan-a" && "$wt_dir" != "$dir_a" ]]; then
pass "linked worktree resolves its own distinct workspace"
else
fail "linked worktree resolves its own distinct workspace"
echo " main: $dir_a"
echo " wt: $wt_dir"
fi
printf 'y\n' > "$wt_dir/artifact.md"
local wt_status
wt_status="$(cd "$wt" && git status --porcelain)"
if [[ "$wt_status" != *".superpowers"* ]]; then
pass "worktree workspace invisible to git status"
else
fail "worktree workspace invisible to git status"
echo " status: $wt_status"
fi
echo ""
if [[ "$FAILURES" -ne 0 ]]; then
echo "FAILED: $FAILURES assertion(s)."
exit 1
fi
echo "PASS"
}
main "$@"