# AGENTS.md — subagent constitution for C/Raylib project > **This is loaded by every agent.** It contains ONLY project-specific, > non-obvious rules. Never restate what a frontier model already knows about C > or raylib. --- ## 1. C dialect & build rules - **C99** (`-std=c99`). No C11/C17 features. - **Compile with `-Wall -Wextra`** — zero warnings. If you cannot silence a warning without reducing correctness, flag it in your report. - **Raylib is the ONLY external library.** Include `raylib.h` for all platform APIs (windowing, audio, input, font loading, drawing). Never include glfw, miniaudio, or stb headers directly. For web: `emscripten.h` is allowed behind `#ifdef PLATFORM_WEB`. - **`build/font_data.h`** (generated by `xxd` from `resources/`) is included behind `#include "font_data.h"` guard its use with `#if FONT_EMBEDDED`. - **No dynamic allocation** unless paired with an explicit free in the same module's cleanup. No leaks. - **No VLAs** (variable-length arrays on the stack). Use fixed-size buffers or guard with `MAX_*` constants. ## 2. Module boundaries (THE KEY RULE) - **Your `.h` file IS your contract.** It declares every public type, constant, and function signature that other modules consume. Keep it minimal — consumers should not see implementation details. - **Your `.c` file IS your implementation.** It is PRIVATE. Static functions are module-internal. No other module includes your `.c` file — ever. - **Include guards:** Every `.h` file starts with `#pragma once`. - **Self-contained headers:** A `.h` file must `#include` all types it references (directly or via forward declaration). Consuming agents should need to include ONLY your `.h`, not hunt for transitive includes. - **Forward-declare when possible:** `typedef struct PlayerState PlayerState;` in a header avoids pulling in the full `types.h` when only a pointer is needed. ## 3. State management - **No global mutable variables.** All shared state lives in `PlayerState` and is passed by pointer. - **File-scope statics** are allowed ONLY for module-private data (e.g. cached fonts, colors, layout constants in the UI module). - **Const correctness:** Mark pointers `const` when the function does not mutate the data. Example: `const char *path` in functions that only read. ## 4. Function naming - **Prefix public functions** with the module name or a clear namespace: - `player_*` for player module - `study_*` for study module - `ui_*` for UI module - **Static helpers** (module-internal) may omit the prefix. - **Verb-first naming:** `player_load`, `player_seek`, `study_detect_silence`. ## 5. Testing & verification - **Build is the primary test.** If `make` exits 0 with zero warnings, your module compiles and links correctly. - **If you add a new `.c` file**, note it in your report — the orchestrator updates the Makefile's `SRCS` list (this is orchestrator-owned build wiring, NOT your responsibility). ## 6. What you may read from other modules - **YES:** The `.h` header files of other modules (their contracts). - **NO:** The `.c` implementation files of ANY other module. If you think you need to read a sibling's `.c` to understand its behavior, STOP — that means the `.h` contract is underspecified. Report this to the orchestrator. ## 7. Report format After completing your work, write `reports/.md` with: 1. **Files touched** (list paths) 2. **What you implemented** (bullet list of functions/changes) 3. **Build result** (`make` output — exit code + any warnings) 4. **Issues or contract gaps** discovered 5. **Any changes needed in other modules** (e.g. "study.h needs a new function declaration") Keep the report concise — the orchestrator reads many of these per wave.