#!/usr/bin/env bash set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" SCRIPT_UNDER_TEST="$REPO_ROOT/scripts/package-codex-plugin.sh" FAILURES=0 TEST_ROOT="$(mktemp -d)" cleanup() { rm -rf "$TEST_ROOT" } trap cleanup EXIT pass() { echo " [PASS] $1" } fail() { echo " [FAIL] $1" FAILURES=$((FAILURES + 1)) } assert_equals() { local actual="$1" local expected="$2" local description="$3" if [[ "$actual" == "$expected" ]]; then pass "$description" else fail "$description" echo " expected: $expected" echo " actual: $actual" fi } assert_contains() { local haystack="$1" local needle="$2" local description="$3" if printf '%s' "$haystack" | grep -Fq -- "$needle"; then pass "$description" else fail "$description" echo " expected to find: $needle" fi } assert_not_matches() { local haystack="$1" local pattern="$2" local description="$3" if printf '%s' "$haystack" | grep -Eq -- "$pattern"; then fail "$description" echo " did not expect to match: $pattern" else pass "$description" fi } write_metadata_fixture() { local destination="$1" local skill while IFS= read -r skill; do mkdir -p "$destination/skills/$skill/agents" cat >"$destination/skills/$skill/agents/openai.yaml" <&1)"; then pass "package script exits successfully" else fail "package script exits successfully" printf '%s\n' "$output" | sed 's/^/ /' fi if [[ -f "$archive" ]]; then pass "package script writes archive" else fail "package script writes archive" fi assert_contains "$output" "Archive:" "reports archive path" assert_contains "$output" "SHA-256:" "reports archive checksum" mkdir -p "$extracted" tar -xzf "$archive" -C "$extracted" archive_paths="$(tar -tzf "$archive" | sort)" unexpected_pattern='(^superpowers/|^\.agents/|^hooks/|package\.json$|^\.git|^\.pytest_cache|^\.ruff_cache|^scripts/|^tests/|^docs/|^evals/|^lib/|^\.claude|^\.cursor|^\.kimi|^\.opencode|^\.pi|^AGENTS\.md$|^CLAUDE\.md$|^GEMINI\.md$|^RELEASE-NOTES\.md$|^CHANGELOG\.md$)' assert_not_matches "$archive_paths" "$unexpected_pattern" "archive excludes source-only paths" assert_contains "$archive_paths" ".codex-plugin/plugin.json" "archive includes Codex manifest" assert_contains "$archive_paths" "skills/brainstorming/SKILL.md" "archive includes skills" assert_contains "$archive_paths" "skills/brainstorming/agents/openai.yaml" "archive includes OpenAI skill metadata" assert_contains "$archive_paths" "assets/app-icon.png" "archive includes app icon" assert_contains "$archive_paths" "assets/superpowers-small.svg" "archive includes composer icon" manifest_summary="$(tar -xOf "$archive" .codex-plugin/plugin.json | python3 -c 'import json,sys; data=json.load(sys.stdin); print("\t".join([data["name"], data["version"], data["skills"], str(data.get("hooks"))]))')" expected_version="$(python3 -c 'import json; print(json.load(open("'"$REPO_ROOT"'/.codex-plugin/plugin.json"))["version"])')" assert_equals "$manifest_summary" "superpowers $expected_version ./skills/ None" "archive manifest is current and hook-free" skill_count="$(find "$extracted/skills" -mindepth 1 -maxdepth 1 -type d | wc -l | tr -d ' ')" metadata_count="$(find "$extracted/skills" -path '*/agents/openai.yaml' -type f | wc -l | tr -d ' ')" assert_equals "$metadata_count" "$skill_count" "every packaged skill has OpenAI metadata" task_brief_mode="$(tar -tzvf "$archive" skills/subagent-driven-development/scripts/task-brief | awk '{print $1}')" assert_equals "$task_brief_mode" "-rwxr-xr-x" "archive preserves executable script mode" metadata_times="$(tar -tzvf "$archive" | awk '{print $6, $7, $8}' | sort -u)" assert_equals "$metadata_times" "Dec 31 1969" "archive normalizes entry timestamps" if [[ "$FAILURES" -eq 0 ]]; then echo "All Codex package archive tests passed" else echo "$FAILURES Codex package archive test(s) failed" exit 1 fi