Add tracked AI skills for Blender assets and release QA
This commit is contained in:
1 parent
e4e1566e55
commit
724e8b183f
13 files changed
+1124
-25
No files matched your search
Whitespace-only changes.
@@ -0,0 +1,210 @@
|
|||||||
|
---
|
||||||
|
name: gig-line-blender-asset-contract
|
||||||
|
description: Use when adding, rebuilding, auditing or fixing any Gig Line Blender-authored character, NPC base, gear, prop or venue geometry. Covers the 13-bone npc_base contract, five tint slots, triangle/vertex budgets, gear attach space, 256² texture/AO rules, headless flatpak Blender commands, and the inspect/audit/fit/proportion/capture gates. Do not use for pure GDScript/UI work or release publishing.
|
||||||
|
compatibility: Gig Line repository checkout. Godot 4.7.2 on PATH; Blender 5.2 LTS via the org.blender.Blender flatpak for build/bake/render. Audit, fit, inspect and proportion checks are stdlib-only.
|
||||||
|
metadata:
|
||||||
|
project: Gig Line
|
||||||
|
domain: 3d-assets
|
||||||
|
version: "1.0.0"
|
||||||
|
triggers: Blender, NPC, character, gear, prop, npc_base, GLB, AO, texel, asset rebuild, fit, audit
|
||||||
|
---
|
||||||
|
|
||||||
|
# Gig Line Blender Asset Contract
|
||||||
|
|
||||||
|
Use this skill for any change that touches:
|
||||||
|
|
||||||
|
- `assets/models/blender/**`
|
||||||
|
- `assets/models/generated/npc_base.glb`
|
||||||
|
- `assets/textures/npc/**`
|
||||||
|
- `tools/blender_assets.py`, `tools/npc_pipeline.py`, `tools/bake_ao.py`,
|
||||||
|
`tools/npc_proportions.py` or `tools/npc_baseline.py`
|
||||||
|
- Blender-authored venue/prop geometry
|
||||||
|
|
||||||
|
The project contract and measured gates override any generic Blender advice.
|
||||||
|
There is **no Blender MCP** in this project. Blender runs headless through the
|
||||||
|
flatpak CLI; the `blender-skills` pack is optional, local guidance only, and
|
||||||
|
gitignored.
|
||||||
|
|
||||||
|
## Read first
|
||||||
|
|
||||||
|
From the repository root, read the relevant sources rather than relying on this
|
||||||
|
skill alone:
|
||||||
|
|
||||||
|
1. `AGENTS.md` — required workflow and verification.
|
||||||
|
2. `TODO.md` and `MEMORY.md` — current track, claimed tasks, known gotchas.
|
||||||
|
3. `docs/blender-assets.md` — library contract and command reference.
|
||||||
|
4. `docs/asset-tooling.md` — exact rebuild/bake/capture commands.
|
||||||
|
5. `docs/npc-visual-review.md` and `docs/3d-model-review.md` — accepted limits,
|
||||||
|
scorecards and known blockers.
|
||||||
|
6. `docs/known-limitations.md` — limits that must not be silently “fixed” into
|
||||||
|
contract changes.
|
||||||
|
|
||||||
|
The contract lives in code and docs, not in this skill. If they disagree, stop
|
||||||
|
and resolve the source of truth before editing assets.
|
||||||
|
|
||||||
|
## Non-negotiable contract
|
||||||
|
|
||||||
|
| Area | Rule |
|
||||||
|
| --- | --- |
|
||||||
|
| Mesh root | `npc_base` mesh node, skinned under `Rig`; preserve the limb node names. |
|
||||||
|
| Bones | 13 contract bones: `Head`, `HipL/R`, `KneeL/R`, `ShoulderL/R`, `ElbowL/R`, `HandL/R`, `Spine`, `Neck` (parent/helper bones must not change the contract). |
|
||||||
|
| Tint slots | `skin`, `cloth`, `pants`, `accessory`, `hair`. |
|
||||||
|
| Orientation | Front is Blender −Y / Godot +Z; feet grounded near y = 0; metres. |
|
||||||
|
| Library budget | **8,000 triangles / 8,000 glTF vertices** per character (`CHAR_MAX_TRIS`/`CHAR_MAX_VERTS`). |
|
||||||
|
| Frozen fallback | `npc_base` keeps **6,000 tris / 4,000 verts**. Do not silently raise or lower it. |
|
||||||
|
| Gear budget | **1,500 triangles** per gear piece; authored in attach-point space. |
|
||||||
|
| Prop budget | **4,000 triangles** per prop. |
|
||||||
|
| Gear attach | Use the catalogued attach points; verify with `fit`. Runtime `GEAR_OFFSETS` (lanyard forward, firefighter helmet up) and `HAND_ITEM_FORWARD` are intentional, not asset-contract changes. |
|
||||||
|
| Textures | 256² albedo/normal/ORM maps. Cloth and pants use `NPC_FABRIC_UV_SCALE = (4,4,1)` and **skip** baked per-character AO; skin/hair/gear keep baked AO. |
|
||||||
|
| CI | Offline and skill-free. Committed GLBs/AO/maps must make CI pass without Blender or MCP. |
|
||||||
|
| Licensing | No new asset source without ADR-0015: CC0, or CC-BY with attribution in `CREDITS.md`; record provenance. |
|
||||||
|
|
||||||
|
Do not change the renderer, engine baseline, runtime dependency graph or the
|
||||||
|
`npc_base` contract as part of an asset pass.
|
||||||
|
|
||||||
|
## Workflow
|
||||||
|
|
||||||
|
### 1. Preflight and claim
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git status --short
|
||||||
|
git log --oneline -5
|
||||||
|
godot --version
|
||||||
|
flatpak run org.blender.Blender --version | head -3
|
||||||
|
```
|
||||||
|
|
||||||
|
Inspect the current asset and the relevant docs. Claim the TODO item with `[-]`
|
||||||
|
before starting. Work on one asset family per commit.
|
||||||
|
|
||||||
|
### 2. Establish a baseline
|
||||||
|
|
||||||
|
Run the checks that do not need Blender first:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 tools/blender_assets.py audit
|
||||||
|
python3 tools/blender_assets.py fit
|
||||||
|
python3 tools/blender_assets.py texels
|
||||||
|
python3 tools/npc_proportions.py report
|
||||||
|
python3 tools/npc_pipeline.py audit
|
||||||
|
```
|
||||||
|
|
||||||
|
For a specific incoming or existing GLB:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
flatpak run org.blender.Blender --background \
|
||||||
|
--python "$PWD/tools/blender_assets.py" -- \
|
||||||
|
inspect --file "$PWD/path/to/asset.glb" --category npc_gear --json
|
||||||
|
```
|
||||||
|
|
||||||
|
Record the before measurements (tris/verts, head/shoulder/hip/leg/arm/foot,
|
||||||
|
fabric texel density, gear clearance). Do not “improve” an asset without a
|
||||||
|
measurable target.
|
||||||
|
|
||||||
|
### 3. Optional Blender-skill routing
|
||||||
|
|
||||||
|
If the local `blender-skills` pack is installed, load `blender-director`, then
|
||||||
|
only the specialists the task needs:
|
||||||
|
|
||||||
|
- character mesh/face/hands: `character-artist`, `retopology`
|
||||||
|
- rig/weights/pose: `rigging`
|
||||||
|
- UVs/texel density: `uv-workflow`
|
||||||
|
- maps/materials: `texture-workflow`, `materials`, `lookdev`
|
||||||
|
- gear/props: `prop-artist`, `hard-surface`
|
||||||
|
- budget/LOD/collision: `asset-optimization`, `lod-pipeline`, `collision-proxy`
|
||||||
|
- final review: `qa-review`
|
||||||
|
|
||||||
|
Translate any MCP instruction into a change to `tools/*.py` or a headless CLI
|
||||||
|
run. Never add an MCP dependency to the build, CI or runtime.
|
||||||
|
|
||||||
|
### 4. Build or bake
|
||||||
|
|
||||||
|
Characters, gear and library props:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
flatpak run org.blender.Blender --background \
|
||||||
|
--python "$PWD/tools/blender_assets.py" -- build --only <name>
|
||||||
|
|
||||||
|
flatpak run org.blender.Blender --background \
|
||||||
|
--python "$PWD/tools/bake_ao.py" -- --only <name>
|
||||||
|
```
|
||||||
|
|
||||||
|
NPC base and its material maps:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 tools/npc_pipeline.py prepare # only when fabric tiles change
|
||||||
|
flatpak run org.blender.Blender --background \
|
||||||
|
--python "$PWD/tools/npc_pipeline.py" -- build
|
||||||
|
python3 tools/npc_pipeline.py audit
|
||||||
|
```
|
||||||
|
|
||||||
|
Do not overwrite a review image or a promoted texture pick. Use a new `-vN`
|
||||||
|
path and document the promotion.
|
||||||
|
|
||||||
|
### 5. Import and capture
|
||||||
|
|
||||||
|
```bash
|
||||||
|
godot --headless --path . --import
|
||||||
|
godot --headless --path . --script res://src/test/test_runner.gd
|
||||||
|
|
||||||
|
# neutral baseline: 8 variants x 6 views, raw frames stay in tmp/
|
||||||
|
godot --path . --script res://src/test/capture_npc_baseline.gd \
|
||||||
|
-- --out=res://tmp/npc-baseline
|
||||||
|
|
||||||
|
# final-context: 96 frames across both venues and day/night
|
||||||
|
godot --path . --script res://src/test/capture_npc_review.gd \
|
||||||
|
-- --out=res://tmp/npc-review
|
||||||
|
```
|
||||||
|
|
||||||
|
Compare before/after with `tools/npc_baseline.py compare`; do not replace the
|
||||||
|
committed baseline sheet until a fix actually lands. See
|
||||||
|
`references/verification.md` for the full gate matrix.
|
||||||
|
|
||||||
|
### 6. Verify and hand off
|
||||||
|
|
||||||
|
At minimum:
|
||||||
|
|
||||||
|
- `blender_assets.py audit` and `fit` exit 0.
|
||||||
|
- `npc_proportions.py` passes the stylized guide.
|
||||||
|
- `npc_pipeline.py audit` passes if the base/textures changed.
|
||||||
|
- texel density is inside the authored/fabric bands.
|
||||||
|
- No character exceeds 8,000/8,000; gear/prop caps hold.
|
||||||
|
- 24-NPC budget and Web/Compatibility path remain green.
|
||||||
|
- Contract tests, headless suite, capture gates and docs check pass.
|
||||||
|
- The diff contains only the intended assets, tools, tests and docs.
|
||||||
|
|
||||||
|
State in the handoff: files changed, measurements before/after, skills used,
|
||||||
|
gates run, and any accepted limit.
|
||||||
|
|
||||||
|
## Failure playbook
|
||||||
|
|
||||||
|
- **`Class "..." hides a global script class`** — a stray `.gd` backup is in the
|
||||||
|
project. Delete `tmp/*.gd` backups, `rm -rf .godot`, re-import; never keep
|
||||||
|
`class_name` copies in `tmp/`.
|
||||||
|
- **Blender cannot see the path** — the flatpak cwd is `/app/blender`; use
|
||||||
|
absolute paths (`"$PWD/..."`).
|
||||||
|
- **Empty or stale captures** — close modals/pause, check the capture script's
|
||||||
|
settle frames, and remove stale output directories before re-running.
|
||||||
|
- **Pose harness mismatch** — the current `capture_npc_pose.gd` is blocked per
|
||||||
|
`docs/3d-model-review.md`; do not use its frames as pose evidence until the
|
||||||
|
recipe is fixed.
|
||||||
|
- **Asset test fails after import** — re-run audit/fit first, then import; if the
|
||||||
|
manifest or AO path changed, rebuild the affected asset rather than editing
|
||||||
|
the manifest by hand.
|
||||||
|
- **Uncertain about a visual change** — produce a labelled before/after sheet and
|
||||||
|
ask for review; do not hide a regression behind a budget claim.
|
||||||
|
|
||||||
|
## Bundled references
|
||||||
|
|
||||||
|
- [`references/asset-contract.md`](references/asset-contract.md) — full contract,
|
||||||
|
inventory, file locations and provenance rules.
|
||||||
|
- [`references/verification.md`](references/verification.md) — command matrix,
|
||||||
|
capture gates, expected results and acceptance criteria.
|
||||||
|
|
||||||
|
## Do not
|
||||||
|
|
||||||
|
- Add an MCP server, Blender dependency or API call to the build/runtime.
|
||||||
|
- Change the bone/tint/contract to make a generic asset fit.
|
||||||
|
- Rewrite committed baselines or overwrite existing images.
|
||||||
|
- Commit `.blend` sources, raw captures or generated AI inputs.
|
||||||
|
- Treat an asset audit as a substitute for visual review at portrait and crowd
|
||||||
|
distance.
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
# Asset Contract Reference
|
||||||
|
|
||||||
|
This is a working summary. The authoritative sources remain
|
||||||
|
`docs/blender-assets.md`, `docs/asset-tooling.md`, ADR-0013, the tests in
|
||||||
|
`src/test/tests/` and the constants in `tools/blender_assets.py` /
|
||||||
|
`tools/npc_pipeline.py`.
|
||||||
|
|
||||||
|
## Library inventory
|
||||||
|
|
||||||
|
- **Character variants (8):** `npc_casual`, `npc_jacket`, `npc_coat`,
|
||||||
|
`npc_vest`, `npc_dress`, `npc_hoodie`, `npc_firefighter`, `npc_guard`.
|
||||||
|
- **Frozen fallback:** `npc_base` / `assets/models/generated/npc_base.glb`.
|
||||||
|
- **Gear:** 18 attach-space pieces covering head, back, chest and hand items.
|
||||||
|
- **Library props:** 20 Blender-authored props plus 6 generated props.
|
||||||
|
- **Venues:** procedural venues in `src/game/world_builder.gd`; Blender venue
|
||||||
|
geometry follows the same budgets and collision/provenance rules.
|
||||||
|
|
||||||
|
## Skeleton and geometry
|
||||||
|
|
||||||
|
The contract skeleton has 13 bones:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Head, Spine, Neck,
|
||||||
|
HipL, HipR,
|
||||||
|
KneeL, KneeR,
|
||||||
|
ShoulderL, ShoulderR,
|
||||||
|
ElbowL, ElbowR,
|
||||||
|
HandL, HandR
|
||||||
|
```
|
||||||
|
|
||||||
|
Requirements:
|
||||||
|
|
||||||
|
- `npc_base` mesh node exists and is skinned under `Rig`.
|
||||||
|
- Limb node names stay stable for `NpcAvatar` and tests.
|
||||||
|
- Front is Blender −Y / Godot +Z.
|
||||||
|
- Feet are grounded at approximately y = 0; no floating origin.
|
||||||
|
- Units are metres; character height is approximately 1.8 m.
|
||||||
|
- No zero-area/duplicate degenerate faces in the exported mesh.
|
||||||
|
- Every character has UVs in [0,1] unless a planned UDIM/atlas change is
|
||||||
|
explicitly accepted.
|
||||||
|
|
||||||
|
## Material slots
|
||||||
|
|
||||||
|
Exactly these five tint slots:
|
||||||
|
|
||||||
|
```text
|
||||||
|
skin, cloth, pants, accessory, hair
|
||||||
|
```
|
||||||
|
|
||||||
|
- Neutral albedo is authored in Blender; runtime tinting is authoritative.
|
||||||
|
- Slot names are contract values; do not rename or add a sixth slot casually.
|
||||||
|
- The procedural fallback (`NpcAvatar._build_body`) must keep working when the
|
||||||
|
GLB is missing.
|
||||||
|
|
||||||
|
## Budgets
|
||||||
|
|
||||||
|
| Asset | Limit |
|
||||||
|
| --- | --- |
|
||||||
|
| Library character | 8,000 triangles / 8,000 glTF vertices |
|
||||||
|
| `npc_base` fallback | 6,000 triangles / 4,000 vertices |
|
||||||
|
| Gear piece | 1,500 triangles |
|
||||||
|
| Prop | 4,000 triangles |
|
||||||
|
| Library prop/venue total | must stay inside the venue tests and library budget |
|
||||||
|
|
||||||
|
`CHAR_MAX_TRIS`, `CHAR_MAX_VERTS`, `GEAR_MAX_TRIS`, `PROP_MAX_TRIS` and related
|
||||||
|
constants live in `tools/blender_assets.py`. The budget is per character, not an
|
||||||
|
average. Measure after every mesh change. Do not lower the cap to make a diff
|
||||||
|
pass.
|
||||||
|
|
||||||
|
## Gear and hand items
|
||||||
|
|
||||||
|
- Gear is authored in the attach-point space documented by `GEAR` /
|
||||||
|
`GEAR_ATTACH` / `ATTACH_BLENDER`.
|
||||||
|
- `blender_assets.py fit` measures gear boxes against the character's head band,
|
||||||
|
clothing radius and back clearance.
|
||||||
|
- Runtime offsets are intentional:
|
||||||
|
- `NpcAvatar.GEAR_OFFSETS = {"lanyard": Vector3(0,0,0.04),
|
||||||
|
"firefighter_helmet": Vector3(0,0.03,0)}`
|
||||||
|
- `NpcAvatar.HAND_ITEM_FORWARD = Vector3(0,0,0.04)`
|
||||||
|
- An offset is **not** an authored-asset change; do not bake it into the GLB
|
||||||
|
without a separate contract decision.
|
||||||
|
- Open-palm grip (no finger-curl rig) is the accepted stylized limit.
|
||||||
|
|
||||||
|
## Textures and AO
|
||||||
|
|
||||||
|
- NPC maps are 256² albedo + normal + packed ORM.
|
||||||
|
- `TEX_SIZE = 256` in `tools/npc_pipeline.py`.
|
||||||
|
- Fabric UV scale is `Materials.NPC_FABRIC_UV_SCALE = Vector3(4,4,1)`.
|
||||||
|
- Cloth/pants skip the per-character baked AO; skin/hair/gear keep it. This
|
||||||
|
avoids the large blotchy magnification that appeared at 256².
|
||||||
|
- Gear/props may have their own AO maps; `tools/bake_ao.py` writes
|
||||||
|
`<name>_ao.png` next to the GLB and Godot wires it into the AO channel.
|
||||||
|
- Never overwrite an existing committed image; use a new `-vN` candidate and
|
||||||
|
promote only after review.
|
||||||
|
- Run `python3 tools/asset_pipeline.py audit <path>` and the relevant
|
||||||
|
`npc_pipeline.py audit` before committing map changes.
|
||||||
|
|
||||||
|
## File map
|
||||||
|
|
||||||
|
| Path | Role |
|
||||||
|
| --- | --- |
|
||||||
|
| `tools/blender_assets.py` | Catalogue, builders, audit/fit/inspect/texels/sheet. |
|
||||||
|
| `tools/npc_pipeline.py` | `npc_base` builder, texture preparation and audit. |
|
||||||
|
| `tools/bake_ao.py` | Blender AO bake into `<name>_ao.png`. |
|
||||||
|
| `tools/npc_proportions.py` | Exported-GLB proportion audit (no Blender). |
|
||||||
|
| `tools/npc_baseline.py` | Contact sheets/comparisons (no Blender). |
|
||||||
|
| `assets/models/blender/manifest.json` | Generated asset manifest. |
|
||||||
|
| `assets/models/blender/**/*.glb` | Committed library assets. |
|
||||||
|
| `assets/models/generated/npc_base.glb` | Frozen NPC fallback. |
|
||||||
|
| `assets/textures/npc/*_{albedo,normal,orm}.png` | Committed NPC maps. |
|
||||||
|
| `src/test/capture_npc_baseline.gd` | 48-frame neutral baseline. |
|
||||||
|
| `src/test/capture_npc_review.gd` | 96-frame final-context review. |
|
||||||
|
|
||||||
|
## Provenance and source rules
|
||||||
|
|
||||||
|
- Procedural Blender assets are project-owned.
|
||||||
|
- External/CC assets need ADR-0015 clearance: CC0 preferred, CC-BY only with
|
||||||
|
attribution in `CREDITS.md`; no service assets with redistribution limits.
|
||||||
|
- Editable `.blend` files under `assets/models/blender_src/` are gitignored;
|
||||||
|
only exported `.glb`, AO maps, manifests and committed preview sheets ship.
|
||||||
|
- AI-generated source images are development inputs, not shipped assets. Keep
|
||||||
|
raw generations under gitignored paths until picked, checked and credited.
|
||||||
|
- Do not copy a downloaded/Street View/AI reference into a committed asset
|
||||||
|
without the licence and provenance review.
|
||||||
|
|
||||||
|
## Verification invariants
|
||||||
|
|
||||||
|
The asset pass is not complete unless:
|
||||||
|
|
||||||
|
1. `python3 tools/blender_assets.py audit` exits 0.
|
||||||
|
2. `python3 tools/blender_assets.py fit` exits 0 and the report is reviewed.
|
||||||
|
3. `python3 tools/npc_proportions.py report` passes the stylized guide.
|
||||||
|
4. `python3 tools/npc_pipeline.py audit` passes when the base/textures changed.
|
||||||
|
5. The 48-frame baseline and 96-frame final-context review are captured, with no
|
||||||
|
blank frames.
|
||||||
|
6. The 24-NPC budget smoke is inside its frame budget.
|
||||||
|
7. The full Godot suite and Python tooling tests pass.
|
||||||
|
8. No runtime contract, renderer or dependency changed except the rebuilt
|
||||||
|
assets and their generated metadata.
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
# Verification Matrix
|
||||||
|
|
||||||
|
Run from the repository root. Stop and fix the first failure before continuing.
|
||||||
|
|
||||||
|
## Environment
|
||||||
|
|
||||||
|
```bash
|
||||||
|
godot --version
|
||||||
|
flatpak run org.blender.Blender --version | head -3
|
||||||
|
git status --short
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: Godot 4.7.2; Blender 5.2 LTS flatpak; clean or intentionally scoped
|
||||||
|
working tree. Blender's flatpak cwd is `/app/blender`; all paths passed to
|
||||||
|
Blender must be absolute.
|
||||||
|
|
||||||
|
## Asset checks
|
||||||
|
|
||||||
|
| Check | Command | Expected |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Contract audit | `python3 tools/blender_assets.py audit` | exit 0, no `BAD` assets |
|
||||||
|
| Gear fit | `python3 tools/blender_assets.py fit` | exit 0; review head band/clothing/back clearances |
|
||||||
|
| Texture/texel density | `python3 tools/blender_assets.py texels` | authored 40–400 px/m; fabric ≥250 px/m |
|
||||||
|
| NPC base | `python3 tools/npc_pipeline.py audit` | exit 0, contract bones/slots/maps |
|
||||||
|
| Proportions | `python3 tools/npc_proportions.py report` | all eight inside the stylized guide |
|
||||||
|
| Single incoming GLB | `flatpak run org.blender.Blender --background --python "$PWD/tools/blender_assets.py" -- inspect --file "$PWD/path.glb" --category <cat> --json` | contract result and measurements |
|
||||||
|
| Prop audit | `python3 tools/model_pipeline.py audit` | exit 0 when generated props changed |
|
||||||
|
| Texture audit | `python3 tools/asset_pipeline.py audit assets/textures/ai/game_ready` | exit 0 when textures changed |
|
||||||
|
|
||||||
|
## Build/bake
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# one library asset
|
||||||
|
flatpak run org.blender.Blender --background \
|
||||||
|
--python "$PWD/tools/blender_assets.py" -- build --only npc_guard
|
||||||
|
|
||||||
|
# bake AO for the same asset
|
||||||
|
flatpak run org.blender.Blender --background \
|
||||||
|
--python "$PWD/tools/bake_ao.py" -- --only npc_guard
|
||||||
|
|
||||||
|
# NPC base material maps/base
|
||||||
|
python3 tools/npc_pipeline.py prepare
|
||||||
|
flatpak run org.blender.Blender --background \
|
||||||
|
--python "$PWD/tools/npc_pipeline.py" -- build
|
||||||
|
python3 tools/npc_pipeline.py audit
|
||||||
|
```
|
||||||
|
|
||||||
|
Only run `prepare` when AI fabric inputs changed. Do not run a full library
|
||||||
|
rebuild just to hide a small diff; build the affected asset and its AO map.
|
||||||
|
|
||||||
|
## Import and tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
godot --headless --path . --import
|
||||||
|
godot --headless --path . --script res://src/test/test_runner.gd
|
||||||
|
python3 -m unittest discover -s tools/tests -t tools -p 'test_*.py'
|
||||||
|
python3 tools/check_docs.py
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: Godot suite passes; Python tooling suite passes; docs check OK. The
|
||||||
|
project uses its own headless runner, not GUT.
|
||||||
|
|
||||||
|
## Capture gates
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# neutral studio baseline: 48 frames (8 characters x 6 views)
|
||||||
|
godot --path . --script res://src/test/capture_npc_baseline.gd \
|
||||||
|
-- --out=res://tmp/npc-baseline-after
|
||||||
|
|
||||||
|
# final-context: 96 frames (8 models x 3 distances x 2 venues x day/night)
|
||||||
|
godot --path . --script res://src/test/capture_npc_review.gd \
|
||||||
|
-- --out=res://tmp/npc-review-after
|
||||||
|
|
||||||
|
# optional hand close-up: 8 frames
|
||||||
|
godot --path . --script res://src/test/capture_npc_baseline.gd \
|
||||||
|
-- --out=res://tmp/npc-hands --view=hand
|
||||||
|
```
|
||||||
|
|
||||||
|
Raw frames stay under `tmp/` and are never committed. Compare with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 tools/npc_baseline.py compare \
|
||||||
|
--before tmp/npc-baseline --after tmp/npc-baseline-after \
|
||||||
|
--out docs/blender_previews/sheet_npc_baseline_compare-<topic>.jpg
|
||||||
|
```
|
||||||
|
|
||||||
|
Do not replace the committed baseline sheet until the change is accepted.
|
||||||
|
|
||||||
|
## Budget/performance
|
||||||
|
|
||||||
|
```bash
|
||||||
|
godot --headless --path . --script res://src/test/smoke_npc_budget.gd
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected report: 24 avatars / 168 meshes / 131,616 triangles (current baseline)
|
||||||
|
inside the 50 ms budget. Record the actual frame time; do not copy an old number
|
||||||
|
without measuring.
|
||||||
|
|
||||||
|
## Visual review criteria
|
||||||
|
|
||||||
|
For each changed variant, inspect at least:
|
||||||
|
|
||||||
|
- 2 m portrait: eyes, mouth, ears, neck/shoulder, hair/headgear clearance.
|
||||||
|
- 4.2 m conversation: hands, gear contact, clothing silhouette.
|
||||||
|
- 8 m crowd: readable silhouette and LOD/impostor swap.
|
||||||
|
- Day and night/LATE final-context frames.
|
||||||
|
- Front, three-quarter and profile for a shape change.
|
||||||
|
|
||||||
|
Accepted stylized limits are in `docs/npc-visual-review.md` and
|
||||||
|
`docs/known-limitations.md`. Do not turn an accepted limit into an unreviewed
|
||||||
|
contract change.
|
||||||
|
|
||||||
|
## Final diff review
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git diff --check
|
||||||
|
git status --short
|
||||||
|
git diff --stat
|
||||||
|
```
|
||||||
|
|
||||||
|
Check that only intended `.glb`, AO/maps, manifest, tests and docs changed. If a
|
||||||
|
`.blend`, raw capture, generated AI input or temporary sheet is staged, stop and
|
||||||
|
remove it. Commit one coherent asset family per commit.
|
||||||
@@ -0,0 +1,254 @@
|
|||||||
|
---
|
||||||
|
name: gig-line-release-qa
|
||||||
|
description: Use when preparing, validating, tagging or publishing a Gig Line release or release candidate, or when running the full screenshot, screen-design and realism QA gates. Covers version/changelog discipline, smoke and tooling matrices, clean-worktree builds, checksums, Web/HQ verification, publish rollback and post-release records. Do not use for ordinary asset edits or feature work.
|
||||||
|
compatibility: Gig Line repository checkout with Godot 4.7.2 on PATH and Python 3 + Pillow. Release export needs installed Godot export templates; publishing needs Gitea credentials and is intentionally CI/tag-driven.
|
||||||
|
metadata:
|
||||||
|
project: Gig Line
|
||||||
|
domain: release-qa
|
||||||
|
version: "1.0.0"
|
||||||
|
triggers: release, tag, version bump, changelog, build releases, publish, screenshots, screen design, realism judge, release candidate, deployment
|
||||||
|
---
|
||||||
|
|
||||||
|
# Gig Line Release and Visual QA
|
||||||
|
|
||||||
|
Use this skill for version bumps, release candidates, tags, artifact builds,
|
||||||
|
publishing, and the full visual/QA gate. For a Blender/asset rebuild, use
|
||||||
|
`gig-line-blender-asset-contract` first.
|
||||||
|
|
||||||
|
## Read first
|
||||||
|
|
||||||
|
1. `AGENTS.md` — release procedure and verification rules.
|
||||||
|
2. `TODO.md` — current milestone, blockers and release exit criteria.
|
||||||
|
3. `docs/RELEASING.md` — build/publish commands, artifact list, macOS policy.
|
||||||
|
4. `docs/smoke-checklist.md` — manual QA matrix.
|
||||||
|
5. `docs/development-status.md`, `CHANGELOG.md`, `README.md` — current claims.
|
||||||
|
6. `MEMORY.md` — release gotchas, especially the clean-worktree rule.
|
||||||
|
|
||||||
|
A release is not just a tag. It includes a version bump, changelog, clean build,
|
||||||
|
artifact/checksum verification, CI publication, and post-release records.
|
||||||
|
|
||||||
|
## Hard rules
|
||||||
|
|
||||||
|
- **Do not tag while the TODO still lists unresolved release blockers.** Check
|
||||||
|
external playtest, legal/AI provenance, signing and target-hardware items.
|
||||||
|
- **Never reuse a tag.** If a published version needs a fix, bump the patch and
|
||||||
|
create a new tag.
|
||||||
|
- **Build from a clean checkout or detached worktree.** A normal working tree can
|
||||||
|
pack ignored `tmp/` and `build/` content into exports, inflating a ~160 MB
|
||||||
|
package to 1.6–3.1 GB.
|
||||||
|
- A tag push triggers CI checks/build/publish. Do not upload manually unless CI is
|
||||||
|
unavailable and you have followed the same preflight.
|
||||||
|
- Do not commit generated realism runs, raw captures, API keys, or build artifacts.
|
||||||
|
- The vision judge is an optional development aid with external API cost, never a
|
||||||
|
hard CI gate.
|
||||||
|
- Keep `project.godot`, changelog, tag and release asset version equal.
|
||||||
|
|
||||||
|
## Release workflow
|
||||||
|
|
||||||
|
### 1. Scope and version
|
||||||
|
|
||||||
|
Choose the semantic increment from `AGENTS.md`:
|
||||||
|
|
||||||
|
- MAJOR: incompatible/removed behavior, save/config contract or core-pillar
|
||||||
|
replacement.
|
||||||
|
- MINOR: new user-facing feature/venue.
|
||||||
|
- PATCH: fixes and polish.
|
||||||
|
|
||||||
|
Update:
|
||||||
|
|
||||||
|
1. `project.godot` `config/version`.
|
||||||
|
2. `CHANGELOG.md` with a dated entry.
|
||||||
|
3. `README.md`, `PLAN.md`, `docs/architecture.md`,
|
||||||
|
`docs/development-status.md`, `TODO.md`/`DONE.md` and `MEMORY.md` as needed.
|
||||||
|
|
||||||
|
For a release candidate, use a prerelease version only if the project policy
|
||||||
|
allows it and never present it as the final release.
|
||||||
|
|
||||||
|
### 2. Preflight
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git status --short
|
||||||
|
git log --oneline -5
|
||||||
|
git tag -l "v<version>"
|
||||||
|
rg -n 'config/version' project.godot
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: only intended release changes; tag does not exist; version matches the
|
||||||
|
changelog and planned artifacts.
|
||||||
|
|
||||||
|
### 3. Automated checks
|
||||||
|
|
||||||
|
```bash
|
||||||
|
godot --headless --path . --script res://src/test/test_runner.gd
|
||||||
|
python3 -m unittest discover -s tools/tests -t tools -p 'test_*.py'
|
||||||
|
python3 tools/check_docs.py
|
||||||
|
python3 tools/blender_assets.py audit
|
||||||
|
python3 tools/blender_assets.py fit
|
||||||
|
python3 tools/npc_proportions.py report
|
||||||
|
python3 tools/npc_pipeline.py audit
|
||||||
|
```
|
||||||
|
|
||||||
|
Then run the smoke matrix, using isolated user-data directories for
|
||||||
|
tutorial/campaign:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
for s in smoke_audio smoke_crowd smoke_emergency smoke_npc_budget \
|
||||||
|
smoke_plan_verbs smoke_scenario_content smoke_session_shell \
|
||||||
|
smoke_timeline smoke_ui_flows; do
|
||||||
|
godot --headless --path . --script res://src/test/$s.gd || exit 1
|
||||||
|
done
|
||||||
|
|
||||||
|
XDG_DATA_HOME=/tmp/gig-line-campaign godot --path . --fixed-fps 60 \
|
||||||
|
--script res://src/test/smoke_campaign.gd
|
||||||
|
XDG_DATA_HOME=/tmp/gig-line-tutorial godot --path . --fixed-fps 60 \
|
||||||
|
--script res://src/test/smoke_tutorial.gd -- --tutorial
|
||||||
|
|
||||||
|
godot --path . --script res://src/test/smoke_movement.gd
|
||||||
|
godot --path . --script res://src/test/smoke_props.gd
|
||||||
|
godot --path . --script res://src/test/smoke_focus_radial.gd
|
||||||
|
```
|
||||||
|
|
||||||
|
Use a fresh `$XDG_DATA_HOME` for campaign/tutorial and check the exit code, not
|
||||||
|
just the log.
|
||||||
|
|
||||||
|
### 4. Visual and judge gates
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./tools/check_screenshots.sh
|
||||||
|
python3 tools/screen_designs.py compare
|
||||||
|
python3 tools/screen_designs.py judge --model auto # optional, record model/verdicts
|
||||||
|
```
|
||||||
|
|
||||||
|
For realism/venue work:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
godot --path . --script res://src/test/capture_realism.gd \
|
||||||
|
-- --out=res://docs/screens/realism/<run>/after
|
||||||
|
python3 tools/scene_concepts.py realism --run docs/screens/realism/<run> \
|
||||||
|
--judge --model <pinned-model>
|
||||||
|
```
|
||||||
|
|
||||||
|
Requirements:
|
||||||
|
|
||||||
|
- Gallery: 21 good / 0 bad; screen judge has no unexplained `diff`.
|
||||||
|
- Realism runs stay under `docs/screens/realism/` (gitignored); only decisions and
|
||||||
|
committed sheets/docs are tracked.
|
||||||
|
- Record judge model, run count/attempts, spend if exposed, and verdicts.
|
||||||
|
- Review every `review` verdict; turn layout regressions into fixes or documented
|
||||||
|
known limitations.
|
||||||
|
|
||||||
|
### 5. Clean build
|
||||||
|
|
||||||
|
Commit the release preparation first, then build the committed tree in a clean
|
||||||
|
worktree:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git worktree add --detach /tmp/gig-line-release HEAD
|
||||||
|
cd /tmp/gig-line-release
|
||||||
|
./tools/build_releases.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Verify artifact names/sizes and checksums:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ls -lh build/gig-line-*<version>*
|
||||||
|
PUBLISH_DRY_RUN=1 ./tools/publish_release.sh <version>
|
||||||
|
sha256sum -c build/SHA256SUMS-<version>.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
Check package contents:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
unzip -l build/gig-line-web-<version>.zip | head
|
||||||
|
unzip -l build/gig-line-desktop-hq-<version>.zip | head
|
||||||
|
unzip -p build/gig-line-desktop-hq-<version>.zip override.cfg
|
||||||
|
```
|
||||||
|
|
||||||
|
Check the runnable Linux and HQ packages:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./build/gig-line-linux-<version>.x86_64 --headless --quit-after 60
|
||||||
|
unzip -q build/gig-line-desktop-hq-<version>.zip -d /tmp/gig-line-hq
|
||||||
|
/tmp/gig-line-hq/gig-line-linux-<version>.x86_64 --headless --quit-after 60
|
||||||
|
```
|
||||||
|
|
||||||
|
Check Web static serving with a local HTTP server and `curl` for `index.html`,
|
||||||
|
`index.wasm`, `index.pck` and the player docs. Windows/macOS/AppImage/installer
|
||||||
|
checks require the target matrix; if unavailable, record that explicitly.
|
||||||
|
|
||||||
|
Remove the worktree after verification:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git worktree remove --force /tmp/gig-line-release
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. Tag and publish
|
||||||
|
|
||||||
|
Only after every gate is green:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add -A
|
||||||
|
git commit -m "Release <version> <topic>"
|
||||||
|
git tag -a "v<version>" -m "Gig Line <version>"
|
||||||
|
git push origin main "v<version>"
|
||||||
|
```
|
||||||
|
|
||||||
|
CI builds and publishes on the tag. Verify:
|
||||||
|
|
||||||
|
- Tag commit equals the release commit.
|
||||||
|
- CI checks/build job succeeded.
|
||||||
|
- Release page has the expected 7 assets (Linux, Windows, macOS, NSIS setup,
|
||||||
|
AppImage, Web, Desktop HQ).
|
||||||
|
- Asset names and download links point at the released version.
|
||||||
|
|
||||||
|
`tools/publish_release.sh` preflights artifact size/free space, writes SHA-256
|
||||||
|
checksums, rolls back newly uploaded assets/release on failure, and supports
|
||||||
|
opt-in retention:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
RETAIN_RELEASES=7 ./tools/publish_release.sh <version>
|
||||||
|
```
|
||||||
|
|
||||||
|
The default `RETAIN_RELEASES=0` never prunes.
|
||||||
|
|
||||||
|
### 7. Post-release record
|
||||||
|
|
||||||
|
Update `README.md`, `docs/development-status.md`, `MEMORY.md`, `CHANGELOG.md`,
|
||||||
|
`TODO.md`/`DONE.md` and the release page with the built/CI result. Commit the
|
||||||
|
release record and push. Record any skipped check and the reason; never leave a
|
||||||
|
tag with unreported missing verification.
|
||||||
|
|
||||||
|
## Known gotchas
|
||||||
|
|
||||||
|
- **Dirty build inflation:** always use the clean worktree above.
|
||||||
|
- **`Class ... hides a global script class`:** remove stray `.gd` backups in
|
||||||
|
`tmp/`, delete `.godot`, re-import.
|
||||||
|
- **Screenshot staging:** `capture_ui_states.gd` needs its settle frames and
|
||||||
|
staged state; do not capture a paused frame or a stale modal.
|
||||||
|
- **Judge keys:** OpenRouter calls need `.env`/`OPENROUTER_API_KEY`; never commit
|
||||||
|
the key or generated review folders.
|
||||||
|
- **Tag builds publish automatically:** do not run a second manual publish that
|
||||||
|
duplicates assets; use the existing release if re-running.
|
||||||
|
- **macOS is unsigned unless policy changes:** record quarantine instructions and
|
||||||
|
do not claim notarization.
|
||||||
|
- **Release blockers are real:** external playtest, legal/storefront approval,
|
||||||
|
AI-provider rights and target-hardware checks cannot be replaced by green unit
|
||||||
|
tests.
|
||||||
|
|
||||||
|
## Bundled references
|
||||||
|
|
||||||
|
- [`references/release-runbook.md`](references/release-runbook.md) — version,
|
||||||
|
build, tag, CI, publish and rollback sequence.
|
||||||
|
- [`references/qa-gates.md`](references/qa-gates.md) — full command matrix,
|
||||||
|
expected results and evidence to record.
|
||||||
|
|
||||||
|
## Completion checklist
|
||||||
|
|
||||||
|
- [ ] Version/changelog/docs/tag match.
|
||||||
|
- [ ] No unresolved release blockers for a final tag.
|
||||||
|
- [ ] Godot, Python, smokes, asset and docs gates pass.
|
||||||
|
- [ ] Gallery and optional judges reviewed with evidence.
|
||||||
|
- [ ] Clean worktree build and checksums verified.
|
||||||
|
- [ ] Linux/HQ/Web checks recorded; unavailable platforms noted.
|
||||||
|
- [ ] Tag pushed; CI/publish succeeded; seven assets verified.
|
||||||
|
- [ ] Release record and durable docs committed.
|
||||||
@@ -0,0 +1,171 @@
|
|||||||
|
# QA Gate Matrix
|
||||||
|
|
||||||
|
Run from the repository root. Capture the exit code and the useful report line,
|
||||||
|
not only the final “OK”.
|
||||||
|
|
||||||
|
## 1. Source and docs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git status --short
|
||||||
|
git log --oneline -5
|
||||||
|
python3 tools/check_docs.py
|
||||||
|
git diff --check
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: intended files only; `check_docs: OK`; no whitespace errors.
|
||||||
|
|
||||||
|
## 2. Automated suites
|
||||||
|
|
||||||
|
```bash
|
||||||
|
godot --headless --path . --script res://src/test/test_runner.gd
|
||||||
|
python3 -m unittest discover -s tools/tests -t tools -p 'test_*.py'
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: the current Godot suite passes (historically 272+ tests) and the
|
||||||
|
Python tooling suite passes (currently 160 tests). Do not edit expected counts
|
||||||
|
without inspecting the suite.
|
||||||
|
|
||||||
|
## 3. Asset gates
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 tools/blender_assets.py audit
|
||||||
|
python3 tools/blender_assets.py fit
|
||||||
|
python3 tools/blender_assets.py texels
|
||||||
|
python3 tools/npc_pipeline.py audit
|
||||||
|
python3 tools/npc_proportions.py report
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: exit 0, no `BAD` assets, all eight characters inside the stylized
|
||||||
|
proportion guide, no budget/contract regression.
|
||||||
|
|
||||||
|
Optional texture/model audits when those assets changed:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 tools/asset_pipeline.py audit assets/textures/ai/game_ready
|
||||||
|
python3 tools/model_pipeline.py audit
|
||||||
|
```
|
||||||
|
|
||||||
|
## 4. Smoke matrix
|
||||||
|
|
||||||
|
Headless:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
for s in smoke_audio smoke_crowd smoke_emergency smoke_npc_budget \
|
||||||
|
smoke_plan_verbs smoke_scenario_content smoke_session_shell \
|
||||||
|
smoke_timeline smoke_ui_flows; do
|
||||||
|
echo "== $s"
|
||||||
|
godot --headless --path . --script res://src/test/$s.gd || exit 1
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
Isolated data:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
rm -rf /tmp/gig-line-release-campaign /tmp/gig-line-release-tutorial
|
||||||
|
XDG_DATA_HOME=/tmp/gig-line-release-campaign godot --path . --fixed-fps 60 \
|
||||||
|
--script res://src/test/smoke_campaign.gd
|
||||||
|
XDG_DATA_HOME=/tmp/gig-line-release-tutorial godot --path . --fixed-fps 60 \
|
||||||
|
--script res://src/test/smoke_tutorial.gd -- --tutorial
|
||||||
|
```
|
||||||
|
|
||||||
|
Windowed input/UI:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
godot --path . --script res://src/test/smoke_movement.gd
|
||||||
|
godot --path . --script res://src/test/smoke_props.gd
|
||||||
|
godot --path . --script res://src/test/smoke_focus_radial.gd
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: 14 smokes green. `smoke_npc_budget` should print the current mesh,
|
||||||
|
triangle and frame-time evidence; the 50 ms budget is a safety ceiling.
|
||||||
|
|
||||||
|
## 5. Screenshot and design gates
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./tools/check_screenshots.sh
|
||||||
|
python3 tools/screen_designs.py compare
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: 21 good / 0 bad; no unexplained compare output. The judge is optional:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 tools/screen_designs.py judge --model auto
|
||||||
|
```
|
||||||
|
|
||||||
|
Record model, confidence/verdict summary, `diff` count and any manual review.
|
||||||
|
`docs/screen-design-report.md` is the durable record.
|
||||||
|
|
||||||
|
## 6. Realism judge (when visual assets/lighting changed)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
godot --path . --script res://src/test/capture_realism.gd \
|
||||||
|
-- --out=res://docs/screens/realism/<run>/after
|
||||||
|
python3 tools/scene_concepts.py realism --run docs/screens/realism/<run> \
|
||||||
|
--judge --model <pinned-model>
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: a complete set of required stage captures, no stale pauses/modals, and
|
||||||
|
a report under the gitignored run directory. Record:
|
||||||
|
|
||||||
|
- pinned model/fallbacks
|
||||||
|
- shots attempted/completed
|
||||||
|
- spend if the tool exposes it
|
||||||
|
- mean score and Pillow gap
|
||||||
|
- every `review` verdict and disposition
|
||||||
|
|
||||||
|
Do not commit the run. Commit only the decision/report summary and any durable
|
||||||
|
comparison sheet explicitly intended for review.
|
||||||
|
|
||||||
|
## 7. Package checks
|
||||||
|
|
||||||
|
Use the clean worktree from `release-runbook.md`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
PUBLISH_DRY_RUN=1 ./tools/publish_release.sh <version>
|
||||||
|
sha256sum -c build/SHA256SUMS-<version>.txt
|
||||||
|
unzip -l build/gig-line-web-<version>.zip
|
||||||
|
unzip -l build/gig-line-desktop-hq-<version>.zip
|
||||||
|
unzip -p build/gig-line-desktop-hq-<version>.zip override.cfg
|
||||||
|
./build/gig-line-linux-<version>.x86_64 --headless --quit-after 60
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected:
|
||||||
|
|
||||||
|
- names match the version;
|
||||||
|
- Linux/Windows/macOS/Web/HQ present locally;
|
||||||
|
- Web contains HTML/wasm/pck and docs;
|
||||||
|
- HQ contains `override.cfg`, executables and docs;
|
||||||
|
- Linux/HQ start without a script error.
|
||||||
|
|
||||||
|
Windows installer/AppImage and macOS launch require CI or the target matrix. If
|
||||||
|
not available, mark them as unverified rather than passing them by analogy.
|
||||||
|
|
||||||
|
## 8. Release verification
|
||||||
|
|
||||||
|
After the tag push:
|
||||||
|
|
||||||
|
- CI checks job succeeded;
|
||||||
|
- CI build job succeeded;
|
||||||
|
- release page has seven assets;
|
||||||
|
- each artifact name includes the released version;
|
||||||
|
- the tag points at the release commit;
|
||||||
|
- README/changelog/status and release notes agree.
|
||||||
|
|
||||||
|
## Evidence summary template
|
||||||
|
|
||||||
|
```text
|
||||||
|
Release: vX.Y.Z (commit)
|
||||||
|
Godot: pass (N/N)
|
||||||
|
Python tooling: pass (N/N)
|
||||||
|
Smokes: 14/14
|
||||||
|
Assets: audit/fit/proportions/npc audit pass
|
||||||
|
Budget: 24 NPCs, N meshes, N triangles, N ms
|
||||||
|
Gallery: 21 good / 0 bad
|
||||||
|
Screen judge: N/N match, N review, N diff
|
||||||
|
Realism: model, attempts, mean, gap, review dispositions
|
||||||
|
Build: clean worktree, artifact sizes/checksums
|
||||||
|
Launch: Linux/HQ/Web checks; unverified platforms
|
||||||
|
CI/release: run id, seven assets
|
||||||
|
Skipped checks + reason:
|
||||||
|
Known limitations:
|
||||||
|
```
|
||||||
@@ -0,0 +1,171 @@
|
|||||||
|
# Release Runbook
|
||||||
|
|
||||||
|
Authoritative source: `AGENTS.md` (Release Procedure), `docs/RELEASING.md`.
|
||||||
|
This runbook is the operational checklist; if it conflicts with those, they win.
|
||||||
|
|
||||||
|
## 0. Decide the release
|
||||||
|
|
||||||
|
Determine whether this is a major, minor, patch, or release-candidate checkpoint.
|
||||||
|
Do not assign a version to an unversioned development track until its scope is
|
||||||
|
accepted into a release.
|
||||||
|
|
||||||
|
Check the current release constraints in `TODO.md`:
|
||||||
|
|
||||||
|
- external playtest evidence
|
||||||
|
- legal/AI-provider/storefront review
|
||||||
|
- macOS signing/notarization policy
|
||||||
|
- target hardware matrix
|
||||||
|
- any manual QA gaps
|
||||||
|
|
||||||
|
If a final release would ship with unresolved blockers, prepare an RC or stop;
|
||||||
|
do not create a final tag.
|
||||||
|
|
||||||
|
## 1. Prepare the version
|
||||||
|
|
||||||
|
Files to update:
|
||||||
|
|
||||||
|
| File | Change |
|
||||||
|
| --- | --- |
|
||||||
|
| `project.godot` | `config/version="X.Y.Z"` |
|
||||||
|
| `CHANGELOG.md` | dated `## [X.Y.Z] — YYYY-MM-DD` entry |
|
||||||
|
| `README.md` | latest/current version and summary |
|
||||||
|
| `PLAN.md` / `docs/architecture.md` | current version reference |
|
||||||
|
| `docs/development-status.md` | shipped capability/release result |
|
||||||
|
| `TODO.md` / `DONE.md` | close/move milestone when complete |
|
||||||
|
| `MEMORY.md` | release state and gotchas |
|
||||||
|
|
||||||
|
Then commit the preparation before building.
|
||||||
|
|
||||||
|
## 2. Run gates
|
||||||
|
|
||||||
|
Use `qa-gates.md` as the command matrix. The minimum release gate is:
|
||||||
|
|
||||||
|
- Godot suite
|
||||||
|
- Python tooling tests
|
||||||
|
- documentation gate
|
||||||
|
- asset audits/fit/proportions
|
||||||
|
- 24-NPC budget
|
||||||
|
- 14 smoke scripts
|
||||||
|
- screenshot compare
|
||||||
|
- optional screen/realism judge with recorded model/attempts
|
||||||
|
- clean build and artifact checks
|
||||||
|
|
||||||
|
Any skipped check must be written into `MEMORY.md` or `TODO.md` with a reason.
|
||||||
|
|
||||||
|
## 3. Build in a clean worktree
|
||||||
|
|
||||||
|
Why: Godot can pack ignored `tmp/` captures and `build/` outputs into the export.
|
||||||
|
A dirty build can produce 1.6–3.1 GB artifacts instead of ~160–240 MB.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git worktree add --detach /tmp/gig-line-release HEAD
|
||||||
|
cd /tmp/gig-line-release
|
||||||
|
./tools/build_releases.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected local artifacts:
|
||||||
|
|
||||||
|
```text
|
||||||
|
build/gig-line-linux-<version>.x86_64
|
||||||
|
build/gig-line-windows-<version>.exe
|
||||||
|
build/gig-line-macos-<version>.zip
|
||||||
|
build/gig-line-web-<version>.zip
|
||||||
|
build/gig-line-desktop-hq-<version>.zip
|
||||||
|
```
|
||||||
|
|
||||||
|
CI additionally produces the NSIS setup and AppImage, for seven release assets.
|
||||||
|
|
||||||
|
## 4. Preflight and checksum
|
||||||
|
|
||||||
|
```bash
|
||||||
|
PUBLISH_DRY_RUN=1 ./tools/publish_release.sh <version>
|
||||||
|
sha256sum -c build/SHA256SUMS-<version>.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
`publish_release.sh` checks non-empty artifacts and local free space before any
|
||||||
|
API call. It writes checksums under `build/` and does not upload them by default.
|
||||||
|
|
||||||
|
Inspect packages:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
unzip -l build/gig-line-web-<version>.zip | head -20
|
||||||
|
unzip -l build/gig-line-desktop-hq-<version>.zip | head -20
|
||||||
|
unzip -p build/gig-line-desktop-hq-<version>.zip override.cfg
|
||||||
|
```
|
||||||
|
|
||||||
|
Web must contain `index.html`, `index.wasm`, `index.pck`, and player docs.
|
||||||
|
Desktop HQ must contain the Linux/Windows executables, `override.cfg`,
|
||||||
|
`README.txt`, `CREDITS.md`, `PRIVACY.md`, `accessibility.md` and
|
||||||
|
`known-limitations.md`.
|
||||||
|
|
||||||
|
## 5. Runtime launch smoke
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./build/gig-line-linux-<version>.x86_64 --headless --quit-after 60
|
||||||
|
unzip -q build/gig-line-desktop-hq-<version>.zip -d /tmp/gig-line-hq
|
||||||
|
/tmp/gig-line-hq/gig-line-linux-<version>.x86_64 --headless --quit-after 60
|
||||||
|
```
|
||||||
|
|
||||||
|
For Web, serve `build/web` and check HTTP 200 for `index.html`, `index.wasm`,
|
||||||
|
`index.pck` and docs. Do not claim browser interaction from a curl check.
|
||||||
|
|
||||||
|
Remove the temporary worktree after checks:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git worktree remove --force /tmp/gig-line-release
|
||||||
|
```
|
||||||
|
|
||||||
|
## 6. Tag and CI
|
||||||
|
|
||||||
|
From the real repository, on the release commit:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git tag -a "v<version>" -m "Gig Line <version>"
|
||||||
|
git push origin main "v<version>"
|
||||||
|
```
|
||||||
|
|
||||||
|
The tag triggers `.gitea/workflows/build.yml`: checks, export, installer,
|
||||||
|
AppImage, release publish. Verify the run and assets:
|
||||||
|
|
||||||
|
- check job success
|
||||||
|
- build job success
|
||||||
|
- seven assets present
|
||||||
|
- tag/version/artifact names equal
|
||||||
|
- download links respond
|
||||||
|
|
||||||
|
Do not reuse a published tag. If a fix is needed, bump patch and repeat.
|
||||||
|
|
||||||
|
## 7. Manual publish fallback
|
||||||
|
|
||||||
|
Only if CI cannot publish:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
RETAIN_RELEASES=7 ./tools/publish_release.sh <version>
|
||||||
|
```
|
||||||
|
|
||||||
|
The script reuses or creates the release, uploads present artifacts, verifies the
|
||||||
|
asset count, and rolls back newly uploaded assets/new release on failure. The
|
||||||
|
default retention is `0` (no deletion). Never delete older releases implicitly.
|
||||||
|
|
||||||
|
## 8. Post-release record
|
||||||
|
|
||||||
|
Commit a release record that includes:
|
||||||
|
|
||||||
|
- tag and commit
|
||||||
|
- CI run/result
|
||||||
|
- seven assets
|
||||||
|
- checksums or size evidence
|
||||||
|
- skipped checks
|
||||||
|
- known limitations
|
||||||
|
- release URL
|
||||||
|
|
||||||
|
Update `DONE.md`/`TODO.md` and `MEMORY.md`; keep the changelog and README
|
||||||
|
consistent. Push the record commit.
|
||||||
|
|
||||||
|
## Versioning pitfalls
|
||||||
|
|
||||||
|
- A `vX.Y.Z` tag is immutable in practice; do not move/replace it.
|
||||||
|
- A release candidate is not a final release. Do not label it as such in the
|
||||||
|
README or release page if blockers remain.
|
||||||
|
- `config/version` must match the tag and artifact filenames.
|
||||||
|
- The clean-worktree build is a release requirement, not an optimization.
|
||||||
+12
-2
@@ -59,9 +59,19 @@ assets/models/generated/npc_base_*_normal.png
|
|||||||
# Local AppImage extraction
|
# Local AppImage extraction
|
||||||
squashfs-root/
|
squashfs-root/
|
||||||
|
|
||||||
# Local agent skills (installed per machine from the Blender Skills Pack; not part of
|
# Local agent skills. The third-party Blender pack is installed per machine and
|
||||||
# the game, tests or release artifacts, and never shipped)
|
# stays ignored; the two project-authored skills are tracked so the workflow can
|
||||||
|
# be shared and reviewed.
|
||||||
.agents/
|
.agents/
|
||||||
|
!.agents/
|
||||||
|
.agents/*
|
||||||
|
!.agents/.gdignore
|
||||||
|
!.agents/skills/
|
||||||
|
.agents/skills/*
|
||||||
|
!.agents/skills/gig-line-blender-asset-contract/
|
||||||
|
!.agents/skills/gig-line-blender-asset-contract/**
|
||||||
|
!.agents/skills/gig-line-release-qa/
|
||||||
|
!.agents/skills/gig-line-release-qa/**
|
||||||
# Blender asset library: per-asset Cycles renders are local review output (the
|
# Blender asset library: per-asset Cycles renders are local review output (the
|
||||||
# committed review artefacts are docs/blender_previews/sheet_*.jpg), and Godot
|
# committed review artefacts are docs/blender_previews/sheet_*.jpg), and Godot
|
||||||
# extracts the GLB-embedded textures next to the models on import.
|
# extracts the GLB-embedded textures next to the models on import.
|
||||||
|
|||||||
@@ -48,6 +48,19 @@ forces one.
|
|||||||
Use them when a task touches `tools/blender_assets.py`, `tools/npc_pipeline.py`,
|
Use them when a task touches `tools/blender_assets.py`, `tools/npc_pipeline.py`,
|
||||||
`tools/bake_ao.py`, `assets/models/blender/**`, or Blender-authored venue/prop geometry.
|
`tools/bake_ao.py`, `assets/models/blender/**`, or Blender-authored venue/prop geometry.
|
||||||
|
|
||||||
|
### Project-authored skills (tracked)
|
||||||
|
|
||||||
|
Two project skills are committed under `.agents/skills/` and are guidance for
|
||||||
|
any agent, not only Pi:
|
||||||
|
|
||||||
|
- `gig-line-blender-asset-contract` — the NPC/gear/prop contract, build order,
|
||||||
|
headless Blender commands, failure playbook and verification gates.
|
||||||
|
- `gig-line-release-qa` — the test/smoke matrix, visual judges, clean-worktree
|
||||||
|
build, checksum/tag/publish sequence and release records.
|
||||||
|
|
||||||
|
They are not runtime dependencies and do not move tool implementations into
|
||||||
|
`.agents/`. The third-party `blender-skills` pack stays local/gitignored.
|
||||||
|
|
||||||
### Routing
|
### Routing
|
||||||
|
|
||||||
Start with `blender-director` for anything multi-discipline, then load only the
|
Start with `blender-director` for anything multi-discipline, then load only the
|
||||||
|
|||||||
@@ -10,6 +10,10 @@ canonical implemented-features list in `docs/development-status.md`.
|
|||||||
the licence gate. Downloads live in `tmp/research/` (gitignored): DDG image search, street-view
|
the licence gate. Downloads live in `tmp/research/` (gitignored): DDG image search, street-view
|
||||||
frames, neighbouring buildings — never committed, never shipped. Promotion into
|
frames, neighbouring buildings — never committed, never shipped. Promotion into
|
||||||
`docs/screens/refs/` always passes the sidecar licence + privacy gate and `CREDITS.md`.
|
`docs/screens/refs/` always passes the sidecar licence + privacy gate and `CREDITS.md`.
|
||||||
|
- **Project agent skills (2026-11-03):** two tracked skills live in `.agents/skills/`:
|
||||||
|
`gig-line-blender-asset-contract` and `gig-line-release-qa`. They are guidance only,
|
||||||
|
add no runtime dependency and are referenced from `tools/README.md`. The third-party
|
||||||
|
`blender-skills` pack remains gitignored.
|
||||||
- **TV Studio shares the Hollywood location (owner):** the Late Night TV Studio is the same El
|
- **TV Studio shares the Hollywood location (owner):** the Late Night TV Studio is the same El
|
||||||
Capitan Entertainment Centre block at 6840 Hollywood Blvd (which houses *Jimmy Kimmel Live!*),
|
Capitan Entertainment Centre block at 6840 Hollywood Blvd (which houses *Jimmy Kimmel Live!*),
|
||||||
restaged for a late-night arrival. `VENUE_SPECS["tv_studio"]` is a 30.0 m variant of the 29.6 m
|
restaged for a late-night arrival. `VENUE_SPECS["tv_studio"]` is a 30.0 m variant of the 29.6 m
|
||||||
|
|||||||
@@ -170,6 +170,8 @@ Full setup, every run/test/smoke command, and the controls table are in
|
|||||||
- [`docs/tutorial.md`](docs/tutorial.md) — First-shift tutorial beats and rules.
|
- [`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.
|
- [`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.
|
- [`tools/README.md`](tools/README.md) — Tool inventory, categories, test commands and AI-skill evaluation.
|
||||||
|
- [`.agents/skills/gig-line-blender-asset-contract`](.agents/skills/gig-line-blender-asset-contract/SKILL.md) — tracked AI skill for Blender/NPC/gear asset work.
|
||||||
|
- [`.agents/skills/gig-line-release-qa`](.agents/skills/gig-line-release-qa/SKILL.md) — tracked AI skill for release and visual-QA work.
|
||||||
- [`docs/getting-started.md`](docs/getting-started.md) — Setup, run/test commands, and controls.
|
- [`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/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.
|
- [`docs/accessibility.md`](docs/accessibility.md) — Accessibility features, known gaps and statement.
|
||||||
|
|||||||
@@ -618,6 +618,17 @@ three-up boards; `tools/refboard.py` + reference-anchored generation (`--referen
|
|||||||
- [ ] Prefer `tools/scene_concepts.py promote` (or a manual move into `game_ready/v2/` plus a
|
- [ ] Prefer `tools/scene_concepts.py promote` (or a manual move into `game_ready/v2/` plus a
|
||||||
`PICKS` entry) so new picks follow the same path as `limestone_ashlar` and `dark_stucco`.
|
`PICKS` entry) so new picks follow the same path as `limestone_ashlar` and `dark_stucco`.
|
||||||
|
|
||||||
|
### Agent skill upkeep
|
||||||
|
|
||||||
|
- [x] Add the tracked project skills `gig-line-blender-asset-contract` and
|
||||||
|
`gig-line-release-qa` under `.agents/skills/`, with references for the
|
||||||
|
asset contract/verification and release/QA runbooks.
|
||||||
|
- [x] Keep the third-party `blender-skills` pack local/gitignored while allowing
|
||||||
|
project-authored skills to be committed; reference the skills from
|
||||||
|
`tools/README.md`, `AGENTS.md` and `MEMORY.md`.
|
||||||
|
- [ ] Revisit the skills after the next Blender or release work changes the
|
||||||
|
contract, commands or gates; stale skills are worse than no skill.
|
||||||
|
|
||||||
### Blender skills upkeep
|
### Blender skills upkeep
|
||||||
|
|
||||||
- [ ] Re-check the installed Blender pack (`version.json`) when updating it and record the version
|
- [ ] Re-check the installed Blender pack (`version.json`) when updating it and record the version
|
||||||
|
|||||||
+14
-23
@@ -129,34 +129,25 @@ 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
|
`requirements-tools.txt` (Pillow) and do not start Godot or Blender. See
|
||||||
[`tests/README.md`](tests/README.md) for the exact discovery command.
|
[`tests/README.md`](tests/README.md) for the exact discovery command.
|
||||||
|
|
||||||
## Which tools could become AI skills?
|
## Project AI skills
|
||||||
|
|
||||||
A skill is a **procedure and decision guide**, not a script wrapper. The useful
|
Two project-authored skills now live under
|
||||||
split is project-specific judgement that an AI repeatedly needs, not a second
|
[`../.agents/skills/`](../.agents/skills/) and are tracked in the repository:
|
||||||
copy of every command.
|
|
||||||
|
|
||||||
### Recommended: elevate as a project skill
|
- [`gig-line-blender-asset-contract`](../.agents/skills/gig-line-blender-asset-contract/SKILL.md) — contract, command order, failure playbook and verification for Blender/NPC/gear/prop work.
|
||||||
|
- [`gig-line-release-qa`](../.agents/skills/gig-line-release-qa/SKILL.md) — test/smoke matrix, visual gates, clean build, checksums, tag/publish and release records.
|
||||||
|
|
||||||
1. **`gig-line-blender-asset-contract` (high value).**
|
The third-party `blender-skills` pack remains local/gitignored. These project
|
||||||
Bundle the ordering and contract around `blender_assets.py`,
|
skills are guidance only; they do not move scripts into `.agents`, add runtime
|
||||||
`npc_pipeline.py`, `bake_ao.py`, `npc_proportions.py` and
|
dependencies or replace the tools above.
|
||||||
`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).**
|
### Remaining skill candidate
|
||||||
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).**
|
- **`gig-line-reference-provenance` (medium value).** Guide `refboard.py` vs
|
||||||
Guide `refboard.py` vs `refcollect.py`: committed Wikimedia-sourced boards
|
`refcollect.py`: committed Wikimedia-sourced boards with sidecars versus
|
||||||
with sidecars versus local-only `tmp/research/` downloads, and the rule that
|
local-only `tmp/research/` downloads, and the rule that generated concepts
|
||||||
generated concepts never override photo evidence. This is more of a policy
|
never override photo evidence. This is more of a policy skill than a command
|
||||||
skill than a command skill.
|
skill.
|
||||||
|
|
||||||
### Keep as scripts
|
### Keep as scripts
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user