ktg-plugin-marketplace/plugins/ultraplan-local/verify.sh

174 lines
5.4 KiB
Bash
Executable file

#!/usr/bin/env bash
# verify.sh — automate brief Success Criteria SC1-SC7 for the voyage rebrand.
# Bash 3.2 compatible (no associative arrays, no readarray, no |&).
#
# Modes:
# --quick (default) artifact-presence + manifest checks; no e2e pipeline run
# --live runs examples/01-add-verbose-flag/ pipeline; diffs against baseline
set -u
MODE="quick"
if [ "${1:-}" = "--live" ]; then
MODE="live"
elif [ "${1:-}" = "--quick" ]; then
MODE="quick"
elif [ -n "${1:-}" ]; then
echo "usage: $0 [--quick|--live]" >&2
exit 2
fi
PASS=0
FAIL=0
pass() { echo "[PASS] SC$1$2"; PASS=$((PASS + 1)); }
fail() { echo "[FAIL] SC$1$2"; FAIL=$((FAIL + 1)); exit 1; }
# Tracked-file exclusions (paths preserved verbatim from old name).
# - CHANGELOG/TRADEMARKS/MIGRATION legitimately reference the old name.
# - architecture-discovery.mjs + project-discovery.mjs are Q8 exceptions
# pointing at the upstream "ultra-cc-architect" producer slot.
# - verify.sh self-references the forbidden patterns to detect them.
# - .claude/, .session-state.local.json, *.local.md handled via gitignore.
exclude_path() {
case "$1" in
*CHANGELOG.md|*TRADEMARKS.md|*MIGRATION.md) return 0 ;;
*lib/validators/architecture-discovery.mjs) return 0 ;;
*lib/parsers/project-discovery.mjs) return 0 ;;
*verify.sh) return 0 ;;
*.local.md|*.local.json) return 0 ;;
esac
return 1
}
tracked_sources() {
git ls-files \
'*.md' '*.mjs' '*.json' '*.sh' '*.yml' '*.yaml' 2>/dev/null
}
# ---------------- SC1: zero `ultra` references in tracked source files ----------------
sc1_hits=""
while IFS= read -r f; do
[ -z "$f" ] && continue
exclude_path "$f" && continue
[ -f "$f" ] || continue
if grep -q 'ultra' "$f" 2>/dev/null; then
sc1_hits="${sc1_hits}${f}
"
fi
done <<EOF
$(tracked_sources)
EOF
if [ -z "$sc1_hits" ]; then
pass 1 "no 'ultra' references in tracked source"
else
echo " Files with 'ultra':"
printf '%s' "$sc1_hits" | sed 's/^/ /'
fail 1 "ultra references remain"
fi
# ---------------- SC2: zero `-local` suffix references ----------------
sc2_hits=""
while IFS= read -r f; do
[ -z "$f" ] && continue
exclude_path "$f" && continue
[ -f "$f" ] || continue
if grep -q -- '-local' "$f" 2>/dev/null; then
sc2_hits="${sc2_hits}${f}
"
fi
done <<EOF
$(tracked_sources)
EOF
if [ -z "$sc2_hits" ]; then
pass 2 "no '-local' suffix in tracked source"
else
echo " Files with '-local':"
printf '%s' "$sc2_hits" | sed 's/^/ /'
fail 2 "-local references remain"
fi
# ---------------- SC3: all seven trek-commands present and parseable ----------------
sc3_missing=""
for cmd in trekbrief trekresearch trekplan trekexecute trekreview trekcontinue trekendsession; do
f="commands/${cmd}.md"
if [ ! -f "$f" ]; then
sc3_missing="$sc3_missing $cmd:missing"
continue
fi
if ! grep -q "^name: ${cmd}$" "$f"; then
sc3_missing="$sc3_missing $cmd:bad-frontmatter"
fi
done
if [ -z "$sc3_missing" ]; then
pass 3 "all seven /trek* commands present and parseable"
else
echo " Issues:$sc3_missing"
fail 3 "trek command files missing or malformed"
fi
# ---------------- SC4: no legacy ultra*-local.md command files ----------------
legacy_count=$(ls commands/ultra*-local.md 2>/dev/null | wc -l | tr -d ' ')
if [ "$legacy_count" = "0" ]; then
pass 4 "no legacy commands/ultra*-local.md files"
else
fail 4 "$legacy_count legacy ultra*-local.md files remain"
fi
# ---------------- SC5: plugin.json name=voyage, version >= 4.0.0 ----------------
manifest=".claude-plugin/plugin.json"
if [ ! -f "$manifest" ]; then
fail 5 "$manifest not found"
fi
manifest_name=$(grep -E '"name"[[:space:]]*:' "$manifest" | head -1 | sed -E 's/.*"name"[[:space:]]*:[[:space:]]*"([^"]+)".*/\1/')
manifest_version=$(grep -E '"version"[[:space:]]*:' "$manifest" | head -1 | sed -E 's/.*"version"[[:space:]]*:[[:space:]]*"([^"]+)".*/\1/')
manifest_ok=1
if [ "$manifest_name" != "voyage" ]; then
manifest_ok=0
fi
case "$manifest_version" in
4.*|5.*|6.*|7.*|8.*|9.*) ;;
*) manifest_ok=0 ;;
esac
if [ "$manifest_ok" = "1" ]; then
pass 5 "plugin.json reports name=$manifest_name version=$manifest_version"
else
echo " Got name=$manifest_name version=$manifest_version (expected name=voyage version>=4.0.0)"
fail 5 "plugin.json mismatch"
fi
# ---------------- SC6: npm test exits 0 ----------------
if npm test >/tmp/voyage-verify-npm-test.log 2>&1; then
test_count=$(grep -E '^[^[:alnum:]]*tests[[:space:]]+[0-9]+' /tmp/voyage-verify-npm-test.log | head -1 | grep -oE '[0-9]+' | head -1)
pass 6 "npm test exits 0 (${test_count:-?} tests)"
else
echo " See /tmp/voyage-verify-npm-test.log"
fail 6 "npm test failed"
fi
# ---------------- SC7: end-to-end smoke ----------------
if [ "$MODE" = "live" ]; then
if [ ! -d "examples/01-add-verbose-flag" ]; then
fail 7 "examples/01-add-verbose-flag not found"
fi
echo " --live mode: pipeline run not yet wired (Step 16+ work)"
pass 7 "examples/01-add-verbose-flag present (live-run TBD)"
else
if [ -d "examples/01-add-verbose-flag" ] || [ -d "examples" ]; then
pass 7 "examples/ artifact present (--quick proxy; use --live for pipeline)"
else
fail 7 "examples/ directory missing"
fi
fi
echo ""
echo "=================================================================="
echo " verify.sh summary: $PASS pass, $FAIL fail (mode: $MODE)"
echo "=================================================================="
exit 0