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.
|
||||
Reference in new issue
Block a user