#!/usr/bin/env zsh set -eu repo_dir="${0:A:h}" source "$repo_dir/func" failures=0 assert_equal() { local expected="$1" local actual="$2" local label="$3" if [ "$actual" != "$expected" ]; then print -u2 -- "FAIL: $label (expected '$expected', got '$actual')" failures=$((failures + 1)) fi } assert_contains() { local output="$1" local expected="$2" local label="$3" if [[ "$output" != *"$expected"* ]]; then print -u2 -- "FAIL: $label (missing '$expected')" failures=$((failures + 1)) fi } assert_not_contains() { local output="$1" local unexpected="$2" local label="$3" if [[ "$output" == *"$unexpected"* ]]; then print -u2 -- "FAIL: $label (unexpected '$unexpected')" failures=$((failures + 1)) fi } preflight_fixture_dir="$(mktemp -d "${TMPDIR:-/tmp}/plan-build-preflight.XXXXXX")" trap 'rm -rf -- "$preflight_fixture_dir"' EXIT command git init -q "$preflight_fixture_dir/worktree" command git init -q --bare "$preflight_fixture_dir/bare.git" (cd "$preflight_fixture_dir/worktree" && _plan_build_is_worktree) && rc=0 || rc=$? assert_equal "0" "$rc" "architect preflight accepts normal worktree" (cd "$preflight_fixture_dir/bare.git" && _plan_build_is_worktree) && rc=0 || rc=$? assert_equal "1" "$rc" "architect preflight rejects bare repository" plugin_state() { printf '%s\n' "$1" | _plan_build_superpowers_state } assert_equal "enabled" "$(plugin_state '[{"id":"superpowers@claude-plugins-official","enabled":true}]')" "compact enabled JSON" assert_equal "disabled" "$(plugin_state $'[\n {\n "enabled": false,\n "id": "superpowers@claude-plugins-official"\n }\n]')" "reordered disabled JSON" assert_equal "enabled" "$(plugin_state $'[\n {"enabled": false, "id": "other@market"},\n {"enabled": true, "id": "superpowers@claude-plugins-official"}\n]')" "multiple plugin JSON" assert_equal "missing" "$(plugin_state '[{"id":"coderabbit@claude-plugins-official","enabled":true}]')" "missing plugin JSON" assert_equal "installed" "$(plugin_state '[{"id":"superpowers@claude-plugins-official"}]')" "malformed plugin JSON" output="$(plan_build --brainstorm --writing-plan 2>&1)" && rc=0 || rc=$? assert_equal "1" "$rc" "mutually exclusive flags status" assert_contains "$output" "mutually exclusive" "mutually exclusive flags message" output="$(plan_build --brainstorm --brainstorm 2>&1)" && rc=0 || rc=$? assert_equal "1" "$rc" "duplicate brainstorm status" assert_contains "$output" "Duplicate argument: --brainstorm" "duplicate brainstorm message" output="$(plan_build --writing-plan --writing-plan 2>&1)" && rc=0 || rc=$? assert_equal "1" "$rc" "duplicate writing-plan status" assert_contains "$output" "Duplicate argument: --writing-plan" "duplicate writing-plan message" output="$(plan_build --v2 2>&1)" && rc=0 || rc=$? assert_equal "1" "$rc" "v2 unknown argument status" assert_contains "$output" "Unknown argument: --v2" "v2 unknown argument message" for args expected label in \ "--architect --architect" "--architect" "duplicate architect" \ "--architect --new --new" "--new" "duplicate new"; do output="$(plan_build ${(z)args} 2>&1)" && rc=0 || rc=$? assert_equal "1" "$rc" "$label status" assert_contains "$output" "Duplicate argument: $expected" "$label message" assert_contains "$output" "plan_build --architect [--new] [--yolo]" "$label usage" done for args in \ "--architect --prompt" \ "--architect --brainstorm" \ "--architect --writing-plan"; do output="$(plan_build ${(z)args} 2>&1)" && rc=0 || rc=$? assert_equal "1" "$rc" "$args incompatible status" assert_contains "$output" "may combine only with --new and --yolo" "$args incompatible message" done output="$(plan_build --new 2>&1)" && rc=0 || rc=$? assert_equal "1" "$rc" "orphan new status" assert_contains "$output" "--new requires --architect" "orphan new message" export CLAUDE_CODE_SAFE_MODE=1 output="$(_plan_build_superpowers_preflight 2>&1)" && rc=0 || rc=$? unset CLAUDE_CODE_SAFE_MODE assert_equal "1" "$rc" "safe mode status" assert_contains "$output" "safe mode disables Superpowers" "safe mode message" require_cli() { return 0; } _plan_build_superpowers_preflight() { return 0; } architect_preflight_calls=0 _plan_build_architect_preflight() { architect_preflight_calls=$((architect_preflight_calls + 1)) return 0 } claude() { printf 'CLAUDE_ARGS:' printf ' <%s>' "$@" printf '\n' } output="$(printf 'build feature\nEOF\n' | plan_build --writing-plan --yolo 2>&1)" && rc=0 || rc=$? assert_equal "0" "$rc" "writing-plan launch status" assert_contains "$output" "Planning mode: writing-plan" "writing-plan prompt" assert_contains "$output" "<--yolo>" "yolo forwarding" output="$(printf 'build feature\nEOF\n' | plan_build --brainstorm 2>&1)" && rc=0 || rc=$? assert_equal "0" "$rc" "brainstorm launch status" assert_contains "$output" "Planning mode: brainstorm" "brainstorm prompt" output="$(printf 'build feature\nEOF\n' | plan_build 2>&1)" && rc=0 || rc=$? assert_equal "0" "$rc" "standard launch status" assert_contains "$output" "Planning mode: standard" "standard prompt" output="$(printf 'design feature\nEOF\n' | plan_build --architect 2>&1)" && rc=0 || rc=$? assert_equal "0" "$rc" "architect launch status" assert_contains "$output" "~/.claude/skills/plan-build-architect/SKILL.md" "architect skill path" assert_contains "$output" "documentation-first architect/orchestrator role" "architect role boundary" assert_contains "$output" "design feature" "architect payload" assert_contains "$output" "Start mode: safe-resume-detection" "architect resume mode" output="$(printf 'fresh design\nEOF\n' | plan_build --architect --new 2>&1)" && rc=0 || rc=$? assert_equal "0" "$rc" "architect new launch status" assert_contains "$output" "Start mode: archive-and-start-new" "architect new mode" assert_contains "$output" "fresh design" "architect new payload" output="$(printf 'fast design\nEOF\n' | plan_build --architect --yolo 2>&1)" && rc=0 || rc=$? assert_equal "0" "$rc" "architect yolo launch status" assert_contains "$output" "<--yolo>" "architect yolo forwarding" assert_contains "$output" "every gate even when --yolo is active" "architect yolo gates" output="$(printf 'EOF\n' | plan_build --architect 2>&1)" && rc=0 || rc=$? assert_equal "1" "$rc" "architect empty payload status" assert_contains "$output" "Payload was empty" "architect empty payload message" _plan_build_architect_preflight() { echo "architect preflight failed" return 1 } output="$(printf 'must not be read\nEOF\n' | plan_build --architect 2>&1)" && rc=0 || rc=$? assert_equal "1" "$rc" "architect preflight failure status" assert_contains "$output" "architect preflight failed" "architect preflight failure message" assert_not_contains "$output" "Reading payload" "architect preflight before payload" assert_not_contains "$output" "CLAUDE_ARGS" "architect preflight prevents launch" if [ "$failures" -ne 0 ]; then exit 1 fi print -- "PASS: plan_build tests"