diff --git a/AGENTS.md b/AGENTS.md index 2035269..1f617d2 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,88 +1,136 @@ -# Repository Guidelines - -## Preferred Commands -- Configure with tests: `cmake -S . -B build -DCFL_TESTS=On` -- Build: `cmake --build build -j8` -- Run all tests: `ctest --test-dir build --output-on-failure` -- Run a focused test: `ctest --test-dir build -R --output-on-failure` -- Check staged or local patches for whitespace before closing a change: - `git diff --check` - -## Project Structure & Module Organization -CFL is a small C library built with CMake. - -- `include/cfl/`: public CFL headers. -- `src/`: library implementation files. -- `tests/`: acutest-based unit tests. -- `lib/xxhash/`: bundled xxHash dependency. -- `cmake/`: project CMake helpers. - -Keep changes scoped to the affected module. Put public declarations in -`include/cfl/`, implementation in `src/`, and matching unit coverage in -`tests/` when behavior changes. - -## Build, Test, and Development Commands -- `cmake -S . -B build -DCFL_TESTS=On`: configure the project with tests. -- `cmake --build build -j8`: compile the static library and tests. -- `ctest --test-dir build --output-on-failure`: run the enabled test suite. -- `ctest --test-dir build -R cfl-test- --output-on-failure`: run a - focused unit test. - -Prefer targeted test runs while iterating, then run the full enabled suite -before closing changes that touch shared code or public APIs. - -## Coding Style & Naming Conventions -- Follow the existing Apache-style C conventions used in this repository. -- Use 4-space indentation and keep lines readable; avoid unnecessary wrapping. -- Always use braces for `if/else/while/do` blocks. -- Put function opening braces on the next line: - `int fn(void)\n{ ... }` -- Declare variables at the start of functions, not mid-block. -- Prefer descriptive `snake_case` names with the `cfl_` prefix for public APIs. -- Use `CFL_TRUE` and `CFL_FALSE` for CFL boolean-style return values. -- Use `/* ... */` comments, and add comments only where they clarify non-obvious - behavior. -- Keep public headers self-contained by including the standard headers they need. - -## Testing Guidelines -- Add or update acutest unit coverage for behavior changes. -- Keep tests close to the affected module and name test binaries through - `tests/CMakeLists.txt`. -- Validate both success and failure paths for parsers, containers, allocation - handling, and boundary conditions. -- Run broader coverage when changing shared headers, CMake wiring, memory - ownership, or common data structures. -- If a relevant test cannot be run, report the exact blocker in the final - response. - -## Downstream Impact Validation -- For every modified CFL function, inspect callers in CFL, Fluent Bit, - cmetrics, ctraces, and cprofiles before closing the change. -- Check for side effects from changes to signatures, return values, error - handling, ownership, object lifetime, allocation behavior, and mutation - semantics. -- Distinguish production callers from bundled CFL source and test copies when - reporting impact. -- Run relevant downstream builds or tests when a change can affect an existing - caller. If a downstream checkout or required test is unavailable, report the - exact validation gap. - -## Commit & Pull Request Guidelines -- Follow observed local history style: - `component: short imperative description` - Examples: `sds: do not export internal sds_alloc function`, - `build: bump to v0.6.2`, `atomic: add atomic operations API`. -- Keep each commit scoped to one component or interface. -- Keep subject/body lines concise; use a body when the reason or scope is not - obvious from the subject. -- Do not mix unrelated code and documentation updates in one commit unless the - user explicitly asks for a combined commit. -- Do not rewrite history, amend commits, create remote branches, or open pull - requests unless explicitly requested. - -## Agent Action Limits -- Do not modify repositories or files outside this project unless the user - explicitly asks. -- Do not revert user changes outside the requested scope. -- Preserve unrelated untracked or modified files in the worktree. -- Prefer minimal patches that avoid unrelated formatting or refactoring churn. +# Repository Guide + +This is the canonical operating guide for contributors and coding agents. CFL +is a compact C library of data structures and low-level utilities embedded by +Fluent Bit and companion telemetry libraries. Keep it portable, allocation-safe, +and usable both as a bundled dependency and as an installed library. + +## Repository map + +- `include/cfl/`: public API. Each header must compile on its own. +- `src/`: implementations and private headers; `src/cfl_arena_internal.h` is + not public API. +- `tests/`: acutest unit tests, public-header tests, and an installed-consumer + fixture. +- `benchmarks/`: arena and mutable-variant performance tools; see + [benchmarks/README.md](benchmarks/README.md). +- `cmake/`, `CMakeLists.txt`: CMake 3.20+ build and packaging definitions. +- `lib/xxhash/`: bundled third-party xxHash sources. Do not apply CFL style or + unrelated edits there. +- `.github/workflows/`: authoritative cross-platform, sanitizer, Valgrind, + installed-consumer, packaging, lint, and downstream validation. + +Start architecture work with [README.md](README.md), the relevant public header, +and its matching source and test file. Arena ownership and tuning are detailed +in [ARENA.md](ARENA.md). + +## Generated and bundled files + +CMake generates these ignored files; edit their `.in` sources instead: + +- `include/cfl/cfl_info.h` from `include/cfl/cfl_info.h.in` +- `include/cfl/cfl_version.h` from `include/cfl/cfl_version.h.in` +- `tests/cfl_tests_internal.h` from `tests/cfl_tests_internal.h.in` + +Do not edit build directories or generated package output. Treat `lib/xxhash/` +and `tests/lib/acutest/` as vendored code unless the task explicitly updates the +dependency. + +## Build and test + +The verified local path is: + +```sh +cmake -S . -B build -DCFL_TESTS=On +cmake --build build -j8 +ctest --test-dir build --output-on-failure +``` + +Convenience wrappers run from any directory: + +```sh +scripts/agent-build.sh +scripts/agent-test.sh +scripts/agent-test.sh cfl-test-arena +scripts/agent-verify.sh +``` + +`scripts/agent-test.sh` accepts a CTest regular expression. The verification +wrapper configures, builds, runs all tests, and checks tracked diffs for +whitespace errors. Set `BUILD_DIR` or `BUILD_JOBS` to override its defaults. + +For a focused test without the wrapper: + +```sh +ctest --test-dir build -R cfl-test- --output-on-failure +``` + +Build benchmarks separately in release mode: + +```sh +cmake -S . -B build/bench -DCMAKE_BUILD_TYPE=Release -DCFL_BENCHMARKS=On +cmake --build build/bench -j8 +``` + +There is no repository-owned formatter or standalone local sanitizer command. +Always run `git diff --check`. GitHub CI is the canonical extended validation +for GNU99/GNU17, GCC/Clang, Windows/MSYS2, ARM64, sanitizers, Valgrind, shell +lint, installed consumers, and downstream consumers. + +## Coding and ownership conventions + +- Follow the existing Apache-style C: four-space indentation, braces for all + control blocks, and function opening braces on the next line. +- Declare variables at the start of functions, not inside executable blocks. +- Use descriptive `snake_case`; public symbols use the `cfl_` prefix. +- Use `CFL_TRUE` and `CFL_FALSE` for CFL boolean-style results. +- Keep public headers self-contained and include the standard headers they use. +- Put public declarations in `include/cfl/`, implementation in `src/`, and + behavioral coverage in `tests/`. +- Check allocation failure and partial initialization. Preserve cleanup paths + and ownership on every error return. +- Verify container ownership transfer, arena lifetime, and mutation behavior + before changing variants, arrays, kvlists, or SDS storage. +- Avoid unrelated formatting, refactoring, generated output, or vendor churn. + +## Compatibility and downstream boundaries + +Public headers and installed library symbols are compatibility-sensitive. +Before changing a public signature, return value, ownership rule, layout, or +allocation behavior, inspect all in-repository callers and tests. Maintain C99 +portability and do not introduce compiler-specific behavior without an existing +compatibility abstraction and cross-platform coverage. + +Fluent Bit, cmetrics, ctraces, and cprofiles bundle CFL under `lib/cfl`. CI tests +the current CFL tree by replacing each consumer's bundled copy. CFL owns its +generic data structures and APIs; consumer-specific behavior remains in the +consumer repository. For changes that can affect callers, follow +[docs/ai/cross-repository.md](docs/ai/cross-repository.md), inspect production +callers separately from bundled source copies, and report any unavailable +checkout or validation. + +## Change workflow + +- Investigation: [docs/ai/investigate.md](docs/ai/investigate.md) +- Bug fixes: [docs/ai/bug-fix.md](docs/ai/bug-fix.md) +- Reviews: [docs/ai/code-review.md](docs/ai/code-review.md) +- Cross-repository changes: [docs/ai/cross-repository.md](docs/ai/cross-repository.md) + +Follow local commit history: `component: short imperative description`. Keep +commits scoped to one component or interface. Do not amend history, create or +delete remote branches, or open pull requests unless explicitly requested. + +## Definition of done + +1. The change is minimal and belongs in this repository. +2. New behavior has success, failure, and boundary tests where applicable. +3. Relevant focused tests pass, followed by `scripts/agent-verify.sh` for shared + code, public APIs, ownership, CMake, or installation changes. +4. Public API and downstream impact are assessed and documented. +5. Generated and vendored files remain untouched unless explicitly in scope. +6. `git diff --check` passes and unrelated user changes remain intact. +7. The final report lists commands run, compatibility impact, and validation + gaps or unresolved risks. + +Do not modify repositories outside this checkout without explicit permission. +Preserve unrelated tracked and untracked work in the shared worktree. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..43c994c --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +@AGENTS.md diff --git a/CMakeLists.txt b/CMakeLists.txt index b289b4b..edc30bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # C Floppy Version set(CFL_VERSION_MAJOR 1) set(CFL_VERSION_MINOR 0) -set(CFL_VERSION_PATCH 1) +set(CFL_VERSION_PATCH 2) set(CFL_VERSION_STR "${CFL_VERSION_MAJOR}.${CFL_VERSION_MINOR}.${CFL_VERSION_PATCH}") # Configuration options diff --git a/docs/ai/bug-fix.md b/docs/ai/bug-fix.md new file mode 100644 index 0000000..12aed8b --- /dev/null +++ b/docs/ai/bug-fix.md @@ -0,0 +1,41 @@ +# Bug-fix workflow + +## Purpose + +Correct a reproducible CFL defect with the smallest safe change and permanent +regression coverage. + +## Investigation + +1. Restate the observed and expected behavior; label assumptions explicitly. +2. Identify the owning subsystem and repository. +3. Trace the complete code path, including allocation failures, partial + initialization, ownership transfer, cleanup, and malformed inputs. +4. Locate existing tests and reproduce the defect when practical. +5. Inspect callers when return values, ownership, layout, or public behavior may + change. Use [cross-repository.md](cross-repository.md) when needed. + +## Implementation + +1. Add a regression test that fails for the reported behavior. +2. Implement the smallest reasonable fix without unrelated refactoring. +3. Preserve API/ABI and existing valid behavior unless the task explicitly + authorizes a compatibility change. +4. Cover failure and boundary paths relevant to the root cause. + +## Validation + +Run the focused CTest target while iterating, then `scripts/agent-verify.sh`. +Public API, allocator, ownership, or common-container changes also require the +relevant downstream assessment and CI coverage. + +## Final report + +Report the root cause, fix, regression test, exact commands and results, +compatibility impact, downstream impact, and unresolved risks. + +## Stop conditions + +Stop when the expected behavior is ambiguous, the fix belongs to a consumer, +or validation requires unavailable external state. Present the evidence and the +smallest decision needed to continue. diff --git a/docs/ai/code-review.md b/docs/ai/code-review.md new file mode 100644 index 0000000..2ee5d85 --- /dev/null +++ b/docs/ai/code-review.md @@ -0,0 +1,36 @@ +# Code-review workflow + +## Purpose + +Review a CFL change for actionable defects and regressions. A review identifies +issues; it does not modify code unless implementation is separately requested. + +## Investigation + +1. Read the complete diff and identify the affected public APIs, ownership + boundaries, generated files, vendor code, tests, and consumers. +2. Trace changed call paths rather than reviewing isolated lines. +3. Prioritize correctness, allocation and resource ownership, partial cleanup, + concurrency, API/ABI compatibility, compiler portability, malformed input, + integer overflow, missing tests, and measurable performance impact. +4. Check whether the implementation adds unnecessary state, abstraction, or + duplicated logic. +5. Verify each suspected issue against current code and existing tests before + reporting it. + +## Validation + +Run focused tests or small read-only checks when they materially confirm a +finding. Use `scripts/agent-verify.sh` only when review scope and time justify a +full local pass. + +## Final report + +List findings by severity. For each, give the file and line, triggering case, +consequence, and smallest useful correction. Then list validation gaps. If no +actionable findings remain, say so explicitly and note residual risk. + +## Stop conditions + +Do not speculate beyond available evidence. Escalate when intended semantics, +supported platforms, or consumer compatibility requirements are unclear. diff --git a/docs/ai/cross-repository.md b/docs/ai/cross-repository.md new file mode 100644 index 0000000..011ab7b --- /dev/null +++ b/docs/ai/cross-repository.md @@ -0,0 +1,52 @@ +# Cross-repository workflow + +## Purpose + +Validate CFL changes that may affect Fluent Bit, cmetrics, ctraces, or cprofiles, +which bundle CFL under `lib/cfl`. + +## Investigation + +1. Decide which repository owns the behavior: generic CFL data structures and + APIs belong here; product- or telemetry-specific behavior belongs to its + consumer. +2. Identify changed public symbols, layouts, return values, ownership, + allocation, mutation, and compatibility guarantees. +3. Search actual consumer call sites. Exclude copied `lib/cfl` implementations + when counting production callers. +4. Determine dependency impact and landing order. A CFL API change normally + lands first, followed by separate consumer changes after a usable CFL + revision exists. + +## Implementation strategy + +Keep commits and pull requests separate per repository. For pre-merge testing, +replace the consumer's bundled `lib/cfl` with an archive of the CFL revision, +matching `.github/workflows/build.yaml`; do not commit a temporary dependency +copy unless explicitly requested. + +## Validation + +1. Run CFL focused tests and `scripts/agent-verify.sh` first. +2. Configure and build each affected consumer against the exact CFL revision. +3. Run cmetrics, ctraces, and cprofiles tests when affected. Fluent Bit's CI + configuration builds selected processor plugins but does not run their test + suites, so add focused consumer validation when behavior—not just linkage—is + at risk. +4. Record the CFL and consumer revisions and exact configuration commands. + +CI currently verifies all four consumers by replacing their bundled CFL tree. +Consult that workflow for the authoritative options rather than copying them +into another canonical document. + +## Final report + +Report behavior ownership, affected production callers, API/compatibility +impact, tested revision pairs, results, landing order, and any consumer not +validated. + +## Stop conditions + +Stop before changing another repository without authorization. Escalate when a +consumer requires an incompatible API, its expected revision is unavailable, +or standalone CFL validation passes but consumer integration fails. diff --git a/docs/ai/investigate.md b/docs/ai/investigate.md new file mode 100644 index 0000000..83884b9 --- /dev/null +++ b/docs/ai/investigate.md @@ -0,0 +1,38 @@ +# Investigation workflow + +## Purpose + +Establish an evidence-based explanation of CFL behavior without changing code. +Use this for bug reports, design questions, compatibility concerns, and unclear +ownership or performance behavior. + +## Investigation + +1. Restate the observed behavior and separate verified facts from assumptions. +2. Identify the owning CFL module from the public header, implementation, and + related tests. Check whether the behavior is actually consumer-owned. +3. Trace inputs, return values, ownership transfers, allocations, mutation, + cleanup, and error paths through every relevant caller. +4. Search tests, changelog entries, documentation, and Git history for intended + behavior and compatibility constraints. +5. Reproduce the behavior with an existing focused test or the smallest + temporary diagnostic possible when practical. +6. For public behavior, inspect the bundled downstream callers described in + [cross-repository.md](cross-repository.md). + +## Validation + +Run the focused test that exercises the path when one exists. Do not mutate +production files merely to complete an investigation. + +## Final report + +Report evidence, root cause or best-supported explanation, affected callers, +compatibility implications, commands run, and remaining uncertainty. Recommend +a change only when the evidence supports it. + +## Stop conditions + +Stop and request direction when reproduction requires unavailable inputs, +access to another repository was not authorized, or multiple plausible API +semantics would materially change the solution. diff --git a/scripts/agent-build.sh b/scripts/agent-build.sh new file mode 100755 index 0000000..f30a00d --- /dev/null +++ b/scripts/agent-build.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +set -eu + +root_dir=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd) +build_dir=${BUILD_DIR:-"$root_dir/build/agent"} +build_jobs=${BUILD_JOBS:-8} + +cmake -S "$root_dir" -B "$build_dir" -DCFL_TESTS=On +cmake --build "$build_dir" -j"$build_jobs" diff --git a/scripts/agent-test.sh b/scripts/agent-test.sh new file mode 100755 index 0000000..f0a411e --- /dev/null +++ b/scripts/agent-test.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +set -eu + +root_dir=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd) +build_dir=${BUILD_DIR:-"$root_dir/build/agent"} + +if [ ! -f "$build_dir/CTestTestfile.cmake" ]; then + echo "test build not found; run scripts/agent-build.sh first" >&2 + exit 1 +fi + +if [ "$#" -gt 1 ]; then + echo "usage: scripts/agent-test.sh [ctest-regular-expression]" >&2 + exit 2 +fi + +if [ "$#" -eq 1 ]; then + ctest --test-dir "$build_dir" -R "$1" --output-on-failure +else + ctest --test-dir "$build_dir" --output-on-failure +fi diff --git a/scripts/agent-verify.sh b/scripts/agent-verify.sh new file mode 100755 index 0000000..65b60d9 --- /dev/null +++ b/scripts/agent-verify.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +set -eu + +root_dir=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd) + +"$root_dir/scripts/agent-build.sh" +"$root_dir/scripts/agent-test.sh" +git -C "$root_dir" diff --check +git -C "$root_dir" diff --cached --check