1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//! Shared search corpus and matchers for `tix search` (CLI, WP04) and the
//! `/` search (TUI, WP05).
//!
//! Both consumers search **exactly the same corpus**: the complete serialized
//! markdown of every issue (`Issue::to_file_contents()`, i.e. frontmatter +
//! body + comments). A single engine here keeps the CLI and TUI behavior from
//! drifting (C-005, FR-012):
//!
//! - [`Corpus::build`] snapshots every issue's full file text.
//! - [`search_substring`] is the case-insensitive single-occurrence matcher
//! the CLI uses, returning matched-line context.
//! - [`query_matches`] is the grammar-aware matcher (`key:value` tokens plus
//! case-insensitive **substring** bare terms) the board's `/` search uses.
//! - [`fuzzy_score`] is the deterministic subsequence scorer, now used only as
//! the help overlay's fallback when a literal substring finds no row (tix
//! #1496); the board's `/` search no longer uses it (tix #1498).
//!
//! Nothing here touches the `-assets/` directories (C-005): binary contents
//! are never indexed, and [`Corpus::build`] inherits that from
//! [`Store::list`], which already excludes non-`.md` files and `-assets` dirs.
use serde::{Deserialize, Serialize};
use crate::error::{Result, TixError};
use crate::model::Issue;
use crate::storage::Store;
use crate::watcher::FsDelta;
use std::collections::HashSet;
use std::path::{Path, PathBuf};
mod corpus;
mod filter;
mod query;
pub use corpus::*;
pub use filter::*;
pub use query::*;
// ---------------------------------------------------------------------------
// Structured filtering (FR-007..FR-013)
// ---------------------------------------------------------------------------
#[cfg(test)]
mod tests;