From e4e1566e55b1f5f4b69cd5c1b317a3346598e286 Mon Sep 17 00:00:00 2001 From: Zwitschi Date: Tue, 3 Nov 2026 19:45:00 +0100 Subject: [PATCH] Organize tools and move Python tests into tools/tests --- README.md | 1 + docs/README.md | 1 + docs/asset-tooling.md | 2 +- docs/blender-assets.md | 2 +- tools/README.md | 179 ++++++++++++++++++++ tools/tests/README.md | 25 +++ tools/tests/__init__.py | 0 tools/{ => tests}/test_asset_pipeline.py | 0 tools/{ => tests}/test_blender_assets.py | 0 tools/{ => tests}/test_check_docs.py | 0 tools/{ => tests}/test_generate_textures.py | 0 tools/{ => tests}/test_model_pipeline.py | 0 tools/{ => tests}/test_model_review.py | 2 +- tools/{ => tests}/test_npc_baseline.py | 0 tools/{ => tests}/test_npc_pipeline.py | 0 tools/{ => tests}/test_npc_proportions.py | 0 tools/{ => tests}/test_openrouter_judge.py | 0 tools/{ => tests}/test_refboard.py | 0 tools/{ => tests}/test_refcollect.py | 0 tools/{ => tests}/test_scene_concepts.py | 0 tools/{ => tests}/test_screen_designs.py | 0 tools/{ => tests}/test_three_up.py | 0 22 files changed, 209 insertions(+), 3 deletions(-) create mode 100644 tools/README.md create mode 100644 tools/tests/README.md create mode 100644 tools/tests/__init__.py rename tools/{ => tests}/test_asset_pipeline.py (100%) rename tools/{ => tests}/test_blender_assets.py (100%) rename tools/{ => tests}/test_check_docs.py (100%) rename tools/{ => tests}/test_generate_textures.py (100%) rename tools/{ => tests}/test_model_pipeline.py (100%) rename tools/{ => tests}/test_model_review.py (97%) rename tools/{ => tests}/test_npc_baseline.py (100%) rename tools/{ => tests}/test_npc_pipeline.py (100%) rename tools/{ => tests}/test_npc_proportions.py (100%) rename tools/{ => tests}/test_openrouter_judge.py (100%) rename tools/{ => tests}/test_refboard.py (100%) rename tools/{ => tests}/test_refcollect.py (100%) rename tools/{ => tests}/test_scene_concepts.py (100%) rename tools/{ => tests}/test_screen_designs.py (100%) rename tools/{ => tests}/test_three_up.py (100%) diff --git a/README.md b/README.md index ba136d2..164fcb7 100644 --- a/README.md +++ b/README.md @@ -169,6 +169,7 @@ Full setup, every run/test/smoke command, and the controls table are in - [`docs/joke-shop-map.md`](docs/joke-shop-map.md) — Real-site references, game mapping and limitations for the Joke Shop / Sunset Strip venue. - [`docs/tutorial.md`](docs/tutorial.md) — First-shift tutorial beats and rules. - [`docs/asset-tooling.md`](docs/asset-tooling.md) — Asset pipelines, model tools, and screenshot gates. +- [`tools/README.md`](tools/README.md) — Tool inventory, categories, test commands and AI-skill evaluation. - [`docs/getting-started.md`](docs/getting-started.md) — Setup, run/test commands, and controls. - [`docs/development-status.md`](docs/development-status.md) — Implemented features and what's next. - [`docs/accessibility.md`](docs/accessibility.md) — Accessibility features, known gaps and statement. diff --git a/docs/README.md b/docs/README.md index b0d4668..f265900 100644 --- a/docs/README.md +++ b/docs/README.md @@ -16,6 +16,7 @@ This folder holds the project documentation, visual references and generated QA - [`architecture.md`](architecture.md) — arc42 system architecture - [`getting-started.md`](getting-started.md) — setup, run/test commands and controls - [`asset-tooling.md`](asset-tooling.md) — image/model pipelines and screenshot gates +- [`../tools/README.md`](../tools/README.md) — tool inventory, categories and test runner - [`gameplay.md`](gameplay.md) — controls, venues and escalation - [`joke-shop-map.md`](joke-shop-map.md) — Sunset Strip real-site mapping - [`tutorial.md`](tutorial.md) — first-shift tutorial beats diff --git a/docs/asset-tooling.md b/docs/asset-tooling.md index df65c40..d8d1176 100644 --- a/docs/asset-tooling.md +++ b/docs/asset-tooling.md @@ -38,7 +38,7 @@ Audit accepts image files or directories. `--role auto` infers common roles from ```bash python3 tools/asset_pipeline.py audit assets/textures python3 tools/asset_pipeline.py audit assets/images/scenes --role background --json -python3 -m unittest discover -s tools -p 'test_*.py' +python3 -m unittest discover -s tools/tests -t tools -p 'test_*.py' ``` The audit classifies measurable fit issues as `good` or `bad` based on role-specific dimensions, aspect ratio, alpha requirements, and tile-edge continuity. It lists perspective/projection as a visual review item because image semantics cannot be judged reliably by these deterministic checks. diff --git a/docs/blender-assets.md b/docs/blender-assets.md index c329421..cfb7b5d 100644 --- a/docs/blender-assets.md +++ b/docs/blender-assets.md @@ -187,7 +187,7 @@ carry baked AO and the shared neutral material maps described above. during LOD generation), budgets (library characters 8000/8000, base fallback 6000/4000, gear 1500, props 4000 triangles), grounding, and an editable `.blend`. For characters it also checks skinning, bones, slots, the `npc_base` mesh node and the height. -- `tools/test_blender_assets.py`: catalogue and contract consistency with +- `tools/tests/test_blender_assets.py`: catalogue and contract consistency with `npc_pipeline.py`, plus a clean audit and full manifest coverage when the library is built. - `src/test/tests/test_blender_assets.gd`: every asset imports as a scene diff --git a/tools/README.md b/tools/README.md new file mode 100644 index 0000000..675def4 --- /dev/null +++ b/tools/README.md @@ -0,0 +1,179 @@ +# Gig Line Tools + +Developer and release tooling for Gig Line. Nothing in this directory runs in +the game at runtime; the tools generate or audit committed assets, capture +visual evidence, and build/publish releases. They are intentionally kept outside +`src/` and outside the exported runtime scripts. + +## File inventory + +All tracked source files are listed here; generated `__pycache__/` and +`.ruff_cache/` contents are ignored. + +| File | Kind | +| --- | --- | +| [`README.md`](README.md) | this guide | +| [`asset_pipeline.py`](asset_pipeline.py) | Python: image generation and audit | +| [`bake_ao.py`](bake_ao.py) | Python/Blender: AO baking | +| [`blender_assets.py`](blender_assets.py) | Python/Blender: character, gear and prop library | +| [`build_releases.sh`](build_releases.sh) | shell: release export/packaging | +| [`check_docs.py`](check_docs.py) | Python: documentation gate | +| [`check_screenshots.sh`](check_screenshots.sh) | shell: gallery capture/compare | +| [`export_venues.gd`](export_venues.gd) | GDScript: venue `.tres` export | +| [`export_venues.gd.uid`](export_venues.gd.uid) | Godot UID sidecar | +| [`generate_textures.py`](generate_textures.py) | Python: procedural/AI textures | +| [`make_normal_maps.py`](make_normal_maps.py) | Python: derived normal maps | +| [`model_pipeline.py`](model_pipeline.py) | Python/Blender: prop models and atlases | +| [`npc_baseline.py`](npc_baseline.py) | Python: NPC baseline/compare sheets | +| [`npc_pipeline.py`](npc_pipeline.py) | Python/Blender: NPC base and texture maps | +| [`npc_proportions.py`](npc_proportions.py) | Python: exported-GLB proportion audit | +| [`openrouter_judge.py`](openrouter_judge.py) | Python: shared OpenRouter judge client | +| [`publish_release.sh`](publish_release.sh) | shell: release upload/preflight | +| [`refboard.py`](refboard.py) | Python: licensed reference candidate board | +| [`refcollect.py`](refcollect.py) | Python: local-only image research fetcher | +| [`scene_concepts.py`](scene_concepts.py) | Python: concepts, texture processing, realism | +| [`screen_designs.py`](screen_designs.py) | Python: screen mockups, compare and judge | +| [`three_up.py`](three_up.py) | Python: photo/concept/capture boards | +| [`tests/`](tests/) | Python tooling tests, test README and package marker | +| [`tests/README.md`](tests/README.md) | test-run instructions | +| [`tests/__init__.py`](tests/__init__.py) | package marker for module-style discovery | + +### Tests in `tests/` + +| Test | Covers | +| --- | --- | +| [`test_asset_pipeline.py`](tests/test_asset_pipeline.py) | image roles, generation helpers and audit | +| [`test_blender_assets.py`](tests/test_blender_assets.py) | catalogue, contract, fit, texels and manifest | +| [`test_check_docs.py`](tests/test_check_docs.py) | README/link/image documentation gate | +| [`test_generate_textures.py`](tests/test_generate_textures.py) | texture generation helpers | +| [`test_model_pipeline.py`](tests/test_model_pipeline.py) | prop models, palette atlas and GLB output | +| [`test_model_review.py`](tests/test_model_review.py) | scorecard coverage for the 3D review | +| [`test_npc_baseline.py`](tests/test_npc_baseline.py) | baseline sheet/comparison selection | +| [`test_npc_pipeline.py`](tests/test_npc_pipeline.py) | NPC contract, textures and committed model | +| [`test_npc_proportions.py`](tests/test_npc_proportions.py) | exported proportion measurements | +| [`test_openrouter_judge.py`](tests/test_openrouter_judge.py) | model selection, retries and errors | +| [`test_refboard.py`](tests/test_refboard.py) | licence gate, recent filter and row output | +| [`test_refcollect.py`](tests/test_refcollect.py) | search parsing, retries and local downloads | +| [`test_scene_concepts.py`](tests/test_scene_concepts.py) | processing, promotion, references and judge | +| [`test_screen_designs.py`](tests/test_screen_designs.py) | design catalogue, compare and judge | +| [`test_three_up.py`](tests/test_three_up.py) | three-up composition and captions | + +Run the suite from the repository root: + +```bash +python3 -m pip install -r requirements-tools.txt +python3 -m unittest discover -s tools/tests -t tools -p 'test_*.py' +``` + +## Categories + +### 1. Asset generation and authoring + +These produce or modify committed assets. Prefer a **clean worktree**, inspect +the diff, and run the matching audit before committing generated files. + +| Tool | Purpose | Typical command | +| --- | --- | --- | +| `blender_assets.py` | Catalogue/build/audit/inspect/fit/texel/sheet the character, gear and prop library. `build`/`render` need Blender; `audit`/`fit`/`inspect` are standalone. | `python3 tools/blender_assets.py audit` | +| `npc_pipeline.py` | Prepare AI fabric tiles, derive outfit palettes, build `npc_base`, audit the NPC contract. | `python3 tools/npc_pipeline.py audit` | +| `bake_ao.py` | Blender AO bake for library assets. | `flatpak run org.blender.Blender --background --python "$PWD/tools/bake_ao.py" -- --only npc_guard` | +| `npc_proportions.py` | Measure exported GLBs against the stylized proportion guide. | `python3 tools/npc_proportions.py report` | +| `npc_baseline.py` | Compose neutral baseline sheets and before/after comparisons. | `python3 tools/npc_baseline.py sheet --dir tmp/npc-baseline` | +| `asset_pipeline.py` | Generate, crop, resize, seam-fix and audit images by role. | `python3 tools/asset_pipeline.py audit assets/textures` | +| `generate_textures.py` | Procedural texture generation with an optional AI mode. | `python3 tools/generate_textures.py` | +| `make_normal_maps.py` | Derive tangent normal maps from albedo textures. | `python3 tools/make_normal_maps.py ` | +| `model_pipeline.py` | Build low-poly props and single-material palette atlases. | `python3 tools/model_pipeline.py build` | +| `scene_concepts.py` | Generate concept frames, process/promote texture picks, and run the realism judge. | `python3 tools/scene_concepts.py audit` | +| `screen_designs.py` | Generate screen-design references and compare/judge captures. | `python3 tools/screen_designs.py compare` | +| `three_up.py` | Compose labelled real-photo/concept/capture boards. | `python3 tools/three_up.py compose --help` | +| `openrouter_judge.py` | Shared OpenRouter client for model selection, retries and JSON parsing. | normally imported by the judge tools | + +### 2. Reference research and provenance + +| Tool | Purpose | Notes | +| --- | --- | --- | +| `refboard.py` | Search Wikimedia Commons (search/geo/category), gate by licence and age, fetch candidates, emit sidecar rows. | Committed-board source; run with the licence gate. | +| `refcollect.py` | DuckDuckGo image search/fetch and local contact sheets. | **Local-only research**: downloads stay in `tmp/research/`, never committed. | +| `three_up.py` | Pair a real reference, generated concept and current capture in one review board. | The photos remain evidence, not shipped art. | + +### 3. Validation and review + +| Tool | Purpose | Typical command | +| --- | --- | --- | +| `check_docs.py` | Verify README coverage, local links and tracked-image links. | `python3 tools/check_docs.py` | +| `check_screenshots.sh` | Re-render the committed gallery and run the Pillow comparison. | `./tools/check_screenshots.sh` | +| `npc_baseline.py` | Baseline/compare character contact sheets. | see above | +| `npc_proportions.py` | Proportion gate on exported GLBs. | see above | +| `screen_designs.py compare/judge` | Screen-design drift gate and optional vision review. | `python3 tools/screen_designs.py compare` | +| `scene_concepts.py realism` | Optional realism-review and judge pass. | `python3 tools/scene_concepts.py realism --run ` | + +### 4. Runtime/content export + +| Tool | Purpose | Typical command | +| --- | --- | --- | +| `export_venues.gd` | Export `content/venues/*.tres` from `ScenarioFactory`. | `godot --headless --path . --script res://tools/export_venues.gd` | + +### 5. Build and release + +| Tool | Purpose | Typical command | +| --- | --- | --- | +| `build_releases.sh` | Export Linux/Windows/macOS/Web and package the optional Desktop HQ zip. **Run from a clean worktree.** | `./tools/build_releases.sh` | +| `publish_release.sh` | Preflight artifacts/free space, write SHA-256 checksums, upload with rollback, optional retention pruning. | `PUBLISH_DRY_RUN=1 ./tools/publish_release.sh` | + +The clean-worktree requirement is important: a normal working tree may contain +ignored `tmp/` and `build/` content that Godot can pack into the export. + +### 6. Tests + +All Python tooling tests live in [`tests/`](tests/). They use the repository's +`requirements-tools.txt` (Pillow) and do not start Godot or Blender. See +[`tests/README.md`](tests/README.md) for the exact discovery command. + +## Which tools could become AI skills? + +A skill is a **procedure and decision guide**, not a script wrapper. The useful +split is project-specific judgement that an AI repeatedly needs, not a second +copy of every command. + +### Recommended: elevate as a project skill + +1. **`gig-line-blender-asset-contract` (high value).** + Bundle the ordering and contract around `blender_assets.py`, + `npc_pipeline.py`, `bake_ao.py`, `npc_proportions.py` and + `npc_baseline.py`: the 13-bone `npc_base` contract, tint slots, 8,000/8,000 + character cap, gear attach space, AO/UV rules, audit → fit → measure → + baseline sequence, and the “inspect the diff before committing” rule. + This is the workflow most likely to be repeated by an AI and most likely to + be damaged by improvising. + +2. **`gig-line-release-and-visual-qa` (high value).** + Capture the sequence `check_docs.py` → `check_screenshots.sh` → + `screen_designs.py compare/judge` → clean-worktree `build_releases.sh` → + `PUBLISH_DRY_RUN` → checksum/upload checks. Include the optional nature of + the vision judge, the clean-worktree trap and the release rollback rules. + +3. **`gig-line-reference-provenance` (medium value).** + Guide `refboard.py` vs `refcollect.py`: committed Wikimedia-sourced boards + with sidecars versus local-only `tmp/research/` downloads, and the rule that + generated concepts never override photo evidence. This is more of a policy + skill than a command skill. + +### Keep as scripts + +- `asset_pipeline.py`, `generate_textures.py`, `make_normal_maps.py`, + `model_pipeline.py` and `scene_concepts.py` are general generation/processing + utilities. A skill should point to their documented commands rather than + duplicate them; several call paid APIs and must stay human-triggered. +- `screen_designs.py` and `scene_concepts.py` judge modes are optional, + network/budget-dependent review aids, not deterministic CI gates. +- `openrouter_judge.py` is an implementation detail imported by other tools. +- `check_docs.py` and `export_venues.gd` are short, single-purpose commands; + documenting them in this README and `docs/asset-tooling.md` is enough. +- `npc_baseline.py`, `npc_proportions.py` and `three_up.py` are better included + as references/steps inside the proposed asset or release skill than exposed as + separate skills; fragmenting them would increase routing mistakes. + +Do **not** move scripts into `.agents/skills/`: the local Blender skill pack is +gitignored guidance, while these tools are tracked project code with tests and +CI-relevant contracts. A future skill should reference this directory and the +project docs, not fork the implementation. diff --git a/tools/tests/README.md b/tools/tests/README.md new file mode 100644 index 0000000..9249410 --- /dev/null +++ b/tools/tests/README.md @@ -0,0 +1,25 @@ +# Python Tooling Tests + +Unit tests for the scripts in `tools/`. They use the standard library +`unittest` plus Pillow; no Godot or Blender process is started. + +Run them from the repository root: + +```bash +python3 -m pip install -r requirements-tools.txt +python3 -m unittest discover -s tools/tests -t tools -p 'test_*.py' +``` + +The `-t tools` top-level directory is required: the tests import the tool +modules by their plain names (for example `import blender_assets`). + +Individual example: + +```bash +python3 -m unittest tools.tests.test_model_review -v +``` + +(Module-style invocation requires `tools/tests/__init__.py`, which is committed.) + +These tests do not call OpenRouter. The judge/image tests mock the HTTP layer; +live generation and judging remain manual, development-only operations. diff --git a/tools/tests/__init__.py b/tools/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tools/test_asset_pipeline.py b/tools/tests/test_asset_pipeline.py similarity index 100% rename from tools/test_asset_pipeline.py rename to tools/tests/test_asset_pipeline.py diff --git a/tools/test_blender_assets.py b/tools/tests/test_blender_assets.py similarity index 100% rename from tools/test_blender_assets.py rename to tools/tests/test_blender_assets.py diff --git a/tools/test_check_docs.py b/tools/tests/test_check_docs.py similarity index 100% rename from tools/test_check_docs.py rename to tools/tests/test_check_docs.py diff --git a/tools/test_generate_textures.py b/tools/tests/test_generate_textures.py similarity index 100% rename from tools/test_generate_textures.py rename to tools/tests/test_generate_textures.py diff --git a/tools/test_model_pipeline.py b/tools/tests/test_model_pipeline.py similarity index 100% rename from tools/test_model_pipeline.py rename to tools/tests/test_model_pipeline.py diff --git a/tools/test_model_review.py b/tools/tests/test_model_review.py similarity index 97% rename from tools/test_model_review.py rename to tools/tests/test_model_review.py index da8e1b1..c426f49 100644 --- a/tools/test_model_review.py +++ b/tools/tests/test_model_review.py @@ -12,7 +12,7 @@ from pathlib import Path import blender_assets as model -ROOT = Path(__file__).resolve().parent.parent +ROOT = Path(model.__file__).resolve().parent.parent REVIEW = ROOT / "docs" / "3d-model-review.md" diff --git a/tools/test_npc_baseline.py b/tools/tests/test_npc_baseline.py similarity index 100% rename from tools/test_npc_baseline.py rename to tools/tests/test_npc_baseline.py diff --git a/tools/test_npc_pipeline.py b/tools/tests/test_npc_pipeline.py similarity index 100% rename from tools/test_npc_pipeline.py rename to tools/tests/test_npc_pipeline.py diff --git a/tools/test_npc_proportions.py b/tools/tests/test_npc_proportions.py similarity index 100% rename from tools/test_npc_proportions.py rename to tools/tests/test_npc_proportions.py diff --git a/tools/test_openrouter_judge.py b/tools/tests/test_openrouter_judge.py similarity index 100% rename from tools/test_openrouter_judge.py rename to tools/tests/test_openrouter_judge.py diff --git a/tools/test_refboard.py b/tools/tests/test_refboard.py similarity index 100% rename from tools/test_refboard.py rename to tools/tests/test_refboard.py diff --git a/tools/test_refcollect.py b/tools/tests/test_refcollect.py similarity index 100% rename from tools/test_refcollect.py rename to tools/tests/test_refcollect.py diff --git a/tools/test_scene_concepts.py b/tools/tests/test_scene_concepts.py similarity index 100% rename from tools/test_scene_concepts.py rename to tools/tests/test_scene_concepts.py diff --git a/tools/test_screen_designs.py b/tools/tests/test_screen_designs.py similarity index 100% rename from tools/test_screen_designs.py rename to tools/tests/test_screen_designs.py diff --git a/tools/test_three_up.py b/tools/tests/test_three_up.py similarity index 100% rename from tools/test_three_up.py rename to tools/tests/test_three_up.py