- Use Zig 0.16.0 through Nix. Wrap every Zig build/test/format command in
nix develop --command; CI uses the narrower.#ci-unitand.#ci-graphicsshells. - Build/run:
nix develop --command zig build nix develop --command zig build run nix develop --command zig build -Doptimize=ReleaseFast
- Format all Zig code, not only
src/(the local hook is less strict than CI):nix develop --command zig fmt src/ modules/ nix develop --command zig fmt --check src/ modules/
zig build testis the broad suite: aggregate/module tests, fuzz roots, shader compilation/validation, SPIR-V size checks, shadow ABI checks, and Phase 5 policy tests.nix develop --command zig build test nix develop --command zig build test -Dtest-filter="name" # Equivalent runtime-filter form: nix develop --command zig build test -- --test-filter "name"
- Graphics/runtime verification is separate:
nix develop --command zig build test-integration -Dskip-present=true nix develop --command zig build test-robustness nix develop --command zig build phase5-gate nix develop --command zig build phase5-visual-gate
-Dskip-present=trueonly suppresses presentation; SDL/Vulkan initialization still needs a display/compositor and driver. Use the repo skillsheadless-crash-test,headless-screenshot,headless-benchmark, orheadless-graphics-verification, and always bound game/graphics commands with a timeout.- For deterministic startup checks, combine
-Dskip-present,-Dauto-world=<normal|overworld|overworld-v2|flat|test>, and-Dstartup-diagnostic-seconds=N.-Dchunk-debug-modedisables LOD, water, caves, and decorations; selectively restorelod,water,watergen,waterrender,caves,decorationswith-Dchunk-debug-enable=.
- The benchmark harness is a separate build step; do not pass benchmark presets to ordinary
runand assume benchmarking is active:Scenarios arenix develop --command zig build benchmark -Doptimize=ReleaseFast \ -Dbenchmark-preset=low -Dbenchmark-scenario=traversal \ -Dbenchmark-duration=60 -Dbenchmark-output=zig-out/benchmark-low.json
stationary,traversal,rapid-turn, andteleport-eviction. Prefer theheadless-benchmarkskill for bounded runs. - Focused CPU-only tools:
nix develop --command zig build worldgen-reportandnix develop --command zig build lod-bench. Pass climate snapshot arguments after--, e.g.nix develop --command zig build worldgen-climate-snapshot -- --seed 42 .... - Building/tests compile GLSL and write tracked
*.spvfiles beside sources inassets/shaders/vulkan/. After intentional shader-size changes, run./scripts/update_spirv_baseline.sh;docs/shaders/spirv-sizes.jsonand shadow runtime SPIR-V parity are test-enforced. - New/changed textures go through
./scripts/process_textures.sh <pack> 512; preserve licensing/attribution for placeholder assets.
src/main.zigandsrc/game/app.zigwire the executable. Reusable session/player/settings/benchmark logic belongs inmodules/game-core; screens belong inmodules/game-ui.engine-rhiowns rendering contracts and opaque handles;engine-graphicsowns the Vulkan backend, render passes, resources, and pipelines. Vulkan is currently the only backend, so interface changes usually require both the RHI vtable/contracts and Vulkan implementation.world-coreowns shared block/chunk/coordinate types; world generation is split acrossworld-worldgen-*packages;world-meshingowns chunk mesh/storage;world-lodowns distant terrain;world-runtimecoordinates streaming, lighting, GPU meshing, mutation, and rendering;world-persistenceowns saves/regions.- Never call RHI/SDL from worker jobs. Pin chunks while background jobs hold them and synchronize shared mesh/chunk state with the project mutex abstraction.
- Convert global coordinates with
worldToChunk/worldToLocalfromworld-core; chunk coordinates are floor-divided, so ad-hoc truncating division is wrong for negative positions. - GPU-shared structs and shader blocks are ABI contracts. Use explicit layouts (
extern/packed as appropriate), assert sizes/offsets, and update CPU, GLSL, descriptors, and backend bindings together.
ZIGCRAFT_LOD_COMPACT=autois qualified only through immutable per-layer descriptors plus expanded fallback for unsupported shoreline topology;offremains the explicit supported fallback.forceis diagnostic only. Do not weaken the saved-world RADV reload, validation, robustness, and Phase 5 qualification requirements based only on generated-world captures.- Dedicated transfer queues cannot upload exclusive graphics buffers safely with semaphore synchronization alone; queue-family release/acquire ownership transfers are required. Until implemented, keep these uploads on the graphics family.
- A descriptor set update affects all previously recorded commands that bind that set when execution happens. Terrain/water or direct/indirect streams that need different buffers require immutable/per-layer descriptor sets, not sequential updates to one set.
- Match verification to the change, but graphics/RHI/shader/runtime work normally requires: format check,
zig build test, ReleaseFast build, integration/robustness as relevant, and the appropriate headless graphics skill. CI additionally runs Debug and ReleaseSafe tests,phase5-gate, Lavapipe/Weston integration smoke tests, andphase5-visual-gate. - Install the repo pre-push hook with
./scripts/setup-hooks.sh, but do not treat it as CI parity: it formats onlysrc/and omits ReleaseSafe and graphics jobs.
- Branch from and target PRs to
dev; do not push directly todevunless explicitly requested. Branch prefixes arefeature/,bug/,hotfix/, andci/. - PR titles and commits use conventional types:
feat,fix,refactor,test,docs,ci,chore,perf,build,style, orrevert. - Every non-merge PR commit needs a DCO trailer; create commits with
git commit -s.