Skip to content

Commit 5f5294e

Browse files
authored
Merge pull request #1 from n-n-code/v2
v2
2 parents d40c70b + aba619d commit 5f5294e

22 files changed

Lines changed: 889 additions & 98 deletions

File tree

.agents/skills/coder/SKILL.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@ Read `AGENTS.md` first. This skill adds implementation guidance only.
2020
1. Inspect the touched code, build shape, and tests.
2121
2. Keep interfaces simple and behavior-oriented.
2222
3. Implement the narrowest change that solves the problem.
23-
4. Add or update tests close to the changed behavior.
24-
5. Run relevant build/test/analyzer targets.
23+
4. Add or update tests close to the changed behavior using `frame_test.h`
24+
macros (`FRAME_TEST`, `FRAME_EXPECT_EQ`, `FRAME_EXPECT_TRUE`, etc.).
25+
5. Run `format` before committing, then run relevant build/test/analyzer
26+
targets.
2527

2628
## C++ Rules
2729

.agents/skills/project-config-and-tests/SKILL.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,7 @@ small deterministic test coverage.
1313
- keep config parsing non-fatal where that preserves recovery/help paths
1414
- keep defaults, example config, and docs aligned
1515
- prefer deterministic tests around parsing, normalization, and helper seams
16+
using `frame_test.h` macros
1617
- keep WHAT/HOW/WHY commentary current in repo-owned tests
18+
- add benchmarks for performance-sensitive helpers using `frame_bench.h`
19+
- use the `coverage` preset and target to verify test coverage for new code

.agents/skills/project-core-dev/SKILL.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ repo-owned C++ code.
1616

1717
## Validation
1818

19-
- build out of tree
19+
- prefer `cmake --preset dev` for development builds
2020
- run `ctest --output-on-failure` for covered changes
21+
- run `cmake --build "$BUILD_DIR" --target format-check` before committing
2122
- run `frame_cli --help` as a lightweight smoke test
2223
- add docs/analyzer/Valgrind validation when the change surface justifies it
24+
- run `cppcheck` target when available for additional static analysis

.clang-format

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
BasedOnStyle: LLVM
2+
IndentWidth: 4
3+
ColumnLimit: 100
4+
BreakBeforeBraces: Custom
5+
BraceWrapping:
6+
AfterFunction: true
7+
AfterNamespace: false
8+
AfterStruct: true
9+
AfterClass: true
10+
AfterEnum: true
11+
BeforeElse: true
12+
BeforeCatch: true
13+
SplitEmptyFunction: false
14+
AllowShortFunctionsOnASingleLine: Empty
15+
AllowShortIfStatementsOnASingleLine: Never
16+
AllowShortLoopsOnASingleLine: false
17+
AllowShortLambdasOnASingleLine: Inline
18+
AlwaysBreakTemplateDeclarations: Yes
19+
PointerAlignment: Right
20+
ReferenceAlignment: Pointer
21+
SpaceAfterCStyleCast: false
22+
SpaceBeforeParens: ControlStatements
23+
IncludeBlocks: Preserve
24+
SortIncludes: CaseSensitive

.github/workflows/ci.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ jobs:
3232
run: |
3333
sudo apt-get update
3434
sudo apt-get install -y --no-install-recommends \
35+
clang-format \
3536
cmake \
3637
doxygen \
3738
g++ \
@@ -41,6 +42,9 @@ jobs:
4142
- name: Configure
4243
run: cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_STANDARD=23
4344

45+
- name: Check formatting
46+
run: cmake --build build --target format-check
47+
4448
- name: Build
4549
run: cmake --build build
4650

AGENTS.md

Lines changed: 70 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,14 @@ Baseline shape:
1212
- Out-of-tree builds are the default workflow
1313
- Repo-owned code should stay portable, local-first, and easy to validate
1414
- One small library target plus one CLI target form the default example shape
15-
- Deterministic `CTest`, `clang-tidy`, Doxygen, release-hygiene, and Valgrind
16-
lanes are part of the maintained contract
15+
- Deterministic `CTest`, `clang-tidy`, `clang-format`, `cppcheck`, Doxygen,
16+
release-hygiene, Valgrind, and coverage lanes are part of the maintained
17+
contract
1718
- Qt/Clazy provide the example UI stack, not the baseline assumption
1819
- Public docs are generated from repo-owned headers and `docs/mainpage.md`
1920
- Feature plans live under `upcoming_features/` as tracked Markdown files only
21+
(see `upcoming_features/TEMPLATE.md` for the expected format)
22+
- CMake presets provide named configurations for common workflows
2023

2124
Repository principles:
2225

@@ -31,20 +34,33 @@ Repository principles:
3134
## Key Paths
3235

3336
- `src/`: repo-owned library and CLI code
34-
- `tests/`: deterministic example tests and test registration
37+
- `tests/`: deterministic example tests, test registration, and `frame_test.h`
38+
micro-framework
3539
- `docs/`: Doxygen config and API-focused main page
3640
- `scripts/`: hygiene, release, and diagnostics helpers
3741
- `contrib/`: optional service/desktop integration examples
3842
- `cmake/`: reusable analyzer helper scripts
3943
- `.agents/skills/`: project-local agent overlays and merged skills
4044
- `.github/workflows/`: generic CI and release workflow templates
45+
- `benchmarks/`: optional chrono-based micro-benchmarks and `frame_bench.h`
46+
harness
4147
- `upcoming_features/`: forward-looking implementation plans
4248

4349
## Build And Validation
4450

4551
Read `README.md` first before changing build, setup, or release behavior.
4652

47-
Use an out-of-tree build:
53+
Prefer CMake presets for common workflows:
54+
55+
```bash
56+
cmake --preset dev
57+
cmake --build build/dev -j"$(nproc)"
58+
```
59+
60+
Available presets: `dev` (debug + sanitizers), `release` (optimized + LTO),
61+
`ci` (matches GitHub Actions), `coverage` (gcov instrumentation).
62+
63+
Manual out-of-tree build (when presets are unavailable):
4864

4965
```bash
5066
BUILD_DIR="$(mktemp -d /tmp/cpp-frame-build-XXXXXX)"
@@ -54,7 +70,7 @@ cmake --build "$BUILD_DIR" -j"$(nproc)"
5470

5571
If `ninja-build` is unavailable, omit `-G Ninja`.
5672

57-
Optional sanitizer lane:
73+
Optional sanitizer lane (included in the `dev` preset):
5874

5975
```bash
6076
cmake -S . -B "$BUILD_DIR" -G Ninja \
@@ -74,7 +90,9 @@ Use the smallest validation set that proves the change, then extend as needed:
7490
- `cmake --build "$BUILD_DIR" --target clang-tidy`
7591
- `cmake --build "$BUILD_DIR" --target clazy` when the project uses the
7692
example Qt-based UI stack and the tool is available
77-
- `cmake --build "$BUILD_DIR" --target lint`
93+
- `cmake --build "$BUILD_DIR" --target format-check`
94+
- `cmake --build "$BUILD_DIR" --target lint` (includes clang-tidy and cppcheck
95+
when available)
7896
- `cmake --build "$BUILD_DIR" --target docs`
7997
- `bash scripts/run-valgrind.sh "$BUILD_DIR"`
8098
- `bash scripts/check-release-hygiene.sh`
@@ -86,9 +104,55 @@ INSTALL_DIR="$(mktemp -d /tmp/cpp-frame-install-XXXXXX)"
86104
cmake --install "$BUILD_DIR" --prefix "$INSTALL_DIR"
87105
```
88106

107+
## Formatting
108+
109+
Run `cmake --build "$BUILD_DIR" --target format` before committing to keep
110+
source files consistently formatted. CI enforces `format-check` and will reject
111+
unformatted code. The `.clang-format` config at the repo root defines the
112+
canonical style.
113+
114+
## Coverage
115+
116+
Build with the `coverage` preset and run the `coverage` target:
117+
118+
```bash
119+
cmake --preset coverage
120+
cmake --build build/coverage
121+
cmake --build build/coverage --target coverage
122+
```
123+
124+
This runs tests and collects coverage via `gcovr`. HTML output lands in
125+
`build/coverage/coverage/`. New code should maintain or improve line coverage.
126+
127+
## Benchmarks
128+
129+
Build with `-DFRAME_ENABLE_BENCHMARKS=ON` and run manually:
130+
131+
```bash
132+
cmake --build "$BUILD_DIR" --target example_bench
133+
"$BUILD_DIR/benchmarks/example_bench"
134+
```
135+
136+
Add benchmarks for hot paths, algorithms, and performance-sensitive code.
137+
Use `FRAME_BENCHMARK(name, iterations)` from `benchmarks/frame_bench.h`.
138+
139+
## Project Setup
140+
141+
When adapting this frame for a new project, use the init script:
142+
143+
```bash
144+
./scripts/init-project.sh --name "Your Project Name" # dry-run
145+
./scripts/init-project.sh --name "Your Project Name" --apply
146+
```
147+
148+
This renames all placeholder targets, namespaces, prefixes, and filenames.
149+
89150
## Testing Rules
90151

91152
- Keep repo-owned tests deterministic and headless under `CTest`
153+
- Use the `frame_test.h` micro-framework: `FRAME_TEST(name)` for registration,
154+
`FRAME_EXPECT_EQ`, `FRAME_EXPECT_TRUE`, `FRAME_EXPECT_FALSE`,
155+
`FRAME_EXPECT_THROWS` for assertions, `FRAME_RUN_TESTS()` in main
92156
- Keep `WHAT/HOW/WHY` commentary near the start of real test bodies; the repo
93157
scripts enforce that contract
94158
- Prefer pure helper seams and injected fakes over environment-heavy tests

CMakeLists.txt

Lines changed: 83 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ set(CMAKE_CXX_EXTENSIONS OFF)
1414

1515
option(FRAME_ENABLE_ASAN "Enable AddressSanitizer for repo-owned code" OFF)
1616
option(FRAME_ENABLE_UBSAN "Enable UndefinedBehaviorSanitizer for repo-owned code" OFF)
17+
option(FRAME_ENABLE_COVERAGE "Enable gcov/llvm-cov coverage instrumentation" OFF)
18+
option(FRAME_ENABLE_BENCHMARKS "Build the benchmarks directory" OFF)
1719
option(FRAME_ENABLE_QT "Enable the example Qt-based UI integration path" OFF)
1820
option(FRAME_ENABLE_CLAZY "Enable the clazy analyzer lane for the Qt-based UI path" OFF)
1921

@@ -41,7 +43,7 @@ set_target_properties(frame_cli PROPERTIES
4143
OUTPUT_NAME frame_cli
4244
)
4345

44-
function(frame_enable_sanitizers target_name)
46+
function(frame_enable_sanitizers target_name visibility)
4547
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang")
4648
message(WARNING "Sanitizers were requested, but ${CMAKE_CXX_COMPILER_ID} is not configured for repo-owned sanitizer flags")
4749
return()
@@ -61,13 +63,28 @@ function(frame_enable_sanitizers target_name)
6163
endif()
6264

6365
if(sanitizer_compile_flags)
64-
target_compile_options(${target_name} PRIVATE ${sanitizer_compile_flags})
65-
target_link_options(${target_name} PRIVATE ${sanitizer_link_flags})
66+
target_compile_options(${target_name} ${visibility} ${sanitizer_compile_flags})
67+
target_link_options(${target_name} ${visibility} ${sanitizer_link_flags})
6668
endif()
6769
endfunction()
6870

69-
frame_enable_sanitizers(project_core)
70-
frame_enable_sanitizers(frame_cli)
71+
frame_enable_sanitizers(project_core PUBLIC)
72+
frame_enable_sanitizers(frame_cli PRIVATE)
73+
74+
function(frame_enable_coverage target_name visibility)
75+
if(NOT FRAME_ENABLE_COVERAGE)
76+
return()
77+
endif()
78+
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang")
79+
message(WARNING "Coverage requested but ${CMAKE_CXX_COMPILER_ID} is not supported")
80+
return()
81+
endif()
82+
target_compile_options(${target_name} ${visibility} --coverage -fprofile-arcs -ftest-coverage)
83+
target_link_options(${target_name} ${visibility} --coverage)
84+
endfunction()
85+
86+
frame_enable_coverage(project_core PUBLIC)
87+
frame_enable_coverage(frame_cli PRIVATE)
7188

7289
set(FRAME_CLAZY_CHECKS "level0" CACHE STRING "Checks passed to clazy-standalone")
7390
find_program(FRAME_CLANG_TIDY_BIN NAMES clang-tidy)
@@ -109,6 +126,63 @@ add_custom_target(valgrind
109126
VERBATIM
110127
)
111128

129+
find_program(FRAME_CLANG_FORMAT_BIN NAMES clang-format)
130+
if(FRAME_CLANG_FORMAT_BIN)
131+
file(GLOB_RECURSE FRAME_FORMAT_SOURCES
132+
${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp
133+
${CMAKE_CURRENT_SOURCE_DIR}/src/*.h
134+
${CMAKE_CURRENT_SOURCE_DIR}/tests/*.cpp
135+
${CMAKE_CURRENT_SOURCE_DIR}/tests/*.h
136+
${CMAKE_CURRENT_SOURCE_DIR}/benchmarks/*.cpp
137+
${CMAKE_CURRENT_SOURCE_DIR}/benchmarks/*.h
138+
)
139+
140+
add_custom_target(format
141+
COMMAND ${FRAME_CLANG_FORMAT_BIN} -i ${FRAME_FORMAT_SOURCES}
142+
COMMENT "Running clang-format on repo-owned sources"
143+
VERBATIM
144+
)
145+
146+
add_custom_target(format-check
147+
COMMAND ${FRAME_CLANG_FORMAT_BIN} --dry-run --Werror ${FRAME_FORMAT_SOURCES}
148+
COMMENT "Checking clang-format compliance"
149+
USES_TERMINAL
150+
VERBATIM
151+
)
152+
else()
153+
message(STATUS "clang-format not found; format and format-check targets will be unavailable")
154+
endif()
155+
156+
find_program(FRAME_CPPCHECK_BIN NAMES cppcheck)
157+
add_custom_target(cppcheck
158+
COMMAND ${CMAKE_COMMAND}
159+
-DTOOL_BIN=${FRAME_CPPCHECK_BIN}
160+
-DTOOL_NAME=cppcheck
161+
-DBUILD_DIR=${CMAKE_BINARY_DIR}
162+
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-cppcheck.cmake
163+
COMMENT "Running cppcheck analysis"
164+
USES_TERMINAL
165+
VERBATIM
166+
)
167+
add_dependencies(lint cppcheck)
168+
169+
if(FRAME_ENABLE_COVERAGE)
170+
find_program(FRAME_GCOVR_BIN NAMES gcovr)
171+
add_custom_target(coverage
172+
COMMAND ${CMAKE_CTEST_COMMAND} --test-dir ${CMAKE_BINARY_DIR} --output-on-failure
173+
COMMAND ${CMAKE_COMMAND} -E echo "---"
174+
COMMAND ${CMAKE_COMMAND} -E echo "Collecting coverage data..."
175+
COMMAND ${FRAME_GCOVR_BIN}
176+
--root ${CMAKE_CURRENT_SOURCE_DIR}
177+
--filter ${CMAKE_CURRENT_SOURCE_DIR}/src/
178+
--print-summary
179+
--html-details ${CMAKE_BINARY_DIR}/coverage/index.html
180+
COMMENT "Running tests and collecting coverage"
181+
USES_TERMINAL
182+
VERBATIM
183+
)
184+
endif()
185+
112186
if(DOXYGEN_FOUND)
113187
set(FRAME_DOXYGEN_OUTPUT_DIR "${CMAKE_BINARY_DIR}/docs/doxygen")
114188
set(FRAME_DOXYGEN_CONFIG "${CMAKE_BINARY_DIR}/Doxyfile")
@@ -137,3 +211,7 @@ install(FILES contrib/org.example.project.desktop DESTINATION ${CMAKE_INSTALL_DA
137211
if(BUILD_TESTING)
138212
add_subdirectory(tests)
139213
endif()
214+
215+
if(FRAME_ENABLE_BENCHMARKS)
216+
add_subdirectory(benchmarks)
217+
endif()

0 commit comments

Comments
 (0)