Originally created by: fu351
The deterministic Unicode scanner cannot see a GCG-style adversarial suffix: the red-team corpus proves those fixtures pass it clean, and the statistical channel that would catch them has stayed inert because core ships no scorer. Ship the reference scorer as an optional extra.
Build
src/doberman/perplexity.py: build_perplexity_fn(model_name="gpt2", window, stride) with lazy transformers/torch imports, scoring the max over sliding token windows so a local suffix inside long benign text still scores high; maybe_build_detector() returns a TokenChannelDetector(perplexity_fn=..., perplexity_threshold=...) or None.pyproject.toml: a new perplexity extra (transformers, torch). Never a default or dev dependency; default CI runs no model.extra_detectors. The host-hook path never imports this module (tested via a clean-interpreter sys.modules check).Double opt-in: the extra must be installed AND DOBERMAN_PERPLEXITY=1 set. Without either, behavior is byte-for-byte unchanged.
Guarantees (each one is a test)
calibrate_perplexity_threshold on their own benign corpus.Honest scope: catches high-perplexity adversarial text within a calibrated FPR budget. Defense-in-depth, not a jailbreak detector.
Blocked by [#234] (the calibration helper lands first).