All five environments are one build. cmake/MMgrModule.cmake emits mmgr_<module>_<env> for every entry in MMGR_ENVIRONMENTS. A single configure builds host, word32, word16, idx16 and checks together, and a single ctest run covers all five.
A clean run is 160 CTest targets. test_memoriam_praetereo and test_memoria_externa are not among them unless MMGR_ENABLE_DMA or MMGR_ENABLE_EXTRAM is on. They are skipped loudly, through MMGR_SUITES_SKIPPED and a CMake status message, because a silently dropped suite leaves a passing run that tested less than it looks like.
A capability gates the whole suite, never a case inside one. A suite that compiles half its cases away still reports as passing.
Three formatters, one per language, each owning its own files, alone. All three wrap at 120 columns. A Python tool and the C it rewrites line up in a side-by-side diff.
CI checks and never rewrites. A formatter that rewrites on CI produces commits nobody reviewed and races the author's own push; the fix belongs in the working tree.
Public headers carry Doxygen comments. Implementation files carry a comment only where the code cannot say it for itself - a bound that is not obvious, a cast that is essential, a failure mode you would see at runtime. A comment that restates the line is worse than none.
Every header opens with an SPDX line and a @file block. The group is mod_<stem>, the stem column of tools/dev_env/names.tsv, and docs/groups.dox already declares it - do not add a @defgroup to a header.
A config struct documents its members with @param in the struct's own block. Do not repeat them on the entries that read it - they are aggregate-initialized members, not function parameters, and listing them as parameters of a one-argument function reads as a lie:
@position{n} is the entry's position in the dispatch table, @par Namespace\ilinebr name` names the table, and [BORROWS], [TAKES OWNERSHIP] and [RETURNS OWNERSHIP] mark who owns a pointer. Everything is a borrow here, and so [BORROWS]` is what you will write.
Doxygen takes one branch of a #if. Put the doc block on the branch it takes, not above the #if, or the entity comes out undocumented - docs/Doxyfile sets PREDEFINED and that setting decides which branch that is.
Run doxygen docs/Doxyfile before committing. WARN_IF_UNDOCUMENTED is on. Anything you added and did not document shows up in docs/doxygen-warnings.log.
Anything in docs/ that can be derived from the tree is derived from the tree and lives inside a generated region. Regenerate before committing:
Never hand-edit between the BEGIN GENERATED and END GENERATED markers. They are HTML comments, and each one names the generator that owns that region.