Skip to content

refactor(exclusion): consolidate duplicate session-text helper + 6 repeated call patterns (closes #23)#24

Merged
wpak-ai merged 1 commit intomasterfrom
chore/exclusion-rule-dedup-23
May 6, 2026
Merged

refactor(exclusion): consolidate duplicate session-text helper + 6 repeated call patterns (closes #23)#24
wpak-ai merged 1 commit intomasterfrom
chore/exclusion-rule-dedup-23

Conversation

@timon0305
Copy link
Copy Markdown
Collaborator

@timon0305 timon0305 commented May 6, 2026

Problem

Three layers of duplication around exclusion-rule filtering:

  1. _session_text_for_exclusion(session) defined twice — byte-identical bodies (only docstring differs) in scripts/export.py:476 and api/export_api.py:43. Two maintenance points for one function.
  2. Six call sites in api/sessions.py, api/projects.py, api/search.py, api/export_api.py (×2), and scripts/export.py repeated the same if rules: build_searchable_text(...) → is_excluded_by_rules(...) → skip pattern (~10 lines each, ~60 lines total).
  3. Latent inconsistency between the two text-extraction styles: the helper rejected whitespace-only message text (isinstance(text, str) and text.strip()); the 4 inline call sites didn't (if msg.get("text")). Bug surface small but real.

Change

Consolidated into utils/exclusion_rules.py:

  • session_text_for_exclusion(session) — moved from the duplicate-defined private helpers. Single source of truth; both old copies deleted.
  • is_session_excluded(rules, session, project_name) -> bool — wraps the full pattern. Returns False when rules is empty/falsy, so callers don't gate on if rules: first.

Six call sites collapsed to one line each. Whitespace-handling inconsistency disappears.

Test plan

Unit (pytest tests/): 91/91 OK (was 75 + 16 new in tests/test_exclusion_helpers.py).

The 16 new cases:

  • session_text_for_exclusion (6 cases): empty session, no messages, joins with blank lines, skips messages without text, skips whitespace-only text (the regression-of-the-old-bug guard), skips non-string text.
  • is_session_excluded (10 cases): empty/None rules → False; matches across each haystack field (project_name / session_title / model_names / message content); AND vs OR rule grammar; quoted-phrase exact match; defensive against missing metadata key; defensive against project_name=None.

Net diff: +228 / −90 lines across 7 files (the +228 is mostly the 165-line new test file; the helper itself is +44 lines, and the 5 application files net −20 lines after removing the duplicate helper defs and the 6 inlined wrapping blocks).

Closes #23.

Summary by CodeRabbit

  • Refactor

    • Consolidated session exclusion filtering logic across exports, project listings, search, and session retrieval for improved consistency and maintainability.
  • Tests

    • Added comprehensive test coverage for session exclusion rules, including filtering scenarios by project name, session title, model name, and message content.

…ated call patterns (closes #23)

Three layers of duplication around exclusion-rule filtering:

1. `_session_text_for_exclusion(session)` was defined twice — byte-identical
   bodies (only docstring differs) in scripts/export.py:476 and
   api/export_api.py:43. Two maintenance points for one function.

2. Six call sites repeated the same `if rules: build_searchable_text(...) →
   is_excluded_by_rules(...) → skip` pattern across api/sessions.py,
   api/projects.py, api/search.py, api/export_api.py (×2), and
   scripts/export.py. ~60 lines of near-identical wrapping.

3. Latent inconsistency: the helper rejected whitespace-only message text
   (`isinstance(text, str) and text.strip()`); the 4 inline call sites did
   not (`if msg.get("text")`). Bug surface small but real, and there was no
   reason for the difference.

Consolidated into utils/exclusion_rules.py:

- session_text_for_exclusion(session) — moved from the duplicate-defined
  private helpers; now the single source of truth.
- is_session_excluded(rules, session, project_name) — wraps the full
  pattern. Returns False when rules is empty/falsy, so callers don't have
  to gate on `if rules:` before calling. Six call sites collapsed to one
  line each.

After: one definition of the extraction logic, one definition of the
wrapping pattern, the whitespace-handling inconsistency disappears
(everyone uses the helper), and ~20 net lines removed across 6 files.

Tests: tests/test_exclusion_helpers.py adds 16 unit cases for the new
helpers — text-extraction edge cases (empty, whitespace-only, non-string,
mixed) and rule-matching across all four haystack fields (project_name,
session_title, model_names, content) plus AND/OR/quoted-phrase grammar
plus defensive cases (no metadata key, project_name=None). 91/91 pytest
pass (was 75; +16 new).
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 6, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 68c159aa-cb4c-453a-8698-1fc915417c55

📥 Commits

Reviewing files that changed from the base of the PR and between 3b72afd and cbf8e61.

📒 Files selected for processing (7)
  • api/export_api.py
  • api/projects.py
  • api/search.py
  • api/sessions.py
  • scripts/export.py
  • tests/test_exclusion_helpers.py
  • utils/exclusion_rules.py

📝 Walkthrough

Walkthrough

The PR consolidates duplicate session exclusion filtering logic from six scattered call sites into two centralized helpers (session_text_for_exclusion and is_session_excluded) in utils/exclusion_rules.py, eliminating redundant implementations and unifying the exclusion-checking pattern across API and script modules.

Changes

Exclusion Rule Consolidation

Layer / File(s) Summary
Core Helpers
utils/exclusion_rules.py
Added session_text_for_exclusion(session) to extract plain-text snippets from session messages, and is_session_excluded(rules, session, project_name) to wrap the full exclusion evaluation pattern (extract text → build searchable text → check rules).
API & Script Updates
api/export_api.py, api/projects.py, api/search.py, api/sessions.py, scripts/export.py
Replaced six duplicated exclusion patterns with single-line calls to is_session_excluded(); removed byte-identical _session_text_for_exclusion implementations and imports of build_searchable_text and is_excluded_by_rules; updated imports to bring in the new centralized helper.
Tests & Documentation
tests/test_exclusion_helpers.py
Added comprehensive test coverage for session_text_for_exclusion (empty sessions, message joining, whitespace handling, text type validation) and is_session_excluded (rule matching on project name, session title, model name, message content, AND/OR logic, quoted phrases, metadata absence).

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~15 minutes

Poem

🐰 Six scattered helpers, now just one—
Text extraction bundled, duplication done!
From utils I hop, a helper so neat,
Makes every exclusion check pure and complete.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 17.24% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and concisely describes the main refactoring change: consolidating duplicate session-text helpers and repeated call patterns across 6 sites.
Linked Issues check ✅ Passed The PR successfully addresses all coding requirements from issue #23: removed duplicate _session_text_for_exclusion definitions, consolidated 6 repeated call patterns into is_session_excluded helper, resolved whitespace-handling inconsistency, and added comprehensive test coverage.
Out of Scope Changes check ✅ Passed All changes are directly in scope with issue #23: consolidation of exclusion helpers and call sites. No unrelated modifications or feature additions detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/exclusion-rule-dedup-23

Comment @coderabbitai help to get the list of available commands and usage tips.

@timon0305 timon0305 self-assigned this May 6, 2026
@timon0305 timon0305 requested a review from clean6378-max-it May 6, 2026 14:21
@clean6378-max-it clean6378-max-it requested a review from wpak-ai May 6, 2026 16:39
@wpak-ai wpak-ai merged commit e1bfb0a into master May 6, 2026
2 checks passed
@wpak-ai wpak-ai deleted the chore/exclusion-rule-dedup-23 branch May 6, 2026 16:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Exclusion rule plumbing: consolidate duplicate _session_text_for_exclusion + 6 repeated call patterns

3 participants