feat(grouper): deterministic QUALITY GATE filter + broader noise strip#33
Merged
Conversation
Stops trusting the LLM to follow negative drop rules. Adds a regex-based
filter that runs on the extracted bullet list before dedup/classification,
catching the noise patterns the prompt-level QUALITY GATE was failing to
suppress in practice (gpt-5.4-mini ignores negative rules at low temp).
Architect's recommendation: "use grep for what grep can do."
Three changes:
1. Broader noise strip in `_strip_channel_summary_noise`:
- 📌 Key points / Ключевые моменты / Puntos clave / etc — template
header was leaking into bullets as `📌 Key points: (channel list)`
- 1️⃣-9️⃣ section numbering prefixes — cosmetic clutter
- [emoji], [brief fact] template token placeholders
2. New `_quality_gate_filter` deterministic pass between extract and dedup.
Drops:
- Admin chatter (new chat members, joins/leaves)
- Meta-empty bullets ("без подробностей", "no details", "just a poll")
- Short bullets (<30 chars) lacking concrete entity (digits/@/URL/proper)
- Speculation/hedging without concrete entity ("вероятно", "probably")
3. QUALITY GATE moved into extractor system prompt as belt-and-suspenders.
Framed as "DROP rules OVERRIDE extract-verbatim" so the model isn't torn
between conflicting instructions. Real safety still comes from #2.
Architecture:
Pass 2a extract → QUALITY GATE filter → cross-channel dedup → Pass 2b classify
^^^^^^^^^^^^^^^^^^
NEW deterministic chokepoint
Tests: 410 passed, 7 skipped, coverage 79.18%.
Real-world digest motivation (from PR #32 post-merge run):
- Tech section had `🆕 В чате появился новый участник Denis Nogtev` (admin chatter)
- Другое had `📌 Key points: (Вастрик Селфхостеры🔧, kyrillic🌍, ...)` (template leak)
- Tech had `🛸 В подборке упомянуты темы, но без дополнительных деталей` (meta-empty)
- Другое had `📊 Парк выглядит как сильный фотоспот` (speculation, no entity)
CI pins black 24.10.0 (per CLAUDE.md note); local newer black accepted the multi-line form. CI black wants the call on one line. Verified locally with: uvx --from "black==24.10.0" black --check src/ tests/
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.
Summary
Architect's call after PR #32 merge analysis: stop trusting the LLM to follow negative drop rules. Add a deterministic regex/heuristic filter pass between extraction and dedup. Move QUALITY GATE prompt rules into the extractor as belt-and-suspenders.
This is the next iteration on top of PR #32. After running `/digest` on real bot, five categories of noise survived all the prompt-level rules:
Architecture change
Same pattern as the dedup chokepoint introduced in PR #32: pull noise removal out of prompts and into code. Prompt rules stay as belt-and-suspenders but the actual safety comes from `_quality_gate_filter`.
QUALITY GATE rules (deterministic)
Substantive bullets pass through untouched (validated by `test_keeps_substantive_bullets_unchanged`).
Broader noise strip in
_strip_channel_summary_noiseFive new regex patterns added to the existing 🚀 + 📎 strip:
Why move QUALITY GATE into extractor prompt too
Architect: "will help marginally because the task is simpler, but you're still asking a weak model to follow negative rules at low temperature on Russian text. Don't bet on it."
So this is belt-and-suspenders only. The deterministic filter is the load-bearing fix. Prompt now explicitly says "DROP rules OVERRIDE extract-verbatim" to resolve the conflict the model previously had between rules.
What's next (out of scope for this PR)
Per architect, the bigger remaining wins:
Test plan
Files