From 637ec1605b4a7b2017f8d5b6a2ab897c5b470b39 Mon Sep 17 00:00:00 2001 From: stacknil Date: Sat, 8 Aug 2026 22:33:27 +0800 Subject: [PATCH 1/3] build: add scoped compiler warning policy --- CMakeLists.txt | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 00beeea..db3e8a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,30 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) option(LOGLENS_BUILD_FUZZERS "Build Clang libFuzzer targets" OFF) +option(LOGLENS_ENABLE_WARNINGS "Enable compiler warnings for LogLens targets" ON) +option( + LOGLENS_WARNINGS_AS_ERRORS + "Treat warnings as errors for LogLens targets" + OFF +) + +function(loglens_enable_warnings target) + if(NOT LOGLENS_ENABLE_WARNINGS) + return() + endif() + + if(MSVC) + target_compile_options(${target} PRIVATE /W4) + if(LOGLENS_WARNINGS_AS_ERRORS) + target_compile_options(${target} PRIVATE /WX) + endif() + elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang") + target_compile_options(${target} PRIVATE -Wall -Wextra -Wpedantic) + if(LOGLENS_WARNINGS_AS_ERRORS) + target_compile_options(${target} PRIVATE -Werror) + endif() + endif() +endfunction() set(LOGLENS_LIBRARY_SOURCES src/config.cpp @@ -35,6 +59,7 @@ set(LOGLENS_LIBRARY_SOURCES ) add_library(loglens_lib ${LOGLENS_LIBRARY_SOURCES}) +loglens_enable_warnings(loglens_lib) target_include_directories(loglens_lib PUBLIC @@ -43,28 +68,34 @@ target_include_directories(loglens_lib add_executable(loglens src/main.cpp) target_link_libraries(loglens PRIVATE loglens_lib) +loglens_enable_warnings(loglens) target_compile_definitions(loglens PRIVATE LOGLENS_VERSION="${LOGLENS_VERSION}") include(CTest) if(BUILD_TESTING) add_executable(test_parser tests/test_parser.cpp) target_link_libraries(test_parser PRIVATE loglens_lib) + loglens_enable_warnings(test_parser) add_test(NAME parser COMMAND test_parser) add_executable(test_parser_properties tests/test_parser_properties.cpp) target_link_libraries(test_parser_properties PRIVATE loglens_lib) + loglens_enable_warnings(test_parser_properties) add_test(NAME parser_properties COMMAND test_parser_properties) add_executable(test_detector tests/test_detector.cpp) target_link_libraries(test_detector PRIVATE loglens_lib) + loglens_enable_warnings(test_detector) add_test(NAME detector COMMAND test_detector) add_executable(test_report tests/test_report.cpp) target_link_libraries(test_report PRIVATE loglens_lib) + loglens_enable_warnings(test_report) add_test(NAME report COMMAND test_report) add_executable(test_cli tests/test_cli.cpp) target_link_libraries(test_cli PRIVATE loglens_lib) + loglens_enable_warnings(test_cli) add_test( NAME cli COMMAND test_cli @@ -75,6 +106,7 @@ if(BUILD_TESTING) ) add_executable(test_report_contracts tests/test_report_contracts.cpp) + loglens_enable_warnings(test_report_contracts) add_test( NAME report_contracts COMMAND test_report_contracts @@ -90,6 +122,7 @@ if(LOGLENS_BUILD_FUZZERS) add_library(loglens_fuzz_lib STATIC ${LOGLENS_LIBRARY_SOURCES}) target_include_directories(loglens_fuzz_lib PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src") + loglens_enable_warnings(loglens_fuzz_lib) target_compile_options( loglens_fuzz_lib PRIVATE @@ -99,6 +132,7 @@ if(LOGLENS_BUILD_FUZZERS) add_executable(fuzz_parser fuzz/parser_fuzz.cpp) target_link_libraries(fuzz_parser PRIVATE loglens_fuzz_lib) + loglens_enable_warnings(fuzz_parser) target_compile_options( fuzz_parser PRIVATE From f67b27fd59622d067dca22cd05ec9bac664d62c9 Mon Sep 17 00:00:00 2001 From: stacknil Date: Sat, 8 Aug 2026 22:33:35 +0800 Subject: [PATCH 2/3] ci: enforce project warnings as errors --- .github/workflows/ci.yml | 7 ++++++- .github/workflows/codeql.yml | 6 +++++- CMakePresets.json | 3 ++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 07674f5..93b1b7a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,11 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Configure - run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Release -D BUILD_TESTING=ON + run: >- + cmake -S . -B build + -D CMAKE_BUILD_TYPE=Release + -D BUILD_TESTING=ON + -D LOGLENS_WARNINGS_AS_ERRORS=ON - name: Build run: cmake --build build --config Release @@ -48,6 +52,7 @@ jobs: -D CMAKE_BUILD_TYPE=RelWithDebInfo -D BUILD_TESTING=OFF -D LOGLENS_BUILD_FUZZERS=ON + -D LOGLENS_WARNINGS_AS_ERRORS=ON - name: Build fuzz target run: cmake --build build-fuzz --target fuzz_parser --config RelWithDebInfo diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 78f35d3..a5f568c 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -28,7 +28,11 @@ jobs: languages: c-cpp - name: Configure - run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Release -D BUILD_TESTING=ON + run: >- + cmake -S . -B build + -D CMAKE_BUILD_TYPE=Release + -D BUILD_TESTING=ON + -D LOGLENS_WARNINGS_AS_ERRORS=ON - name: Build run: cmake --build build --config Release diff --git a/CMakePresets.json b/CMakePresets.json index e134a5b..3ecce5f 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -24,7 +24,8 @@ "binaryDir": "${sourceDir}/build/ci-release", "cacheVariables": { "BUILD_TESTING": "ON", - "CMAKE_BUILD_TYPE": "Release" + "CMAKE_BUILD_TYPE": "Release", + "LOGLENS_WARNINGS_AS_ERRORS": "ON" } } ], From 56ed10e88f056ad7e14d21d7884abd1c44b3f64f Mon Sep 17 00:00:00 2001 From: stacknil Date: Sat, 8 Aug 2026 22:33:45 +0800 Subject: [PATCH 3/3] docs: record episode semantics research boundary --- docs/adr/0001-episode-semantics-boundaries.md | 118 ++++++++++++++++++ docs/design.md | 4 + docs/dev-setup.md | 10 ++ 3 files changed, 132 insertions(+) create mode 100644 docs/adr/0001-episode-semantics-boundaries.md diff --git a/docs/adr/0001-episode-semantics-boundaries.md b/docs/adr/0001-episode-semantics-boundaries.md new file mode 100644 index 0000000..300d689 --- /dev/null +++ b/docs/adr/0001-episode-semantics-boundaries.md @@ -0,0 +1,118 @@ +# ADR 0001: Episode Semantics Boundaries for v0.7 Research + +- Status: Proposed +- Date: 2026-08-08 +- Owner: stacknil + +## Context + +LogLens v0.6 reports repeated findings as detector episodes. The public v0.6 +contract names four policy points: threshold crossing, maximal window, +non-overlapping windows, and cooldown merge. An episode is a reporting unit, +not an incident boundary. + +The current implementation groups each rule subject by source IP or username, +sorts its signals by time, cuts an activity segment when an adjacent event gap +is greater than the rule window, and selects one best sliding window inside +each segment. The selected window must meet the rule threshold before a finding +is emitted. See [`src/detector.cpp`](../../src/detector.cpp) and the v0.6 +[`Episode Policy`](../release-v0.6.0.md#episode-policy). + +This baseline is deterministic and works for clearly separated bursts. It has +an important research boundary: a continuous low-density background stream can +keep two dense peaks in the same activity segment. The best-window selection +then emits one peak and can hide the fact that a second dense peak exists. + +For example, with a ten-minute rule window and five-event threshold, sparse +background events every nine minutes can connect two five-event bursts. There +is no adjacent gap large enough to cut the segment, even if the two bursts are +far apart in aggregate time. Under the current algorithm, the segment is +eligible for one best-window selection; it is not eligible for two peak-based +episodes merely because its internal density is bimodal. + +This is a v0.7 research boundary, not a v0.6 release blocker. The v0.6 +algorithm and report contract remain unchanged by this ADR. + +## Decision + +Keep the v0.6 episode algorithm unchanged and make the following semantics +explicit for v0.7 research: + +1. **Threshold crossing** is an eligibility event. The first window that meets + the threshold proves that a candidate can emit a finding; it does not by + itself define the episode start or the final reported window. +2. **Maximal window** means the selected highest-signal window under the rule's + objective. In v0.6 this is a best-count sliding window (or the + distinct-username objective for multi-user probing), not the longest possible + time span. Tie-breaking and whether a candidate may be extended without + increasing its score are v0.7 research questions. +3. **Non-overlapping episode** is currently enforced by segment construction + and one selection per segment. It does not yet describe a global candidate + ranking problem where two windows compete for shared events. v0.7 must state + whether exclusion is by event IDs, time intervals, or a rule-specific signal + budget. +4. **Cooldown merge** currently means that adjacent signals with a gap less + than or equal to the rule window remain in one candidate segment. A gap + larger than the rule window starts another segment. This is an adjacency + rule, not a density-aware model of background activity. +5. **Continuous background with two dense peaks** is a required research fixture + category. The fixture must preserve the sparse bridge events, show both + dense peaks, and record that the v0.6 baseline may return one finding. A + candidate v0.7 algorithm may split the peaks only with an explicit, tested + separation policy. + +No detector implementation change is part of this ADR. The first v0.7 change +should be a fixture and oracle that makes the baseline behavior measurable +before a new segmentation algorithm is selected. + +## Research fixture contract + +The fixture should use sanitized synthetic events and a fixed rule configuration +that makes each boundary observable. At minimum it should cover: + +| Case | Required observation | +| --- | --- | +| Isolated dense bursts | Two bursts separated by a gap greater than the rule window produce two baseline episodes. | +| Continuous bridge | Two dense bursts connected by background gaps at or below the rule window remain one baseline segment. | +| Threshold edge | A candidate exactly at threshold is eligible; one event below threshold is not. | +| Maximal-window tie | Equal-score windows have a documented deterministic tie-break. | +| Shared evidence | Overlapping candidate windows make the non-overlap unit explicit. | +| Cooldown boundary | A gap exactly at the rule window and one second beyond it test the inclusive boundary. | +| Bimodal background | Two dense peaks are surrounded by lower-rate background, with expected baseline output recorded separately from the research candidate output. | + +Each case should record raw event IDs, timestamps, rule window, threshold, +candidate windows, selected windows, episode indexes, and the reason an event +was included or excluded. The fixture must not claim compromise, intent, +attribution, or an incident boundary. + +## Alternatives considered + +- **Keep adjacent-gap segmentation as the final model** - simple and + deterministic, but it cannot distinguish a continuous background bridge from + a single coherent burst. +- **Split every local density peak** - can expose bimodal activity, but needs + explicit peak prominence, minimum separation, and noise-handling parameters; + it may over-split one operational burst. +- **Use a density-aware cooldown or bridge budget** - directly targets the + continuous-background case, but introduces additional policy knobs and needs + fixture-backed calibration before it can become a stable contract. +- **Emit all threshold-crossing windows** - preserves more evidence, but creates + overlapping findings and makes `finding_id`, episode identity, and downstream + deduplication ambiguous. + +## Consequences + +- v0.6 remains stable and does not acquire an untested density model. +- v0.7 gets a concrete research target instead of an ambiguous request to + "improve episodes." +- A future algorithm must be compared with the current baseline on the same + fixture, including cases where the baseline behavior is intentionally + preserved. +- The report contract may need an explicit candidate/selection distinction if + v0.7 emits multiple peak candidates from one continuous segment. + +## References + +- [`v0.6 Episode Policy`](../release-v0.6.0.md#episode-policy) +- [`Detector implementation`](../../src/detector.cpp) +- [`Detector tests`](../../tests/test_detector.cpp) diff --git a/docs/design.md b/docs/design.md index 7a74003..a614fd6 100644 --- a/docs/design.md +++ b/docs/design.md @@ -16,3 +16,7 @@ The CLI in `src/main.cpp` wires those layers together: - write `report.md` and `report.json` This keeps the MVP easy to test and extend without introducing heavy dependencies or unnecessary abstractions. + +## Architecture decisions + +- [ADR 0001: Episode Semantics Boundaries for v0.7 Research](adr/0001-episode-semantics-boundaries.md) diff --git a/docs/dev-setup.md b/docs/dev-setup.md index a287024..9422ac8 100644 --- a/docs/dev-setup.md +++ b/docs/dev-setup.md @@ -34,6 +34,16 @@ cmake --build --preset ci-release ctest --preset ci-release ``` +Normal LogLens targets enable compiler warnings by default. GCC/Clang builds +use `-Wall -Wextra -Wpedantic`; MSVC builds use `/W4`. Warnings are scoped to +LogLens-owned targets rather than applied globally to a consumer's directory. + +Warnings-as-errors are disabled for ordinary local builds. CI enables +`LOGLENS_WARNINGS_AS_ERRORS=ON`, which adds `-Werror` or `/WX` only to those +LogLens-owned targets. A local toolchain can opt out of the warning flags with +`-D LOGLENS_ENABLE_WARNINGS=OFF` when compiler or third-party integration +differences require it. + ## Manual Fallback If you do not want to use presets, or if your local CMake is 3.20 but not 3.21+, the equivalent manual flow is: