Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 21 additions & 5 deletions docs/adr/0001-episode-semantics-boundaries.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,25 @@ Reversing the fixture input produces the same ordered oracle. Boundary tests
also retain one episode at an exact 600-second cooldown gap and permit two at
601 seconds.

This accepts the hypothesis for the bounded fixture only. Isolated bursts,
maximal-window ties, shared evidence, background calibration, and a production
complexity design still require independent evidence. `Detector::analyze()` and
`loglens.report.v3` remain unchanged.
The `isolated_dense_bursts` null control uses the same threshold of five and
inclusive 600-second rule window. Its two five-event bursts have a 1,080-second
inter-segment gap. Both the replayed v0.6 baseline and the candidate emit two
episodes, preserve all ten events exactly once, report no exclusions, and keep
`continuous_segment_split` false. The candidate preserves these deterministic
finding IDs:

- `finding:brute_force:883357c5e7697574`
- `finding:brute_force:ba242483f59f6f4e`

Reversing the input or replacing timestamps with equivalent timezone offsets
does not change the ordered oracle. This accepts the candidate as compatible
with already-correct isolated segmentation for this bounded null control; it
does not expand the candidate's production scope.

Together, the two fixtures accept the recovery and null-control hypotheses for
their bounded cases only. Maximal-window ties, shared evidence, background
calibration, and a production complexity design still require independent
evidence. `Detector::analyze()` and `loglens.report.v3` remain unchanged.

## Alternatives considered

Expand Down Expand Up @@ -178,4 +193,5 @@ complexity design still require independent evidence. `Detector::analyze()` and
- [`Baseline contract tests`](../../tests/test_episode_candidate_baseline_contract.py)
- [`Candidate evaluator`](../../scripts/evaluate_episode_candidate.py)
- [`Candidate regression tests`](../../tests/test_episode_candidate.py)
- [`Candidate oracle`](../../tests/fixtures/episode_semantics_v0.7/continuous_background_two_peaks/candidate.window-separated-v1.expected.json)
- [`Continuous-background candidate oracle`](../../tests/fixtures/episode_semantics_v0.7/continuous_background_two_peaks/candidate.window-separated-v1.expected.json)
- [`Isolated-burst candidate oracle`](../../tests/fixtures/episode_semantics_v0.7/isolated_dense_bursts/candidate.window-separated-v1.expected.json)
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
{
"format": "loglens.episode_baseline_expected.v1",
"fixture_id": "episode_semantics_v0.7.isolated_dense_bursts",
"algorithm": {
"id": "v0.6.activity_segments_best_count_window",
"implementation": "src/detector.cpp",
"segment_boundary": "split when an adjacent event gap is greater than the rule window",
"selection_tie_break": "keep the first maximum encountered in chronological scan order"
},
"rule": {
"rule_id": "brute_force",
"grouping_key": "source_ip",
"subject": "203.0.113.78",
"threshold": 5,
"window_seconds": 600,
"window_boundary": "inclusive"
},
"derived_input": {
"event_count": 10,
"dense_peak_count": 2,
"activity_segment_count": 2,
"activity_segments": [
{
"segment_id": "segment:1",
"event_ids": [
"line:1",
"line:2",
"line:3",
"line:4",
"line:5"
],
"first_seen": "2026-03-11T09:00:00Z",
"last_seen": "2026-03-11T09:02:00Z",
"max_adjacent_gap_seconds": 30,
"boundary_observation": "Five dense events remain inside one inclusive 600-second activity segment."
},
{
"segment_id": "segment:2",
"event_ids": [
"line:6",
"line:7",
"line:8",
"line:9",
"line:10"
],
"first_seen": "2026-03-11T09:20:00Z",
"last_seen": "2026-03-11T09:22:00Z",
"max_adjacent_gap_seconds": 30,
"boundary_observation": "The 1,080-second gap after segment 1 exceeds the rule window, so v0.6 starts a second activity segment."
}
]
},
"candidate_windows": [
{
"candidate_id": "baseline:burst-a",
"threshold_crossing_event_id": "line:5",
"event_ids": [
"line:1",
"line:2",
"line:3",
"line:4",
"line:5"
],
"first_seen": "2026-03-11T09:00:00Z",
"last_seen": "2026-03-11T09:02:00Z",
"event_count": 5,
"threshold_met": true,
"decision": "selected",
"decision_reason": "Only threshold-eligible window in the first activity segment."
},
{
"candidate_id": "baseline:burst-b",
"threshold_crossing_event_id": "line:10",
"event_ids": [
"line:6",
"line:7",
"line:8",
"line:9",
"line:10"
],
"first_seen": "2026-03-11T09:20:00Z",
"last_seen": "2026-03-11T09:22:00Z",
"event_count": 5,
"threshold_met": true,
"decision": "selected",
"decision_reason": "Only threshold-eligible window in the second activity segment."
}
],
"expected_output": {
"episode_count": 2,
"findings": [
{
"finding_id": "finding:brute_force:883357c5e7697574",
"episode_index": 1,
"rule_id": "brute_force",
"subject_kind": "source_ip",
"subject": "203.0.113.78",
"grouping_key": "source_ip",
"threshold": 5,
"observed_count": 5,
"event_count": 5,
"window_start": "2026-03-11 09:00:00",
"window_end": "2026-03-11 09:02:00",
"evidence_event_ids": [
"line:1",
"line:2",
"line:3",
"line:4",
"line:5"
],
"verdict_boundary": "triage_signal_not_compromise_or_attribution"
},
{
"finding_id": "finding:brute_force:ba242483f59f6f4e",
"episode_index": 2,
"rule_id": "brute_force",
"subject_kind": "source_ip",
"subject": "203.0.113.78",
"grouping_key": "source_ip",
"threshold": 5,
"observed_count": 5,
"event_count": 5,
"window_start": "2026-03-11 09:20:00",
"window_end": "2026-03-11 09:22:00",
"evidence_event_ids": [
"line:6",
"line:7",
"line:8",
"line:9",
"line:10"
],
"verdict_boundary": "triage_signal_not_compromise_or_attribution"
}
],
"excluded_event_decisions": []
},
"research_observation": {
"baseline_already_separates_dense_bursts": true,
"candidate_should_preserve_episode_count_and_identity": true,
"not_a_v0.6_regression": true
}
}
Loading
Loading