From dc8e5f5ad36605b18ac1ebbba51ccd991f3140d0 Mon Sep 17 00:00:00 2001 From: Robert Sigmundsson Date: Thu, 23 Jul 2026 16:37:16 +0200 Subject: [PATCH] feat(write-gate): machine-noise denylist gate (Gate 1b) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Empiryczny denylist z gate_decision false-accepts: hard-reject dla struktur powiadomień/tagów które nigdy nie są wiedzą — //task-notification, tool-use-id, *-caveat>, Monitor event, Background command, oraz prefiksów Session activity:/ps -o/echo/curl. Zamyka lukę: enforce przepuszczał 89% szumu przy score=5 (monitor-events, task-notif, echa shell). Zwalidowane fixture: JUNK 8/8 reject, GOOD (z tagami/typem) 3/3 pass. + config auto_capture_min_score 5->6. (cherry picked from commit 2bb52f47da177ca077b2239cac2d0966fda7b3ba) --- src/surreal_memory/engine/quality_scorer.py | 40 +++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/surreal_memory/engine/quality_scorer.py b/src/surreal_memory/engine/quality_scorer.py index cd6c8f1d..1e513bc0 100755 --- a/src/surreal_memory/engine/quality_scorer.py +++ b/src/surreal_memory/engine/quality_scorer.py @@ -67,6 +67,36 @@ } ) +# Machine-output / notification noise — never valuable knowledge. Empirical denylist +# from gate_decision false-accepts (2026-07-23): 180x "Session activity:", 30x , +# 20x "Background command", 19x , 12x task-notification, tool-use-id, *-caveat>, etc. +_NOISE_TAG_RE = re.compile( + r"|||||tool-use-id>|" + r'|\bMonitor event\b|Background command "', + re.IGNORECASE, +) +_NOISE_PREFIXES = ( + "session activity:", + " bool: + """True if content is machine output / session-notification noise, not knowledge. + + Two signals: (a) starts with a known auto-capture/shell noise prefix, or + (b) contains a structural notification/tool tag that never appears in a real memory. + """ + stripped = content.strip() + if stripped.lower().startswith(_NOISE_PREFIXES): + return True + return bool(_NOISE_TAG_RE.search(stripped)) + + # -- Quality thresholds ----------------------------------------------------- _MIN_CONTENT_LENGTH = 10 @@ -237,6 +267,16 @@ def check_write_gate( rejection_reason=f"Generic filler rejected: '{stripped[:50]}'", ) + # Gate 1b: Machine-output / session-notification noise (empirical denylist) + if _is_machine_noise(stripped): + return QualityResult( + score=0, + quality="low", + hints=("Machine output / session-notification noise is not a memory",), + rejected=True, + rejection_reason=f"Machine-noise rejected: '{stripped[:50]}'", + ) + # Gate 2: Minimum length if len(stripped) < gate_config.min_length: return QualityResult(