Release 1.1.2 — the default path works end to end

Fix release for 1.1.1: the minimal path end to end, engine commands that
run on Godot, Unity and Unreal, hook warnings you can see, and verdicts
that say when they could not check. Details in CHANGELOG.md; upgrade
steps in UPGRADING.md (v1.1.1 → v1.1.2).

Fixes #67
Fixes #131

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WuJn2FdynEybfL5KC697nJ
This commit is contained in:
Donchitos
2026-09-29 21:32:19 +10:00
co-authored by Claude Opus 5.5
parent 7ed2c3e9c4
commit b21fa0f7f2
383 changed files with 22888 additions and 10618 deletions
+65 -26
View File
@@ -28,11 +28,12 @@ fi
[ -n "$CCGS_ROOT" ] && cd "$CCGS_ROOT" 2>/dev/null || true
# Claude Code PostToolUse hook: Validates asset files after Write/Edit
# Checks naming conventions for files in assets/ directory
# Checks JSON validity of data files and, in Godot's assets/, naming conventions.
# Asset roots per engine: Godot assets/, Unity Assets/, Unreal Content/.
#
# Exit behavior:
# exit 0 = success or advisory warnings only
# exit 2 = build-breaking issue (invalid JSON, missing required fields)
# exit 2 = build-breaking issue (a data file that is not valid JSON)
#
# A PostToolUse hook CANNOT block -- the write has already happened by the time
# this runs (see .claude/docs/hooks-reference/hook-input-schemas.md). The only
@@ -64,60 +65,98 @@ fi
# validates nothing on Windows.
FILE_PATH=$(printf '%s' "$FILE_PATH" | sed 's|\\\\|/|g; s|\\|/|g')
# Only check files in assets/
if ! echo "$FILE_PATH" | grep -qE '(^|/)assets/'; then
exit 0
fi
# Make the path project-relative. Claude Code sends a file tool's path
# ABSOLUTE, with native separators (C:\... on Windows), so an unanchored
# `(^|/)assets/` matched every file in a project with any parent folder named
# assets, and node_modules/*/assets/ too. Strip the project root in either
# spelling Git Bash gives it (/c/Users/... from pwd, C:/Users/... from pwd -W,
# drive letter in either case); a path still absolute is outside the project.
_VA_ROOT=$(pwd); _VA_ROOT_W=$(pwd -W 2>/dev/null || printf '%s' "$_VA_ROOT")
shopt -s nocasematch
case "$FILE_PATH" in
"$_VA_ROOT"/*) REL_PATH="${FILE_PATH:${#_VA_ROOT}+1}" ;;
"$_VA_ROOT_W"/*) REL_PATH="${FILE_PATH:${#_VA_ROOT_W}+1}" ;;
/*|[A-Za-z]:/*) exit 0 ;;
*) REL_PATH="${FILE_PATH#./}" ;;
esac
shopt -u nocasematch
FILENAME=$(basename "$FILE_PATH")
# Only check files under an asset root.
case "$REL_PATH" in
assets/*|Assets/*|Content/*) ;;
*) exit 0 ;;
esac
FILENAME=$(basename "$REL_PATH")
WARNINGS="" # Style/convention issues -- exit 0 with advisory message
ERRORS="" # Build-breaking issues -- exit 1 to block the operation
ERRORS="" # Build-breaking issues -- exit 2 so Claude hears about it
# ADVISORY: Check naming convention (lowercase with underscores only)
# Naming issues are style violations -- warn but do not block
# ADVISORY: naming convention -- lowercase with underscores, the Godot
# convention, so only in Godot's assets/. Unity and Unreal name assets in
# PascalCase with type prefixes; warning on every one of them trains the user
# to ignore this hook. Naming issues warn, never block.
# Uses grep -E (POSIX) not grep -P (Perl) for Windows Git Bash compatibility
if echo "$FILENAME" | grep -qE '[A-Z[:space:]-]'; then
WARNINGS="$WARNINGS\n NAMING: $FILE_PATH must be lowercase with underscores (got: $FILENAME)"
fi
case "$REL_PATH" in
assets/*)
if echo "$FILENAME" | grep -qE '[A-Z[:space:]-]'; then
WARNINGS="$WARNINGS\n NAMING: $REL_PATH must be lowercase with underscores (got: $FILENAME)"
fi ;;
esac
# BLOCKING: Check JSON validity for data files
# BLOCKING: Check JSON validity for data files, in any engine's data folder --
# the same set validate-commit.sh blocks on.
# Invalid JSON will break runtime loading -- this is a build-breaking error
if echo "$FILE_PATH" | grep -qE '(^|/)assets/data/.*\.json$'; then
if echo "$REL_PATH" | grep -qE '^(assets|Assets|Content)/(.*/)?[Dd]ata/.*\.[Jj][Ss][Oo][Nn]$'; then
FILE_PATH="$REL_PATH"
if [ -f "$FILE_PATH" ]; then
# Find a working Python command
PYTHON_CMD=""
# Run it, do not just find it: the Windows Store `python` placeholder
# passes `command -v`, then fails, and valid JSON was reported invalid.
for cmd in python python3 py; do
if command -v "$cmd" >/dev/null 2>&1; then
if command -v "$cmd" >/dev/null 2>&1 && "$cmd" -c 'import sys; sys.exit(sys.version_info[0] < 3)' >/dev/null 2>&1; then
PYTHON_CMD="$cmd"
break
fi
done
if [ -n "$PYTHON_CMD" ]; then
if ! "$PYTHON_CMD" -m json.tool "$FILE_PATH" > /dev/null 2>&1; then
# utf-8-sig, as validate-commit.sh reads it: `json.tool` rejected a
# file with a UTF-8 BOM that the commit check then accepted.
if ! "$PYTHON_CMD" -c 'import json, sys; json.load(open(sys.argv[1], encoding="utf-8-sig"))' "$FILE_PATH" > /dev/null 2>&1; then
ERRORS="$ERRORS\n FORMAT: $FILE_PATH is not valid JSON — fix syntax errors before continuing"
fi
else
# Say so rather than skipping in silence. This is the only BLOCKING
# check in this hook, so without an interpreter the hook exits 0 on
# a file it never opened -- indistinguishable from valid JSON. The
# sibling validate-commit.sh already warns in exactly this case;
# this half was the one that did not.
echo "WARNING: Cannot validate JSON (python not found) — $FILE_PATH unchecked" >&2
# sibling validate-commit.sh blocks in this case; this half, which
# runs after the file is written, says so instead.
WARNINGS="$WARNINGS\n UNCHECKED: cannot validate JSON (python not found) — $FILE_PATH"
fi
fi
fi
# Report warnings (advisory -- non-blocking)
if [ -n "$WARNINGS" ]; then
echo -e "=== Asset Validation: Warnings ===$WARNINGS\n==================================\n(Warnings are advisory. Fix before final commit.)" >&2
fi
# Report build-breaking issues. exit 2 routes this to Claude, not just the user,
# so the file that was already written can actually be corrected.
# so the file that was already written can actually be corrected. Any warnings
# ride along on the same channel.
if [ -n "$ERRORS" ]; then
echo -e "=== Asset Validation: ERRORS ===$ERRORS\n================================\nThe file was written but is broken. Fix it now, before continuing." >&2
[ -n "$WARNINGS" ] && echo -e "=== Asset Validation: Warnings ===$WARNINGS" >&2
exit 2
fi
# Warnings alone do not need a fix now, but they must be seen: stderr on exit 0
# reaches the debug log only. Hook JSON reaches the user and Claude -- see
# hook_warn in yaml-helper.sh. stderr stays as the fallback without the helper.
if [ -n "$WARNINGS" ]; then
_VA_MSG=$(echo -e "=== Asset Validation: Warnings ===$WARNINGS\n==================================\n(Warnings are advisory. Fix before final commit.)")
[ -f .claude/hooks/yaml-helper.sh ] && . .claude/hooks/yaml-helper.sh 2>/dev/null
if command -v hook_warn >/dev/null 2>&1; then
hook_warn PostToolUse "$_VA_MSG"
else
printf '%s\n' "$_VA_MSG" >&2
fi
fi
exit 0