From 5594ce01c405136baacb7aa79f83af652ec2abf2 Mon Sep 17 00:00:00 2001 From: Claude Code Date: Tue, 31 Mar 2026 04:35:13 -0700 Subject: [PATCH] =?UTF-8?q?chore(hooks):=20=F0=9F=94=A7=20Update=20enforce?= =?UTF-8?q?-structure.sh=20hook=20rules=20for=20code=20validation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Lilith Autocommit --- .claude/hooks/enforce-structure.sh | 32 +++++++++++++++++++----------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/.claude/hooks/enforce-structure.sh b/.claude/hooks/enforce-structure.sh index ea18f16e..1ec95e0a 100755 --- a/.claude/hooks/enforce-structure.sh +++ b/.claude/hooks/enforce-structure.sh @@ -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