chore(hooks): 🔧 Update enforce-structure.sh hook rules for code validation

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
Claude Code 2026-03-31 04:35:13 -07:00
parent 285f4ae971
commit 5594ce01c4

View file

@ -16,16 +16,24 @@
# │ │ └── rendering/ # hex, city, unit, fog renderers
# │ ├── scenes/ # .tscn + .gd (main, menus, world_map, tests)
# │ └── tests/ # GUT unit + integration tests
# ├── resources/ # Shared content library (all games subscribe to this)
# │ ├── races/ # All 16 race definitions (one JSON per race)
# │ ├── worlds/ # Race homeworld planet profiles
# │ ├── tiles/ # Terrain/tile definitions
# │ ├── throne_rooms/ # Buildings and wonders
# │ └── world/ # Biomes, fauna, flora, ecosystem, traits
# ├── games/
# │ └── age-of-dwarves/
# │ ├── data/ # ALL game JSON (terrain/, units/, spells/, etc.)
# │ ├── assets/ # sprites, icons
# │ ├── docs/ # game design docs
# │ ├── game.json # game manifest
# │ └── vocabulary.json # engine term -> display string
# │ ├── age-of-dwarves/ # EA: 1 race, no magic
# │ │ ├── data/ # Game-specific JSON (setup, map_types, eras, etc.)
# │ │ ├── assets/ # sprites, icons
# │ │ ├── docs/ # game design docs
# │ │ ├── game.json # game manifest
# │ │ └── vocabulary.json # engine term -> display string
# │ ├── age-of-4/ # Expansion: 4 races + magic
# │ └── age-of-16/ # Full release: all 16 races
# ├── guide/
# │ ├── engine/ # @magic-civ/guide-engine (shared React components)
# │ ├── age-of-dwarves/ # web app (React + Vite)
# │ ├── age-of-dwarves/ # web app (React + Vite)
# │ └── themes/ -> ../../games/age-of-dwarves # SYMLINK (do not write here)
# ├── packages/
# │ └── engine-ts/ # @magic-civ/engine-ts (auto-generated from GDScript)
@ -42,7 +50,7 @@
# 2. Files must be in allowed top-level directories
# 3. No .messy/ paths in runtime code (planning docs exempt)
# 4. GDScript files must be <=500 lines
# 5. Game data JSON must live in games/age-of-dwarves/data/
# 5. Game data JSON must live in games/*/data/ or resources/
# 6. guide/themes/ is read-only symlink territory
#
set -euo pipefail
@ -71,7 +79,7 @@ if [[ "$REL" == guide/themes/* ]]; then
fi
# ── Rule 2: Allowed top-level directories ─────────────────────────────────────
ALLOWED_DIRS="engine/ games/ guide/ packages/ tools/ .project/ .claude/ .env docs/ README.md CLAUDE.md .gitignore .gutconfig.json .pnpmfile.cjs export_presets.cfg gdlintrc gdformatrc pnpm-workspace.yaml pnpm-lock.yaml project.godot run addons/"
ALLOWED_DIRS="engine/ games/ guide/ packages/ resources/ tools/ .project/ .claude/ .env docs/ README.md CLAUDE.md .gitignore .gutconfig.json .pnpmfile.cjs export_presets.cfg gdlintrc gdformatrc pnpm-workspace.yaml pnpm-lock.yaml project.godot run addons/"
MATCH=0
for prefix in $ALLOWED_DIRS; do
if [[ "$REL" == "$prefix"* || "$REL" == "$prefix" ]]; then
@ -119,11 +127,11 @@ if [[ "$REL" == *.json ]]; then
case "$BASENAME" in
package.json|tsconfig.json|tsconfig.*.json|vitest.config.*|.gutconfig.json) ;;
*)
# If it's game data (not config), it must be in games/age-of-dwarves/data/
if [[ "$REL" != games/age-of-dwarves/data/* && "$REL" != games/age-of-dwarves/game.json && "$REL" != games/age-of-dwarves/vocabulary.json && "$REL" != .claude/* && "$REL" != .project/* ]]; then
# If it's game data (not config), it must be in games/*/data/ or resources/
if [[ "$REL" != games/*/data/* && "$REL" != games/*/game.json && "$REL" != games/*/vocabulary.json && "$REL" != resources/* && "$REL" != .claude/* && "$REL" != .project/* && "$REL" != engine/src/worlds/* ]]; then
# Check if it looks like game data (has "id" field or is in a data-like path)
if echo "$CONTENT" | jq -e '.[0].id // .id // .races // .terrain // empty' >/dev/null 2>&1; then
echo "{\"decision\":\"block\",\"reason\":\"STRUCTURE VIOLATION: Game data JSON '$REL' must live in games/age-of-dwarves/data/. The guide reads from there via symlink — never duplicate data.\"}"
echo "{\"decision\":\"block\",\"reason\":\"STRUCTURE VIOLATION: Game data JSON '$REL' must live in games/*/data/, resources/, or engine/src/worlds/. The guide reads from there via symlink — never duplicate data.\"}"
exit 0
fi
fi