Create a new asset pipeline lesson. This is a hybrid track — the pipeline
orchestrator is Python, performance-critical processing uses compiled C tools
(meshoptimizer, MikkTSpace), and procedural geometry lives in a header-only C
library (common/shapes/forge_shapes.h).
The goal is not just pedagogical. Every library, tool, and pipeline
component built in an asset lesson must be production-quality — well-tested,
documented, and designed for reuse beyond the lesson. The project's own
PLAN.md has a "Project Integration" section where forge-gpu's existing
assets (models, textures, skyboxes) are processed through the pipeline we
build. So the pipeline, plugins, and C tools are not toy examples scoped to a
single lesson — they are the actual tooling this project depends on.
Concretely this means:
- Libraries and tools are shared, not lesson-local. Python code goes in
pipeline/, C libraries go in common/, C tools go in tools/. The
lesson directory contains the walkthrough, not the implementation.
- Test thoroughly. Every module gets a test suite (
tests/pipeline/ for
Python, tests/test_*.c for C). Edge cases, error paths, and realistic
inputs — not just happy-path smoke tests.
- Design for integration. The Python pipeline will process forge-gpu's
own models and textures. The C mesh tool will be invoked by the pipeline
as a subprocess. The shapes library is already used by GPU and physics
lessons. Build APIs that work for real projects.
- Don't cut corners for pedagogy. If the correct approach requires more
code, write more code. Simplifying for the lesson at the cost of
correctness or reusability defeats the purpose.
When to use this skill:
- You need to teach asset import, processing, or optimization concepts
- A learner wants to build tooling that transforms raw art into GPU-ready formats
- The lesson involves texture compression, mesh optimization, or asset bundling
- The lesson adds a web UI for browsing, previewing, or configuring assets
- The lesson creates procedural geometry from parametric equations
- The lesson integrates third-party C libraries (meshoptimizer, MikkTSpace)
Smart behavior:
- Before creating a lesson, check if an existing asset lesson already covers it
- Asset lessons are tool-building lessons — every concept must produce a working
CLI command, C tool, library, or web page
- Focus on why each processing step matters for GPU performance
- Cross-reference GPU lessons that consume the processed assets
- Determine the lesson type (Python, C tool, or C library) before scaffolding
Arguments
The user (or you) can provide:
- Number: two-digit lesson number (e.g. 01, 02)
- Topic name: kebab-case (e.g. pipeline-scaffold, texture-processing)
- Description: what this teaches (e.g. "Plugin discovery, CLI entry point, TOML config")
If any are missing, infer from context or ask.
Lesson Types
The asset pipeline track has three lesson types. Determine which type applies
before scaffolding.
Type A: Python lessons
Pipeline scaffold, texture processing, asset bundles, web frontend. These add
functionality to the shared pipeline/ package at the repo root (not
lesson-local code). The lesson directory contains only the README, diagrams,
example config, and sample assets.
Directory structure:
pipeline/ # shared library (repo root) — code goes HERE
__init__.py
__main__.py
config.py, plugin.py, scanner.py, ...
plugins/
<type>.py # built-in plugins grow lesson by lesson
tests/
pipeline/ # tests for the shared library
test_<module>.py
lessons/assets/NN-topic-name/
README.md # lesson walkthrough pointing at pipeline/ code
pipeline.toml # example config for hands-on testing
assets/ # sample source files, diagrams
Not added to CMakeLists.txt — Python projects are not C targets.
pyproject.toml is at the repo root — one package for the whole pipeline.
Type B: C tool lessons
Mesh processing with third-party C libraries (meshoptimizer, MikkTSpace). The
C tool is a standalone executable that the Python pipeline invokes as a
subprocess.
Directory structure:
lessons/assets/NN-topic-name/
README.md
main.c # standalone C tool
CMakeLists.txt # builds the tool, fetches dependencies
tests/
test_<tool>.c # C test suite
Added to CMakeLists.txt — C tools need a build target. Add under an
"Asset Pipeline Lessons" section (create it if needed, after Physics Lessons
or at the end before Tests).
Type C: C library lessons
Procedural geometry and other header-only libraries that live in common/.
These produce a library, a test suite, and optionally a GPU lesson that
renders the output.
Directory structure:
common/<lib>/
forge_<lib>.h # header-only library
README.md # API reference
lessons/assets/NN-topic-name/
README.md # lesson walkthrough (may also have a GPU demo)
PLAN.md # main.c decomposition (if GPU demo included)
main.c # GPU showcase program (optional)
CMakeLists.txt
shaders/ # if GPU demo
assets/
tests/
test_<lib>.c # comprehensive test suite
Added to CMakeLists.txt — register the test target and any GPU demo.
Steps
1. Analyze what's needed
- Determine lesson type: Python (A), C tool (B), or C library (C)?
- Check existing asset lessons: Is there already a lesson for this topic?
- Identify the scope: What specific pipeline concepts does this lesson cover?
- Find cross-references: Which GPU/engine/math lessons relate?
- Check PLAN.md: Where does this lesson fit in the asset pipeline track?
2. Create the lesson directory
Follow the directory structure for the determined lesson type (A, B, or C).
3. Create the lesson content
For Python lessons (Type A)
Package conventions:
- Python 3.10+ — Use modern Python features (type hints, match statements,
dataclasses, pathlib)
- CLI: Use
argparse or click for command-line interface
- Config: TOML for project/asset configuration (
tomllib in 3.11+, or
tomli as fallback)
- Testing: pytest for unit tests
- Naming:
snake_case for modules and functions, PascalCase for classes
- No global state — Pass configuration explicitly
Create pyproject.toml:
[project]
name = "forge-asset-pipeline"
version = "0.1.0"
description = "Asset processing pipeline for forge-gpu"
requires-python = ">=3.10"
dependencies = [
# Add per-lesson dependencies here
]
[project.optional-dependencies]
dev = [
"pytest>=7.0",
"ruff>=0.4",
]
[project.scripts]
forge-pipeline = "pipeline.__main__:main"
For C tool lessons (Type B)
- Follow all forge-gpu C conventions (C99, naming, error handling)
- Use
FetchContent to pull third-party libraries (meshoptimizer, MikkTSpace)
- Build a standalone CLI tool that reads input files and writes output files
- The Python pipeline invokes the tool as a subprocess
- Test with forge-gpu's existing test harness pattern
For C library lessons (Type C)
- Follow the
forge_math.h pattern: header-only, static inline,
thorough inline documentation
- Use
SDL_malloc/SDL_free (not malloc/free)
- Use
forge_math.h types (vec3, vec2, mat4, quat)
- Create a comprehensive test suite following
tests/test_math.c pattern
- Optionally include a GPU demo that renders the library output
- For files over 800 lines, use the chunked-write pattern (mandatory)
4. Create README.md
Structure varies by lesson type but always includes:
- What you'll learn (bullet list)
- Result (screenshot, CLI output, or demo)
- Main explanation with diagrams
- Code walkthrough
- Key concepts
- Cross-references to other tracks
- Exercises
- Further reading
5. Update project files
README.md (root): Add a row to the asset lessons table
lessons/assets/README.md: Add a row to the lessons table
PLAN.md: Check off the asset lesson entry
CMakeLists.txt (root): Add targets for C tools/libraries (Types B and C
only — Python lessons are not registered here)
6. Cross-reference other lessons
- Find related GPU lessons: Which rendering features consume these assets?
- Find related engine lessons: Build systems, dependency management
- Find related math lessons: Vectors, parametric equations, trigonometry
- Update those lesson READMEs: Add cross-reference notes
- Update asset lesson README: List related lessons in "Where it connects"
7. Test
Python lessons:
cd lessons/assets/NN-topic-name
pip install -e ".[dev]"
pytest
ruff check .
C tool/library lessons:
cmake -B build
cmake --build build --config Debug --target <test-target>
ctest --test-dir build -R <test-name>
Use a Task agent with model: "haiku" for build commands per project
conventions.
8. Run markdown linting
npx markdownlint-cli2 "**/*.md"
Asset Lesson Conventions
Scope
- Core pipeline (Python) — CLI scaffold, plugin discovery, configuration,
scanning, fingerprinting
- Texture processing (Python) — Resize, compress, mipmap generation,
format conversion
- Mesh processing (C tool) — Vertex deduplication, index optimization,
tangent generation (MikkTSpace), LOD generation (meshoptimizer), binary output
- Procedural geometry (C library) — Parametric surface generation, smooth
and flat normals, struct-of-arrays GPU layout
- Asset bundles (Python) — Packing, compression, table of contents,
dependency tracking
- Web frontend (Python) — Asset browser, 3D preview, import settings
editor, scene editor
Python style
- Python 3.10+ with type hints
snake_case for functions and variables, PascalCase for classes
- Docstrings on public functions and classes
pathlib.Path for file paths (not string concatenation)
dataclasses or attrs for structured data
- Lint with Ruff (same config as existing
pyproject.toml in repo root)
C style
Follow the same conventions as all forge-gpu code:
- C99, matching SDL's style
ForgeShapes prefix for public types, forge_shapes_ for functions
(adjust prefix per library)
PascalCase for typedefs, lowercase_snake_case for locals
UPPER_SNAKE_CASE for #define constants
- No magic numbers —
#define or enum everything
SDL_malloc/SDL_free — not malloc/free
- Extensive comments explaining why and purpose
Plugin architecture
The Python pipeline uses a plugin system where each asset type registers a
processor. C tools are invoked as subprocesses by the Python plugin:
import subprocess
from pathlib import Path
class MeshPlugin(AssetPlugin):
"""Mesh processing plugin — invokes compiled C tool."""
name = "mesh"
extensions = [".gltf", ".glb", ".obj"]
def process(self, source: Path, config: dict) -> AssetResult:
result = subprocess.run(
["forge-mesh-tool", str(source), "--output", str(output)],
capture_output=True, text=True
)
if result.returncode != 0:
raise ProcessingError(result.stderr)
return AssetResult(source=source, output=output, metadata={...})
Incremental builds
Every processing step must support incremental builds:
- Fingerprint source files (content hash, not timestamp)
- Compare against cached fingerprints from the last build
- Skip unchanged assets
- Track dependencies — if a texture changes, re-process meshes that
reference it
Configuration
Use TOML for pipeline and per-asset configuration:
# pipeline.toml — project-level config
[pipeline]
source_dir = "assets/raw"
output_dir = "assets/processed"
bundle_dir = "assets/bundles"
[texture]
default_format = "bc7"
max_size = 2048
generate_mipmaps = true
[mesh]
deduplicate = true
generate_tangents = true
lod_levels = [1.0, 0.5, 0.25]
Tone
Asset pipeline lessons should be practical and tool-focused. Pipeline tooling
is infrastructure that enables art and rendering — treat it with the same
rigor as the rendering code it serves. The output of these lessons is not
disposable teaching material; it is production tooling that forge-gpu itself
will use to process its own assets.
- Name the techniques and formats — BC7, KTX2, glTF, meshoptimizer,
MikkTSpace — named tools and formats carry weight and help readers find
documentation
- Show the data flow — Diagrams showing source -> process -> output are
essential for pipeline lessons
- Measure improvement — Show file sizes, load times, or vertex counts
before and after processing
- Connect to GPU — Always explain how the processed output maps to GPU
concepts (texture formats, vertex layouts, draw calls)
- Build for real use — Every API, CLI flag, and config option should work
for a real project, not just the lesson's sample assets
Example: Pipeline Scaffold Lesson (Type A — Python)
- Scope: CLI entry point, plugin discovery, asset scanning, fingerprinting,
TOML configuration
- Create:
lessons/assets/01-pipeline-scaffold/
- Package:
pipeline/ with __main__.py, config.py, scanner.py,
plugin.py
- Program: CLI that scans a directory for assets, fingerprints them, and
reports what would be processed. No actual processing yet.
- README: Explain plugin architecture, fingerprinting, TOML config, CLI
design
- Exercises: Add a new file type to the scanner, implement cache
invalidation, add
--verbose output
Example: Mesh Processing Lesson (Type B — C tool)
- Scope: meshoptimizer for vertex/index optimization, MikkTSpace for
tangent generation, binary output format, LOD generation
- Create:
lessons/assets/03-mesh-processing/
- Tool:
main.c that reads glTF/OBJ, processes with meshoptimizer and
MikkTSpace, writes optimized binary output
- CMake: FetchContent for meshoptimizer and MikkTSpace
- Python plugin:
plugins/mesh.py invokes the compiled tool as subprocess
- README: Explain vertex cache optimization, overdraw optimization, tangent
space, LOD simplification metrics
- Exercises: Add vertex quantization, compare draw call performance before
and after optimization
Example: Procedural Geometry Lesson (Type C — C library)
- Scope:
forge_shapes.h — parametric surface generation (sphere,
icosphere, cylinder, cone, torus, plane, cube, capsule), struct-of-arrays
layout, smooth vs flat normals
- Create:
common/shapes/forge_shapes.h, common/shapes/README.md,
lessons/assets/04-procedural-geometry/, tests/test_shapes.c
- Library: Header-only with
FORGE_SHAPES_IMPLEMENTATION guard
- GPU demo: Five-shape showcase with Blinn-Phong lighting
- Tests: 28 tests covering vertex counts, normals, UVs, winding, memory
- README: Parametric surfaces, slices/stacks, seam duplication, smooth vs
flat normals, struct-of-arrays vs interleaved
When NOT to Create an Asset Lesson
- The topic is covered by an existing asset lesson
- The concept is about GPU rendering only (belongs in a GPU lesson)
- The concept is about C fundamentals only (belongs in an engine lesson)
- The concept is pure math only (belongs in a math lesson)
- The topic is too narrow for a full lesson (add to an existing lesson instead)
In these cases, update existing documentation or plan for later.
Tips
- Start with the CLI — Get the command-line interface working first, then
add processing logic. A well-structured CLI with no-op plugins is a solid
foundation.
- Test with real assets — Use assets from existing GPU lessons as test
inputs. This validates that the pipeline produces output the C code can
actually consume.
- Fingerprint, don't timestamp — Content hashes are deterministic and
portable. Timestamps break on copy, git clone, and CI.
- Show before/after — File size comparisons, vertex count reductions, and
load time improvements make the value of the pipeline concrete.
- Keep the web UI simple — Static HTML/CSS/JS served by Python. No npm,
no webpack, no framework. The pipeline is the lesson, not the frontend stack.
- Chunked writes for large C files —
forge_shapes.h and GPU demo
main.c will exceed 800 lines. Use the chunked-write pattern per
.claude/large-file-strategy.md.
1---2name: dev-asset-lesson-23description: Add an asset pipeline lesson — hybrid Python + C track for asset processing, procedural geometry, and web frontend4---56Create a new asset pipeline lesson. This is a **hybrid track** — the pipeline7orchestrator is Python, performance-critical processing uses compiled C tools8(meshoptimizer, MikkTSpace), and procedural geometry lives in a header-only C9library (`common/shapes/forge_shapes.h`).1011**The goal is not just pedagogical.** Every library, tool, and pipeline12component built in an asset lesson must be production-quality — well-tested,13documented, and designed for reuse beyond the lesson. The project's own14`PLAN.md` has a "Project Integration" section where forge-gpu's existing15assets (models, textures, skyboxes) are processed through the pipeline we16build. So the pipeline, plugins, and C tools are not toy examples scoped to a17single lesson — they are the actual tooling this project depends on.1819Concretely this means:2021- **Libraries and tools are shared, not lesson-local.** Python code goes in22 `pipeline/`, C libraries go in `common/`, C tools go in `tools/`. The23 lesson directory contains the walkthrough, not the implementation.24- **Test thoroughly.** Every module gets a test suite (`tests/pipeline/` for25 Python, `tests/test_*.c` for C). Edge cases, error paths, and realistic26 inputs — not just happy-path smoke tests.27- **Design for integration.** The Python pipeline will process forge-gpu's28 own models and textures. The C mesh tool will be invoked by the pipeline29 as a subprocess. The shapes library is already used by GPU and physics30 lessons. Build APIs that work for real projects.31- **Don't cut corners for pedagogy.** If the correct approach requires more32 code, write more code. Simplifying for the lesson at the cost of33 correctness or reusability defeats the purpose.3435**When to use this skill:**3637- You need to teach asset import, processing, or optimization concepts38- A learner wants to build tooling that transforms raw art into GPU-ready formats39- The lesson involves texture compression, mesh optimization, or asset bundling40- The lesson adds a web UI for browsing, previewing, or configuring assets41- The lesson creates procedural geometry from parametric equations42- The lesson integrates third-party C libraries (meshoptimizer, MikkTSpace)4344**Smart behavior:**4546- Before creating a lesson, check if an existing asset lesson already covers it47- Asset lessons are tool-building lessons — every concept must produce a working48 CLI command, C tool, library, or web page49- Focus on *why* each processing step matters for GPU performance50- Cross-reference GPU lessons that consume the processed assets51- Determine the lesson type (Python, C tool, or C library) before scaffolding5253## Arguments5455The user (or you) can provide:5657- **Number**: two-digit lesson number (e.g. 01, 02)58- **Topic name**: kebab-case (e.g. pipeline-scaffold, texture-processing)59- **Description**: what this teaches (e.g. "Plugin discovery, CLI entry point, TOML config")6061If any are missing, infer from context or ask.6263## Lesson Types6465The asset pipeline track has three lesson types. Determine which type applies66before scaffolding.6768### Type A: Python lessons6970Pipeline scaffold, texture processing, asset bundles, web frontend. These add71functionality to the **shared `pipeline/` package** at the repo root (not72lesson-local code). The lesson directory contains only the README, diagrams,73example config, and sample assets.7475**Directory structure:**7677```text78pipeline/ # shared library (repo root) — code goes HERE79 __init__.py80 __main__.py81 config.py, plugin.py, scanner.py, ...82 plugins/83 <type>.py # built-in plugins grow lesson by lesson84tests/85 pipeline/ # tests for the shared library86 test_<module>.py87lessons/assets/NN-topic-name/88 README.md # lesson walkthrough pointing at pipeline/ code89 pipeline.toml # example config for hands-on testing90 assets/ # sample source files, diagrams91```9293**Not added to CMakeLists.txt** — Python projects are not C targets.94**`pyproject.toml` is at the repo root** — one package for the whole pipeline.9596### Type B: C tool lessons9798Mesh processing with third-party C libraries (meshoptimizer, MikkTSpace). The99C tool is a standalone executable that the Python pipeline invokes as a100subprocess.101102**Directory structure:**103104```text105lessons/assets/NN-topic-name/106 README.md107 main.c # standalone C tool108 CMakeLists.txt # builds the tool, fetches dependencies109 tests/110 test_<tool>.c # C test suite111```112113**Added to CMakeLists.txt** — C tools need a build target. Add under an114"Asset Pipeline Lessons" section (create it if needed, after Physics Lessons115or at the end before Tests).116117### Type C: C library lessons118119Procedural geometry and other header-only libraries that live in `common/`.120These produce a library, a test suite, and optionally a GPU lesson that121renders the output.122123**Directory structure:**124125```text126common/<lib>/127 forge_<lib>.h # header-only library128 README.md # API reference129lessons/assets/NN-topic-name/130 README.md # lesson walkthrough (may also have a GPU demo)131 PLAN.md # main.c decomposition (if GPU demo included)132 main.c # GPU showcase program (optional)133 CMakeLists.txt134 shaders/ # if GPU demo135 assets/136tests/137 test_<lib>.c # comprehensive test suite138```139140**Added to CMakeLists.txt** — register the test target and any GPU demo.141142## Steps143144### 1. Analyze what's needed145146- **Determine lesson type**: Python (A), C tool (B), or C library (C)?147- **Check existing asset lessons**: Is there already a lesson for this topic?148- **Identify the scope**: What specific pipeline concepts does this lesson cover?149- **Find cross-references**: Which GPU/engine/math lessons relate?150- **Check PLAN.md**: Where does this lesson fit in the asset pipeline track?151152### 2. Create the lesson directory153154Follow the directory structure for the determined lesson type (A, B, or C).155156### 3. Create the lesson content157158#### For Python lessons (Type A)159160**Package conventions:**161162- **Python 3.10+** — Use modern Python features (type hints, match statements,163 dataclasses, pathlib)164- **CLI**: Use `argparse` or `click` for command-line interface165- **Config**: TOML for project/asset configuration (`tomllib` in 3.11+, or166 `tomli` as fallback)167- **Testing**: pytest for unit tests168- **Naming**: `snake_case` for modules and functions, `PascalCase` for classes169- **No global state** — Pass configuration explicitly170171Create `pyproject.toml`:172173```toml174[project]175name = "forge-asset-pipeline"176version = "0.1.0"177description = "Asset processing pipeline for forge-gpu"178requires-python = ">=3.10"179dependencies = [180 # Add per-lesson dependencies here181]182183[project.optional-dependencies]184dev = [185 "pytest>=7.0",186 "ruff>=0.4",187]188189[project.scripts]190forge-pipeline = "pipeline.__main__:main"191```192193#### For C tool lessons (Type B)194195- Follow all forge-gpu C conventions (C99, naming, error handling)196- Use `FetchContent` to pull third-party libraries (meshoptimizer, MikkTSpace)197- Build a standalone CLI tool that reads input files and writes output files198- The Python pipeline invokes the tool as a subprocess199- Test with forge-gpu's existing test harness pattern200201#### For C library lessons (Type C)202203- Follow the `forge_math.h` pattern: header-only, `static inline`,204 thorough inline documentation205- Use `SDL_malloc`/`SDL_free` (not `malloc`/`free`)206- Use `forge_math.h` types (`vec3`, `vec2`, `mat4`, `quat`)207- Create a comprehensive test suite following `tests/test_math.c` pattern208- Optionally include a GPU demo that renders the library output209- For files over 800 lines, use the chunked-write pattern (mandatory)210211### 4. Create `README.md`212213Structure varies by lesson type but always includes:214215- What you'll learn (bullet list)216- Result (screenshot, CLI output, or demo)217- Main explanation with diagrams218- Code walkthrough219- Key concepts220- Cross-references to other tracks221- Exercises222- Further reading223224### 5. Update project files225226- **`README.md` (root)**: Add a row to the asset lessons table227- **`lessons/assets/README.md`**: Add a row to the lessons table228- **`PLAN.md`**: Check off the asset lesson entry229- **`CMakeLists.txt` (root)**: Add targets for C tools/libraries (Types B and C230 only — Python lessons are not registered here)231232### 6. Cross-reference other lessons233234- **Find related GPU lessons**: Which rendering features consume these assets?235- **Find related engine lessons**: Build systems, dependency management236- **Find related math lessons**: Vectors, parametric equations, trigonometry237- **Update those lesson READMEs**: Add cross-reference notes238- **Update asset lesson README**: List related lessons in "Where it connects"239240### 7. Test241242**Python lessons:**243244```bash245cd lessons/assets/NN-topic-name246pip install -e ".[dev]"247pytest248ruff check .249```250251**C tool/library lessons:**252253```bash254cmake -B build255cmake --build build --config Debug --target <test-target>256ctest --test-dir build -R <test-name>257```258259Use a Task agent with `model: "haiku"` for build commands per project260conventions.261262### 8. Run markdown linting263264```bash265npx markdownlint-cli2 "**/*.md"266```267268## Asset Lesson Conventions269270### Scope271272- **Core pipeline** (Python) — CLI scaffold, plugin discovery, configuration,273 scanning, fingerprinting274- **Texture processing** (Python) — Resize, compress, mipmap generation,275 format conversion276- **Mesh processing** (C tool) — Vertex deduplication, index optimization,277 tangent generation (MikkTSpace), LOD generation (meshoptimizer), binary output278- **Procedural geometry** (C library) — Parametric surface generation, smooth279 and flat normals, struct-of-arrays GPU layout280- **Asset bundles** (Python) — Packing, compression, table of contents,281 dependency tracking282- **Web frontend** (Python) — Asset browser, 3D preview, import settings283 editor, scene editor284285### Python style286287- Python 3.10+ with type hints288- `snake_case` for functions and variables, `PascalCase` for classes289- Docstrings on public functions and classes290- `pathlib.Path` for file paths (not string concatenation)291- `dataclasses` or `attrs` for structured data292- Lint with Ruff (same config as existing `pyproject.toml` in repo root)293294### C style295296Follow the same conventions as all forge-gpu code:297298- C99, matching SDL's style299- `ForgeShapes` prefix for public types, `forge_shapes_` for functions300 (adjust prefix per library)301- `PascalCase` for typedefs, `lowercase_snake_case` for locals302- `UPPER_SNAKE_CASE` for `#define` constants303- No magic numbers — `#define` or `enum` everything304- `SDL_malloc`/`SDL_free` — not `malloc`/`free`305- Extensive comments explaining *why* and *purpose*306307### Plugin architecture308309The Python pipeline uses a plugin system where each asset type registers a310processor. C tools are invoked as subprocesses by the Python plugin:311312```python313import subprocess314from pathlib import Path315316class MeshPlugin(AssetPlugin):317 """Mesh processing plugin — invokes compiled C tool."""318 name = "mesh"319 extensions = [".gltf", ".glb", ".obj"]320321 def process(self, source: Path, config: dict) -> AssetResult:322 result = subprocess.run(323 ["forge-mesh-tool", str(source), "--output", str(output)],324 capture_output=True, text=True325 )326 if result.returncode != 0:327 raise ProcessingError(result.stderr)328 return AssetResult(source=source, output=output, metadata={...})329```330331### Incremental builds332333Every processing step must support incremental builds:3343351. **Fingerprint** source files (content hash, not timestamp)3362. **Compare** against cached fingerprints from the last build3373. **Skip** unchanged assets3384. **Track dependencies** — if a texture changes, re-process meshes that339 reference it340341### Configuration342343Use TOML for pipeline and per-asset configuration:344345```toml346# pipeline.toml — project-level config347[pipeline]348source_dir = "assets/raw"349output_dir = "assets/processed"350bundle_dir = "assets/bundles"351352[texture]353default_format = "bc7"354max_size = 2048355generate_mipmaps = true356357[mesh]358deduplicate = true359generate_tangents = true360lod_levels = [1.0, 0.5, 0.25]361```362363### Tone364365Asset pipeline lessons should be practical and tool-focused. Pipeline tooling366is infrastructure that enables art and rendering — treat it with the same367rigor as the rendering code it serves. The output of these lessons is not368disposable teaching material; it is production tooling that forge-gpu itself369will use to process its own assets.370371- **Name the techniques and formats** — BC7, KTX2, glTF, meshoptimizer,372 MikkTSpace — named tools and formats carry weight and help readers find373 documentation374- **Show the data flow** — Diagrams showing source -> process -> output are375 essential for pipeline lessons376- **Measure improvement** — Show file sizes, load times, or vertex counts377 before and after processing378- **Connect to GPU** — Always explain how the processed output maps to GPU379 concepts (texture formats, vertex layouts, draw calls)380- **Build for real use** — Every API, CLI flag, and config option should work381 for a real project, not just the lesson's sample assets382383## Example: Pipeline Scaffold Lesson (Type A — Python)3843851. **Scope**: CLI entry point, plugin discovery, asset scanning, fingerprinting,386 TOML configuration3872. **Create**: `lessons/assets/01-pipeline-scaffold/`3883. **Package**: `pipeline/` with `__main__.py`, `config.py`, `scanner.py`,389 `plugin.py`3904. **Program**: CLI that scans a directory for assets, fingerprints them, and391 reports what would be processed. No actual processing yet.3925. **README**: Explain plugin architecture, fingerprinting, TOML config, CLI393 design3946. **Exercises**: Add a new file type to the scanner, implement cache395 invalidation, add `--verbose` output396397## Example: Mesh Processing Lesson (Type B — C tool)3983991. **Scope**: meshoptimizer for vertex/index optimization, MikkTSpace for400 tangent generation, binary output format, LOD generation4012. **Create**: `lessons/assets/03-mesh-processing/`4023. **Tool**: `main.c` that reads glTF/OBJ, processes with meshoptimizer and403 MikkTSpace, writes optimized binary output4044. **CMake**: FetchContent for meshoptimizer and MikkTSpace4055. **Python plugin**: `plugins/mesh.py` invokes the compiled tool as subprocess4066. **README**: Explain vertex cache optimization, overdraw optimization, tangent407 space, LOD simplification metrics4087. **Exercises**: Add vertex quantization, compare draw call performance before409 and after optimization410411## Example: Procedural Geometry Lesson (Type C — C library)4124131. **Scope**: `forge_shapes.h` — parametric surface generation (sphere,414 icosphere, cylinder, cone, torus, plane, cube, capsule), struct-of-arrays415 layout, smooth vs flat normals4162. **Create**: `common/shapes/forge_shapes.h`, `common/shapes/README.md`,417 `lessons/assets/04-procedural-geometry/`, `tests/test_shapes.c`4183. **Library**: Header-only with `FORGE_SHAPES_IMPLEMENTATION` guard4194. **GPU demo**: Five-shape showcase with Blinn-Phong lighting4205. **Tests**: 28 tests covering vertex counts, normals, UVs, winding, memory4216. **README**: Parametric surfaces, slices/stacks, seam duplication, smooth vs422 flat normals, struct-of-arrays vs interleaved423424## When NOT to Create an Asset Lesson425426- The topic is covered by an existing asset lesson427- The concept is about GPU rendering only (belongs in a GPU lesson)428- The concept is about C fundamentals only (belongs in an engine lesson)429- The concept is pure math only (belongs in a math lesson)430- The topic is too narrow for a full lesson (add to an existing lesson instead)431432In these cases, update existing documentation or plan for later.433434## Tips435436- **Start with the CLI** — Get the command-line interface working first, then437 add processing logic. A well-structured CLI with no-op plugins is a solid438 foundation.439- **Test with real assets** — Use assets from existing GPU lessons as test440 inputs. This validates that the pipeline produces output the C code can441 actually consume.442- **Fingerprint, don't timestamp** — Content hashes are deterministic and443 portable. Timestamps break on copy, git clone, and CI.444- **Show before/after** — File size comparisons, vertex count reductions, and445 load time improvements make the value of the pipeline concrete.446- **Keep the web UI simple** — Static HTML/CSS/JS served by Python. No npm,447 no webpack, no framework. The pipeline is the lesson, not the frontend stack.448- **Chunked writes for large C files** — `forge_shapes.h` and GPU demo449 `main.c` will exceed 800 lines. Use the chunked-write pattern per450 `.claude/large-file-strategy.md`.