summaryrefslogtreecommitdiffhomepage
path: root/AGENTS.md
blob: 5a7fc3dfc6b7c21b6f1151281ea0f690ef7214ea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# 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 an
  **array definition**, not a declaration. Include it in EXACTLY ONE `.c` file
  (currently `ui.c`). Guard its use with `#if FONT_EMBEDDED`. Never include it
  from a `.h` file or from multiple `.c` files — that causes multiple-definition
  link errors.
- **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. Naming & vocabulary

- **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`.
- **Vocabulary is governed by `GLOSSARY.md`.** Reuse existing terms; never invent
  a synonym for a concept that already has a canonical name (see its "Avoid
  calling it…" column). Prefer standard, training-baked names over novel ones.
  If you genuinely need a new term, propose it — do not coin one silently in
  code.

## 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 Makefile uses
  `$(wildcard src/*.c)` so new modules are auto-discovered — no `SRCS` edit
  needed. The orchestrator owns the Makefile for any structural changes.

## 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/<module>.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.

## 8. Tribal knowledge (`notes/`)

- **What it is:** project-specific, non-inferable knowledge and scar tissue —
  the operational gotchas, environment quirks, and hard-won debugging facts that
  a fresh frontier model could NOT derive by reading the source. This is the
  only kind of prose that belongs in docs here.
- **The test (P6):** *Could a fresh frontier model figure this out by reading
  the code? If yes, leave it out.* Never restate generic C/raylib/Linux
  best-practice the model already knows — that is noise.
- **Where it lives:** `notes/<topic>.md`, one file per topic. Existing entries:
  - `notes/restructure-plan.md` — module-decomposition plan
  - `notes/wsl-arch-razer-run.md` — running the desktop app under WSLg on the
    Arch/Razer dev machine (the `LIBGL_ALWAYS_INDIRECT` segfault trap)
- **When you add one:** after solving something non-obvious — a crash that only
  reproduces in one environment, a build/run invocation that needs specific env
  vars, an undocumented platform constraint. Write the symptom, the root cause,
  and the fix. Keep it to the non-inferable facts only.