3.4 KiB
Whetstone DSL — Architecture & Coding Standards
Audience: All agents (Codex, Claude, future) working on this codebase. Authority: Treat these norms as hard constraints. Deviations require explicit user approval.
File Size Limits
| Scope | Max Lines | Action When Exceeded |
|---|---|---|
Header file (.h) |
600 | Split into multiple headers |
main.cpp |
1500 | Extract panels/utilities to headers |
| Single function | 80 | Extract sub-routines |
Naming Conventions
| Element | Convention | Example |
|---|---|---|
| Classes / Structs | PascalCase |
LayoutManager, BufferState |
| Methods / Functions | camelCase |
getChildren, recordSnapshot |
| Member variables | trailingUnderscore_ |
cursor_, currentPreset_ |
| Constants / Enum values | PascalCase |
BufferMode::Structured |
| Files | PascalCase.h |
Matches the primary class name |
Architecture Patterns
Header-Only
All core components are .h files. Sanctioned non-vendored .cpp entrypoints are:
main.cpp, orchestrator_main.cpp, mcp_main.cpp, pipeline_main.cpp,
eval_main.cpp, and FileDialog.cpp.
Panel Extraction
UI panels are free functions in their own headers, included and called from main.cpp:
// panels/MenuBarPanel.h
#pragma once
#include "EditorState.h"
void renderMenuBar(EditorState& state);
EditorState
Single state struct defined in EditorState.h. Panels receive it by reference — they never own global state.
Generators
One file per language, inheriting from ProjectionGenerator base in ProjectionGenerator.h. The shared dispatch helper dispatchGenerate() eliminates duplicated generate() bodies.
No God Objects
For new state structs, if a struct exceeds 50 fields, group related fields into
sub-structs (e.g., DiffState, LSPState). Legacy EditorState remains under
incremental decomposition; new feature state should be added via extracted
sub-structs rather than direct top-level field growth.
Test Requirements
- Minimum 2 tests per step for non-trivial features.
- Real assertions only: Every test must use
assert()or theexpect()helper with actual value checks. - No print-only tests:
std::cout << "PASS"without a preceding assertion is forbidden. - Test pattern: Use the standard
expect()helper,int passed/failedcounters,return failed ? 1 : 0. - Edge cases: At least 1 edge case test per step (empty input, null, boundary).
- Coverage continuity: If a test is removed or simplified, add equivalent coverage in a new unit or integration test and note the replacement in the commit/progress log.
Dependency Rules
- Pin all FetchContent tags: Use release tags (e.g.,
v0.23.6), nevermasterormain. - vcpkg for system libs: nlohmann-json, SDL2, imgui, tree-sitter core via vcpkg.
- FetchContent for grammars: Tree-sitter grammars and tinyfiledialogs via FetchContent with pinned tags.
Code Quality
- No stale TODOs: If something is not implemented, mark it
// STUB:with a reason. - No dead code: Remove commented-out code; git has history.
- Comments for "why" not "what": The code shows what; comments explain non-obvious decisions.
- No
goto: Use structured control flow. - Platform portability: Use
#ifdef _WIN32/#elseguards for platform-specific code (e.g.,_popenvspopen).