feat: Rust CLI — declarative alert rules, deterministic engine, replay source (LEO-335) (#24)
* feat: Rust CLI — declarative alert rules, deterministic engine, replay source (LEO-335) A strict [[rules]] config section (threshold/rate/stale/missing/ source-unavailable, with hysteresis, debounce, and per-series state), a deterministic sample-count-based engine emitting fired/cleared transitions, and the SampleSource abstraction: LiveSource (fresh HWiNFO session per poll) and ReplaySource (logged JSONL, bounded reads, Python-era NaN-token fixup). No new CLI subcommand — the engine ships test-first and gets wired to the watch command in LEO-336. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test: bind a named LiveSource before calling next_tick (review readability) Addresses the round-1 Copilot comment. Note the original code did compile and pass (method-call auto-ref mutably borrows the temporary; the cfg(not(windows)) test ran green on ubuntu CI) — the change is for readability: a named mutable binding mirrors how a real caller holds a source across ticks. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * review round 2: address non-blocking findings from agent reviewers - engine: the rate NaN comment now says what the code does — only the delta's ENDPOINTS can make it unevaluable; a NaN strictly inside the window is invisible. Kept endpoint semantics deliberately (poisoning would blind the rule for a whole window after every blip) and pinned it with the reviewer's 10 -> NaN -> 30 scenario as a permanent test. - engine: Transition equality is now NaN-reflexive (hand-written PartialEq mirroring the safe wrapper's Reading), so identical replays carrying NaN payloads compare equal; the determinism test now runs a dead NaN rail through the comparison to prove it. - rules: kind-independent validation (matcher patterns, finiteness, clear side, for_samples range) moved before the kind gate, so a rule missing its kind still gets its other problems aggregated; pinned. - SECURITY.md: enumerate replayed JSONL as parsed untrusted input in the Current-implementation attack-surface list — this PR ships the first read-back parser, and the round-1 PR-body claim that it was already enumerated was wrong (credit: lcj-claude-reviewer). Not changed, deliberately: LiveSource's debug-level source-loss logging (the warn-once latch is a command-loop concern, LEO-336) and the O(n^2) duplicate-name scan (rule counts are hand-written-config tiny). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Agent for Leonard Janke <leonard.janke.agent@proton.me> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
L
lcj-claude-coder committed
3ecc0fc8db0a0690da7916388fa2f10d684560fb
Parent: de15106
Committed by GitHub <noreply@github.com>
on 7/3/2026, 2:46:03 AM