#!/usr/bin/env bash # Structural validation for the Makepad game skills pack. set -uo pipefail script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" fail=0 warn=0 err() { printf 'FAIL %s\n' "$*"; fail=$((fail + 1)); } wrn() { printf 'WARN %s\n' "$*"; warn=$((warn + 1)); } ok() { printf 'ok %s\n' "$*"; } mapfile -t skills < <(find "$script_dir" -mindepth 1 -maxdepth 1 -type d -name 'makepad-*' -printf '%f\n' | sort) printf 'Validating %d skills in %s\n\n' "${#skills[@]}" "$script_dir" [[ -f "$script_dir/makepad-game-director/SKILL.md" ]] \ || err "director skill missing - nothing routes the pack" for s in "${skills[@]}"; do d="$script_dir/$s" skill_md="$d/SKILL.md" if [[ ! -f "$skill_md" ]]; then err "$s: no SKILL.md" continue fi # --- frontmatter ----------------------------------------------------- if [[ "$(head -1 "$skill_md")" != "---" ]]; then err "$s: SKILL.md must start with YAML frontmatter" fi name=$(sed -n 's/^name:[[:space:]]*//p' "$skill_md" | head -1 | tr -d '"') desc=$(sed -n 's/^description:[[:space:]]*//p' "$skill_md" | head -1) [[ -n "$name" ]] || err "$s: frontmatter has no name" [[ "$name" == "$s" ]] || err "$s: frontmatter name '$name' != directory name" [[ -n "$desc" ]] || err "$s: frontmatter has no description" if [[ -n "$desc" && "${#desc}" -lt 80 ]]; then wrn "$s: description is short (${#desc} chars) - routing quality suffers" fi # --- agent manifest -------------------------------------------------- if [[ -f "$d/agents/openai.yaml" ]]; then grep -q 'display_name' "$d/agents/openai.yaml" \ || err "$s: agents/openai.yaml has no display_name" else err "$s: missing agents/openai.yaml" fi # --- referenced files exist ------------------------------------------ while read -r ref; do [[ -z "$ref" ]] && continue if [[ ! -e "$d/$ref" ]]; then err "$s: SKILL.md references missing file '$ref'" fi done < <(grep -oE '`references/[a-z0-9._-]+`|`scripts/[a-z0-9._-]+`' "$skill_md" \ | tr -d '`' | sort -u) # --- scripts are executable ------------------------------------------ if [[ -d "$d/scripts" ]]; then while read -r f; do [[ -x "$f" ]] || err "$s: script not executable: ${f#$d/}" if [[ "$f" == *.sh ]] && command -v bash >/dev/null; then bash -n "$f" || err "$s: bash syntax error in ${f#$d/}" fi done < <(find "$d/scripts" -type f 2>/dev/null) fi ok "$s" done # --- sibling cross-references resolve ---------------------------------- printf '\nChecking cross-skill references\n' while read -r line; do target="${line%%:*}" src="${line#*:}" if [[ ! -d "$script_dir/$target" ]]; then err "$src references unknown sibling skill '$target'" fi done < <(grep -rhoE 'makepad-[a-z0-9-]+/(SKILL\.md|references/)' "$script_dir"/*/SKILL.md 2>/dev/null \ | sed 's|/.*||' | sort -u | while read -r t; do echo "$t:pack"; done) printf '\n%d failures, %d warnings\n' "$fail" "$warn" [[ "$fail" -eq 0 ]] || exit 1 echo "Pack is structurally valid."