Skip to content

feat: DecisionSearchService — search, filter, and ranking for decisions (#69)#79

Merged
csharpfritz merged 1 commit intomainfrom
squad/69-decision-search-filter
Feb 26, 2026
Merged

feat: DecisionSearchService — search, filter, and ranking for decisions (#69)#79
csharpfritz merged 1 commit intomainfrom
squad/69-decision-search-filter

Conversation

@csharpfritz
Copy link
Owner

Summary

Closes #69 — Adds a pure service-layer DecisionSearchService that provides full-text search, date range filtering, and author filtering for parsed decisions.

Working as Linus (Backend Dev).

What's New

src/services/DecisionSearchService.ts

New stateless service operating on DecisionEntry[] arrays:

Method Description
search(decisions, query) Full-text search with relevance ranking
filterByDate(decisions, start, end) Inclusive date range filter
filterByAuthor(decisions, author) Case-insensitive substring match
filter(decisions, criteria) Combined criteria — chains all three

Ranking strategy: title match (10×) > author match (5×) > content match (3×). Multi-word queries are split on whitespace; each term scored independently and summed.

Exported Types

  • DecisionSearchCriteria — criteria bundle for the combined filter() method
  • ScoredDecision — decision + relevance score pair

Tests

37 new tests in decisionSearchService.test.ts covering:

  • Search: empty query, title/content/author matching, case-insensitivity, ranking, multi-word queries
  • Date filtering: inclusive range, single-day, missing dates, empty range
  • Author filtering: exact, partial, case-insensitive, missing authors
  • Combined: all criteria together, partial criteria, open-ended date ranges
  • Edge cases: regex characters in query, empty arrays, long queries, reversed date ranges

Design Decisions

  • Decoupled from DecisionService — operates on DecisionEntry[], not files
  • No VS Code deps — pure TypeScript, testable in isolation
  • No model changesDecisionEntry already had all needed fields
  • Search-first chaining in filter() preserves relevance ordering through subsequent filters

For Rusty

The tree view integration is your follow-up. The filter() method accepts a DecisionSearchCriteria object — bind the search box and filter controls to this interface. Import from src/services:

import { DecisionSearchService, DecisionSearchCriteria } from '../services';

Test Results

All 1093 tests passing (1056 existing + 37 new).

Add pure service-layer search, date filtering, and author filtering
for parsed decisions. Designed for tree view integration (Rusty follow-up).

- DecisionSearchService with search(), filterByDate(), filterByAuthor(), filter()
- Relevance ranking: title (10x) > author (5x) > content (3x)
- DecisionSearchCriteria and ScoredDecision interfaces exported
- 37 comprehensive tests covering all methods and edge cases
- Decision inbox entry for team awareness

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@csharpfritz csharpfritz merged commit 379edac into main Feb 26, 2026
3 of 4 checks passed
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.

Decision Search & Filter in tree view

1 participant