feat(python): regex hit suppression (--suppress-hit-regex/-file) — closes #53#183
Merged
Conversation
…oses #53 Drop known/uninteresting *crashing sessions* by regex-matching their captured stdout — the automated version of the by-hand dedup a triager does. This is the general/non-OOM analogue of the OOM catalog dedupe (--oom-dedup-catalog). Engine: fusil/python/hit_suppression.py — pure-Python (no runtime stack), mirroring oom_dedup.py's split so it unit-tests in isolation. Rules union three composable sources: * repeatable --suppress-hit-regex, * one or more --suppress-hit-file files (one regex/line; '#' comments; optional reason after ' ## '), and * plugins via PluginManager.add_suppression_entry (the extensible store #52 asked for). --suppress-hit-ignore-case toggles case-insensitive matching. Wiring: Fuzzer._suppression_keep_policy reads the crash stdout (bounded via read_crash_stdout) and, on a match, prunes the session dir (reason logged), returning (False, None) through the same application.session_keep_policy hook SessionDirectory.checkKeepDirectory already consults. It composes with the OOM dedupe: suppression runs first (a matched hit is pruned even if the OOM deduper would keep it), otherwise it defers to the previously-installed policy. Absent any --suppress-hit-* option nothing is installed and behaviour is unchanged. Failures fall back to keep so a crash is never lost. Tests (mirror the oom_dedup split): * tests/python/test_hit_suppression.py — pure engine (compile/parse/decide/ report/build_suppressor), no skip guard. * tests/python/test_hit_suppression_wiring.py — skip-guarded keep-policy glue (prune+log, keep, defer-to-prev, suppression-wins-over-prev, read-error). * tests/test_plugin_manager.py — add_suppression_entry / get_suppression_entries. Docs: doc/python-fuzzer.md (new Hit-suppression subsection + Where-to-look row), CLAUDE.md (options block + architecture subsection). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #53.
What
Adds regex-based hit suppression: drop known/uninteresting crashing sessions by matching a regex against their captured stdout — the automated version of the by-hand dedup a triager does ("filter out hits that mention source code lines and abort/segfault messages"). This is the general/non-OOM analogue of the OOM catalog dedupe (
--oom-dedup-catalog), and needs no catalog.How to use
Suppression-file example:
Rules union three composable sources:
--suppress-hit-regex,--suppress-hit-file, and plugins viaPluginManager.add_suppression_entry(pattern, reason)— the extensible suppression store called for in #52. On a match the session dir is pruned and the reason logged; an end-of-run summary reports how many hits each rule dropped.Design
fusil/python/hit_suppression.py: pure-Python (no runtime stack), mirroringoom_dedup.py's split so it unit-tests in isolation.build_suppressor()→HitSuppressor.decide(text) -> (keep, rule).Fuzzer._suppression_keep_policyreads the crash stdout (bounded viaread_crash_stdout, to avoid catastrophic regex backtracking on huge/OOM-verbose spew) and returns(False, None)on a match through the sameapplication.session_keep_policyhookSessionDirectory.checkKeepDirectoryalready consults for OOM dedupe.--oom-dedup-catalog: suppression runs first (a matched hit is pruned even if the OOM deduper would keep it); otherwise it defers to the previously-installed policy. Absent any--suppress-hit-*option, nothing is installed and behaviour is unchanged. Any failure falls back to keep, so a crash is never lost to a suppression error.Tests
Mirror the
oom_dedupsplit — all green (python -m unittest discover -s tests, 420 tests),ruff check+ruff format --checkclean:tests/python/test_hit_suppression.py— pure engine (compile / parse-file / decide / report /build_suppressor), no skip guard.tests/python/test_hit_suppression_wiring.py— skip-guarded keep-policy glue: prune+log, keep, defer-to-prev, suppression-wins-over-prev, and read-error → keep.tests/test_plugin_manager.py—add_suppression_entry/get_suppression_entries.Also smoke-tested end-to-end (
--suppress-hit-regex/-file/-ignore-caseon a live 1-session run): the startup log reports the rule count and the run exits cleanly.Docs
doc/python-fuzzer.md(new Hit suppression subsection + Where to look row) andCLAUDE.md(options block + architecture subsection).🤖 Generated with Claude Code